2D Uniaxial Tensile/compresion test

This notebook shows how to use the toolbox and the Argiope module to perform a parametric simulation of a cyclic uniaxial test.

%load_ext autoreload
%matplotlib nbagg
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload
import MechanicalTest.model_traction as model
import os, subprocess, time, local_settings, time
import matplotlib.pyplot as plt
import matplotlib as mpl
import argiope as ag
import numpy as np

#-------------------------------------------------------------------------------
# USEFUL FUNCTIONS
def create_dir(path):
  try:
    os.mkdir(path)
  except:
    pass
#-------------------------------------------------------------------------------

SETTINGS

GMSH_PATH = local_settings.GMSH_PATH
workdir   = "workdir/"
outputdir = "outputs/"
label   = "Trac"
template_dir = "TensileTest2D"
#-------------------------------------------------------------------------------

create_dir(workdir)
create_dir(workdir + outputdir)

Element type definition

def element_map(mesh):
    mesh.elements.loc[mesh.elements.type.argiope == "tri3", ("type", "solver", "")] = "CPE3"
    mesh.elements.loc[mesh.elements.type.argiope == "quad4", ("type", "solver", "")] = "CPE4R"
    return mesh

Material

def material_map(mesh):
    mesh.elements["materials"] = "SAMPLE_MAT"
    return mesh

materials = []
materials.append(ag.materials.Hollomon(label = "SAMPLE_MAT", strain_data_points = 100,
                                   young_modulus = 200e3,
                                   poisson_ratio = 0.3,
                                   hardening_exponent = 0.3,
                                   yield_stress = 450))

Sample definition

Mesh generation using gmsh

\(L\) and \(l\) parametres are the dimension of the central part of the sample.

parts = {
    "sample" :model.Sample2D(workdir = workdir,
                                   L = 10., # length
                                   l = 10., #width
                                   r = 5., #radius
                                   lcf = .2, #fine element size
                                   lcg = 3., #coars element size
                                   gmsh_path = GMSH_PATH,
                                   gmsh_space = 2,
                                   gmsh_options = "-algo delquad",
                                   element_map = element_map,
                                   material_map = material_map)}

Steps definition

Here 3 steps are implemented : * Traction * Compression * Traction

steps = [
        model.Step2D_traction(name = "LOADING1",
                              kind = "adaptative",
                              control_type = "disp",
                              duration = 0.5,
                              min_frame_duration = .1,
                              controlled_value = .5 ),
         model.Step2D_traction(name = "LOADING2",
                              kind = "adaptative",
                              control_type = "disp",
                              duration = 1.,
                              min_frame_duration = .1,
                              controlled_value = -.5 ),
        model.Step2D_traction(name = "LOADING3",
                              kind = "adaptative",
                              control_type = "disp",
                              duration = 1.5,
                              min_frame_duration = .1,
                              controlled_value = 1. )
        ]

TracModel = model.Traction2D(label = label,
                      parts = parts,
                      steps = steps,
                      materials = materials,
                      solver = "abaqus",
                      solver_path = local_settings.ABAQUS_PATH,
                      workdir = workdir,
                      verbose = True)

Write the inp file for Abaqus

The model can be check within CAE Abaqus if needed, unsing the file>import>model>*.inp menu.

TracModel.write_input()

Mesh checking

i = 1
fig = plt.figure()
parts_names = parts.keys()
for name, part in parts.items():
    mesh = part.mesh
    patches = mesh.to_polycollection(edgecolor = "black", linewidth = .1, alpha = 1.)
    stats = mesh.stats()
    patches.set_array( stats.stats.max_abs_angular_deviation )
    patches.set_cmap(mpl.cm.YlOrRd)
    ax = fig.add_subplot(1, 1, 1)
    ax.set_aspect("equal")
    ax.set_xlim(mesh.nodes.coords.x.min(), mesh.nodes.coords.x.max())
    ax.set_ylim(mesh.nodes.coords.y.min(), mesh.nodes.coords.y.max())
    #ax.set_xlim(-6, 6)
    #ax.set_ylim(-1,11)
    ax.add_collection(patches)
cbar = plt.colorbar(patches, orientation = "horizontal")
cbar.set_label("Max Abs. Angular Deviation [$^o$]")
plt.xlabel("$x$")
plt.ylabel("$y$")
plt.grid('off')
plt.title(name.title())
    #i+= 1
plt.show()
<IPython.core.display.Javascript object>

Run using Abaqus/Standart

TracModel.run_simulation()

Postprocess and save the model for further analyze

TracModel.postproc()
TracModel.save(workdir +label+ ".pcklz")

Re-load the case for post process within the pythonic environement

TracModel = ag.utils.load(workdir +label+ ".pcklz")

Ploting the results

Force date comming from history output

hist = TracModel.data["history"]
hist.head()
RF dtot t step F
0 -0.000000 0.000 0.000 0 -0.000000
1 361.051483 0.005 0.005 0 361.051483
2 722.023315 0.010 0.010 0 722.023315
3 1082.915410 0.015 0.015 0 1082.915410
4 1443.727780 0.020 0.020 0 1443.727780
plt.figure()
for step, group in hist.groupby("step"):
  plt.plot(group.dtot, group.F,'.-', label = "Step {0}".format(step))
plt.grid()
plt.legend(loc = "best")
plt.ylabel("Total force $F$, []")
plt.xlabel("Displacement, $\delta$ []")
plt.show()
<IPython.core.display.Javascript object>

