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
109 changes: 86 additions & 23 deletions src/cubitpy/cubit_to_fourc_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
from cubitpy.conf import cupy


def add_node_sets(cubit, exo, input_file):
"""Add the node sets contained in the cubit session/exo file to the
dat_lines."""
def add_node_sets(cubit, exo, input_file, write_topology_information=True):
"""Add the node sets contained in the cubit session/exo file to the yaml
file."""

# If there are no node sets we can return immediately
if len(cubit.node_sets) == 0:
Expand Down Expand Up @@ -69,28 +69,91 @@ def add_node_sets(cubit, exo, input_file):
input_file[bc_section] = []
bc_description["E"] = len(node_sets[geometry_type])

if not write_topology_information:
# when working with external .exo meshes, we do not write the
# topology information for the node sets explicitly, since 4C will
# deduce them based on the node set ids, when reading the .exo file
bc_description["ENTITY_TYPE"] = "node_set_id"

input_file[bc_section].append(bc_description)

name_geometry_tuple = [
[cupy.geometry.vertex, "DNODE-NODE TOPOLOGY", "DNODE"],
[cupy.geometry.curve, "DLINE-NODE TOPOLOGY", "DLINE"],
[cupy.geometry.surface, "DSURF-NODE TOPOLOGY", "DSURFACE"],
[cupy.geometry.volume, "DVOL-NODE TOPOLOGY", "DVOL"],
]
for geo, section_name, set_label in name_geometry_tuple:
if len(node_sets[geo]) > 0:
input_file[section_name] = []
for i_set, node_set in enumerate(node_sets[geo]):
node_set.sort()
for i_node in node_set:
input_file[section_name].append(
{
"type": "NODE",
"node_id": i_node,
"d_type": set_label,
"d_id": i_set + 1,
}
)
if write_topology_information:
# this is the default case: when the mesh is supposed to be contained
# in the .yaml file, we have to write the topology information of the
# node sets
name_geometry_tuple = [
[cupy.geometry.vertex, "DNODE-NODE TOPOLOGY", "DNODE"],
[cupy.geometry.curve, "DLINE-NODE TOPOLOGY", "DLINE"],
[cupy.geometry.surface, "DSURF-NODE TOPOLOGY", "DSURFACE"],
[cupy.geometry.volume, "DVOL-NODE TOPOLOGY", "DVOL"],
]
for geo, section_name, set_label in name_geometry_tuple:
if len(node_sets[geo]) > 0:
input_file[section_name] = []
for i_set, node_set in enumerate(node_sets[geo]):
node_set.sort()
for i_node in node_set:
input_file[section_name].append(
{
"type": "NODE",
"node_id": i_node,
"d_type": set_label,
"d_id": i_set + 1,
}
)


def add_exodus_geometry_section(cubit, input_file, rel_exo_file_path):
"""Add the problem specific geometry section to the input file required to
directly read the mesh from an exodus file.

This section contains information about all element blocks as well as the
path to the exo file that contains the mesh.

Args
----
cubit: CubitPy
The python object for managing the current Cubit session (exclusively
used in a read-only fashion).
input_file: dict
The input file dictionary that will be modified to include the geometry
section.
rel_exo_file_path: str
The relative path (as seen from the yaml input file) to the exodus
file that contains the mesh.
"""
# Retrieve a list of the block IDs and the corresponding block data of the current session
element_block_ids = cubit.cubit.get_block_id_list()
element_blocks = cubit.blocks

# Iterate over all blocks and add them to the input file
for cur_block_id, cur_block_data in zip(element_block_ids, element_blocks):
# retrieve the name of the geometry section that this block belongs to
cur_geometry_section_key = cur_block_data[0].get_four_c_section() + " GEOMETRY"
# If the geometry section for this block does not exist yet, create it
if input_file.sections.get(cur_geometry_section_key) is None:
# add the geometry section to the input file
input_file[cur_geometry_section_key] = {
"FILE": rel_exo_file_path,
"SHOW_INFO": "detailed_summary",
"ELEMENT_BLOCKS": [],
}
# retrieve the fourc name for the element
four_c_element_name = cur_block_data[0].get_four_c_name()
# convert the material data from dict to string because 4C currently does not support a dict here
element_data_string = " ".join(
f"{key} {value}" for key, value in cur_block_data[1].items()
)
# add block id, fourc element name and element data string to the element block dictionary
element_block_dict = {
"ID": cur_block_id,
"ELEMENT_NAME": four_c_element_name,
"ELEMENT_DATA": element_data_string,
}
# append the dictionary with the element block information to the element block list
input_file[cur_geometry_section_key]["ELEMENT_BLOCKS"].append(
element_block_dict
)


def get_element_connectivity_list(connectivity):
Expand Down
44 changes: 37 additions & 7 deletions src/cubitpy/cubitpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@
import time
import warnings

import netCDF4
from fourcipp.fourc_input import FourCInput

