diff --git a/src/cmlibs/utils/zinc/finiteelement.py b/src/cmlibs/utils/zinc/finiteelement.py index 4302324..f1eb591 100644 --- a/src/cmlibs/utils/zinc/finiteelement.py +++ b/src/cmlibs/utils/zinc/finiteelement.py @@ -120,17 +120,17 @@ def create_line_element(mesh: Mesh, finite_element_field: Field, node_coordinate assert mesh.getDimension() == 1 assert finite_element_field.castFiniteElement().isValid() assert len(node_coordinate_set) == 2 - fieldmodule = finite_element_field.getFieldmodule() - nodeset = fieldmodule.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) + field_module = finite_element_field.getFieldmodule() + nodeset = field_module.findNodesetByFieldDomainType(Field.DOMAIN_TYPE_NODES) node_template = nodeset.createNodetemplate() node_template.defineField(finite_element_field) element_template = mesh.createElementtemplate() element_template.setElementShapeType(Element.SHAPE_TYPE_LINE) - linear_basis = fieldmodule.createElementbasis(1, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE) + linear_basis = field_module.createElementbasis(1, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE) eft = mesh.createElementfieldtemplate(linear_basis) element_template.defineField(finite_element_field, -1, eft) - field_cache = fieldmodule.createFieldcache() - with ChangeManager(fieldmodule): + field_cache = field_module.createFieldcache() + with ChangeManager(field_module): node_identifiers = [] for node_coordinate in node_coordinate_set: node = nodeset.createNode(-1, node_template) @@ -140,6 +140,45 @@ def create_line_element(mesh: Mesh, finite_element_field: Field, node_coordinate element = mesh.createElement(-1, element_template) element.setNodesByIdentifier(eft, node_identifiers) + return element.getIdentifier() + + +def create_element_from_node_identifiers( + mesh, + finite_element_field, + node_identifiers, + element_basis=Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE, + element_shape_type=Element.SHAPE_TYPE_LINE): + """ + Create an element from a list of node identifiers. + + Raises an exception if the combination of the element basis and element shape type is not implemented. + + :param mesh: The Zinc Mesh to create element in. + :param finite_element_field: Zinc FieldFiniteElement to use in element template. + :param node_identifiers: The node identifiers to create element from. + :param element_basis: The element basis to create element from. + :param element_shape_type: The element shape to create element from. + + :return: Element identifier. + """ + if element_basis != Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE: + raise NotImplementedError("Only LINEAR LAGRANGE elements are supported") + + if element_shape_type != Element.SHAPE_TYPE_LINE: + raise NotImplementedError("Only line type elements are supported") + + field_module = mesh.getFieldmodule() + element_template = mesh.createElementtemplate() + element_template.setElementShapeType(Element.SHAPE_TYPE_LINE) + linear_basis = field_module.createElementbasis(1, Elementbasis.FUNCTION_TYPE_LINEAR_LAGRANGE) + eft = mesh.createElementfieldtemplate(linear_basis) + element_template.defineField(finite_element_field, -1, eft) + element = mesh.createElement(-1, element_template) + element.setNodesByIdentifier(eft, node_identifiers) + + return element.getIdentifier() + def find_node_with_name(nodeset: Nodeset, name_field: Field, name: str, ignore_case=False, strip_whitespace=False): """ diff --git a/src/cmlibs/utils/zinc/general.py b/src/cmlibs/utils/zinc/general.py index a8971d5..76a586e 100644 --- a/src/cmlibs/utils/zinc/general.py +++ b/src/cmlibs/utils/zinc/general.py @@ -28,9 +28,9 @@ def __init__(self, field_names, time_sequence=None, time_sequence_field_names=No self._field_names = field_names self._time_sequence = time_sequence if time_sequence else [] self._time_sequence_field_names = time_sequence_field_names if time_sequence_field_names else [] - self._check_field_names() + # self._check_field_names() - def _check_field_names(self): + def check_field_names(self): for field_name in self._field_names: if not hasattr(self, field_name): raise NotImplementedError('Missing data method for field: %s' % field_name) @@ -40,7 +40,7 @@ def get_field_names(self): def set_field_names(self, field_names): self._field_names = field_names - self._check_field_names() + self.check_field_names() def get_time_sequence(self): return self._time_sequence @@ -141,6 +141,7 @@ def create_node(field_module, data_object, identifier=-1, node_set_name='nodes', node_set = field_module.findNodesetByName(node_set_name) node_template = node_set.createNodetemplate() + data_object.check_field_names() # Set the finite element coordinate field for the nodes to use fields = [] field_names = data_object.get_field_names() diff --git a/tests/test_zinc_finiteelement.py b/tests/test_zinc_finiteelement.py index 37c0fcc..1641582 100644 --- a/tests/test_zinc_finiteelement.py +++ b/tests/test_zinc_finiteelement.py @@ -1,10 +1,14 @@ import math import unittest -from cmlibs.utils.zinc.finiteelement import define_grid_field_on_mesh +from cmlibs.utils.zinc.finiteelement import define_grid_field_on_mesh, create_element_from_node_identifiers from cmlibs.zinc.context import Context from cmlibs.zinc.result import RESULT_OK -from utilities import assert_almost_equal_list, get_test_resource_name + +try: + from utilities import assert_almost_equal_list, get_test_resource_name +except ImportError: + from .utilities import assert_almost_equal_list, get_test_resource_name class ZincFiniteElementTestCase(unittest.TestCase): @@ -242,6 +246,24 @@ def test_mesh3d_grid_vector(self): self.assertTrue(result == RESULT_OK) assert_almost_equal_list(self, x, grid_x, delta=1.0E-8) + def test_create_element_from_node_identifiers(self): + exf_file = get_test_resource_name('warped_two_element_cube.exf') + + context = Context("test") + region = context.createRegion() + result = region.readFile(exf_file) + self.assertTrue(result == RESULT_OK) + + fm = region.getFieldmodule() + mesh = fm.findMeshByDimension(1) + coordinates_field = fm.findFieldByName("coordinates") + + element_identifier = create_element_from_node_identifiers(mesh, coordinates_field, [1, 2]) + self.assertEqual(21, element_identifier) + + element_identifier = create_element_from_node_identifiers(mesh, coordinates_field, [134, 516]) + self.assertEqual(22, element_identifier) + if __name__ == "__main__": unittest.main()