|
| 1 | +""" |
| 2 | +Metalforming |
| 3 | +============ |
| 4 | +This example shows how to use the PyDYNA ``pre`` service to create |
| 5 | +a Metalforming model. The executable file for LS-DYNA is |
| 6 | +``ls-dyna_smp_d_R13.0_365-gf8a97bda2a_winx64_ifort190.exe``. |
| 7 | +
|
| 8 | +""" |
| 9 | +############################################################################### |
| 10 | +# Perform required imports |
| 11 | +# ~~~~~~~~~~~~~~~~~~~~~~~~ |
| 12 | +# Peform the required imports. |
| 13 | +import os |
| 14 | +import sys |
| 15 | + |
| 16 | + |
| 17 | +from ansys.dyna.core.pre import launch_dyna |
| 18 | +from ansys.dyna.core.pre.dynamech import ( |
| 19 | + DynaMech, |
| 20 | + PartSet, |
| 21 | + Curve, |
| 22 | + ShellPart, |
| 23 | + NodeSet, |
| 24 | + Contact, |
| 25 | + Motion, |
| 26 | + ContactSurface, |
| 27 | + ShellFormulation, |
| 28 | + ContactType, |
| 29 | + ContactCategory, |
| 30 | + AnalysisType, |
| 31 | + MetalFormingAnalysis, |
| 32 | + DOF, |
| 33 | + BulkViscosity, |
| 34 | + EnergyFlag, |
| 35 | + HourglassControl, |
| 36 | +) |
| 37 | +from ansys.dyna.core.pre.dynamaterial import ( |
| 38 | + MatRigid, |
| 39 | + MatTransverselyAnisotropicElasticPlastic, |
| 40 | +) |
| 41 | +from ansys.dyna.core.pre import examples |
| 42 | +from ansys.dyna.core.pre.misc import check_valid_ip |
| 43 | +# sphinx_gallery_thumbnail_path = '_static/pre/explicit/ball_plate.png' |
| 44 | + |
| 45 | +############################################################################### |
| 46 | +# Start the ``pre`` service |
| 47 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 48 | +# Before starting the ``pre`` service, you must ensure that the Docker container |
| 49 | +# for this service has been started. For more information, see "Start the Docker |
| 50 | +# container for the ``pre`` service" in https://dyna.docs.pyansys.com/version/stable/index.html. |
| 51 | +# |
| 52 | +# The ``pre`` service can also be started locally, please download the latest version of |
| 53 | +# ansys-pydyna-pre-server.zip package from https://github.com/ansys/pydyna/releases and start it |
| 54 | +# refering to the README.rst file in this server package. |
| 55 | +# |
| 56 | +# Once the ``pre`` service is running, you can connect a client to it using |
| 57 | +# the host name and port. This code uses the default localhost and port |
| 58 | +# (``"localhost"`` and ``"50051"`` respectively). |
| 59 | +# |
| 60 | +hostname = "localhost" |
| 61 | +if len(sys.argv) > 1 and check_valid_ip(sys.argv[1]): |
| 62 | + hostname = sys.argv[1] |
| 63 | +solution = launch_dyna(ip = hostname) |
| 64 | + |
| 65 | +############################################################################### |
| 66 | +# Start the solution workflow |
| 67 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 68 | +# NODES and ELEMENTS are read in from the ``model.k`` file. This file |
| 69 | +# also has the *PART* defined in it, but the section and material fields are |
| 70 | +# empty to begin with. |
| 71 | +# |
| 72 | +fns = [] |
| 73 | +path = examples.mf_simple_roll + os.sep |
| 74 | +fns.append(path+"model.k") |
| 75 | +solution.open_files(fns) |
| 76 | + |
| 77 | +############################################################################### |
| 78 | +# Create database and control cards |
| 79 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 80 | +# For the D3plots, set simulation termination time, simulation timestep, and |
| 81 | +# output frequency. |
| 82 | + |
| 83 | +solution.set_termination(termination_time=0.05) |
| 84 | + |
| 85 | +mf = DynaMech(AnalysisType.NONE) |
| 86 | +solution.add(mf) |
| 87 | + |
| 88 | +mfanalysis = MetalFormingAnalysis() |
| 89 | +mfanalysis.set_springback(PartSet([1]),100) |
| 90 | +mfanalysis.set_rigid_body_nodes_fast_update(fast_update=1) |
| 91 | +mf.add(mfanalysis) |
| 92 | + |
| 93 | +mf.set_timestep(timestep_size_for_mass_scaled=-7e-7) |
| 94 | +mf.set_accuracy() |
| 95 | +mf.set_bulk_viscosity(bulk_viscosity_type=BulkViscosity.STANDARD_BULK_VISCOSITY_SHELL) |
| 96 | +mf.set_energy(hourglass_energy=EnergyFlag.COMPUTED, |
| 97 | + rigidwall_energy=EnergyFlag.NOT_COMPUTED, |
| 98 | + sliding_interface_energy=EnergyFlag.COMPUTED |
| 99 | + ) |
| 100 | +mf.set_hourglass(HourglassControl.FLANAGAN_BELYTSCHKO_EXACT_VOLUME_INTEGRATION_SOLID) |
| 101 | +mf.set_output(print_suppression_d3hsp=True) |
| 102 | +mf.create_control_shell(esort=1,istupd=1) |
| 103 | +mf.create_control_contact(initial_penetration_check = 2, |
| 104 | + shlthk = 1, |
| 105 | + penalty_stiffness_option = 4, |
| 106 | + orien = 4, |
| 107 | + penetration_check_multiplier = 1.0) |
| 108 | +mf.set_adaptive(time_interval_refinement=2.5e-4, |
| 109 | + adaptive_error_tolerance=5.0, |
| 110 | + adaptive_type = 2, |
| 111 | + generate_adaptive_mesh_at_exit = 1, |
| 112 | + min_shell_size = 1.83, |
| 113 | + h_adaptivity_pass_flag = 1, |
| 114 | + shell_h_adapt = 5.0, |
| 115 | + fission_control_flag = -1, |
| 116 | + ) |
| 117 | + |
| 118 | +############################################################################### |
| 119 | +# Define materials |
| 120 | +# ~~~~~~~~~~~~~~~~ |
| 121 | +# The ``dynamaterials`` class is used to define these materials: ``MAT_RIGID``, |
| 122 | +# ``MAT_TRANSVERSELY_ANISOTROPIC_ELASTIC_PLASTIC``, |
| 123 | + |
| 124 | +mat_upper_punch = MatRigid( |
| 125 | + mass_density=7.83e-9, |
| 126 | + young_modulus=2.07e5, |
| 127 | + poisson_ratio=0.28, |
| 128 | + center_of_mass_constraint=1, |
| 129 | + translational_constraint=7, |
| 130 | + rotational_constraint=6, |
| 131 | +) |
| 132 | +mat_lower_cavity = MatRigid( |
| 133 | + mass_density=7.83e-9, |
| 134 | + young_modulus=2.07e5, |
| 135 | + poisson_ratio=0.28, |
| 136 | + center_of_mass_constraint=1, |
| 137 | + translational_constraint=7, |
| 138 | + rotational_constraint=6, |
| 139 | +) |
| 140 | +mat_binder = MatRigid( |
| 141 | + mass_density=7.83e-9, |
| 142 | + young_modulus=2.07e5, |
| 143 | + poisson_ratio=0.28, |
| 144 | + center_of_mass_constraint=1, |
| 145 | + translational_constraint=7, |
| 146 | + rotational_constraint=7, |
| 147 | +) |
| 148 | +crv = Curve(x=[0, 1],y=[0, 13]) |
| 149 | +matblank = MatTransverselyAnisotropicElasticPlastic( |
| 150 | + mass_density=7.9e-09, |
| 151 | + young_modulus=2.07e5, |
| 152 | + yield_stress=201.3, |
| 153 | + anisotropic_hardening_parameter=-1.5930001, |
| 154 | + curve_stress = crv) |
| 155 | + |
| 156 | + |
| 157 | +############################################################################### |
| 158 | +# Define section properties and assign materials |
| 159 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 160 | +# Now that you have materials with the material ID corresponding to |
| 161 | +# the Part ID, you can assign these materials to the |
| 162 | +# parts. You can also define section properties, element |
| 163 | +# formulations, and constraints. |
| 164 | +# |
| 165 | + |
| 166 | +blank = ShellPart(1) |
| 167 | +blank.set_element_formulation(ShellFormulation.FULLY_INTEGRATED_FAST) |
| 168 | +blank.set_material(matblank) |
| 169 | +blank.set_thickness(1.5) |
| 170 | +blank.set_integration_points(5) |
| 171 | +blank.set_shear_factor(0.833) |
| 172 | +mf.parts.add(blank) |
| 173 | + |
| 174 | +upper_punch = ShellPart(2) |
| 175 | +upper_punch.set_material(mat_upper_punch) |
| 176 | +upper_punch.set_element_formulation(ShellFormulation.BELYTSCHKO_TSAY) |
| 177 | +upper_punch.set_integration_points(3) |
| 178 | +mf.parts.add(upper_punch) |
| 179 | + |
| 180 | +lower_cavity = ShellPart(3) |
| 181 | +lower_cavity.set_material(mat_lower_cavity) |
| 182 | +lower_cavity.set_element_formulation(ShellFormulation.BELYTSCHKO_TSAY) |
| 183 | +lower_cavity.set_integration_points(3) |
| 184 | +mf.parts.add(lower_cavity) |
| 185 | + |
| 186 | +upper_binder = ShellPart(4) |
| 187 | +upper_binder.set_material(mat_binder) |
| 188 | +upper_binder.set_element_formulation(ShellFormulation.BELYTSCHKO_TSAY) |
| 189 | +upper_binder.set_integration_points(3) |
| 190 | +mf.parts.add(upper_binder) |
| 191 | + |
| 192 | +lower_binder = ShellPart(5) |
| 193 | +lower_binder.set_material(mat_binder) |
| 194 | +lower_binder.set_element_formulation(ShellFormulation.BELYTSCHKO_TSAY) |
| 195 | +lower_binder.set_integration_points(3) |
| 196 | +mf.parts.add(lower_binder) |
| 197 | + |
| 198 | + |
| 199 | +############################################################################### |
| 200 | +# Define one_way_surface_to_surface contacts |
| 201 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 202 | + |
| 203 | +mfcontact = Contact(type=ContactType.FORMING, category=ContactCategory.ONE_WAY_SURFACE_TO_SURFACE) |
| 204 | +mfcontact.set_friction_coefficient(static=0.125, dynamic=0) |
| 205 | +mfcontact.set_extra_coefficient(viscous_damping = 20) |
| 206 | +surf1 = ContactSurface(PartSet([1]),save_interface_force = 1) |
| 207 | +surf2 = ContactSurface(PartSet([2]),save_interface_force = 1) |
| 208 | +mfcontact.set_slave_surface(surf1) |
| 209 | +mfcontact.set_master_surface(surf2) |
| 210 | +mf.contacts.add(mfcontact) |
| 211 | + |
| 212 | +mfcontact = Contact(type=ContactType.FORMING, category=ContactCategory.ONE_WAY_SURFACE_TO_SURFACE) |
| 213 | +mfcontact.set_friction_coefficient(static=0.125, dynamic=0) |
| 214 | +mfcontact.set_extra_coefficient(viscous_damping = 20) |
| 215 | +surf1 = ContactSurface(PartSet([1]),save_interface_force = 1) |
| 216 | +surf2 = ContactSurface(PartSet([3]),save_interface_force = 1) |
| 217 | +mfcontact.set_slave_surface(surf1) |
| 218 | +mfcontact.set_master_surface(surf2) |
| 219 | +mf.contacts.add(mfcontact) |
| 220 | + |
| 221 | +mfcontact = Contact(type=ContactType.FORMING, category=ContactCategory.ONE_WAY_SURFACE_TO_SURFACE) |
| 222 | +mfcontact.set_friction_coefficient(static=0.125, dynamic=0) |
| 223 | +mfcontact.set_extra_coefficient(viscous_damping = 20) |
| 224 | +surf1 = ContactSurface(PartSet([1]),save_interface_force = 1) |
| 225 | +surf2 = ContactSurface(PartSet([4]),save_interface_force = 1) |
| 226 | +mfcontact.set_slave_surface(surf1) |
| 227 | +mfcontact.set_master_surface(surf2) |
| 228 | +mf.contacts.add(mfcontact) |
| 229 | + |
| 230 | +mfcontact = Contact(type=ContactType.FORMING, category=ContactCategory.ONE_WAY_SURFACE_TO_SURFACE) |
| 231 | +mfcontact.set_friction_coefficient(static=0.125, dynamic=0) |
| 232 | +mfcontact.set_extra_coefficient(viscous_damping = 20) |
| 233 | +surf1 = ContactSurface(PartSet([1]),save_interface_force = 1) |
| 234 | +surf2 = ContactSurface(PartSet([5]),save_interface_force = 1) |
| 235 | +mfcontact.set_slave_surface(surf1) |
| 236 | +mfcontact.set_master_surface(surf2) |
| 237 | +mf.contacts.add(mfcontact) |
| 238 | + |
| 239 | +############################################################################### |
| 240 | +# Define nodal single point constraints. |
| 241 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 242 | +# Constrain the nodes in a list of single point constraints (spc). |
| 243 | + |
| 244 | +spc = [600,593] |
| 245 | +mf.boundaryconditions.create_spc(NodeSet(spc),tx = False, tz = False,ry=False) |
| 246 | + |
| 247 | +mf.boundaryconditions.create_imposed_motion( |
| 248 | + PartSet([2]), |
| 249 | + Curve(x=[0,100], y=[600,600]), |
| 250 | + dof=DOF.Y_ROTATIONAL, |
| 251 | + motion=Motion.VELOCITY, |
| 252 | + scalefactor=-1, |
| 253 | +) |
| 254 | +mf.boundaryconditions.create_imposed_motion( |
| 255 | + PartSet([3]), |
| 256 | + Curve(x=[0,100], y=[600,600]), |
| 257 | + dof=DOF.Y_ROTATIONAL, |
| 258 | + motion=Motion.VELOCITY, |
| 259 | + scalefactor=1, |
| 260 | +) |
| 261 | +############################################################################### |
| 262 | +# Define applied forces. |
| 263 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 264 | + |
| 265 | +mf.loads.create_nodal_force( |
| 266 | + NodeSet([695,696,697,698,694,693,692]), |
| 267 | + load_curve = Curve(x=[0,0.015,0.016,100],y=[100,100,0,0]) |
| 268 | +) |
| 269 | + |
| 270 | +############################################################################### |
| 271 | +# Define database outputs |
| 272 | +# ~~~~~~~~~~~~~~~~~~~~~~~ |
| 273 | +# Define the frequency for the D3PLOT file and write out the input file. |
| 274 | +# |
| 275 | +solution.set_output_database(glstat=0.00025, matsum=0.00025, rcforc=0.00025) |
| 276 | +solution.create_database_binary(dt=5e-4) |
| 277 | +serverpath = solution.save_file() |
| 278 | + |
| 279 | +############################################################################### |
| 280 | +# Download output file |
| 281 | +# ~~~~~~~~~~~~~~~~~~~~ |
| 282 | +# Download output file from Docker image for the server to |
| 283 | +# your local ``<working directory>/output/`` location. |
| 284 | + |
| 285 | +serveroutfile = '/'.join((serverpath,"model.k")) |
| 286 | +downloadpath = os.path.join(os.getcwd(), "output") |
| 287 | +if not os.path.exists(downloadpath): |
| 288 | + os.makedirs(downloadpath) |
| 289 | +downloadfile = os.path.join(downloadpath,"model.k") |
| 290 | +solution.download(serveroutfile,downloadfile) |
0 commit comments