t4_geom_convert.Kernel.Transformation package
Submodules
t4_geom_convert.Kernel.Transformation.Transformation module
- t4_geom_convert.Kernel.Transformation.Transformation.adjust_matrix(matrix)
Perform a certain number of magical tweaks to the matrix that make sure that it is orthogonal.
MCNP tolerates some skewness but internally adjusts the matrix. We need to do the same thing, or we will not generate the same geometry.
>>> adjust_matrix([1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]) [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
>>> from math import cos, sin, isclose >>> cos_a, sin_a = cos(1.23), sin(1.23) >>> rot = [1.0, 0.0, 0.0, 0.0, cos_a, sin_a, 0.0, -sin_a, cos_a] >>> rot2 = adjust_matrix(rot) >>> all(isclose(x, y) for x, y in zip(rot, rot2)) True
The following matrix has too few significant digits, so
adjust_matrix()raises a warning:>>> import pytest >>> mat = [ 0.8021, 0.1056, -0.5878, ... -0.1305, 0.9914, 0.0000, ... 0.5828, 0.0767, 0.8090] >>> with pytest.warns(UserWarning, match='is not orthogonal'): ... mat2 = adjust_matrix(mat)
The new matrix is close to the original one, with a tolerance of 1e-4:
>>> all(isclose(x, y, abs_tol=1e-4) for x, y in zip(mat, mat2)) True
Based on r̶a̶t̶i̶o̶n̶a̶l̶ ̶g̶e̶o̶m̶e̶t̶r̶i̶c̶a̶l̶ ̶c̶o̶n̶s̶i̶d̶e̶r̶a̶t̶i̶o̶n̶s̶ c̶a̶r̶e̶f̶u̶l̶ ̶r̶e̶a̶d̶i̶n̶g̶ ̶o̶f̶ ̶t̶h̶e̶ ̶M̶C̶N̶P̶ ̶s̶o̶u̶r̶c̶e̶ ̶c̶o̶d̶e̶ desperate debugging with
gdb, the adjusted matrix generated by MCNP is:>>> mat2_expected = [ ... 0.80207826071476684, 0.10559100917526101, -0.58781034566441959, ... -0.13050431946672519, 0.99144774047316964, 2.260914180407525e-05, ... 0.58278562635784137, 0.07669365483530112, 0.80899876206252763 ... ]
The matrix generated by
adjust_mat()is close to the expected value:>>> all(isclose(x, y) for x, y in zip(mat2_expected, mat2)) True
The entries are really close to the expected values!
>>> for x, y in zip(mat2_expected, mat2): ... ratio = (x-y)/x ... print(f'{x: 20.18e} {y: 20.18e} {ratio: 7.5e}') 8.020782607147668442e-01 8.020782607147668442e-01 0.00000e+00 1.055910091752610136e-01 1.055910091752610136e-01 0.00000e+00 -5.878103456644195868e-01 -5.878103456644196978e-01 -1.88874e-16 -1.305043194667251938e-01 -1.305043194667251938e-01 -0.00000e+00 9.914477404731696364e-01 9.914477404731696364e-01 0.00000e+00 2.260914180407525009e-05 2.260914180407525348e-05 -1.49857e-16 5.827856263578413687e-01 5.827856263578413687e-01 0.00000e+00 7.669365483530111993e-02 7.669365483530111993e-02 0.00000e+00 8.089987620625276321e-01 8.089987620625278542e-01 -2.74468e-16
- t4_geom_convert.Kernel.Transformation.Transformation.compose_transform(trans1, trans2)
Compose trans1 and trans2.
Returns trans2 o trans1 (i.e. trans1 is applied first).
- t4_geom_convert.Kernel.Transformation.Transformation.get_mcnp_transforms(parser)
Return the dictionary of parsed MCNP transformation, in a canonical, 12-parameter form.
- Parameters:
parser – the MCNP parser
- Returns:
a dictionary associating each transformation number to a list of 12 transformation parameters.
- t4_geom_convert.Kernel.Transformation.Transformation.is_matrix_rowwise(matrix)
Returns True if the matrix has at least one fully defined row.
>>> is_matrix_rowwise([1, 2, 3, 4, 5, 6, 7, 8, 9]) True >>> is_matrix_rowwise([None, None, None, 4, 5, 6, 7, 8, 9]) True >>> is_matrix_rowwise([1, 2, 3, None, None, None, 7, 8, 9]) True >>> is_matrix_rowwise([1, 2, 3, 4, 5, 6, None, None, None]) True >>> is_matrix_rowwise([None, 2, 3, None, 5, 6, None, 8, 9]) False >>> is_matrix_rowwise([1, None, 3, 4, None, 6, 7, None, 9]) False >>> is_matrix_rowwise([1, 2, None, 4, 5, None, 7, 8, None]) False >>> is_matrix_rowwise([None, None, None, None, None, None, 7, 8, 9]) True >>> is_matrix_rowwise([None, None, None, 4, 5, 6, None, None, None]) True >>> is_matrix_rowwise([1, 2, 3, None, None, None, None, None, None]) True >>> is_matrix_rowwise([None, None, 3, None, None, 6, None, None, 9]) False >>> is_matrix_rowwise([1, None, None, 4, None, None, 7, None, None]) False >>> is_matrix_rowwise([None, 2, None, None, 5, None, None, 8, None]) False
- t4_geom_convert.Kernel.Transformation.Transformation.normalize_matrix(matrix)
Return a normalized version of the given 3x3 rotation matrix.
The input matrix may be missing some elements (3, 5, 6 and 9 elements are possible) or some of the elements may be None. The rules for normalizing a 3x3 rotation matrix are given in the MCNP6 manual, section 3.3.1.3 (TR card, Surface coordinate transformation).
- t4_geom_convert.Kernel.Transformation.Transformation.normalize_matrix3(matrix)
Return the canonical form of a 3x3 matrix where exactly one row has been defined.
>>> from ..VectUtils import scal, rotate >>> mat = normalize_matrix3([1.0, 0.0, 0.0, ... None, None, None, ... None, None, None]) >>> rows = matrix_rows(mat) >>> rows[0] == [1, 0, 0] True >>> scal(rows[0], rows[1]) 0.0 >>> scal(rows[0], rows[2]) 0.0 >>> scal(rows[1], rows[2]) 0.0 >>> scal(rows[0], rows[0]) 1.0 >>> scal(rows[1], rows[1]) 1.0 >>> scal(rows[2], rows[2]) 1.0
We can also check that it works with a somewhat generically aligned vector:
>>> vec = rotate((1.0, 0.0, 0.0), (0.0, 1.0, 0.0), 37.5) >>> vec = rotate(vec, (0.0, 0.0, 1.0), 194.2) >>> vec = rotate(vec, (1.0, 0.0, 0.0), -446.3) >>> mat = normalize_matrix3([None]*3 + list(vec) + [None]*3) >>> rows = matrix_rows(mat) >>> rows[1] == list(vec) True >>> abs(scal(rows[0], rows[1])) < 1e-10 True >>> abs(scal(rows[0], rows[2])) < 1e-10 True >>> abs(scal(rows[1], rows[2])) < 1e-10 True >>> abs(scal(rows[0], rows[0]) - 1.0) < 1e-10 True >>> abs(scal(rows[1], rows[1]) - 1.0) < 1e-10 True >>> abs(scal(rows[2], rows[2]) - 1.0) < 1e-10 True
- t4_geom_convert.Kernel.Transformation.Transformation.normalize_matrix5(matrix)
Return the canonical form of a 3x3 matrix where exactly one row and one column have been defined.
>>> from math import sqrt, cos, sin >>> def make_euler(alpha, beta, gamma): ... s1, c1 = sin(alpha), cos(alpha) ... s2, c2 = sin(beta), cos(beta) ... s3, c3 = sin(gamma), cos(gamma) ... mat = [c2, -c3*s2, s2*s3, ... c1*s2, c1*c2*c3 - s1*s3, - c3*s1 - c1*c2*s3, ... s1*s2, c1*s3 + c2*c3*s1, c1*c3 - c2*s1*s3] ... return mat >>> full_mat = make_euler(100.0, 200.0, 300.0)
>>> some_mat = full_mat[0:4] + [None]*2 + [full_mat[6]] + [None]*2 >>> norm_mat = normalize_matrix5(some_mat) >>> np.allclose(norm_mat, full_mat) True
>>> some_mat = [full_mat[0]] + [None]*2 + full_mat[3:7] + [None]*2 >>> norm_mat = normalize_matrix5(some_mat) >>> np.allclose(norm_mat, full_mat) True
- t4_geom_convert.Kernel.Transformation.Transformation.normalize_matrix6(matrix)
Return the canonical form of a 3x3 matrix where exactly two rows have been defined.
- t4_geom_convert.Kernel.Transformation.Transformation.normalize_transform(transf)
Return a normalized, 12-param version of the affine transformation.
- t4_geom_convert.Kernel.Transformation.Transformation.to_numpy(trans)
Split a transformation into a NumPy 3x3 matrix and a vector.
>>> to_numpy([1., 2., 3., ... 1., 0., 0., ... 0., 1., 0., ... 0., 0., 1.]) (array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]), array([1., 2., 3.]))
- t4_geom_convert.Kernel.Transformation.Transformation.transform_vector(trans, vec)
Apply the (normalised) transformation trans to the vector vec.
If trans is
(b, A), then this function returnsv’ = A*v+b
- t4_geom_convert.Kernel.Transformation.Transformation.transformation(trpl, surface)
Apply a transformation to the given surface parameters.
- Parameters:
trpl – the transformation
surface (SurfaceMCNP) – an MCNP surface
t4_geom_convert.Kernel.Transformation.TransformationError module
Module that defines an error type for affine transformations.
t4_geom_convert.Kernel.Transformation.TransformationQuad module
- t4_geom_convert.Kernel.Transformation.TransformationQuad.transformation_quad(params, trans)
Apply the trans affine transformation to the quadric described by the params parameters.