A full PyMAPDL example#

Let’s see a full PyMAPDL example!

We will reuse some of the code we used to plot the section of a NACA airfoil. With this section we will create a simple and straight wing where we will apply some constrains and loads.

The idea is you can have an idea on how to use PyMAPDL together with other Python libraries for your own purposes (TFG? TFM? PhD?)

Setting up the environment#

First, let’s do some imports

from matplotlib import pyplot as plt
import numpy as np

from ansys.mapdl.core import launch_mapdl

and let’s launch PyMAPDL.

mapdl = launch_mapdl()
mapdl.prep7()
*** MAPDL - ENGINEERING ANALYSIS SYSTEM  RELEASE                  22.2     ***
 Ansys Mechanical Enterprise
 00000000  VERSION=LINUX x64     10:48:52  OCT 03, 2022 CP=      4.017





          ***** MAPDL ANALYSIS DEFINITION (PREP7) *****

Geometry definition#

In the previous part of the talk we showed how to use some Python functions to plot a NACA airfoil. Here we will reuse those functions to generate the same section inside PyMAPDL.

# Helper functions
def camber_line(x, m, p, c):
    return np.where(
        (x >= 0) & (x <= (c * p)),
        m * (x / np.power(p, 2)) * (2.0 * p - (x / c)),
        m * ((c - x) / np.power(1 - p, 2)) * (1.0 + (x / c) - 2.0 * p),
    )


def dyc_over_dx(x, m, p, c):
    return np.where(
        (x >= 0) & (x <= (c * p)),
        ((2.0 * m) / np.power(p, 2)) * (p - x / c),
        ((2.0 * m) / np.power(1 - p, 2)) * (p - x / c),
    )


def thickness(x, t, c):
    term1 = 0.2969 * (np.sqrt(x / c))
    term2 = -0.1260 * (x / c)
    term3 = -0.3516 * np.power(x / c, 2)
    term4 = 0.2843 * np.power(x / c, 3)
    term5 = -0.1015 * np.power(x / c, 4)
    return 5 * t * c * (term1 + term2 + term3 + term4 + term5)


def naca4(x, m, p, t, c=1):
    dyc_dx = dyc_over_dx(x, m, p, c)
    th = np.arctan(dyc_dx)
    yt = thickness(x, t, c)
    yc = camber_line(x, m, p, c)

    # We are tuning a bit the output of this function to facilitate later processing.
    x = x - yt * np.sin(th)
    x = np.concatenate((x, x + yt * np.sin(th)), axis=0)

    y = yc + yt * np.cos(th)
    y = np.concatenate((y, yc - yt * np.cos(th)), axis=0)
    return x, y

NACA Parameters for naca2412

m = 0.02
p = 0.4
t = 0.12
c = 1.0

Generating NACA points for the section.

npoints = 50  # Increase this number to increase smoothness.
x_ = np.linspace(0, 1, npoints)
x, y = naca4(x_, m, p, t, c)

Generating keypoints#

mapdl.clear()
mapdl.prep7()

for each_x, each_y in zip(x, y):
    mapdl.k("", each_x, each_y)

Checking results

pl = mapdl.kplot(return_plotter=True)
pl.view_xy()
pl.show()
02 example

Generate lines from the points#

Because the helper functions give us two points per x-coordinate, we need to join those points in two times:

half = len(mapdl.geometry.knum) // 2

# Upper half points
for kp in mapdl.geometry.knum[: half - 1]:
    mapdl.l(kp, kp + 1)

# Lower half points
for kp in mapdl.geometry.knum[half + 1 : -1]:
    mapdl.l(kp, kp + 1)

Closing the section

mapdl.l(1, half + 2)
mapdl.l(half, mapdl.geometry.knum[-1])

