Source code for model_package.Tardigrade_MOOSE.cylinder_from_bounds_with_platens

#!python
import argparse
import os
import pathlib
import sys

import cubit
import pandas
import numpy
import subprocess


[docs] def mesh(rad, height, x0, y0, z0, seed_size, output_file, platen_rad_factor, platen_depth, gap=None): ''' Mesh a cylinder using Cubit with platens :param float rad: Cylinder radius :param float height: Cylinder height :param float x0: The x-distance to translate the cylinder :param float y0: The y-distance to translate the cylinder :param float z0: The z-distance to translate the cylinder :param float seed-size: The approximate mesh size :param str output_file: The output filename :param float platen_rad_factor: The factor to multiply the specimen radius by to determine the specimen radius :param float platen_depth: The thickness of the platens :returns: ``{output_file}.e`` ''' cubit.init(['cubit', '-noecho', '-nojournal', '-nographics', '-batch']) cubit.cmd('new') cubit.cmd('reset') cubit.cmd(f'create Cylinder height {height} radius {rad}') # Cut with planes cubit.cmd('webcut volume all with plane xplane offset 0') cubit.cmd('webcut volume all with plane yplane offset 0') cubit.cmd('webcut volume all with plane zplane offset 0') # Side sets cubit.cmd('sideset 1 add surface 28 20 26 14') cubit.cmd('sideset 1 name "top"') cubit.cmd('sideset 2 add surface 24 16 30 18') cubit.cmd('sideset 2 name "bottom"') cubit.cmd('sideset 3 add surface 41 59 47 61') cubit.cmd('sideset 3 name "x_plane"') cubit.cmd('sideset 4 add surface 58 50 62 54') cubit.cmd('sideset 4 name "y_plane"') # Top Platen cubit.cmd(f'create cylinder height {platen_depth} radius {rad*platen_rad_factor}') cubit.cmd('webcut volume 9 with plane xplane offset 0') cubit.cmd('webcut volume 9 10 with plane yplane offset 0') cubit.cmd(f'move Volume 9 10 11 12 x 0 y 0 z {0.5*(height + platen_depth)} include_merged') # Bottom Platen cubit.cmd(f'create cylinder height {platen_depth} radius {rad*platen_rad_factor}') cubit.cmd('webcut volume 13 with plane xplane offset 0') cubit.cmd('webcut volume 13 14 with plane yplane offset 0') cubit.cmd(f'move Volume 13 14 15 16 x 0 y 0 z {-0.5*(height + platen_depth)} include_merged') # Partition by using specimen surface cubit.cmd(f'webcut volume 9 10 11 12 13 14 15 16 with sheet extended from surface 39 45 63 53') # Platen Side sets cubit.cmd('sideset 5 add surface 128 135 140 143 150 153 158 165') cubit.cmd('sideset 5 name "top_platen_bottom"') cubit.cmd('sideset 6 add surface 130 133 138 145 148 155 160 163') cubit.cmd('sideset 6 name "top_platen_top"') cubit.cmd('sideset 7 add surface 168 175 180 183 190 193 198 205') cubit.cmd('sideset 7 name "bottom_platen_bottom"') cubit.cmd('sideset 8 add surface 170 173 178 185 188 195 200 203') cubit.cmd('sideset 8 name "bottom_platen_top"') # Mesh and Move cubit.cmd('imprint volume 1 2 3 4 5 6 7 8') cubit.cmd('merge volume 1 2 3 4 5 6 7 8') cubit.cmd(f'volume 1 2 3 4 5 6 7 8 size {seed_size}') cubit.cmd('mesh volume 1 2 3 4 5 6 7 8') cubit.cmd('imprint volume all') cubit.cmd('merge volume all') cubit.cmd(f'volume 9 10 11 12 17 18 19 20 13 14 15 16 21 22 23 24 size {seed_size}') cubit.cmd('mesh volume 9 10 11 12 17 18 19 20 13 14 15 16 21 22 23 24') cubit.cmd(f'move Volume all x {x0} y {y0} z {z0} include_merged') if gap: cubit.cmd(f'move Volume 9 10 11 12 17 18 19 20 x 0 y 0 z {gap} include_merged') # Blocks cubit.cmd('block 1 add volume 1 2 3 4 5 6 7 8') cubit.cmd('block 1 name "specimen"') cubit.cmd('block 2 add volume 9 10 11 12 17 18 19 20') cubit.cmd('block 2 name "top_platen"') cubit.cmd('block 3 add volume 13 14 15 16 21 22 23 24') cubit.cmd('block 3 name "bottom_platen"') # Export #cubit.cmd(f' cubit.cmd(f'export mesh "{output_file}.e" block 1 2 3 overwrite') return 0
[docs] def cylinder_from_bounds_with_platens(output_file, bounds_file, seed_size, platen_rad_factor=1.5, platen_depth=1.0, xdmf=True, ascii=False, gap=None): '''Create a cylinder mesh from the bounds of a DNS file with platens :param str output_file: The output filename :param str bounds_file: The file containing the bounds of the DNS :param float seed_size: The approximate mesh size :param float platen_rad_factor: The factor to multiply the specimen radius by to determine the specimen radius :param float platen_depth: The thickness of the platens :param bool xdmf: The option to convert default exodus mesh to XDMF (binary) :param bool ascii: The option to convert binary XDMF mesh to ascii Calls "mesh" function and converts ``{output_file}.e`` to ``{output_file}.xdmf`` ''' # Process the bounds data to calculate cylinder geometry info bounds_data = pandas.read_csv(bounds_file, sep=',') xmin = bounds_data['xmin'][0] xmax = bounds_data['xmax'][0] ymin = bounds_data['ymin'][0] ymax = bounds_data['ymax'][0] zmin = bounds_data['zmin'][0] zmax = bounds_data['zmax'][0] radx = (xmax - xmin) / 2 rady = (ymax - ymin) / 2 rad = numpy.mean([radx, rady]) height = zmax - zmin x0 = xmin + rad y0 = ymin + rad z0 = zmin + (height / 2) # create mesh mesh(rad, height, x0, y0, z0, seed_size, output_file, platen_rad_factor, platen_depth, gap) # convert to XDMF with subprocess if xdmf: subprocess.run([f'meshio convert {output_file}.e {output_file}.xdmf'], shell=True) if ascii: subprocess.run([f'meshio ascii {output_file}.xdmf'], shell=True) return 0
def get_parser(): script_name = pathlib.Path(__file__) prog = f"python {script_name.name} " cli_description = "Create a cylinder mesh from the bounds of a DNS file with platens." parser = argparse.ArgumentParser(description=cli_description, prog=prog) parser.add_argument('--output-file', type=str, required=True, help="The output filename") parser.add_argument('--bounds-file', type=str, required=True, help='The file containing the bounds of the DNS') parser.add_argument('--seed-size', type=float, required=True, help='The approximate mesh size') parser.add_argument('--platen-rad-factor', type=float, required=False, default=1.5, help='The factor to multiply the specimen radius by to determine the specimen radius') parser.add_argument('--platen-depth', type=float, required=False, default=1.0, help='The thickness of the platens') parser.add_argument('--xdmf', type=str, required=False, help='The option to convert default exodus mesh to XDMF (binary)') parser.add_argument('--ascii', type=str, required=False, default=False, help='The option to convert binary XDMF mesh to ascii') parser.add_argument('--gap', type=str, required=False, default=None, help='An initial gap to place between specimen and platens') return parser if __name__ == '__main__': parser = get_parser() args = parser.parse_args() sys.exit(cylinder_from_bounds_with_platens(output_file=args.output_file, bounds_file=args.bounds_file, seed_size=args.seed_size, platen_rad_factor=args.platen_rad_factor, platen_depth=args.platen_depth, xdmf=bool(args.xdmf), ascii=bool(args.ascii), gap=args.gap, ))