.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/workflows/05-pymechanical-to-cdb-workflow.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_workflows_05-pymechanical-to-cdb-workflow.py: .. _pymechanical_to_cdb_example: PyMechanical to CDB shell workflow ================================== This example shows how to set up a workflow that uses PyMechanical to mesh the geometry and define the load case, PyACP to define a layup, PyMAPDL to solve the model, and PyDPF Composites to post-process the results. This workflow does *not* suffer from the limitations of the PyACP to PyMechanical integration. .. GENERATED FROM PYTHON SOURCE LINES 42-44 Import modules and start the Ansys products ------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 47-48 Import the standard library and third-party dependencies. .. GENERATED FROM PYTHON SOURCE LINES 48-54 .. code-block:: Python from concurrent.futures import ThreadPoolExecutor import pathlib import tempfile import textwrap .. GENERATED FROM PYTHON SOURCE LINES 55-56 Import PyACP, PyMechanical, and PyDPF Composites. .. GENERATED FROM PYTHON SOURCE LINES 56-65 .. code-block:: Python # isort: off import ansys.acp.core as pyacp import ansys.dpf.core as pydpf_core import ansys.dpf.composites as pydpf_composites import ansys.mapdl.core as pymapdl import ansys.mechanical.core as pymechanical .. GENERATED FROM PYTHON SOURCE LINES 67-69 Start the ACP, Mechanical, and DPF servers. We use a ``ThreadPoolExecutor`` to start them in parallel. .. GENERATED FROM PYTHON SOURCE LINES 69-79 .. code-block:: Python with ThreadPoolExecutor() as executor: futures = [ executor.submit(pymechanical.launch_mechanical, batch=True), executor.submit(pyacp.launch_acp), executor.submit(pymapdl.launch_mapdl), executor.submit(pydpf_composites.server_helpers.connect_to_or_start_server), ] mechanical, acp, mapdl, dpf = (fut.result() for fut in futures) mapdl.clear() .. GENERATED FROM PYTHON SOURCE LINES 80-85 Get example input files ----------------------- Create a temporary working directory, and download the example input files to this directory. .. GENERATED FROM PYTHON SOURCE LINES 85-92 .. code-block:: Python working_dir = tempfile.TemporaryDirectory() working_dir_path = pathlib.Path(working_dir.name) input_geometry = pyacp.extras.example_helpers.get_example_file( pyacp.extras.example_helpers.ExampleKeys.CLASS40_AGDB, working_dir_path ) .. GENERATED FROM PYTHON SOURCE LINES 93-98 Generate the mesh in PyMechanical --------------------------------- Load the geometry into Mechanical, generate the mesh, and define the load case. .. GENERATED FROM PYTHON SOURCE LINES 98-167 .. code-block:: Python cdb_path_initial = working_dir_path / "model_from_mechanical.cdb" mechanical.run_python_script( # This script runs in the Mechanical Python environment, which uses IronPython 2.7. textwrap.dedent( f"""\ # Import the geometry geometry_import = Model.GeometryImportGroup.AddGeometryImport() import_format = Ansys.Mechanical.DataModel.Enums.GeometryImportPreference.Format.Automatic import_preferences = Ansys.ACT.Mechanical.Utilities.GeometryImportPreferences() import_preferences.ProcessNamedSelections = True import_preferences.ProcessCoordinateSystems = True geometry_file = {str(input_geometry)!r} geometry_import.Import( geometry_file, import_format, import_preferences ) # The thickness will be overridden by the ACP model, but is required # for the model to be valid. for body in Model.Geometry.GetChildren( Ansys.Mechanical.DataModel.Enums.DataModelObjectCategory.Body, True ): body.Thickness = Quantity(1e-6, "m") # Define named selections at the front and back edges front_edge = Model.AddNamedSelection() front_edge.Name = "Front Edge" front_edge.ScopingMethod = GeometryDefineByType.Worksheet front_edge.GenerationCriteria.Add(None) front_edge.GenerationCriteria[0].EntityType = SelectionType.GeoEdge front_edge.GenerationCriteria[0].Criterion = SelectionCriterionType.LocationX front_edge.GenerationCriteria[0].Operator = SelectionOperatorType.GreaterThan front_edge.GenerationCriteria[0].Value = Quantity('-4.6 [m]') front_edge.Generate() back_edge = Model.AddNamedSelection() back_edge.Name = "Back Edge" back_edge.ScopingMethod = GeometryDefineByType.Worksheet back_edge.GenerationCriteria.Add(None) back_edge.GenerationCriteria[0].EntityType = SelectionType.GeoEdge back_edge.GenerationCriteria[0].Criterion = SelectionCriterionType.LocationX back_edge.GenerationCriteria[0].Operator = SelectionOperatorType.LessThan back_edge.GenerationCriteria[0].Value = Quantity('-7.8 [m]') back_edge.Generate() # Create a static structural analysis, and define the boundary # conditions (fixed support at the back edge, force at the front edge). analysis = Model.AddStaticStructuralAnalysis() fixed_support = analysis.AddFixedSupport() fixed_support.Location = back_edge force = analysis.AddForce() force.DefineBy = LoadDefineBy.Components force.XComponent.Output.SetDiscreteValue(0, Quantity(1e6, "N")) force.Location = front_edge # Export the model to a CDB file analysis.WriteInputFile({str(cdb_path_initial)!r}) """ ) ) .. GENERATED FROM PYTHON SOURCE LINES 168-172 Set up the ACP model -------------------- Setup basic ACP lay-up based on the CDB file. .. GENERATED FROM PYTHON SOURCE LINES 172-231 .. code-block:: Python model = acp.import_model(path=acp.upload_file(cdb_path_initial), format="ansys:cdb") mat = model.create_material(name="mat") mat.ply_type = "regular" mat.engineering_constants.E1 = 1e12 mat.engineering_constants.E2 = 1e11 mat.engineering_constants.E3 = 1e11 mat.engineering_constants.G12 = 1e10 mat.engineering_constants.G23 = 1e10 mat.engineering_constants.G31 = 1e10 mat.engineering_constants.nu12 = 0.3 mat.engineering_constants.nu13 = 0.3 mat.engineering_constants.nu23 = 0.3 mat.strain_limits = pyacp.material_property_sets.ConstantStrainLimits.from_orthotropic_constants( eXc=-0.01, eYc=-0.01, eZc=-0.01, eXt=0.01, eYt=0.01, eZt=0.01, eSxy=0.01, eSyz=0.01, eSxz=0.01, ) corecell_81kg_5mm = model.create_fabric(name="Corecell 81kg", thickness=0.005, material=mat) ros = model.create_rosette(name="ros", origin=(0, 0, 0)) oss = model.create_oriented_selection_set( name="oss", orientation_point=(-0, 0, 0), orientation_direction=(0.0, 1, 0.0), element_sets=[model.element_sets["All_Elements"]], rosettes=[ros], ) mg = model.create_modeling_group(name="group") mg.create_modeling_ply( name="ply", ply_material=corecell_81kg_5mm, oriented_selection_sets=[oss], ply_angle=45, number_of_layers=1, global_ply_nr=0, # add at the end ) mg.create_modeling_ply( name="ply2", ply_material=corecell_81kg_5mm, oriented_selection_sets=[oss], ply_angle=0, number_of_layers=2, global_ply_nr=0, # add at the end ) .. GENERATED FROM PYTHON SOURCE LINES 232-234 Update and Save the ACP model ----------------------------- .. GENERATED FROM PYTHON SOURCE LINES 234-254 .. code-block:: Python model.update() if acp.is_remote: export_path = pathlib.PurePosixPath(".") else: export_path = working_dir_path # type: ignore cdb_filename_out = "model_from_acp.cdb" composite_definitions_h5_filename = "ACPCompositeDefinitions.h5" matml_filename = "materials.xml" model.export_analysis_model(export_path / cdb_filename_out) model.export_shell_composite_definitions(export_path / composite_definitions_h5_filename) model.export_materials(export_path / matml_filename) for filename in [cdb_filename_out, composite_definitions_h5_filename, matml_filename]: acp.download_file(export_path / filename, working_dir_path / filename) .. GENERATED FROM PYTHON SOURCE LINES 255-257 Solve with PyMAPDL ------------------ .. GENERATED FROM PYTHON SOURCE LINES 257-259 .. code-block:: Python mapdl.clear() .. GENERATED FROM PYTHON SOURCE LINES 260-261 Load the CDB file into PyMAPDL. .. GENERATED FROM PYTHON SOURCE LINES 261-263 .. code-block:: Python mapdl.input(str(working_dir_path / cdb_filename_out)) .. GENERATED FROM PYTHON SOURCE LINES 264-265 Solve the model. .. GENERATED FROM PYTHON SOURCE LINES 265-269 .. code-block:: Python mapdl.allsel() mapdl.slashsolu() mapdl.solve() .. GENERATED FROM PYTHON SOURCE LINES 270-271 Show the displacements in postprocessing. .. GENERATED FROM PYTHON SOURCE LINES 271-275 .. code-block:: Python mapdl.post1() mapdl.set("last") mapdl.post_processing.plot_nodal_displacement(component="NORM") .. GENERATED FROM PYTHON SOURCE LINES 276-277 Download the RST file for further postprocessing. .. GENERATED FROM PYTHON SOURCE LINES 277-281 .. code-block:: Python rstfile_name = f"{mapdl.jobname}.rst" rst_file_local_path = working_dir_path / rstfile_name mapdl.download(rstfile_name, working_dir_path) .. GENERATED FROM PYTHON SOURCE LINES 282-286 Postprocessing with PyDPF Composites ------------------------------------ Specify the combined failure criterion. .. GENERATED FROM PYTHON SOURCE LINES 286-293 .. code-block:: Python max_strain = pydpf_composites.failure_criteria.MaxStrainCriterion() cfc = pydpf_composites.failure_criteria.CombinedFailureCriterion( name="Combined Failure Criterion", failure_criteria=[max_strain], ) .. GENERATED FROM PYTHON SOURCE LINES 294-295 Create the composite model and configure its input. .. GENERATED FROM PYTHON SOURCE LINES 295-309 .. code-block:: Python composite_model = pydpf_composites.composite_model.CompositeModel( composite_files=pydpf_composites.data_sources.ContinuousFiberCompositesFiles( rst=rst_file_local_path, composite={ "shell": pydpf_composites.data_sources.CompositeDefinitionFiles( definition=working_dir_path / composite_definitions_h5_filename ), }, engineering_data=working_dir_path / matml_filename, ), default_unit_system=pydpf_core.unit_system.unit_systems.solver_nmm, server=dpf, ) .. GENERATED FROM PYTHON SOURCE LINES 310-311 Evaluate the failure criteria. .. GENERATED FROM PYTHON SOURCE LINES 311-313 .. code-block:: Python output_all_elements = composite_model.evaluate_failure_criteria(cfc) .. GENERATED FROM PYTHON SOURCE LINES 314-315 Query and plot the results. .. GENERATED FROM PYTHON SOURCE LINES 315-319 .. code-block:: Python irf_field = output_all_elements.get_field( {"failure_label": pydpf_composites.constants.FailureOutput.FAILURE_VALUE} ) irf_field.plot() .. _sphx_glr_download_examples_workflows_05-pymechanical-to-cdb-workflow.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 05-pymechanical-to-cdb-workflow.ipynb <05-pymechanical-to-cdb-workflow.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 05-pymechanical-to-cdb-workflow.py <05-pymechanical-to-cdb-workflow.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 05-pymechanical-to-cdb-workflow.zip <05-pymechanical-to-cdb-workflow.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_