mapdl.nummrg("all", 0.05)  # Remove duplicated entities if any
MERGE COINCIDENT NODES WITHIN TOLERANCE OF  0.50000E-01

 MERGE IDENTICAL MATERIALS WITHIN TOLERANCE OF  0.50000E-01

 MERGE IDENTICAL ELEMENT TYPES

 MERGE IDENTICAL REAL CONSTANT SETS WITHIN TOLERANCE OF  0.50000E-01

 MERGE IDENTICAL SECTION ID SET WITHIN TOLERANCE OF  0.50000E-01

 MERGE IDENTICAL ELEMENTS

 MERGE IDENTICAL COUPLED DOF SETS

 MERGE IDENTICAL CONSTRAINT EQUATIONS WITHIN TOLERANCE OF 0.50000E-01

 MERGE COINCIDENT KEYPOINTS WITHIN TOLERANCE OF  0.50000E-01

 *** WARNING ***                         CP =       4.177   TIME= 10:48:52
 Keypoints 1 and 2 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 3.146864964E-02) exceeds the
  tolerance ( 3.146864964E-07).

 *** WARNING ***                         CP =       4.177   TIME= 10:48:52
 Keypoints 1 and 3 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 5.248710857E-02) exceeds the
  tolerance ( 2.241384605E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 4 and 5 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.121503862E-02) exceeds the
  tolerance ( 2.121503862E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 4 and 6 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.223893985E-02) exceeds the
  tolerance ( 2.103681832E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 54 and 55 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.063299177E-02) exceeds the
  tolerance ( 2.063299177E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 54 and 56 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.115008769E-02) exceeds the
  tolerance ( 2.05256279E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 7 and 8 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.086321658E-02) exceeds the
  tolerance ( 2.086321658E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 7 and 9 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.167705446E-02) exceeds the
  tolerance ( 2.081774221E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 57 and 58 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.043941462E-02) exceeds the
  tolerance ( 2.043941462E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 57 and 59 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.086043642E-02) exceeds the
  tolerance ( 2.042261826E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 10 and 11 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.076424706E-02) exceeds the
  tolerance ( 2.076424706E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 10 and 12 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.151084944E-02) exceeds the
  tolerance ( 2.074861222E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 60 and 61 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.04095237E-02) exceeds the
  tolerance ( 2.04095237E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 60 and 62 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.081723023E-02) exceeds the
  tolerance ( 2.040858385E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 13 and 14 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.072979806E-02) exceeds the
  tolerance ( 2.072979806E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 13 and 15 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.145299864E-02) exceeds the
  tolerance ( 2.072447958E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 63 and 64 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.040996261E-02) exceeds the
  tolerance ( 2.041185603E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 63 and 65 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.082165033E-02) exceeds the
  tolerance ( 2.041394947E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 16 and 17 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 2.071880202E-02) exceeds the
  tolerance ( 2.071880202E-07).

 *** WARNING ***                         CP =       4.178   TIME= 10:48:52
 Keypoints 16 and 18 cannot be merged because:
  (1) One or both of them belong to lines.
  (2) The distance between them ( 4.14355417E-02) exceeds the
  tolerance ( 2.071764713E-07).

 ************************************************************************
 The number of ERROR and WARNING messages exceeds 20.
 Additional messages suppressed.  See ( /file.err ) for suppressed
 messages.
 ************************************************************************
 KEYPOINT      1 USED FOR KEYPOINT(S)      51

Let’s check the results

pl = mapdl.lplot(return_plotter=True)
pl.view_xy()
pl.show()
02 example

Create section area#

Let’s create an area from those lines:

mapdl.lsel("all")
mapdl.al("all")
1

Create volume from extruding the area#

We are going to use the command mapdl.vdrag to create a volume by dragging an area along a line.

help(mapdl.vdrag)
Help on method vdrag in module ansys.mapdl.core._commands.preproc.volumes:

