Skip to content

Commit 594eebb

Browse files
committed
Add calculate_jacobian and report_on_lowest_value functions.
1 parent 584c47c commit 594eebb

3 files changed

Lines changed: 490 additions & 1 deletion

File tree

src/cmlibs/utils/zinc/mesh.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import math
2+
3+
from cmlibs.zinc.element import Element
14
from cmlibs.zinc.field import FieldGroup, Field
5+
from cmlibs.zinc.result import RESULT_OK
26

37
from cmlibs.utils.zinc.finiteelement import get_highest_dimension_mesh
48
from cmlibs.utils.zinc.general import ChangeManager
@@ -181,7 +185,6 @@ def _find_connected(element_nodes, seed_index=None, ignore_element_indices=None,
181185

182186
update_indexes = {}
183187
if progress_callback is not None:
184-
185188
update_interval = max(1, int(num_elements * 0.01))
186189
update_indexes = set([i for i in range(update_interval)] + [i for i in range(update_interval, num_elements, update_interval)])
187190

@@ -279,3 +282,57 @@ def undefine_field(field):
279282
mesh = fm.findMeshByDimension(i)
280283
mesh_group = mesh
281284
_undefine_field_on_elements(field, mesh_group)
285+
286+
287+
def calculate_jacobian(coordinates):
288+
jacobian = None
289+
if coordinates.getNumberOfComponents() == 3:
290+
fm = coordinates.getFieldmodule()
291+
jacobian = fm.createFieldDotProduct(
292+
fm.createFieldCrossProduct(
293+
fm.createFieldDerivative(coordinates, 1),
294+
fm.createFieldDerivative(coordinates, 2)),
295+
fm.createFieldDerivative(coordinates, 3))
296+
jacobian.setName("Jacobian")
297+
298+
return jacobian
299+
300+
301+
def report_on_lowest_value(real_field, group_field=None):
302+
"""
303+
Evaluate the 3D mesh associated with the given field and
304+
report back on the element with the lowest field value.
305+
Returns (-1, inf) if the evaluation of the mesh failed.
306+
:param real_field: A real value field to find the lowest value of.
307+
:param group_field: A group of 3D elements from the associated mesh (optional, default None).
308+
:return: A tuple of element identifier and minimum value within that element.
309+
"""
310+
fm = real_field.getFieldmodule()
311+
mesh_3d = fm.findMeshByDimension(3)
312+
with ChangeManager(fm):
313+
fc = fm.createFieldcache()
314+
fr = fc.createFieldrange()
315+
316+
if group_field is not None:
317+
if group_field.castGroup().isValid():
318+
mesh_group = group_field.castGroup().getMeshGroup(mesh_3d)
319+
element_iter = mesh_group.createElementiterator()
320+
else:
321+
return -1, math.inf
322+
else:
323+
element_iter = mesh_3d.createElementiterator()
324+
element = element_iter.next()
325+
minimum_element_id = -1
326+
minimum_element_value = math.inf
327+
while element.isValid():
328+
fc.setElement(element)
329+
result = real_field.evaluateFieldrange(fc, fr)
330+
if result == RESULT_OK:
331+
result, min_value, max_value = fr.getRangeReal(1)
332+
if result == RESULT_OK and min_value < minimum_element_value:
333+
minimum_element_id = element.getIdentifier()
334+
minimum_element_value = min_value
335+
336+
element = element_iter.next()
337+
338+
return minimum_element_id, minimum_element_value

0 commit comments

Comments
 (0)