Buckling of beer can example#

This example is inspired by the “Buckling of Beer Can” example on the LS-DYNA Knowledge Base site. It shows how to use PyDyna to create a keyword file for LS-DYNA and then solve it from Python.

Perform required imports#

Import required packages, including those for the keywords, deck, and solver.

import os
import shutil

# subprocess is used to run LS-DYNA commands, excluding bandit warning
import subprocess  # nosec: B404
import tempfile

import numpy as np
import pandas as pd

from ansys.dyna.core import Deck, keywords as kwd
from ansys.dyna.core.pre.examples.download_utilities import EXAMPLES_PATH, DownloadManager
from ansys.dyna.core.run import MemoryUnit, MpiOption, run_dyna

rundir = tempfile.TemporaryDirectory()
mesh_file_name = "mesh.k"
mesh_file = DownloadManager().download_file(
    mesh_file_name, "ls-dyna", "Buckling_Beer_Can", destination=os.path.join(EXAMPLES_PATH, "Buckling_Beer_Can")
)

dynafile = "beer_can.k"

Create a deck and keywords#

Create a deck, which is the container for all the keywords. Then, create and append individual keywords to the deck.

def write_deck(filepath):
    deck = Deck()

    # Append control keywords
    contact_auto = kwd.ContactAutomaticSingleSurfaceMortar(cid=1)
    contact_auto.options["ID"].active = True
    contact_auto.heading = "Single-Surface Mortar Contact (The New Explicit/Implicit Standard)"
    deck.extend(
        [
            contact_auto,
            kwd.ControlAccuracy(iacc=1),
            kwd.ControlImplicitAuto(iauto=1, dtmax=0.01),
            kwd.ControlImplicitDynamics(imass=1, gamma=0.6, beta=0.38),
            kwd.ControlImplicitGeneral(imflag=1, dt0=0.01),
            kwd.ControlImplicitSolution(nlprint=2),
            kwd.ControlShell(esort=2, theory=-16, intgrd=1, nfail4=1, irquad=0),
            kwd.ControlTermination(endtim=1.0),
        ]
    )

    # Append database keywords
    deck.extend(
        [
            kwd.DatabaseGlstat(dt=1.0e-4, binary=3, ioopt=0),
            kwd.DatabaseSpcforc(dt=1e-4, binary=3, ioopt=0),
            kwd.DatabaseBinaryD3Plot(dt=1.0e-4),
            kwd.DatabaseExtentBinary(maxint=-3, nintsld=1),
        ]
    )

    # Part keywords
    can_part = kwd.Part(heading="Beer Can", pid=1, secid=1, mid=1, eosid=0)
    floor_part = kwd.Part(heading="Floor", pid=2, secid=2, mid=1)

    # Material keywords
    mat_elastic = kwd.MatElastic(mid=1, ro=2.59e-4, e=1.0e7, pr=0.33, title="Aluminum")
    mat_elastic.options["TITLE"].active = True

    # Section keywords
    can_shell = kwd.SectionShell(secid=1, elform=-16, shrf=0.8333, nip=3, t1=0.002, propt=0.0, title="Beer Can")
    can_shell.options["TITLE"].active = True

    floor_shell = kwd.SectionShell(secid=2, elform=-16, shrf=0.833, t1=0.01, propt=0.0)
    floor_shell.options["TITLE"].active = True
    floor_shell.title = "Floor - Just for Contact (Rigid Wall Would Have Worked Also)"

    deck.extend(
        [
            can_part,
            can_shell,
            floor_part,
            floor_shell,
            mat_elastic,
        ]
    )

    # Load curve
    load_curve = kwd.DefineCurve(lcid=1, curves=pd.DataFrame({"a1": [0.00, 1.00], "o1": [0.0, 1.000]}))
    load_curve.options["TITLE"].active = True
    load_curve.title = "Load vs. Time"
    deck.append(load_curve)

    # Define boundary conditions
    load_nodes = [
        50,
        621,
        670,
        671,
        672,
        673,
        674,
        675,
        676,
        677,
        678,
        679,
        680,
        681,
        682,
        683,
        684,
        685,
        686,
        687,
        31,
        32,
        33,
        34,
        35,
        36,
        37,
        38,
        39,
        40,
        41,
        42,
        43,
        44,
        45,
        46,
        47,
        48,
        49,
        1229,
        1230,
        1231,
        1232,
        1233,
        1234,
        1235,
        1236,
        1237,
        1238,
        1239,
        1240,
        1241,
        1242,
        1243,
        1244,
        1245,
        1246,
        1247,
        1799,
        1800,
        1801,
        1802,
        1803,
        1804,
        1805,
        1806,
        1807,
        1808,
        1809,
        1810,
        1811,
        1812,
        1813,
        1814,
        1815,
        1816,
    ]

    count = len(load_nodes)
    zeros = np.zeros(count)

    load_node_point = kwd.LoadNodePoint(
        nodes=pd.DataFrame(
            {
                "nid": load_nodes,
                "dof": np.full((count), 3),
                "lcid": np.full((count), 1),
                "sf": np.full((count), -13.1579),
                "cid": zeros,
                "m1": zeros,
                "m2": zeros,
                "m3": zeros,
            }
        )
    )

    deck.append(load_node_point)

    nid = [
        1,
        31,
        32,
        33,
        34,
        35,
        36,
        37,
        38,
        39,
        40,
        41,
        42,
        43,
        44,
        45,
        46,
        47,
        48,
        49,
        50,
        80,
        81,
        82,
        83,
        84,
        85,
        86,
        87,
        88,
        89,
        90,
        91,
        92,
        93,
        94,
        95,
        96,
        97,
        98,
        621,
        651,
        652,
        653,
        654,
        655,
        656,
        657,
        658,
        659,
        660,
        661,
        662,
        663,
        664,
        665,
        666,
        667,
        668,
        669,
        670,
        671,
        672,
        673,
        674,
        675,
        676,
        677,
        678,
        679,
        680,
        681,
        682,
        683,
        684,
        685,
        686,
        687,
        1210,
        1211,
        1212,
        1213,
        1214,
        1215,
        1216,
        1217,
        1218,
        1219,
        1220,
        1221,
        1222,
        1223,
        1224,
        1225,
        1226,
        1227,
        1228,
        1229,
        1230,
        1231,
        1232,
        1233,
        1234,
        1235,
        1236,
        1237,
        1238,
        1239,
        1240,
        1241,
        1242,
        1243,
        1244,
        1245,
        1246,
        1247,
        1799,
        1800,
        1801,
        1802,
        1803,
        1804,
        1805,
        1806,
        1807,
        1808,
        1809,
        1810,
        1811,
        1812,
        1813,
        1814,
        1815,
        1816,
        1817,
        1818,
        1819,
        1820,
        1821,
        1822,
        1823,
        1824,
        1825,
        1826,
        1827,
        1828,
        1829,
        1830,
        1831,
        1832,
        1833,
        1834,
    ]

    count = len(nid)
    zeros = np.zeros(count)
    ones = np.full((count), 1)

    dofz = [
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        0,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        0,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
        1,
    ]

    boundary_spc_node = kwd.BoundarySpcNode(
        nodes=pd.DataFrame(
            {
                "nid": nid,
                "cid": zeros,
                "dofx": ones,
                "dofy": ones,
                "dofz": dofz,
                "dofrx": ones,
                "dofry": ones,
                "dofrz": ones,
            }
        )
    )

    deck.append(boundary_spc_node)

    # Define nodes and elements
    deck.append(kwd.Include(filename=mesh_file_name))

    deck.export_file(filepath)
    return deck