vdrag(na1='', na2='', na3='', na4='', na5='', na6='', nlp1='', nlp2='', nlp3='', nlp4='', nlp5='', nlp6='', **kwargs) -> str method of ansys.mapdl.core.mapdl_grpc.MapdlGrpc instance
    Generate volumes by dragging an area pattern along a path.

    APDL Command: VDRAG

    Parameters
    ----------
    na1, na2, na3, . . . , na6
        List of areas in the pattern to be dragged (6 maximum if
        using keyboard entry).  If NA1 = ALL, all selected areas
        will be swept along the path.  A component name may also
        be substituted for NA1.

    nlp1, nlp2, nlp3, . . . , nlp6
        List of lines defining the path along which the pattern is
        to be dragged (6 maximum if using keyboard entry).  Must
        be a continuous set of lines.  To be continuous, adjacent
        lines must share the connecting keypoint (the end keypoint
        of one line must also be first keypoint of the next line).

    Returns
    -------
    str
        MAPDL command output.

    Notes
    -----
    Generates volumes (and their corresponding keypoints, lines,
    and areas) by sweeping a given area pattern along a
    characteristic drag path.  If the drag path consists of
    multiple lines, the drag direction is determined by the
    sequence in which the path lines are input (NLP1, NLP2, etc.).
    If the drag path is a single line (NLP1), the drag direction
    is from the keypoint on the drag line that is closest to the
    first keypoint of the given area pattern to the other end of
    the drag line.

    The magnitude of the vector between the keypoints of the given
    pattern and the first path keypoint remains constant for all
    generated keypoint patterns and the path keypoints.  The
    direction of the vector relative to the path slope also
    remains constant so that patterns may be swept around curves.
    Lines are generated with the same shapes as the given pattern
    and the path lines.

    Keypoint, line, area, and volume numbers are automatically
    assigned (beginning with the lowest available values
    [NUMSTR]).  Adjacent lines use a common keypoint, adjacent
    areas use a common line, and adjacent volumes use a common
    area.  For best results, the entities to be dragged should be
    orthogonal to the start of the drag path.  Drag operations
    that produce an error message may create some of the desired
    entities prior to terminating.

    If element attributes have been associated with the input area
    via the AATT command, the opposite area generated by the VDRAG
    operation will also have those attributes (i.e., the element
    attributes from the input area are copied to the opposite
    area).  Note that only the area opposite the input area will
    have the same attributes as the input area; the areas adjacent
    to the input area will not.

    If the input areas are meshed or belong to a meshed volume,
    the area(s) can be extruded to a 3-D mesh.  Note that the NDIV
    argument of the ESIZE command should be set before extruding
    the meshed areas.  Alternatively, mesh divisions can be
    specified directly on the drag line(s) (LESIZE).  See the
    Modeling and Meshing Guide for more information.

    You can use the VDRAG command to generate 3-D interface
    element meshes for elements INTER194 and INTER195. When
    generating interface element meshes using VDRAG, you must
    specify the line divisions to generate one interface element
    directly on the drag line using the LESIZE command.  The
    source area to be extruded becomes the bottom surface of the
    interface element. Interface elements must be extruded in what
    will become the element's local x direction, that is, bottom
    to top.

    Examples
    --------
    Create a square with a hole in it and drag it along an arc.

    >>> anum0 = mapdl.blc4(0, 0, 1, 1)
    >>> anum1 = mapdl.blc4(0.25, 0.25, 0.5, 0.5)
    >>> aout = mapdl.asba(anum0, anum1)
    >>> k0 = mapdl.k("", 0, 0, 0)
    >>> k1 = mapdl.k("", 1, 0, 1)
    >>> k2 = mapdl.k("", 1, 0, 0)
    >>> l0 = mapdl.larc(k0, k1, k2, 2)
    >>> output = mapdl.vdrag(aout, nlp1=l0)
    >>> print(output)
    DRAG AREAS
      3,
    ALONG LINES
      9

First, let’s define the length we are going to use to drag the area along.

lenght_wing = 1.5  # [m] MAPDL is unit agnostic.

k0 = mapdl.k("", 0, 0, 0)
kz = mapdl.k("", 0, 0, lenght_wing)

ldrag = mapdl.l(k0, kz)

Create the volume

vol0 = mapdl.vdrag("all", nlp1=ldrag)

Let’s check the results

mapdl.vplot()
02 example

Finite element definition#

As you all know, finite element approaches split the domains into “finite elements” where you solve your equations in their quadrature points. Therefore, we need to define how that domain split is going to be performed, aka “choosing element type”.

# Defining element type
mapdl.et(1, "SOLID187")
1

Here we could also define other element options using the mapdl.keyopt command.

Material definition#

Let’s define the material our wing is made off. We are going to choose steel in its simplest configuration (elastic linear material). But you could define other parameters (plasticity, fatige, viscoelasticity, etc).

