External Mesh Morphing Integration#
This integration sends volume meshes to an external mesh morphing tool and returns deformed node coordinates to EMSolution. Separate from the general Python API list, this page describes the data contract, execution sequence, and constraints.
Warning
This function is at the proof-of-concept stage with schema versions 1 and 2. It is not a stable API until integration testing and compatibility policy for external tools are established. External tools must check the schema version and stop processing when they receive an unsupported version.
Overview#
For DEFORM regions, EMSolution passes the static volume mesh required by the external tool and node states for each step to Python. The external tool returns global absolute coordinates that already reflect RIGID motion. EMSolution uses these coordinates to assemble the deformation matrix.
Coordinate units are always
m.Coordinates use the global Cartesian XYZ coordinate system.
Return absolute coordinates after deformation, not displacement from reference coordinates.
For a step supplied with an external payload, the existing
set_deformed_node_position()is not applied in addition.
Execution flow#
Immediately after initialization, obtain the static topology once and cache it in the external tool. At each step, obtain the current deformation state and return a payload. Use CoupledSession rather than module-level functions to manage the lifecycle.
import pyemsol
with pyemsol.CoupledSession(input_json, str(run_directory)) as session:
# セッション中に変わらない体積メッシュ。最初のstepより前に1回だけ取得する。
topology = session.describe_deformation_mesh()
for end_time, delta_time, motion_state in time_steps:
description = session.describe_deformation()
deformation = morph_deformation(
description, topology, motion_state, time=end_time
)
result = session.step(
time=end_time,
delta_time=delta_time,
deformation=deformation,
)
current_coordinates in describe_deformation() is updated after each step. The static topology does not need to be retrieved again until the session ends when immutable_during_session is True.
Python APIs used#
- class CoupledSession(inputJson, run_directory)#
This is a session for external step analysis. When used in a
withstatement,close()is called at exit. Running multiple active analyses in the same process is not supported.
- CoupledSession.describe_deformation() dict#
Returns reference coordinates, target coordinates from existing linear deformation, and current coordinates for each DEFORM region. The current schema version is
1.
- CoupledSession.describe_deformation_mesh() dict#
Returns the static volume mesh and boundary roles for external morphing. The current schema version is
2.
- CoupledSession.step(time, delta_time, inputs={}, deformation=None) dict#
Executes one transient step.
timeis the previous end time plusdelta_time, anddelta_timemust be positive and finite. When electrical coupling is also used, specify port inputs ininputs.
- linear_deformation(description, position, *, mesh_revision=None) dict#
This reference helper creates an absolute-coordinate payload equivalent to existing linear deformation rules. It can verify connection to an external tool, but general mesh morphing replaces it with an external-tool adapter. For one region, pass a numeric
position; for multiple regions, pass{deform_id: position}.
Static mesh topology (schema version 2)#
Top-level structure returned by describe_deformation_mesh().
{
"schema_version": 2,
"enabled": True,
"mesh_revision": 0,
"unit": "m",
"coordinate_frame": "global",
"immutable_during_session": True,
"regions": [...],
}
Each item in
regionscontainsdeform_id,motion_id, reference and target motion positions,return_node_ids, andmesh.return_node_idsare the node IDs returned in the step payload, in the same order asnode_idsfor the same region indescribe_deformation().mesh.nodescontainsids,reference_coordinates, androles; the same index identifies the same node.mesh.volume_elementscontainselement_id,element_type_id,element_type,material_id,role, andnode_ids.node_idspreserves EMSolution local node ordering.
There are three node roles:
deformable: volume region that deforms (internalMOTION_DEFORM).rigid: region that moves while retaining its shape (internalMOTION_RIGID).fixed: boundary node kept stationary by existing processing because it is shared with an outer fixed region.
Elements include only deformable and rigid roles; fixed elements for the entire model are not passed. Shared boundary nodes are included with the fixed role so the external tool can recognize fixed conditions. element_type is an EMSolution abbreviated name (for example, H1 or PR1). When converting to an external-tool-specific element type, map it in the adapter using element_type_id, node count, and local node order.
Dynamic deformation description (schema version 1)#
describe_deformation() returns node states used at each step.
{
"schema_version": 1,
"enabled": True,
"mode": "absolute",
"unit": "m",
"coordinate_frame": "global_after_rigid",
"regions": [
{
"deform_id": 1,
"motion_id": 1,
"position_pre_geom": 0.0,
"position_deform_mesh": 0.24,
"node_ids": [10, 11, 12],
"reference_coordinates": [[...], [...], [...]],
"target_coordinates": [[...], [...], [...]],
"current_coordinates": [[...], [...], [...]],
},
],
}
node_ids, reference_coordinates, target_coordinates, and current_coordinates use the same index for the same node. target_coordinates are target values for linear deformation by existing deform_mesh; they are not constraints on all nodes. Pass motion positions to the external tool from an external solver, a time function evaluated in Python, or higher-level coupling control code.
Payload returned by the external tool#
The external tool returns regions containing each DEFORM region exactly once.
deformation = {
"mode": "absolute",
"unit": "m",
"coordinate_frame": "global_after_rigid",
"mesh_revision": 25, # 任意。結果へそのまま返される。
"regions": [
{
"deform_id": 1,
"node_ids": [10, 11, 12],
"coordinates": [
[-0.15, 0.50, 0.00],
[-0.09, 0.51, 0.00],
[-0.03, 0.50, 0.00],
],
},
],
}
coordinates are global absolute coordinates with shape (N, 3). node_ids[i] and coordinates[i] identify the same node. Input order is arbitrary, but retain the order returned by description for debuggability and compatibility. Partial updates, renumbering node IDs, and returning displacements are not supported.
Even when NumPy is used internally, convert values to Python built-in types immediately before passing them to pyemsol.
region_payload = {
"deform_id": int(deform_id),
"node_ids": node_ids.astype(int).tolist(),
"coordinates": coordinates.astype(float).tolist(),
}
Results and validation#
On success, the return value from step() includes deformation information such as the following.
result["deformation"] == {
"mode": "absolute",
"coordinate_frame": "global_after_rigid",
"region_count": 1,
"node_count": 548,
"mesh_revision": 25,
}
EMSolution validates all regions before updating node coordinates. In the following cases, it raises an exception without advancing coordinates or analysis time.
There are no DEFORM regions, or the region count or
deform_idvalues do not match.mode,unit, orcoordinate_framediffers from its specified value.The length, target IDs, or number of XYZ components in
node_idsorcoordinatesis invalid.Duplicate, missing, or unknown node IDs; coordinates containing NaN or Inf; or values other than Python built-in types.
A model containing gap elements, or a model using Slide motion and external Deform simultaneously.
External-tool acceptance checks#
An adapter implementation must at least verify the following.
Do not modify received
descriptionortopologydestructively.For every
deform_id, return allreturn_node_idswith no omissions or duplicates.Coordinates are finite global absolute coordinates in
mand satisfy boundaries after RIGID motion and fixed boundaries.Return deterministic results for the same input.
Return the expected shape in the reference state and complete the 40-step integration test using
Deform_sample.
Calling describe_deformation() again after a step and comparing current_coordinates with the transmitted coordinates verifies coordinate transfer.
Current limitations#
Surface elements, periodic boundaries and sliding surfaces, and element quality metrics are not included in the topology API.
Element inversion, negative Jacobians, and volume changes are not checked for external coordinates.
Complete rollback on solver calculation failure and coordinate history for post-processing replay of nonlinear morphing are not implemented.
Coordinates for all applicable nodes must be returned at every step.