def run_post(filepath):
    pass


shutil.copy(mesh_file, os.path.join(rundir.name, mesh_file_name))
deck = write_deck(os.path.join(rundir.name, dynafile))

View the model#

You can use the PyVista plot method in the deck class to view the model.

deck.plot(cwd=rundir.name)
plot beercan

Run the Dyna solver#

try:
    run_dyna(
        dynafile,
        working_directory=rundir.name,
        ncpu=2,
        mpi_option=MpiOption.MPP_INTEL_MPI,
        memory=20,
        memory_unit=MemoryUnit.MB,
    )
except subprocess.CalledProcessError:
    # this example doesn't run to completion because it is a highly nonlinear buckling
    pass

run_post(rundir.name)
 License option : check ansys licenses only


 ***************************************************************
 *            ANSYS LEGAL NOTICES                              *
 ***************************************************************
 *                                                             *
 * Copyright 1971-2023 ANSYS, Inc.  All rights reserved.       *
 * Unauthorized use, distribution or duplication is            *
 * prohibited.                                                 *
 *                                                             *
 * Ansys is a registered trademark of ANSYS, Inc. or its       *
 * subsidiaries in the United States or other countries.       *
 * See the ANSYS, Inc. online documentation or the ANSYS, Inc. *
 * documentation CD or online help for the complete Legal      *
 * Notice.                                                     *
 *                                                             *
 ***************************************************************
 *                                                             *
 * THIS ANSYS SOFTWARE PRODUCT AND PROGRAM DOCUMENTATION       *
 * INCLUDE TRADE SECRETS AND CONFIDENTIAL AND PROPRIETARY      *
 * PRODUCTS OF ANSYS, INC., ITS SUBSIDIARIES, OR LICENSORS.    *
 * The software products and documentation are furnished by    *
 * ANSYS, Inc. or its subsidiaries under a software license    *
 * agreement that contains provisions concerning               *
 * non-disclosure, copying, length and nature of use,          *
 * compliance with exporting laws, warranties, disclaimers,    *
 * limitations of liability, and remedies, and other           *
 * provisions.  The software products and documentation may be *
 * used, disclosed, transferred, or copied only in accordance  *
 * with the terms and conditions of that software license      *
 * agreement.                                                  *
 *                                                             *
 * ANSYS, Inc. is a UL registered                              *
 * ISO 9001:2015 company.                                      *
 *                                                             *
 ***************************************************************
 *                                                             *
 * This product is subject to U.S. laws governing export and   *
 * re-export.                                                  *
 *                                                             *
 * For U.S. Government users, except as specifically granted   *
 * by the ANSYS, Inc. software license agreement, the use,     *
 * duplication, or disclosure by the United States Government  *
 * is subject to restrictions stated in the ANSYS, Inc.        *
 * software license agreement and FAR 12.212 (for non-DOD      *
 * licenses).                                                  *
 *                                                             *
 ***************************************************************

      Date: 01/27/2026      Time: 14:40:25
      ___________________________________________________
     |                                                   |
     |  LS-DYNA, A Program for Nonlinear Dynamic         |
     |  Analysis of Structures in Three Dimensions       |
     |  Date    : 10/16/2023    Time: 19:29:09           |
     |  Version : mpp d R14                              |
     |  Revision: R14.1-205-geb5348f751                  |
     |  AnLicVer: 2024 R1 (20231025+2752148)             |
     |                                                   |
     |  Features enabled in this version:                |
     |    Distributed Memory Parallel                    |
     |    CESE CHEMISTRY EM ICFD STOCHASTIC_PARTICLES    |
     |    FFTW (multi-dimensional FFTW Library)          |
     |    ANSYSLIC enabled                               |
     |                                                   |
     |  Platform   : Intel-MPI 2018 Xeon64               |
     |  OS Level   : Linux CentOS 7.9 uum                |
     |  Compiler   : Intel Fortran Compiler 19.0 SSE2    |
     |  Hostname   : 6c9a4250757f                        |
     |  Precision  : Double precision (I8R8)             |
     |                                                   |
     |  Unauthorized use infringes Ansys Inc. copyrights |
     |___________________________________________________|