# Define a material (nominal steel in SI)
mapdl.mp("EX", 1, 210e9)  # Elastic moduli in Pa (kg/(m*s**2))
mapdl.mp("DENS", 1, 7800)  # Density in kg/m3
mapdl.mp("NUXY", 1, 0.3)  # Poisson's Ratio
MATERIAL          1     NUXY =  0.3000000

Mesh Generation#

Let’s finally split the domain:

maximum_element_size = 1 / 10
mapdl.esize(maximum_element_size)

mapdl.vmesh("all")  # Mesh
GENERATE NODES AND ELEMENTS   IN  ALL  SELECTED VOLUMES
  Sharp angle warning:
    triangle facet defined at line  199 forms an angle of 1.4 degrees
    with facet at line  197
  Sharp angle warning:
    triangle facet defined at line  199 forms an angle of 1.4 degrees
    with facet at line  197
  Sharp angle warning:
    triangle facet defined at line  199 forms an angle of 1.4 degrees
    with facet at line  197
  Sharp angle warning:
    triangle facet defined at line  201 forms an angle of 1.4 degrees
    with facet at line  197
  Sharp angle warning:
    triangle facet defined at line  201 forms an angle of 1.4 degrees
    with facet at line  199
  Sharp angle warning:
    triangle facet defined at area   51 forms an angle of 1.4 degrees
    with facet at area   50
  Sharp angle warning:
    triangle facet defined at area   51 forms an angle of 1.4 degrees
    with facet at area   50
  Sharp angle warning:
    triangle facet defined at area   51 forms an angle of 1.4 degrees
    with facet at area   50
  Sharp angle warning:
    triangle facet defined at area   51 forms an angle of 1.4 degrees
    with facet at area   50
  Sharp angle warning:
    triangle facet defined at line  201 forms an angle of 1.4 degrees
    with facet at line  199
  Sharp angle warning:
    triangle facets defined at line  199 form an angle of 1.4 degrees
   etc... (see error file)

 *** WARNING ***                         CP =       5.949   TIME= 10:48:56
 68 angles less than 2.5 degrees found in triangle facets of volume 1,
 with smallest angle = 1.4 degrees.  Poor element quality or mesh
 failure may result.  A smaller element size specification may give
 better results.

 NUMBER OF VOLUMES MESHED   =         1
 MAXIMUM NODE NUMBER        =     16044
 MAXIMUM ELEMENT NUMBER     =      8879

 ------------------------------------------------------------------------------
            <<<<<<          SHAPE TESTING SUMMARY           >>>>>>
            <<<<<<       FOR NEW OR MODIFIED ELEMENTS       >>>>>>
 ------------------------------------------------------------------------------
                    --------------------------------------
                    |  Element count      8879 SOLID187  |
                    --------------------------------------

  Test                Number tested  Warning count  Error count    Warn+Err %
  ----                -------------  -------------  -----------    ----------
  Aspect Ratio               8879             77             0         0.87 %
  Maximum Angle              8879             59             0         0.66 %
  Jacobian Ratio             8879              0             0         0.00 %

  Any                        8879            107             0         1.21 %
 ------------------------------------------------------------------------------

 *** WARNING ***                         CP =       6.167   TIME= 10:48:56
 Shape testing revealed that 107 of the 8879 new or modified elements
 violate shape warning limits.  To review test results, please see the
 output file or issue the CHECK command.

Let’s check the results:

mapdl.eplot()
02 example

Boundary Conditions Definition#

Let’s fix the nodes at the origin to not move.

mapdl.nsel("s", "loc", "z", 0)
mapdl.d("all", "all", 0)
SPECIFIED CONSTRAINT UX   FOR SELECTED NODES            1 TO       16044 BY           1
 REAL=  0.00000000       IMAG=  0.00000000
 ADDITIONAL DOFS=  UY    UZ

Wind Excitation#

Let’s apply an excitation to our wing. However, we don’t really know what wind speed to apply, so let’s pull some online data first.

We are going to retrieve some data from NASA regarding the wind speed at Ansys Madrid office in Paseo de la Castellana.

Madrid office

Paseo de la Castellana Ansys office (Madrid). Yes, we love coffee.#

From: https://power.larc.nasa.gov/data-access-viewer/

import json

import pandas as pd
import requests

latitude, longitude = (40.447488, -3.691763)
parameters = ["T2M_MAX", "T2M_MIN"]