Field plots

Check the available output fields

meta=TracModel.parts["sample"].mesh.fields_metadata()
meta.head(40)
part step_num step_label frame frame_value label position
0 I_SAMPLE 0 LOADING1 0 0 PEEQ element
1 I_SAMPLE 0 LOADING1 0 0 S element
2 I_SAMPLE 0 LOADING1 0 0 Seq element
3 I_SAMPLE 0 LOADING1 0 0 U node
4 I_SAMPLE 0 LOADING1 1 0.5 PEEQ element
5 I_SAMPLE 0 LOADING1 1 0.5 S element
6 I_SAMPLE 0 LOADING1 1 0.5 Seq element
7 I_SAMPLE 0 LOADING1 1 0.5 U node
8 I_SAMPLE 1 LOADING2 0 0 PEEQ element
9 I_SAMPLE 1 LOADING2 0 0 S element
10 I_SAMPLE 1 LOADING2 0 0 Seq element
11 I_SAMPLE 1 LOADING2 0 0 U node
12 I_SAMPLE 1 LOADING2 1 1 PEEQ element
13 I_SAMPLE 1 LOADING2 1 1 S element
14 I_SAMPLE 1 LOADING2 1 1 Seq element
15 I_SAMPLE 1 LOADING2 1 1 U node
16 I_SAMPLE 2 LOADING3 0 0 PEEQ element
17 I_SAMPLE 2 LOADING3 0 0 S element
18 I_SAMPLE 2 LOADING3 0 0 Seq element
19 I_SAMPLE 2 LOADING3 0 0 U node
20 I_SAMPLE 2 LOADING3 1 1.5 PEEQ element
21 I_SAMPLE 2 LOADING3 1 1.5 S element
22 I_SAMPLE 2 LOADING3 1 1.5 Seq element
23 I_SAMPLE 2 LOADING3 1 1.5 U node

Plot field at nodes

#Frame number to plot
frame_num=1
Step_name='LOADING3'
parts = {k:part.mesh.copy() for k, part in TracModel.parts.items() }

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

field_num = meta[(meta.label=='U') & (meta.frame==frame_num) & (meta.step_label==Step_name)].index[0]
disp_num  = meta[(meta.label=='U')  & (meta.frame==frame_num) & (meta.step_label==Step_name)].index[0]
levels = np.linspace(-.35, .35, 21)
dispMagnification = 1.

for k, mesh in parts.items():

    field =mesh.fields[field_num].data.v1
    disp = mesh.fields[disp_num].data
    frame = mesh.fields[disp_num].frame
    mesh.nodes[("coords", "x")] += dispMagnification*disp.v1
    mesh.nodes[("coords", "y")] += dispMagnification*disp.v2
    tri = mesh.to_triangulation()
    patches = mesh.to_polycollection(facecolor='none',edgecolor = "black",linewidth = .02)
    #patches.set_array(field)
    patches.set_cmap(mpl.cm.jet)


    g=ax.tricontourf(tri, field, levels, cmap = mpl.cm.jet, alpha = 1)
    ax.add_collection(patches)
    cbar = plt.colorbar(g)
    cbar.set_label("$U_{2} (mm)$")

    plt.title("Frame:{0}".format(frame))
    ax.set_aspect("equal")
    ax.set_xlim(mesh.nodes.coords.x.min(), mesh.nodes.coords.x.max())
    ax.set_ylim(mesh.nodes.coords.y.min(), mesh.nodes.coords.y.max())

    plt.xlabel("$x$")
    plt.ylabel("$y$")
    plt.show()
<IPython.core.display.Javascript object>

Plot fields at element

#Frame number to plot
frame_num=1
Step_name='LOADING3'
parts = {k:part.mesh.copy() for k, part in TracModel.parts.items() }

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

field_num = meta[(meta.label=='PEEQ') & (meta.frame==frame_num) & (meta.step_label==Step_name)].index[0]
disp_num  = meta[(meta.label=='U')  & (meta.frame==frame_num) & (meta.step_label==Step_name)].index[0]
levels = np.linspace(.0, 0.03, 21)
dispMagnification = 1.

for k, mesh in parts.items():

    field =mesh.fields[field_num].data.v
    disp = mesh.fields[disp_num].data
    frame = mesh.fields[disp_num].frame
    mesh.nodes[("coords", "x")] += dispMagnification*disp.v1
    mesh.nodes[("coords", "y")] += dispMagnification*disp.v2
    #tri = mesh.to_triangulation()
    patches = mesh.to_polycollection(edgecolor = "black",linewidth = .02)
    patches.set_array(field)
    patches.set_cmap(mpl.cm.jet)
    cbar = plt.colorbar(patches)
    cbar.set_label("$\epsilon^p_{eq} (-)$")
    ax.add_collection(patches)
    #g=ax.tricontourf(tri, field, levels, cmap = mpl.cm.jet, alpha = 1)



    plt.title("Frame:{0}".format(frame))
    ax.set_aspect("equal")
    ax.set_xlim(mesh.nodes.coords.x.min(), mesh.nodes.coords.x.max())
    ax.set_ylim(mesh.nodes.coords.y.min(), mesh.nodes.coords.y.max())

    plt.xlabel("$x$")
    plt.ylabel("$y$")
    plt.show()
<IPython.core.display.Javascript object>