[license/info] Successfully checked out 2 of "dyna_solver_core".
[license/info] --> Checkout ID: 6c9a4250757f-root-23-000004 (days left: 357)
[license/info] --> Customer ID: 0
[license/info] Successfully started "LSDYNA (Core-based License)".

 Executing with ANSYS license

 Command line options: i=beer_can.k
                       memory=20m

 Input file: beer_can.k

 The native file format       : 64-bit small endian
 Memory size from command line:    20000000,            0
 Memory size from command line:    20000000,     20000000

 Memory for the head node
 Memory installed (MB)        :        64301
 Memory available (MB)        :        61634

 on UNIX computers note the following change:

 ctrl-c interrupts ls-dyna and prompts for a sense  switch.
 type the desired sense switch: sw1., sw2., etc. to continue
 the execution.  ls-dyna will respond as explained in the users manual

    type                      response
   -----   ------------------------------------------------------------
   quit    ls-dyna terminates.
   stop    ls-dyna terminates.
   sw1.    a restart file is written and ls-dyna terminates.
   sw2.    ls-dyna responds with time and cycle numbers.
   sw3.    a restart file is written and ls-dyna continues calculations.
   sw4.    a plot state is written and ls-dyna continues calculations.
   sw5.    ls-dyna enters interactive graphics phase.
   swa.    ls-dyna flushes all output i/o buffers.
   swb.    a dynain is written and ls-dyna continues calculations.
   swc.    a restart and dynain are written and ls-dyna continues calculations.
   swd.    a restart and dynain are written and ls-dyna terminates.
   swe.    stop dynamic relaxation just as though convergence
   endtime=time change the termination time
   lpri    toggle implicit lin. alg. solver output on/off.
   nlpr    toggle implicit nonlinear solver output on/off.
   iter    toggle implicit output to d3iter database on/off.
   prof    output timing data to prof.out and continue.
   conv    force implicit nonlinear convergence for current time step.
   ttrm    terminate implicit time step, reduce time step, retry time step.
   rtrm    terminate implicit at end of current time step.


 ********  notice  ********  notice  ********  notice  ********
 *                                                            *
 * This is the LS-DYNA Finite Element code.                   *
 *                                                            *
 * Neither LST nor the authors assume any responsibility for  *
 * the validity, accuracy, or applicability of any results    *
 * obtained from this system. Users must verify their own     *
 * results.                                                   *
 *                                                            *
 * LST endeavors to make the LS-DYNA code as complete,        *
 * accurate and easy to use as possible.                      *
 * Suggestions and comments are welcomed.  Please report any  *
 * errors encountered in either the documentation or results  *
 * immediately to LST through your site focus.                *
 *                                                            *
 * Copyright (C) 1990-2021                                    *
 * by Livermore Software Technology, LLC                      *
 * All rights reserved                                        *
 *                                                            *
 ********  notice  ********  notice  ********  notice  ********

 Beginning of keyword reader                                   01/27/26 14:40:35

                                                               01/27/26 14:40:35
 Open include file: mesh.k


 Memory required to process keyword     :     285092
 Additional dynamic memory required     :    2394491


 MPP execution with       2 procs

 Initial reading of file                                       01/27/26 14:40:35

 Implicit dynamics is now active

 Performing Decomposition -- Phase 1                           01/27/26 14:40:35

 Performing Recursive Coordinate Bisection (RCB)

 Memory required for decomposition      :      53592
 Additional dynamic memory required     :    2559869


 Performing Decomposition -- Phase 2                           01/27/26 14:40:35
 Performing Decomposition -- Phase 3                           01/27/26 14:40:35

 Implicit dynamics is now active

 input of data is completed

 initial kinetic energy = 0.00000000E+00

 The LS-DYNA time step size should not exceed     1.656E-07
 to avoid contact instabilities.  If the step size is
 bigger then scale the penalty of the offending surface.

 Implicit dynamics is now active

 termination time                  = 1.000E+00

 The following binary output files are being created,
 and contain data equivalent to the indicated ascii output files
   binout0000: (on processor       0)
    glstat
    spcforc

 Memory required to begin solution (memory=    320K)
          Minimum    281K on processor     1
          Maximum    320K on processor     0
          Average    301K

 Matrix Assembly dynamically allocated memory
          Maximum    160K

 Additional dynamically allocated memory
          Minimum   4056K on processor     1
          Maximum   4374K on processor     0
          Average   4215K

 Total allocated memory
          Minimum   4496K on processor     1
          Maximum   4854K on processor     0
          Average   4675K

 initialization completed

 calculation with mass scaling for minimum dt
    added mass   =   0.0000E+00
    physical mass=   6.5553E-05
    ratio        =   0.0000E+00
       1 t 0.0000E+00 dt 1.00E-02 flush i/o buffers            01/27/26 14:40:35
       1 t 0.0000E+00 dt 1.00E-02 write d3plot file            01/27/26 14:40:35

 Implicit dynamics is now active

 BEGIN implicit dynamics step      1 t= 1.0000E-02             01/27/26 14:40:35
 ============================================================
                time =  1.00000E-02
   current step size =  1.00000E-02


     ================================================
     ==            IMPLICIT USAGE ALERT            ==
     ================================================
     == Memory Management for Implicit has changed ==
     == after R10.  Please use:                    ==
     ==       memory=     1M memory2=     1M       ==
     ================================================


===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   RANK 0 PID 19 RUNNING AT 6c9a4250757f
=   KILLED BY SIGNAL: 7 (Bus error)
===================================================================================

===================================================================================
=   BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
=   RANK 1 PID 20 RUNNING AT 6c9a4250757f
=   KILLED BY SIGNAL: 9 (Killed)
===================================================================================

Total running time of the script: (0 minutes 21.696 seconds)

Gallery generated by Sphinx-Gallery