base_url = r"https://power.larc.nasa.gov/api/temporal/daily/point?parameters={parameters}&community=RE&longitude={longitude}&latitude={latitude}&start=20200101&end=20210305&format=JSON"
api_request_url = base_url.format(
    longitude=longitude, latitude=latitude, parameters=",".join(parameters)
)  # Another way to format f-strings!

response = requests.get(url=api_request_url, verify=True, timeout=30.00)

content = json.loads(response.content.decode("utf-8"))
df = pd.DataFrame(content["properties"]["parameter"])

df.columns = ["MAX", "MIN"]  # renaming columns
df = df.set_index(
    pd.to_datetime(df.index, format="%Y%m%d")
)  # Formatting dataframe index as date.

Let’s see the data

MAX MIN
2020-01-01 11.52 0.32
2020-01-02 10.33 0.50
2020-01-03 8.28 0.21
2020-01-04 10.68 0.44
2020-01-05 11.88 -1.61


and describe it…

MAX MIN
count 430.000000 430.000000
mean 18.896744 7.028326
std 9.354319 6.669664
min -0.430000 -12.030000
25% 11.947500 2.302500
50% 16.345000 5.880000
75% 25.737500 11.770000
max 39.390000 22.990000


We see there are negative wind speed, probably because of the direction, since we are not interested in direction, only magnitude, let’s use the absolute value then.

df = df.abs()

Let’s plot it…

_ = df.plot(title="Wind speed per day")
Wind speed per day

As we can see, the most frequent maximum speeds are:

_ = df["MAX"].hist(bins=20)
02 example

As we can see, we could stablish there are two main peaks, one at 15 m/s and another at 33 m/s.

Let’s generate some random wind signal with those speeds. We are going to do a superposition of harmonics:

amplitude = [15, 33]
frequencies = (
    np.array([10, 16]) * 2 * np.pi
)  # Typical wind frequencies range between 2 and 20 Hz
phase = np.random.random(size=len(frequencies)) * 2 * np.pi


def wind_speed(t):
    sum_ = 0
    for each_amp, each_w, each_phase in zip(amplitude, frequencies, phase):
        sum_ = sum_ + each_amp * np.cos(each_w * t + each_phase)
    return sum_


t = np.arange(0, 1, 0.01)

plt.plot(t, wind_speed(t))
plt.show()
02 example

To apply these velocities, we are going instead to convert it to acceleration using the following equation:

\[a = \omega * v\]

where:

  • a is acceleration

  • w is frequency

  • v is velocity

def acceleration(t):
    sum_ = 0
    for each_amp, each_w, each_phase in zip(amplitude, frequencies, phase):
        sum_ = sum_ + each_amp * each_w * np.cos(each_w * t + each_phase)
    return sum_


plt.plot(t, acceleration(t))
plt.show()
02 example

Now let’s use that in our analysis We are going to apply a global acceleration using mapdl.acce.

help(mapdl.acel)
Help on method acel in module ansys.mapdl.core._commands.solution.inertia:

acel(acel_x='', acel_y='', acel_z='', **kwargs) method of ansys.mapdl.core.mapdl_grpc.MapdlGrpc instance
    Specifies the linear acceleration of the global Cartesian reference

    APDL Command: ACEL
    frame for the analysis.

    Parameters
    ----------
    acel_x, acel_y, acel_z
        Linear acceleration of the reference frame along global Cartesian
        X, Y, and Z axes, respectively.

    Notes
    -----
    In the absence of any other loads or supports, the acceleration of the
    structure in each of the global Cartesian (X, Y, and Z) axes would be
    equal in magnitude but opposite in sign to that applied in the ACEL
    command. Thus, to simulate gravity (by using inertial effects),
    accelerate the reference frame with an ACEL command in the direction
    opposite to gravity.

    You can define the acceleration for the following analyses types:

    Static (ANTYPE,STATIC)

    Harmonic (ANTYPE,HARMIC), full or mode-superposition method

    Transient (ANTYPE,TRANS)

    Substructure (ANTYPE,SUBSTR).

    For all transient dynamic (ANTYPE,TRANS) analyses, accelerations are
    combined with the element mass matrices to form a body force load
    vector term. The element mass matrix may be formed from a mass input
    constant or from a nonzero density (DENS) property, depending upon the
    element type.

    For analysis type ANTYPE,HARMIC, the acceleration is assumed to be the
    real component with a zero imaginary component.

    Units of acceleration and mass must be consistent to give a product of
    force units.

    The ACEL command supports tabular boundary conditions (%TABNAME_X%,
    %TABNAME_Y%, and %TABNAME_Z%) for ACEL_X, ACEL_Y, and ACEL_Z input
    values (``*DIM``) as a function of both time and frequency for full
    transient and harmonic analyses.

    Related commands for rotational effects are CMACEL, CGLOC, CGOMGA,
    DCGOMG, DOMEGA, OMEGA, CMOMEGA, and CMDOMEGA.

    See Analysis Tools in the Mechanical APDL Theory Reference for more
    information.

    This command is also valid in /PREP7.

    Examples
    --------
    Set global y-acceleration to 9.81

    >>> mapdl.acel(acel_y=9.81)

