Quickstart

Examples

You can find an examples of how to use the package under peripy/examples/.

There are two examples that will output mesh files that can be viewed in Paraview.

Example 1

Run the first example by typing python peripy/examples/example1/example.py

Example 1 is a simple, 2D peridynamics simulation example. This example is a 1.0m x 1.0m 2D plate with a central pre-crack subjected to uniform velocity displacements on the left-hand side and right-hand side of 2.5x10^-6 metres per time-step. The --opencl argument toggles between OpenCL and cython implementations. The --profile argument generates profiling information for the example.

Example 2

Run the second example by typing python peripy/examples/example2/example.py

Example 2 is a simple, 3D peridynamics simulation example. This example is a 1.65m x 0.25m x 0.6m plain concrete canteliver beam with no pre-crack subjected to force controlled loading on the right-hand side of the beam which linearly increases up to 45kN. In this example, the first time the volume, family and connectivity of the model are calculated, they are also stored in file ‘1650beam13539_model.h5’. In subsequent simulations, the arrays are loaded from this h5 file instead of being calculated again, therefore reducing the overhead of initiating the model. The --profile argument generates profiling information for the example

The Model class

The peripy.model.Model class allows users to define a bond-based peridynamics model for composite materials with non-linear micromodulus functions, stiffness correction factors and boundary conditions. The model is defined by parameters and a set of initial conditions (coordinates, connectivity and optionally bond_types and stiffness_corrections). For this an peripy.integrators.Integrator is required, and optionally functions implementing the boundarys.

The Integrator class

The peripy.integrators.Integrator is the explicit time integration method, see peripy.integrators for options. Any integrator with the suffix ‘CL’ uses OpenCL kernels to calculate the bond force and displacement update, resulting in orders of magnitude faster simulation time when compared to using the cython implementation, peripy.integrators.Euler. OpenCL is ‘heterogeneous’ which means the ‘CL’ integrator classes will work on a CPU device as well as a GPU device. The preferable (faster) CL device will be chosen automatically.

>>> from peridynamics import Model
>>> from  peripy.integrators import EulerCL
>>>
>>> def is_displacement_boundary(x):
>>>     # Node does not live on a boundary
>>>     bnd = [None, None, None]
>>>     # Node does live on a boundary
>>>     if x[0] < 1.5 * 0.1:
>>>         # These displacement boundary conditions
>>>         # are applied in the negative x direction
>>>         bnd[0] = -1
>>>     elif x[0] > 1.0 - 1.5 * 0.1:
>>>         # These displacement boundary conditions
>>>         # are applied in the positive x direction
>>>         bnd[0] = 1
>>>     return bnd
>>>
>>> # for the cython implementation, use euler = Euler(dt)
>>> euler = EulerCL(dt=1e-3)
>>>
>>> model = Model(
>>>     mesh_file,
>>>     integrator=euler,
>>>     horizon=0.1,
>>>     critical_stretch=0.005,
>>>     bond_stiffness=18.00 * 0.05 / (np.pi * 0.1**4),
>>>     is_displacement_boundary=is_displacement_boundary,
>>>     )

Defining a crack

To define a crack in the inital configuration, you may supply a list of pairs of nodes between which the crack is.

>>> initial_crack = [(1,2), (5,7), (3,9)]
>>> model = Model(
>>>     mesh_file,
>>>     integrator=euler,
>>>     horizon=0.1,
>>>     critical_stretch=0.005,
>>>     bond_stiffness=18.00 * 0.05 / (np.pi * 0.1**4),
>>>     is_displacement_boundary=is_displacement_boundary,
>>>     initial_crack=initial_crack
>>>     )

If it is more convenient to define the crack as a function you may also pass a function to the constructor which takes the array of coordinates as its only argument and returns a list of tuples as described above. The peripy.model.initial_crack_helper() decorator has been provided to easily create a function of the correct form from one which tests a single pair of node coordinates and returns True or False.

>>> from peridynamics import initial_crack_helper
>>>
>>> @initial_crack_helper
>>> def initial_crack(x, y):
>>>     ...
>>>     if crack:
>>>         return True
>>>     else:
>>>         return False
>>>
>>> model = Model(
>>>     mesh_file,
>>>     integrator=euler,
>>>     horizon=0.1,
>>>     critical_stretch=0.005,
>>>     bond_stiffness=18.00 * 0.05 / (np.pi * 0.1**4),
>>>     is_displacement_boundary=is_displacement_boundary,
>>>     initial_crack=initial_crack
>>>     )

Conducting a simulation

The peripy.model.Model.simulate() method can be used to conduct a peridynamics simulation. Here it is possible to define the boundary condition magnitude throughout the simulation.

>>> model = Model(...)
>>>
>>> # Number of time-steps
>>> steps = 1000
>>>
>>> # Boundary condition magnitude throughout the simulation
>>> displacement_bc_array = np.linspace(2.5e-6, 2.5e-3, steps)
>>>
>>> (u,
>>>  ud,
>>>  udd,
>>>  force,
>>>  body_force,
>>>  damage,
>>>  nlist,
>>>  n_neigh) = model.simulate(
>>>     steps=steps,
>>>     displacement_bc_magnitudes=displacement_bc_array,
>>>     write=100
>>>     )

Conducting a simulation with initial conditions

It is possible to define initial conditions such as the displacement vector u, the velocity vector ud and the connectivity which is a tuple, (nlist, n_neigh). In this example the first 1000 steps have been simulated, generating the initial conditions for the next 1000 steps. The first step has been set to 1000 in the second simulation.

>>> model = Model(...)
>>>
>>> # Number of time-steps
>>> steps = 1000
>>>
>>> # Boundary condition magnitude throughout the simulation
>>> displacement_bc_array = np.linspace(2.5e-6, 2.5e-3, steps)
>>>
>>>  (u,
>>>  ud,
>>>  udd,
>>>  force,
>>>  body_force,
>>>  damage,
>>>  nlist,
>>>  n_neigh) = model.simulate(
>>>      ...displacement_bc_magnitudes=displacement_bc_array,
>>>      ...)
>>>
>>> # Boundary condition magnitude throughout the simulation
>>> displacement_bc_array = np.linspace(2.5025e-3, 5.0e-3, steps)
>>>
>>> u, *_ = model.simulate(
>>>     u=u,
>>>     ud=ud,
>>>     connectivity=(nlist, n_neigh),
>>>     steps=steps,
>>>     first_step=1000,
>>>     displacement_bc_magnitudes=displacement_bc_array,
>>>     write=100
>>>     )