Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 44 additions & 5 deletions src/cmlibs/utils/zinc/finiteelement.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
"""
Expand Down
7 changes: 4 additions & 3 deletions src/cmlibs/utils/zinc/general.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down
26 changes: 24 additions & 2 deletions tests/test_zinc_finiteelement.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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()
Loading