Model solution#

mapdl.slashsolu()
mapdl.allsel()  # making sure all nodes and elements are selected.
mapdl.antype("TRANS")
mapdl.nsubst(carry="ON")

accelerations = acceleration(t)

for each_time, each_acceleration in zip(t[1:], accelerations):
    mapdl.time(each_time)
    mapdl.acel(acel_y=each_acceleration)
    mapdl.solve()

Post-processing#

Let’s see what we got. Let’s print the displacements for the first step.

mapdl.post1()
mapdl.set(1, 1)
mapdl.post_processing.nodal_displacement("all")
array([[ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00,  0.00000000e+00],
       ...,
       [-2.25461341e-05,  4.01419365e-02,  4.04008850e-04],
       [-3.32841972e-05,  1.25655615e-02,  3.32471074e-04],
       [-4.27405267e-05,  1.06756207e-02,  3.81884332e-04]])

and let’s plot them

mapdl.post_processing.plot_nodal_displacement("y")
02 example

We can follow this approach to get the results at each step

For example let’s get the maximum principal stresses and where it happens:

i = 0
max_stress_per_step = []
elem_max_stress_per_step = []

for step in mapdl.post_processing.time_values:
    i += 1
    mapdl.set(i)
    stresses = mapdl.post_processing.element_stress("1")  # First principal stresses
    max_stress_per_step.append(stresses.max())
    elem_max_stress_per_step.append(stresses.argmax())

max_stress_per_step = np.array(max_stress_per_step)
elem_max_stress_per_step = np.array(elem_max_stress_per_step)

elem_ = mapdl.mesh.enum[elem_max_stress_per_step[max_stress_per_step.argmax()]]
time_ = mapdl.post_processing.time_values[max_stress_per_step.argmax()]

print(
    f"The maximum principal stress\n\tValue: {max_stress_per_step.max():0.2f} Pascals."
)
print(f"\tAt the element {elem_}.")
print(f"\tAt the time {time_}.")
The maximum principal stress
        Value: 3982711613.36 Pascals.
        At the element 5399.
        At the time 0.04.

Post-processing time dependent results#

Let’s now check the displacement across time for a node in the tip

We can get the nodes max and min coordenates as:

mapdl.post26()

nod_max = mapdl.mesh.nodes.max(axis=0)
nod_min = mapdl.mesh.nodes.min(axis=0)

coord_node = (nod_max[0] + nod_min[0]) / 2, (nod_max[1] + nod_min[1]) / 2, nod_max[2]

node = mapdl.queries.node(*coord_node)

Getting the displacement at the tip

item = "U"
comp = "Y"
nvar = 9

# node_uy = mapdl.get_nsol(node, item, comp)  # Available in 0.62.3
mapdl.nsol(nvar, node, item, comp)
mapdl.vget("temp_", nvar)

node_uy = mapdl.parameters["temp_"]
time = mapdl.post_processing.time_values

plt.plot(time, node_uy)
plt.title("Displacement across time at the tip")
plt.show()
Displacement across time at the tip

Closing session#

Thank you all for your time and attention!

mapdl.exit()

Total running time of the script: ( 1 minutes 53.689 seconds)

Gallery generated by Sphinx-Gallery