# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
from __future__ import annotations
from typing import Union, List, Any, Tuple, Iterator, NoReturn, Union, Iterable, Generator, Optional
import bisect
import numpy as np
from Muscat.Helpers.Decorators import froze_it
from Muscat.Types import MuscatIndex, MuscatFloat, ArrayLike, NDArray
import Muscat.MeshContainers.ElementsDescription as ED
from Muscat.MeshContainers.Tags import Tags, Tag
from Muscat.Helpers.Interpolation import BinarySearch
from Muscat.FE.Spaces.FESpaces import LagrangeSpaceP1
[docs]
@froze_it
class ElementsContainer:
"""
Class to hold a list of elements of the same type
* elementType : a string from Muscat.MeshContainers.ElementsDescription
* connectivity : the connectivity matrix starting form 0
* tags : an instance of the Tags class
* originalIds : the id or number from the previous mesh/file
The user can use this data to find the mapping from the initial mesh/file
to the current mesh (self).
* self.cpt : an internal counter to do efficient add of elements one by one
The user is responsible to call self.Tighten() to compact the connectivity
matrix after the population ( calls AddNewElement(...) or allocate(...))
"""
def __init__(self, elementType: Union[ED.ElementType, str]):
super().__init__()
self.elementType: ED.ElementType = ED.ElementType(elementType)
self.connectivity: NDArray[MuscatIndex] = np.empty((0, ED.numberOfNodes[elementType]), dtype=MuscatIndex)
self.tags: Tags = Tags()
self.cpt: MuscatIndex = 0
self.originalIds: np.ndarray = np.empty((0,), dtype=MuscatIndex)
def __eq__(self, other: Any) -> bool:
"""return True if 2 container are equal
Parameters
----------
other : ElementsContainer
_description_
Returns
-------
bool
True if the 2 containers are equal, False ir not
"""
if not isinstance(other, ElementsContainer):
return False
if self.elementType != other.elementType:
return False
if not np.array_equal(
self.connectivity[
0 : self.cpt,
:,
],
other.connectivity[0 : other.cpt, :],
):
return False
if not np.array_equal(self.originalIds[: self.cpt], other.originalIds[: other.cpt]):
return False
if self.tags != other.tags:
return False
return True
[docs]
def View(self) -> ElementsContainer:
"""return a copy of this object recursively, numpy arrays are view to the original ones
but with the flags.writeable = False
Returns
-------
ElementsContainer
a view of ElementsContainer
"""
res = ElementsContainer(self.elementType)
res.connectivity = self.connectivity
res.connectivity.flags.writeable = False
res.tags = self.tags.View()
res.cpt = self.cpt
res.originalIds = self.originalIds.view()
res.originalIds.flags.writeable = False
return res
[docs]
def GetNumberOfElements(self) -> MuscatIndex:
"""return the number of elements in this container
Returns
-------
int
Number of elements
"""
return self.cpt
# return self.connectivity.shape[0]
[docs]
def Merge(self, other: ElementContainerLike, offset: Optional[MuscatIndex] = None) -> None:
"""
Merge the elements from the other container into this.
Warning!!! Non elimination of double elements is done
if an offset is supplied the connectivity of the other container is
shifted by the value of the offset during the merge. Useful for after
merging the nodes from the other mesh.
"""
if self is other:
raise RuntimeError("self and other are the same object")
if other.cpt == 0:
return
self.Reserve(self.cpt + other.cpt)
if offset is None:
offset = 0
self.connectivity[self.cpt :, :] = other.connectivity[0 : other.cpt, :] + offset
self.originalIds[self.cpt :] = np.arange(other.cpt)
for tag in other.tags:
self.GetTag(tag.name).AddToTag(tag.GetIds() + self.cpt)
self.cpt += other.cpt
[docs]
def AddNewElements(self, connectivity: ArrayLike, originalIds: Optional[ArrayLike] = None) -> int:
"""Append a new elements to the connectivity
Parameters
----------
conn : ArrayLike
connectivity of the added elements
originalIds : ArrayLike, optional
the original id of the added element, by default -1 is used
Returns
-------
int
the total number of elements in the container
"""
connectivity = np.asarray(connectivity, dtype=MuscatIndex)
originalNOE = self.GetNumberOfElements()
self.Allocate(originalNOE + connectivity.shape[0])
self.connectivity[originalNOE : originalNOE + connectivity.shape[0], :] = connectivity
if originalIds is None:
self.originalIds[originalNOE : originalNOE + connectivity.shape[0]] = -1
else:
originalIds = np.asarray(originalIds)
self.originalIds[originalNOE : originalNOE + connectivity.shape[0]] = originalIds
return self.cpt
[docs]
def AddNewElement(self, connectivity: ArrayLike, originalId: int) -> int:
"""append a single element to the connectivity
Parameters
----------
connectivity : ArrayLike
connectivity of the added element
originalId : int
the original id of the added element
Returns
-------
int
the total number of elements in the container
"""
if self.cpt >= self.connectivity.shape[0]:
self.Reserve(2 * self.cpt + 1)
self.connectivity[self.cpt, :] = connectivity
self.originalIds[self.cpt] = originalId
self.cpt += 1
return self.cpt
[docs]
def GetNumberOfNodesPerElement(self) -> int:
"""return the number of nodes per element for the elements in this container
Returns
-------
int
the number of nodes per element for the elements in this container
"""
return ED.numberOfNodes[self.elementType]
[docs]
def GetNodesIndexFor(self, ids: Union[int, ArrayLike]) -> np.ndarray:
"""return the nodes used by the list of elements
input:
ids :
Parameters
----------
ids : Union[int,ArrayLike]
the id or a list of ids of elements to treat (always a local id list)
Returns
-------
np.ndarray
the ids of the nodes used by the elements ids
"""
return np.unique(self.connectivity[ids, :])
[docs]
def GetTag(self, tagName: str) -> Tag:
"""return the tag by name.
If the tag does not exist a new tag is created
Parameters
----------
tagName : str
the name of the tag to retrieve
Returns
-------
Tag
a tag with the name tagName
"""
return self.tags.CreateTag(tagName, False)
[docs]
def GetDimensionality(self) -> int:
"""Return the dimensionality (2 for 2D, 3 for 3D) of this container
Returns
-------
int
the dimensionality of this containers
"""
return ED.ElementsInfo[self.elementType].dimension
[docs]
def Reserve(self, nbElements: Union[int, MuscatIndex]) -> None:
"""Reserve the storage for nbElements
The user is responsible to call self.Tighten() to compact the connectivity
and the originalIds.
matrix after the population
Parameters
----------
nbElements : int
Number of element to reserve
"""
if nbElements != self.connectivity.shape[0]:
self.connectivity = np.resize(self.connectivity, (nbElements, self.GetNumberOfNodesPerElement()))
self.originalIds = np.resize(self.originalIds, (nbElements,))
[docs]
def Allocate(self, nbElements: Union[int, MuscatIndex]) -> None:
"""Allocate the storage for nbElements
the user is responsible of filling the connectivity and the originalIds
with valid values
Parameters
----------
nbElements : int, MuscatIndex
Number of element to Allocate
"""
self.Reserve(nbElements)
self.cpt = nbElements
[docs]
def Tighten(self) -> None:
"""Compact the storage and free non used space."""
self.Reserve(self.cpt)
self.tags.Tighten()
def __str__(self) -> str:
"""Return a string representation"""
res = " ElementsContainer, "
res += f" Type : ({self.elementType},{self.GetNumberOfElements()}), "
res += " Tags : " + " ".join([("(" + x.name + ":" + str(len(x)) + ")") for x in self.tags]) + "\n"
return res
[docs]
def ConvertDataForNativeTreatment(self) -> None:
self.originalIds = np.asarray(self.originalIds, dtype=MuscatIndex, order="C")
self.connectivity = np.asarray(self.connectivity, dtype=MuscatIndex, order="C")
[docs]
def AddElementToTag(self, tagname: str, ids: Union[int, List[int]]) -> None:
self.tags.CreateTag(tagname, False).AddToTag(ids)
[docs]
@froze_it
class StructuredElementsContainer:
"""Element container of a topologically regular array of elements.
This class can hold regular element in 2D and 3D. Pixels and Voxel.
The grid is defined by the dimensions (number of nodes in each direction)
"""
def __init__(self, elementType: Union[ED.ElementType, str]) -> None:
"""init this class
Parameters
----------
elementType : str
The type of element ot create the rectilinear
can only be Hexahedron_8 or Quadrangle_4
"""
super().__init__()
if elementType not in [ED.Hexahedron_8, ED.Quadrangle_4]:
raise RuntimeError("Only elements of type ED.Hexahedron_8, ED.Quadrangle_4 are supported on StructuredElementContainer ")
self.elementType = elementType
self.space = LagrangeSpaceP1[elementType]
self.space.Create()
self.tags = Tags()
self._connectivity = None
self.originalIds = np.empty((0,), dtype=MuscatIndex)
# internal data
self.nodesPerElement = 2 ** self.GetDimensionality()
self.__dimensions = None
[docs]
def View(self) -> StructuredElementsContainer:
"""return a copy of this object recursively, numpy arrays are view to the original ones
but with the flags.writeable = False
Returns
-------
StructuredElementsContainer
a view of StructuredElementsContainer
"""
res = StructuredElementsContainer(self.elementType)
res.SetDimensions(self.__dimensions)
if self._connectivity is not None:
res._connectivity = self._connectivity.view()
res._connectivity.flags.writeable = False
res.originalIds = self.originalIds.view()
res.originalIds.flags.writeable = False
return res
def __eq__(self, other: Any) -> bool:
"""return True if 2 container are equal
Parameters
----------
other : Any
_description_
Returns
-------
bool
True if the 2 containers are equal, False ir not
"""
if not isinstance(other, StructuredElementsContainer):
return False
if self.elementType != other.elementType:
return False
if not np.array_equal(self.__dimensions, other.__dimensions):
return False
if not np.array_equal(self.originalIds, other.originalIds):
return False
if self.tags != other.tags:
return False
return True
@property
def connectivity(self) -> np.ndarray:
"""Generate and retrieve the connectivity of the elements
Returns
-------
np.ndarray
Connectivity of the elements size (self.GetNumberOfElements(), 4 or 8)
"""
if self._connectivity is None:
self._connectivity = self.GetConnectivityForElements(np.arange(self.GetNumberOfElements()))
self._connectivity.flags.writeable = False
return self._connectivity
@property
def cpt(self):
return self.GetNumberOfElements()
[docs]
def SetDimensions(self, data: ArrayLike) -> None:
"""Set the number of points for the grid in each dimension
Parameters
----------
data : ArrayLike
the number of points in each dimension for this grid
"""
data = np.asarray(data, dtype=MuscatIndex)
if len(data) != ED.ElementsInfo[self.elementType].dimension:
raise RuntimeError(f"Data must be compatible with the dimensionality of {self.elementType}")
self.__dimensions = np.array(data, dtype=MuscatIndex)
self.originalIds = np.arange(self.GetNumberOfElements(), dtype=MuscatIndex)
[docs]
def GetDimensionality(self) -> int:
"""Return the dimensionality (2 for 2D, 3 for 3D) of this container
Returns
-------
int
the dimensionality of this containers
"""
return ED.ElementsInfo[self.elementType].dimension
[docs]
def GetConnectivityForElements(self, indices: ArrayLike) -> np.ndarray:
"""Return the connectivity for the element listed in the indices array.
If the connectivity is used many times, a simple call of self.connectivity will generate the
connectivity for all the elements and keep it for later use.
Parameters
----------
indices : ArrayLike
the indices of the elements to generate the connectivity
Returns
-------
np.ndarray
the connectivity of the selected elements size = (len(indices), 4 or 8 )
"""
if not isinstance(indices, (np.ndarray, list)):
return self.GetMultiIndexOfElements([indices])
elements_ijk = self.GetMultiIndexOfElements(np.asarray(indices, dtype=MuscatIndex))
if self.GetDimensionality() == 3:
res = np.empty((elements_ijk.shape[0], 8), dtype=MuscatIndex)
# n0
res[:, 0] = elements_ijk[:, 0] * self.__dimensions[1] * self.__dimensions[2] + elements_ijk[:, 1] * self.__dimensions[2] + elements_ijk[:, 2]
# n1
res[:, 1] = res[:, 0] + self.__dimensions[1] * self.__dimensions[2]
res[:, 2] = res[:, 1] + self.__dimensions[2]
res[:, 3] = res[:, 0] + self.__dimensions[2]
res[:, 4:8] = res[:, 0:4] + 1
return res
else:
res = np.empty((elements_ijk.shape[0], 4), dtype=MuscatIndex)
res[:, 0] = elements_ijk[:, 0] * self.__dimensions[1] + elements_ijk[:, 1]
res[:, 1] = res[:, 0] + self.__dimensions[1]
res[:, 2] = res[:, 1] + 1
res[:, 3] = res[:, 0] + 1
return res
[docs]
def GetMultiIndexOfElements(self, indices: Union[ArrayLike, int]) -> np.ndarray:
"""Return the multi-index ijk for element with indices
Parameters
----------
indices : ArrayLike
the indices of the elements to treat
Returns
-------
np.ndarray
an array with the ijk indices for every element in indices
size (nb element, 2 (ij) or 3 (ijk) )
"""
if not isinstance(indices, (np.ndarray, list)):
return self.GetMultiIndexOfElements([indices])
indices = np.asarray(indices, dtype=MuscatIndex)
if self.GetDimensionality() == 3:
planeSize = (self.__dimensions[1] - 1) * (self.__dimensions[2] - 1)
res = np.empty((len(indices), 3), dtype=MuscatIndex)
res[:, 0] = indices // planeSize
resYZ = indices - res[:, 0] * planeSize
res[:, 1] = resYZ // (self.__dimensions[2] - 1)
res[:, 2] = resYZ - res[:, 1] * (self.__dimensions[2] - 1)
return res
else:
res = np.empty((len(indices), 2), dtype=MuscatIndex)
planeSize = self.__dimensions[1] - 1
res[:, 0] = indices // planeSize
res[:, 1] = indices - res[:, 0] * planeSize
return res
[docs]
def GetMultiIndexOfElement(self, index: int) -> np.ndarray:
"""Return the multi-index ijk for an element
please see documentation for GetMultiIndexOfElements
Parameters
----------
index : int
the index of the element
Returns
-------
np.ndarray
ij or ijk for the element
"""
return self.GetMultiIndexOfElements([index])[0, :]
[docs]
def GetNumberOfElements(self) -> MuscatIndex:
"""Return the number of element in this container
Returns
-------
int
the number of elements
"""
return np.prod((self.__dimensions - 1)[self.__dimensions >= 1])
[docs]
def Merge(self, other: ElementsContainer, offset: int = None) -> NoReturn:
"""Not possible for a StructuredElementContainer"""
raise RuntimeError("Merge is not possible for a StructuredElementContainer")
[docs]
def AddNewElements(self, connectivity: ArrayLike, originalIds: ArrayLike = None) -> NoReturn:
"""Not possible for a StructuredElementContainer"""
raise RuntimeError("AddNewElements is not possible for a StructuredElementContainer")
[docs]
def AddNewElement(self, connectivity: ArrayLike, originalId: int) -> NoReturn:
"""Not possible for a StructuredElementContainer"""
raise RuntimeError("AddNewElement is not possible for a StructuredElementContainer")
[docs]
def GetNumberOfNodesPerElement(self) -> MuscatIndex:
"""Return the number of node per element
Returns
-------
int
number of nodes
"""
return MuscatIndex(2) ** len(self.__dimensions)
[docs]
def GetNodesIndexFor(self, ids: Union[int, ArrayLike]) -> np.ndarray:
"""return the nodes used by the list of elements
input:
ids :
Parameters
----------
ids : Union[int,ArrayLike]
the id or a list of ids of elements to treat (always a local id list)
Returns
-------
np.ndarray
the ids of the nodes used by the elements ids
"""
return np.unique(self.GetConnectivityForElements(ids))
[docs]
def GetTag(self, tagName: str) -> Tag:
"""Return the Tag by the name
if the tag does not exist a new tag is created
Parameters
----------
tagName : str
The name of the tag
Returns
-------
Tag
an instance of type Tag
"""
return self.tags.CreateTag(tagName, False)
[docs]
def AddElementToTag(self, tagname: str, ids: Union[int, List[int]]):
self.tags.CreateTag(tagname, False).AddToTag(ids)
def __str__(self) -> str:
"""return a string of a summary of this container
Returns
-------
str
The description
"""
res = f" StructuredElementContainer({self.__dimensions}), "
res += f" Type : ({self.elementType},{self.GetNumberOfElements()}), "
res += " Tags : " + " ".join([("(" + x.name + ":" + str(len(x)) + ")") for x in self.tags]) + "\n"
return res
[docs]
def Tighten(self) -> None:
"""Tighten all the tags (free unused memory)
Call Tag.Tighten on every tag
"""
self.tags.Tighten()
[docs]
def ConvertDataForNativeTreatment(self) -> None:
pass
ElementContainerLike = Union[ElementsContainer, StructuredElementsContainer]
"""Meta type for the element type names"""
[docs]
@froze_it
class AllElements:
"""
Class to store a list of element containers. This class is mostly a re-implementation of dict
but with ordered elementType.
This class is sorted by elementTypes in lexicographic order, so the retrieving order is stable,
and independent on the order of filling.
"""
def __init__(self) -> None:
super().__init__()
self.storage: List[ElementContainerLike] = []
def __eq__(self, other: Any) -> bool:
"""return True if 2 AllElements are equal
Parameters
----------
other : AllElements
the other instance
Returns
-------
bool
True if the 2 instances are equal, False ir not
"""
if len(self.storage) != len(other.storage):
return False
# because the storage are sorted we can do:
for l, r in zip(self.storage, other.storage):
if l != r:
return False
return True
[docs]
def View(self) -> AllElements:
"""return a copy of this object recursively, numpy arrays are view to the original ones
but with the flags.writeable = False
Returns
-------
AllElements
a view of AllElements
"""
res = AllElements()
for ec in self:
res.AddContainer(ec.View())
return res
[docs]
def MergeElements(self, other: AllElements, nodesOffset: int = 0) -> None:
"""Merge the elements for a AllElements into this (self)
Parameters
----------
other : AllElements
the element to merge into this
nodesOffset : int, optional
an node offset to use to shift the connectivity of the elements, by default 0
"""
for elementType, data in other.items():
self.GetElementsOfType(elementType).Merge(data, offset=nodesOffset)
[docs]
def keys(self) -> Iterable[ED.ElementType]:
"""Return the list of elementType present on the mesh
Returns
-------
List
list of elementType in the mesh
"""
return [ec.elementType for ec in self.storage]
# return (ec.elementType for ec in self.storage)
# return map(lambda x: x.elementType, self.storage)
[docs]
def values(self) -> List:
"""return the internal storage.
.. note::
This list must be kept in alphabetical order for consistency
Returns
-------
List
list of ElementsContainer
"""
return self.storage
def __iter__(self) -> Iterator:
"""Iterator on the internal storage
Returns
-------
Iterator
Iterator of ElementsContainer
"""
return iter(self.storage)
[docs]
def items(self) -> Generator[Tuple[ED.ElementType, ElementContainerLike], None, None]:
"""List of (elementType, ElementsContainer)
Returns
-------
List[Tuple]
_description_
"""
return ((x.elementType, x) for x in self.storage)
def __delitem__(self, key: Union[ED.ElementType, str]) -> None:
"""Remove an element container using elementType
Parameters
----------
key : str
the elementType to be eliminated
"""
index = [x.elementType for x in self.storage].index(key)
del self.storage[index]
def __getitem__(self, key: Union[ED.ElementType, str]) -> ElementsContainer:
"""getitem operator, no creation of elementsContainer is done
Parameters
----------
key : str
elementType to be extracted
Returns
-------
ElementContainer
the extracted instance
"""
index = self.Index(key)
return self.storage[index]
[docs]
def AddContainer(self, value: Union[ED.ElementsContainer, StructuredElementsContainer]) -> None:
"""add an ElementsContainer
Parameters
----------
value : ElementsContainer
the ElementsContainer to be added
"""
key = value.elementType
keys = self.keys()
if key in keys:
index = self.Index(key)
self.storage[index] = value
else:
index = bisect.bisect_right(keys, key)
self.storage.insert(index, value)
[docs]
def Index(self, elementType: Union[ED.ElementType, str]) -> int:
"""Get the position of the container of type elementType inside the storage"""
keys = self.keys()
return keys.index(elementType)
def __len__(self) -> int:
"""Return the number of ElementsContainer in the storage
Returns
-------
int
number of ElementsContainer
"""
return len(self.storage)
def __contains__(self, elementType: Union[ED.ElementType, str]) -> bool:
"""True if elementType exist in the storage
Parameters
----------
elementType : str
elementType name
"""
return elementType in self.keys()
[docs]
def GetElementsOfType(self, typename: Union[ED.ElementType, str]) -> ElementsContainer:
"""return an ElementContainer by name, if the container does not exist
a new is inserted and returned
Parameters
----------
typename : str
the name of the elements to retrieve
Returns
-------
ElementsContainer
the container
"""
if typename not in self:
self.AddContainer(ElementsContainer(typename))
return self[typename]
def __str__(self) -> str:
"""String representation
Returns
-------
str
description
"""
res = ""
for data in self.storage:
res += str(data)
return res
[docs]
def CheckIntegrity(GUI: bool = False):
from Muscat.Helpers.CheckTools import MustFailFunction
ec_T3 = ElementsContainer(ED.Triangle_3)
ec_T3.ConvertDataForNativeTreatment()
ec_T3.Allocate(1)
ec_T3.connectivity[0, :] = [0, 1, 2]
ec_T3.originalIds[0] = 0
ec_T3.tags.CreateTag("First").SetIds([0])
ec_T3.AddElementToTag("First2", [0])
ec_T3.View()
assert ec_T3 != object # different types
ec_T6 = ElementsContainer(ED.Triangle_6)
assert ec_T3 != ec_T6 # different elements types
ec_T3_II = ElementsContainer(ED.Triangle_3)
ec_T3_II.Allocate(1)
ec_T3_II.connectivity[0, :] = [0, 1, 20]
ec_T3_II.originalIds[0] = 1
assert ec_T3 != ec_T3_II # diff connectivity
ec_T3_II.connectivity[0, :] = [0, 1, 2]
assert ec_T3 != ec_T3_II # diff originalIds
ec_T3_II.originalIds[0] = 0
assert ec_T3 != ec_T3_II # diff tags
ec_T3_II.tags.CreateTag("First").SetIds([0])
ec_T3_II.AddElementToTag("First2", [0])
assert ec_T3 == ec_T3_II # equal meshes
ec_T3.GetDimensionality()
ec_T3.Merge(ElementsContainer(ED.Triangle_3))
ec_T3.Merge(ec_T3_II, 3)
ec_T3.Merge(ec_T3_II)
ec_T3.AddNewElements([[4, 5, 6]])
ec_T3.AddNewElements([[7, 8, 9]], [0])
ec_T3.AddNewElement([10, 11, 12], 2)
assert ec_T3.GetNumberOfNodesPerElement() == 3
AssertionError(ec_T3.GetNumberOfElements() == 2)
np.testing.assert_equal(ec_T3.GetNodesIndexFor([0, 1]), [0, 1, 2, 3, 4, 5])
ec_T3.Tighten()
print(ec_T3)
MustFailFunction(ec_T3.Merge, ec_T3)
### StructuredElementContainer ##
MustFailFunction(StructuredElementsContainer, ED.Bar_2)
### StructuredElementContainer 2D ##
ec2 = StructuredElementsContainer(ED.Quadrangle_4)
ec2.ConvertDataForNativeTreatment()
ec2.SetDimensions([2, 2])
ec2.AddElementToTag("First", [0])
np.testing.assert_equal(ec2.GetMultiIndexOfElements(0), [[0, 0]])
MustFailFunction(ec2.SetDimensions, [3, 3, 3])
coon = ec2.connectivity
ec2.View()
assert ec2.GetNumberOfNodesPerElement() == 4
### StructuredElementContainer 2D ##
ec = StructuredElementsContainer(ED.Hexahedron_8)
ec.SetDimensions([2, 2, 2])
coon = ec.connectivity
print(ec.GetConnectivityForElements(0))
np.testing.assert_equal(ec.GetMultiIndexOfElement(0), [0, 0, 0])
assert ec.GetNumberOfNodesPerElement() == 8
ec.GetTag("testTag")
print(ec)
ec.Tighten()
assert ec != 0
assert ec != ec2
other = StructuredElementsContainer(ED.Hexahedron_8)
assert ec != other
other.SetDimensions([2, 2, 2])
assert ec != other
other.originalIds += 1
assert ec != other
assert ec == ec
np.testing.assert_equal(ec.GetNodesIndexFor([0]), [0, 1, 2, 3, 4, 5, 6, 7])
MustFailFunction(ec.Merge, other)
MustFailFunction(ec.AddNewElements, [[]])
MustFailFunction(ec.AddNewElement, [], 0)
### AllElements ##
# check order of insertion and preservation of the order of extractions
aeI = AllElements()
aeI.AddContainer(ec_T3)
aeI.AddContainer(ec2)
print(aeI)
aeII = AllElements()
aeII.AddContainer(ec2)
aeII.AddContainer(ec_T3)
np.testing.assert_equal(aeI.keys(), aeII.keys())
ae = AllElements()
ae.AddContainer(ec_T3)
ae.AddContainer(ec_T3)
ae__II = AllElements()
assert ae__II != ae
ae__II.AddContainer(ec_T6)
assert ae__II != ae
assert ae != ae__II
del ae__II[ec_T6.elementType]
assert ae__II != ae
ae__II.AddContainer(ec_T3_II)
assert ae != ae__II
del ae__II[ec_T3_II.elementType]
ae__II.AddContainer(ec_T3)
assert ae == ae__II
assert ae__II == ae
ae__II.View()
np.testing.assert_equal(ae.values(), [ec_T3])
for ec in ae:
assert ec is ec_T3
for elementType, data in ae.items():
assert elementType == ED.Triangle_3
assert data == ec_T3
assert len(ae) == 1
assert ae.GetElementsOfType(ED.Triangle_3) == ec_T3
ae.GetElementsOfType(ED.Triangle_6)
print(ae.GetTagsNames())
print(ae)
AllElements().MergeElements(ae)
return "ok"
if __name__ == "__main__":
print(CheckIntegrity(True)) # pragma: no cover