t4_geom_convert.Kernel.Volume package
Submodules
t4_geom_convert.Kernel.Volume.ByUniverse module
- t4_geom_convert.Kernel.Volume.ByUniverse.by_universe(mcnp_cell_dict)
Classify MCNP cells by the universe which they belong to. Return the classification as a dictionary associating the universe number to the list of cell IDs.
t4_geom_convert.Kernel.Volume.CellConversion module
- class t4_geom_convert.Kernel.Volume.CellConversion.CellConversion(int_cell, int_surf, d_dictClassT4, d_dictSurfaceT4, d_dicSurfaceMCNP, d_dicCellMCNP)
Bases:
objectClass which contains methods to convert the Cell of MCNP in T4 Volume
- apply_trcl(trcls, geometry)
Apply the given coordinate transformation to the given cell AST (geometry).
- Returns:
the transformed AST
- cell_transform(cell_key, transform, cache=True)
Apply transform to cell, update dictionaries and return the ID of the new cell.
- static conv_equa(list_surface)
Method converting a list of if of surface and return a tuple with the informations of the volume EQUA T4
- static conv_intersection(*ids)
Convert a T4 INTE and return a tuple with the information of the T4 VOLUME
- static conv_union(*ids)
Convert a T4 UNION and return a tuple with the information of the T4 VOLUME
- static conv_union_helpers(*ids, union_ids)
Convert a T4 UNION and return a tuple with the information of the T4 VOLUME
- convert_cellref(cell, matching, union_ids)
- convert_surface(surf, idorigin)
- develop_lattice(key)
- extract_surfaces(cell)
- pot_complement(tree)
- pot_convert(cell, matching, union_ids)
- pot_expand_surfs(p_tree, matching)
Replace collections of surfaces with ASTs representing the intersection/union of the collection (necessary for one-nappe cones and macrobodies). Also replace MCNP surface IDs with T4 surface IDs.
- pot_fill(key, dict_universe, inline_filled=False, inline_filling=False)
- pot_flag(p_tree)
Method that takes a tree and return a tuple of tuple with flag to decorate each tree in the tree.
- pot_optimise(p_tree)
Method that optimizes the MCNP cells.
- pot_to_t4_cell(p_tree, idorigin, matching, union_ids)
Take the tree create by
pot_flag()and fill a dictionary (of VolumeT4 instance).
- pot_transform(p_tree, p_transf)
t4_geom_convert.Kernel.Volume.CellConversionError module
Module containing the definition of the CellConversionError
class.
t4_geom_convert.Kernel.Volume.CellInlining module
Utilities for cell definition inlining.
- t4_geom_convert.Kernel.Volume.CellInlining.compute_inlining_scores(dic, occurrences)
Associate scores for inlining to each of the cells in occurrences. The lower the score, the more likely the cell is to be inlined.
- t4_geom_convert.Kernel.Volume.CellInlining.extract_subcells(geometry)
Extract any subcells from the given geometry tree and return them as a list.
>>> from .CellMCNP import CellRef >>> extract_subcells(['*', 1, 2]) [] >>> extract_subcells(['*', 1, CellRef(100), 2]) [100] >>> extract_subcells(['*', 1, CellRef(100), [':', CellRef(5), CellRef(6)]]) [100, 5, 6]
- t4_geom_convert.Kernel.Volume.CellInlining.find_occurrences(dic)
Find occurrences of inlined cells. Returns a dictionary associating a cell id key to a list of cell ids where key is inlined.
- t4_geom_convert.Kernel.Volume.CellInlining.geometry_size(geometry)
Count the number of nodes in the given geometry.
>>> from .CellMCNP import CellRef >>> geometry_size(['*', 1, 2]) 2 >>> geometry_size(['*', 1, CellRef(100), 2]) 3 >>> geometry_size(['*', 1, CellRef(100), [':', CellRef(5), CellRef(6)]]) 4
- t4_geom_convert.Kernel.Volume.CellInlining.inline_cells(dic, max_inline_score)
Perform inlining on the cells in dic.
- t4_geom_convert.Kernel.Volume.CellInlining.inline_cells_worker(geometry, dic, to_inline)
Inline the cells in the to_inline set in geometry. Returns a new geometry.
t4_geom_convert.Kernel.Volume.CellMCNP module
- class t4_geom_convert.Kernel.Volume.CellMCNP.CellMCNP(p_materialID, p_density, syntaxTreeMCNP, p_importance, p_universe, fillid, filltr, lattice, trcl, idorigin=None)
Bases:
objectClass which permit to access precisely to the information of the block CELLS.
- copy()
- evaluateASTMCNP()
Method evaluating the syntax tree of the geometry of a cell of MCNP.
- inverseASTMCNP()
Method applying the De Morgan law on a syntax tree.
t4_geom_convert.Kernel.Volume.ConstructVolumeT4 module
- t4_geom_convert.Kernel.Volume.ConstructVolumeT4.construct_volume_t4(mcnp_parser, lattice_params, cell_cache_path, dic_surface_t4, dic_surface_mcnp, inline_filled, inline_filling, max_inline_score)
A function that orchestrates the conversion steps for TRIPOLI-4 volumes.
- t4_geom_convert.Kernel.Volume.ConstructVolumeT4.extract_tr_surf_ids(mcnp_dict)
Return the list of MCNP surface IDs above 1000.
Surface IDs above 1000 are interpreted by MCNP as (surf_id + 1000*cell_id), where cell_id indicates a cell with a trcl card. The surface is modified by applying the trcl card of the cell.
- t4_geom_convert.Kernel.Volume.ConstructVolumeT4.extract_used_surfaces(volumes)
Return the IDs of the surfaces used in the given volumes, as a set.
- t4_geom_convert.Kernel.Volume.ConstructVolumeT4.remove_empty_volumes(dic_volume, union_ids)
Remove cells that are patently empty.
- t4_geom_convert.Kernel.Volume.ConstructVolumeT4.remove_unused_volumes(dic)
Remove unused virtual (
FICTIVE) volumes from the given dictionary. This function modifies the given dictionary in place.- Parameters:
dic (DictVolumeT4) – a dictionary of
VolumeT4objects.
>>> from .VolumeT4 import VolumeT4 >>> dic = DictVolumeT4() >>> dic[1] = VolumeT4([], [], ops=['UNION', (2, 3)], fictive=False) >>> dic[2] = VolumeT4([], [], ops=None, fictive=True) >>> dic[3] = VolumeT4([], [], ops=None, fictive=True) >>> dic[4] = VolumeT4([], [], ops=None, fictive=True) >>> dic[5] = VolumeT4([], [], ops=None, fictive=False) >>> remove_unused_volumes(dic) >>> sorted(list(dic.keys())) [1, 2, 3, 5]
t4_geom_convert.Kernel.Volume.DictVolumeT4 module
- class t4_geom_convert.Kernel.Volume.DictVolumeT4.DictVolumeT4
Bases:
MutableMappingA simple wrapper around an
collections.OrderedDictfor storingVolumeT4objects.- copy()
Return a copy of self.
t4_geom_convert.Kernel.Volume.Lattice module
Utilities for handling lattices.
- class t4_geom_convert.Kernel.Volume.Lattice.LatticeBounds(bounds)
Bases:
objectA simple class to hold a list of range bounds. It provides some useful services such as the
size()method.- copy()
Return a copy of self.
- dims()
Return the number of non-trivial dimensions.
- indices()
Yield all the valid indices in the bounds, in canonical order (loop over the leftmost index first).
>>> bounds = LatticeBounds([(-1, 1), (-2, 2)]) >>> list(bounds.indices()) [(-1, -2), (0, -2), (1, -2), (-1, -1), (0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1), (1, 1), (-1, 2), (0, 2), (1, 2)] >>> list(LatticeBounds([(0, 2)]).indices()) [(0,), (1,), (2,)]
- size()
Return the total size of the range bounds, i.e. the product of the range lengths.
>>> LatticeBounds([(0, 4)]).size() 5 >>> LatticeBounds([(-1, 1), (-3, 3)]).size() 21 >>> LatticeBounds([]).size() 1
- exception t4_geom_convert.Kernel.Volume.Lattice.LatticeError
Bases:
ExceptionAn exception class for errors generated during lattice processing.
- class t4_geom_convert.Kernel.Volume.Lattice.LatticeSpec(bounds, spec)
Bases:
objectA simple class that holds a list of n*m*l integers and provides n-dimensional indexing into the list.
- items()
Iterate over the lattice indices and the lattice specification, as (indices, spec) pairs.
>>> bounds = LatticeBounds([(1, 2), (0, 1)]) >>> spec = LatticeSpec(bounds, ['a', 'b', 'c', 'd']) >>> list(spec.items()) [((1, 0), 'a'), ((2, 0), 'b'), ((1, 1), 'c'), ((2, 1), 'd')]
- t4_geom_convert.Kernel.Volume.Lattice.areHexSidesAdjacent(plane1, plane2, other_surf1, other_surf2)
If plane1 and plane2 are adjacent in the hexagonal prism closed off by other_plane1 and other_plane2, this function returns the line given by the intersection of the two planes, in the form of a (point, vector) pair; otherwise, it returns None.
- t4_geom_convert.Kernel.Volume.Lattice.hexLatticeBaseVectors(surfaces)
Compute the base vectors for a hexagonal lattice.
- t4_geom_convert.Kernel.Volume.Lattice.hexSortSides(surfs)
Return an adjacency dictionary for the sides of the hexagon. The dictionary keys are pairs of indices of sides of the hexagon; the possible values are None if the given sides are not adjacent, or a straight line (in (point, direction) form) representing the intersection between the two planes if they are adjacent. The keys are always sorted in such a way that the smallest index comes first: so, for instance, (0, 1) is a possible key, but (1, 0) is not.
The surfs argument is the list of surfaces representing the hexagon. Each surface must be a (plane, side) pair, where plane is a plane (represented as a (point, normal) pair) and side indicates on which side of the plane the hexagonal cell lies (±1). The surfaces in surfs must appear in the canonical order: first, the surface that separates the base cell of the hexagonal lattice from the (1, 0, 0) cell; then the opposite plane; then the surface that separates the base cell from the (0, 1, 0) cell; then the opposite plane; and, finally, the two remaining planes, in no particular order.
As an example, consider the regular hexagon:
>>> from math import cos, sin, pi, isclose, fabs >>> vertices = [(cos(i*pi/3.), sin(i*pi/3.), 0.) for i in range(6)] >>> sides = [vdiff(v2, v1) ... for v1, v2 in zip(vertices, vertices[1:] + [vertices[0]])]
We compute the normals to the planes:
>>> from t4_geom_convert.Kernel.VectUtils import renorm, vect >>> normals = [renorm(vect(side, (0, 0, 1))) for side in sides] ... # these are outgoing normals
The hexagon looks like this:
2———/4 / 0//1 / 5/———3The numbers indicate the way we have chosen to order the planes. We construct the list of surfaces to respect this constraint:
>>> planes = [((vertices[i], normals[i]), -1) # -1 is the side ... for i in (0, 3, 1, 4, 2, 5)]
Here is the adjacency dictionary:
>>> adj = hexSortSides(planes) >>> adj[(0, 2)] is not None True >>> adj[(0, 5)] is not None True >>> adj[(0, 1)] is None True
We can also modify the plane numbering. For instance:
5———/2 / 0//1 / 3/———4>>> planes = [((vertices[i], normals[i]), -1) # -1 is the side ... for i in (0, 3, 2, 5, 4, 1)] >>> adj = hexSortSides(planes) >>> adj[(0, 2)] is None True >>> adj[(0, 3)] is not None True >>> point, direction = adj[(0, 3)] >>> (isclose(point[0], 1) ... and isclose(point[1], 0, abs_tol=1e-10) ... and isclose(point[2], 0, abs_tol=1e-10)) True >>> (isclose(direction[0], 0, abs_tol=1e-10) ... and isclose(direction[1], 0, abs_tol=1e-10) ... and isclose(fabs(direction[2]), 1)) True
We can also test a weird hexagon:
>>> vertices = [(0, 1, 0), (3, 1, 0), (5, 2, 0), ... (5, 3, 0), (2, 3, 0), (0, 2, 0)] >>> sides = [vdiff(v2, v1) ... for v1, v2 in zip(vertices, vertices[1:] + [vertices[0]])] >>> normals = [renorm(vect(side, (0, 0, 1))) for side in sides]
It looks approximately like this:
0/———+3 / |/ | 4| /5 | / 2x———/1The x represents the first vertex and the sides unfold counterclockwise. We impose the numbering given in the figure:
>>> planes = [((vertices[i], normals[i]), -1) # -1 is the side ... for i in (3, 0, 1, 4, 2, 5)] >>> adj = hexSortSides(planes) >>> adj[(0, 1)] is None True >>> adj[(0, 2)] is None True >>> adj[(0, 3)] is not None True >>> point, _ = adj[(0, 3)] >>> point (2.0, 3.0, 0.0) >>> point, _ = adj[(1, 2)] >>> point (3.0, 1.0, 0.0)
- t4_geom_convert.Kernel.Volume.Lattice.hexVertices(surfs, first_side)
Return the vertices of a base of the hexagonal prism described by the given surfaces and the direction of the prism axis.
The vertices are returned as a list of points. This function guarantees that the returned vertices are consecutive (i.e.
v[i]andv[i+i]share a side, and so dov[-1]andv[0]).The first_side argument is an integer from 0 to 5 that specifies which side should be shared by
v[0]andv[-1].The prism axis is returned as a vector.
Example:
>>> vertices = [(0, 1, 0), (3, 1, 0), (5, 2, 0), ... (5, 3, 0), (2, 3, 0), (0, 2, 0)] >>> sides = [vdiff(v2, v1) ... for v1, v2 in zip(vertices, vertices[1:] + [vertices[0]])] >>> from t4_geom_convert.Kernel.VectUtils import renorm, vect >>> normals = [renorm(vect(side, (0, 0, 1))) for side in sides] >>> planes = [((vertices[i], normals[i]), -1) # -1 is the side ... for i in (3, 0, 1, 4, 2, 5)]
This is the same weird hexagonal prism that is used in the docstring for
hexSortSides().Calling
hexVertices()withfirst_side=0yields the vertices of the hexagon sorted in such a way that the first one and the last one lie on side 0:>>> verts, axis = hexVertices(planes, 0) >>> from t4_geom_convert.Kernel.VectUtils import isPointOnPlane >>> isPointOnPlane(verts[0], planes[0][0]) True >>> isPointOnPlane(verts[-1], planes[0][0]) True
Other values of first_side lead to different orderings of the vertices:
>>> verts, axis = hexVertices(planes, 4) >>> isPointOnPlane(verts[0], planes[4][0]) True >>> isPointOnPlane(verts[-1], planes[4][0]) True
We can check that each plane contains exactly two vertices:
>>> [sum(1 for vert in verts if isPointOnPlane(vert, plane[0])) ... for plane in planes] [2, 2, 2, 2, 2, 2]
The axis vector, by construction is parallel to all the side planes:
>>> from t4_geom_convert.Kernel.VectUtils import isVectorParallelToPlane >>> all(isVectorParallelToPlane(axis, plane[0]) for plane in planes) True
It is also possible to pass a list of eight planes. In this case, the hexagon is guaranteed to lie on the “top” plane (i.e. surfs[-2]).
>>> planes += [(((10.0, 0.0, 0.0), (1.0, 1.0, 1.0)), -1), ... (((-10.0, 0.0, 0.0), (1.0, 1.0, 1.0)), 1)] >>> verts, axis = hexVertices(planes, 2) >>> all(isPointOnPlane(vert, planes[-2][0]) for vert in verts) True >>> [sum(1 for vert in verts if isPointOnPlane(vert, plane[0])) ... for plane in planes[:-2]] [2, 2, 2, 2, 2, 2] >>> all(isVectorParallelToPlane(axis, plane[0]) for plane in planes[:-2]) True
- t4_geom_convert.Kernel.Volume.Lattice.latticeReciprocal(base_vecs)
Yield the unit vectors of the reciprocal lattice.
- Parameters:
base_vecs – a list of one, two or three vectors describing the base cell of the direct lattice. Vectors are triples of the form
(x, y, z).- Returns:
a list of one, two or three base vectors of the reciprocal lattice.
>>> from math import isclose >>> from ..VectUtils import scal
In the case of a one-dimensional lattice, the reciprocal vector has the same direction as the base vector, but its length is equal to the inverse of the length of the direct vector: >>> vec1 = (3, 0, 4) >>> rec1 = latticeReciprocal([vec1])[0] >>> isclose(scal(rec1, vec1), 1.0) True >>> isclose(scal(rec1, rec1) * scal(vec1, vec1), 1.0) True
A few cases with two-dimensional lattices. The square lattice is self-dual: >>> vec1 = (1, 0, 0) >>> vec2 = (0, 1, 0) >>> latticeReciprocal([vec1, vec2]) [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0)]
A skew lattice: >>> vec1 = (1, 0, 0) >>> vec2 = (1, 1, 0) >>> latticeReciprocal([vec1, vec2]) [(1.0, -1.0, 0.0), (0.0, 1.0, 0.0)]
In three dimensions, the cubic lattice is self-dual: >>> vec1 = (1, 0, 0) >>> vec2 = (0, 1, 0) >>> vec3 = (0, 0, 1) >>> latticeReciprocal([vec1, vec2, vec3]) [(1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, 1.0)]
The length of the reciprocal vectors are inversely proportional to the length of the base vectors of the direct lattice: >>> vec1 = (2, 0, 0) >>> vec2 = (0, 4, 0) >>> vec3 = (0, 0, 0.5) >>> latticeReciprocal([vec1, vec2, vec3]) [(0.5, 0.0, 0.0), (0.0, 0.25, 0.0), (0.0, 0.0, 2.0)]
- t4_geom_convert.Kernel.Volume.Lattice.latticeVector(base_vecs, index)
Compute a lattice displacement vector from a set of basis vectors and a tuple of indices.
>>> base_vecs = [(1, 0, 0), ... (0, 0, 2)] >>> latticeVector(base_vecs, (0, 0)) (0.0, 0.0, 0.0) >>> latticeVector(base_vecs, (3, 2)) (3.0, 0.0, 4.0) >>> latticeVector(base_vecs, (-1, -1)) (-1.0, 0.0, -2.0)
- t4_geom_convert.Kernel.Volume.Lattice.parse_ranges(intervals)
Parse a list of intervals (in the MCNP syntax:
start:end) into a list of pairs of integers.- Parameters:
intervals (list(str)) – A list of strings of the form
'i:j', where i and j are integers.- Returns:
a list of pairs of integers representing the parsed bounds
- Return type:
>>> parse_ranges(['0:4', '0:4', '0:4']) [(0, 4), (0, 4), (0, 4)] >>> parse_ranges(['1:2', '3:4', '5:6', '7:8']) [(1, 2), (3, 4), (5, 6), (7, 8)] >>> parse_ranges([]) [] >>> parse_ranges(['0::5']) Traceback (most recent call last): ... ValueError: needs exactly 2 colon-separated range bounds in argument '0::5'
- t4_geom_convert.Kernel.Volume.Lattice.squareLatticeBaseVectors(surfaces)
Compute the base vectors of a square lattice.
- t4_geom_convert.Kernel.Volume.Lattice.squareLatticeReciprocalVecs(surfaces)
Compute the reciprocal vectors of a square lattice.
t4_geom_convert.Kernel.Volume.TreeFunctions module
- t4_geom_convert.Kernel.Volume.TreeFunctions.isCellRef(tree)
Returns True if tree is a
CellRef.- Return type:
- t4_geom_convert.Kernel.Volume.TreeFunctions.isIntersection(tree)
Function that tells if a node is an intersection.
- Return type:
- t4_geom_convert.Kernel.Volume.TreeFunctions.isLeaf(tree)
Function which tells if a tree is an instance of a Surface or a Geometry.
- Return type:
- t4_geom_convert.Kernel.Volume.TreeFunctions.isSurface(tree)
Returns True if tree is a surface.
- Return type:
- t4_geom_convert.Kernel.Volume.TreeFunctions.isUnion(tree)
Function that tells if a node is a union.
- Return type:
- t4_geom_convert.Kernel.Volume.TreeFunctions.largestPureIntersectionNode(nodes)
Returns the index of the largest node of the nodes list that is an intersection of surfaces, or None if no such node is present.
>>> from .CellMCNP import CellRef >>> largestPureIntersectionNode([[2, '*', 1, 2], [3, '*', 4, 5, 6]]) 1 >>> largestPureIntersectionNode([4, 5, 6]) 0 >>> largestPureIntersectionNode([[2, '*', 1, 2], ... [3, '*', 4, 5, 6], ... [4, ':', 7, 8, 9, 10]]) 1 >>> largestPureIntersectionNode([[3, '*', 4, 5, 6], ... [2, '*', 1, 2], ... [4, ':', 7, 8, 9, 10]]) 0 >>> largestPureIntersectionNode([[2, ':', 1, 2], [3, ':', 4, 5, 6]]) >>> largestPureIntersectionNode([[3, '*', CellRef(4), 5, 6], ... [2, '*', 1, 2]]) 1
t4_geom_convert.Kernel.Volume.VolumeT4 module
- class t4_geom_convert.Kernel.Volume.VolumeT4.VolumeT4(pluses, minuses, ops=None, idorigin=None, fictive=True)
Bases:
objectClass which permits to access precisely of the value of a volume T4.
- comment()
- copy()
Return a copy of self.
- empty()
Return True if the cell is patently empty, i.e. if the same surface ID appears with opposite signs.
- surface_ids()
Return the surface IDs used in this volume, as a set.