from cubitpy.conf import cupy
from cubitpy.cubit_group import CubitGroup
from cubitpy.cubit_to_fourc_input import get_input_file_with_mesh
from cubitpy.cubit_to_fourc_input import (
add_exodus_geometry_section,
add_node_sets,
get_input_file_with_mesh,
)
from cubitpy.cubit_wrapper.cubit_wrapper_host import CubitConnect


Expand Down Expand Up @@ -329,21 +334,46 @@ def export_exo(self, path):
"""Export the mesh."""
self.cubit.cmd('export mesh "{}" dimension 3 overwrite'.format(path))

def dump(self, yaml_path):
def dump(self, yaml_path, mesh_in_exo=False):
"""Create the yaml file and save it in under provided yaml_path.

Args
----
yaml_path: str
Path where the input file will be saved
mesh_in_exo: bool
If True, the mesh will be exported in exodus format and the input file
will contain a reference to the exodus file. If False, the mesh will
be exported in the 4C format and the input file will contain the mesh
directly in the yaml file.
Default is False.
"""

# Check if output path exists
dat_dir = os.path.dirname(os.path.abspath(yaml_path))
if not os.path.exists(dat_dir):
raise ValueError("Path {} does not exist!".format(dat_dir))

input_file = get_input_file_with_mesh(self)
yaml_dir = os.path.dirname(os.path.abspath(yaml_path))
if not os.path.exists(yaml_dir):
raise ValueError("Path {} does not exist!".format(yaml_dir))

if mesh_in_exo:
# Determine the path stem: Strip the '(.4C).yaml' suffix
# (if the filename does not contain '.4C' the second call to
# 'removesuffix' won't alter the string at all)
path_stem = yaml_path.removesuffix(".yaml").removesuffix(".4C")
# Export the mesh in exodus format
exo_path = path_stem + ".exo"
self.export_exo(exo_path)
# parse the exodus file
exo = netCDF4.Dataset(exo_path)
# create a deep copy of the input_file
input_file = self.fourc_input.copy()
# Add the node sets
add_node_sets(self, exo, input_file, write_topology_information=False)
# Add the problem geometry section
rel_exo_path = os.path.relpath(exo_path, start=yaml_dir)
add_exodus_geometry_section(self, input_file, rel_exo_path)
else:
input_file = get_input_file_with_mesh(self)
# Export the input file in YAML format
input_file.dump(yaml_path)

def group(self, **kwargs):
Expand Down
54 changes: 54 additions & 0 deletions tests/input-files-ref/test_yaml_with_exo_export.4C.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
PROBLEM SIZE:
DIM: 3
PROBLEM TYPE:
PROBLEMTYPE: "Structure"
DESIGN SURF MORTAR CONTACT CONDITIONS 3D:
- InterfaceID: 1
Side: "Slave"
E: 1
ENTITY_TYPE: "node_set_id"
- InterfaceID: 1
Side: "Master"
E: 2
ENTITY_TYPE: "node_set_id"
DESIGN SURF DIRICH CONDITIONS:
- NUMDOF: 3
ONOFF:
- 1
- 1
- 1
VAL:
- 0
- 0
- 0
FUNCT:
- null
- null
- null
E: 3
ENTITY_TYPE: "node_set_id"
- NUMDOF: 3
ONOFF:
- 1
- 0
- 0
VAL:
- -1.0
- 0.0
- 0.0
FUNCT:
- 1
- null
- null
E: 4
ENTITY_TYPE: "node_set_id"
STRUCTURE GEOMETRY:
FILE: "test_yaml_with_exo_export.exo"
SHOW_INFO: "detailed_summary"
ELEMENT_BLOCKS:
- ID: 1
ELEMENT_NAME: "SOLID"
ELEMENT_DATA: "MAT 1 KINEM nonlinear"
- ID: 2
ELEMENT_NAME: "SOLID"
ELEMENT_DATA: "MAT 2 KINEM nonlinear"
21 changes: 21 additions & 0 deletions tests/input-files-ref/test_yaml_with_exo_export_fsi.4C.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
PROBLEM TYPE:
PROBLEMTYPE: "Fluid_Structure_Interaction"
PROBLEM SIZE:
DIM: 3
STRUCTURAL DYNAMIC:
INT_STRATEGY: "Standard"
LINEAR_SOLVER: 3
STRUCTURE GEOMETRY:
FILE: "test_yaml_with_exo_export_fsi.exo"
SHOW_INFO: "detailed_summary"
ELEMENT_BLOCKS:
- ID: 1
ELEMENT_NAME: "SOLID"
ELEMENT_DATA: "MAT 1 KINEM nonlinear TECH eas_full"
FLUID GEOMETRY:
FILE: "test_yaml_with_exo_export_fsi.exo"
SHOW_INFO: "detailed_summary"
ELEMENT_BLOCKS:
- ID: 2
ELEMENT_NAME: "FLUID"
ELEMENT_DATA: "MAT 2 NA ALE"
Loading