reduce_box_vectors

mdcraft.lib.cell.reduce_box_vectors(box_vectors: np.ndarray[float_t] | 'unit.Quantity' | Q_, /) np.ndarray[float_t] | 'unit.Quantity' | Q_[source]

Reduces the box vectors of a general triclinic cell to those of a restricted one.

Two-dimensional box vectors

General parallelogram box vectors have the form

\[\begin{split}\begin{align*} \mathbf{A}&=(A_x,A_y),\\ \mathbf{B}&=(B_x,B_y), \end{align*}\end{split}\]

whereas restricted box vectors have the form

\[\begin{split}\begin{align*} \mathbf{a}&=(a_x,0),\\ \mathbf{b}&=(b_x,b_y), \end{align*}\end{split}\]

where \(a_x>0\), \(b_y>0\), and \(a_x\geq2|b_x|\).

The conversion is done using

\[\begin{split}\begin{align*} a_x&=\|\mathbf{A}\|,\\ b_x&=\mathbf{B}\cdot\hat{\mathbf{A}},\\ b_y&=\|\hat{\mathbf{A}}\times\mathbf{B}\|, \end{align*}\end{split}\]

where \(v=\|\mathbf{v}\|\) is the norm of a vector \(\mathbf{v}\) and \(\hat{\mathbf{v}}\equiv\mathbf{v}/\|\mathbf{v}\|\) is the unit vector in the direction of \(\mathbf{v}\).

Three-dimensional box vectors

General triclinic box vectors have the form

\[\begin{split}\begin{align*} \mathbf{A}&=(A_x,A_y,A_z),\\ \mathbf{B}&=(B_x,B_y,B_z),\\ \mathbf{C}&=(C_x,C_y,C_z), \end{align*}\end{split}\]

whereas restricted box vectors have the form

\[\begin{split}\begin{align*} \mathbf{a}&=(a_x,0,0),\\ \mathbf{b}&=(b_x,b_y,0),\\ \mathbf{c}&=(c_x,c_y,c_z), \end{align*}\end{split}\]

where \(a_x>0\), \(b_y>0\), \(c_z>0\), \(a_x\geq2|b_x|\), \(a_x\geq2|c_x|\), and \(b_y\geq2|c_y|\).

The conversion is done using

\[\begin{split}\begin{align*} a_x&=\|\mathbf{A}\|,\\ b_x&=\mathbf{B}\cdot\hat{\mathbf{A}},\\ b_y&=\|\hat{\mathbf{A}}\times\mathbf{B}\|,\\ c_x&=\mathbf{C}\cdot\hat{\mathbf{A}},\\ c_y&=\mathbf{C}\cdot[ (\widehat{\mathbf{A}\times\mathbf{B}}) \times\hat{\mathbf{A}}],\\ c_z&=\|\mathbf{C}\cdot (\widehat{\mathbf{A}\times\mathbf{B}})\|, \end{align*}\end{split}\]

where \(v=\|\mathbf{v}\|\) is the norm of a vector \(\mathbf{v}\) and \(\hat{\mathbf{v}}\equiv\mathbf{v}/\|\mathbf{v}\|\) is the unit vector in the direction of \(\mathbf{v}\).

Parameters:
box_vectorsnumpy.ndarray, openmm.unit.Quantity, or pint.Quantity, positional-only

Box vectors \((\mathbf{A};\mathbf{B}[;\mathbf{C}])\).

Shape: \((d,d)\), where \(d\in\{2,3\}\) is the dimensionality.

Reference unit: \(\mathrm{nm}\).

Returns:
reduced_box_vectorsnumpy.ndarray, openmm.unit.Quantity, or pint.Quantity

Reduced box vectors \((\mathbf{a};\mathbf{b}[;\mathbf{c}])\).

Shape: Same as box_vectors.

Unit: Same as box_vectors.

Examples

If the provided box vectors are already in their reduced forms, they are returned as is:

>>> box_vectors = np.array(((1, 0, 0), (2, 3, 0), (4, 5, 6)))
>>> reduce_box_vectors(box_vectors)
array([[1, 0, 0],
       [2, 3, 0],
       [4, 5, 6]])

If the box vectors for a general triclinic simulation box are provided, they are reduced to those of a restricted one:

>>> box_vectors = np.array(
...     (
...         (9 / np.sqrt(11), 3 / np.sqrt(11), 3 / np.sqrt(11)),
...         (-4 / np.sqrt(6), 8 / np.sqrt(6), 4 / np.sqrt(6)),
...         (5 / np.sqrt(66), 20 / np.sqrt(66), -35 / np.sqrt(66))
...     )
... )
>>> reduce_box_vectors(box_vectors)
array([[3., 0., 0.],
       [0., 4., 0.],
       [0., 0., 5.]])

With unit referring to the openmm.unit module and ureg referring to a pint.UnitRegistry instance, this function also supports OpenMM and Pint quantities:

>>> reduce_box_vectors(box_vectors * unit.nanometer)
Quantity(value=array([[3., 0., 0.],
       [0., 4., 0.],
       [0., 0., 5.]]), unit=nanometer)
>>> reduce_box_vectors(box_vectors * ureg.nanometer)
<Quantity([[3., 0., 0.],
 [0., 4., 0.],
 [0., 0., 5.]], 'nanometer')>