Note
This notebook can be downloaded here: indentation_2D.ipynb
2D indentation using Argiope & Hardness¶
%load_ext autoreload
%autoreload 2
The autoreload extension is already loaded. To reload it, use:
%reload_ext autoreload
!cat local_settings.py.example
# LOCAL SETTINGS
# Modify as needed and rename local_settings.py
GMSH_PATH = "gmsh"
ABAQUS_PATH = "abaqus"
import matplotlib.pyplot as plt
import matplotlib as mpl
import hardness as hd
import argiope as ag
import pandas as pd
import numpy as np
import os, subprocess, time, local_settings, time
%matplotlib nbagg
mpl.rcParams['grid.color'] = 'k'
mpl.rcParams['grid.linestyle'] = ':'
mpl.rcParams['grid.linewidth'] = 0.5
mpl.rcParams['contour.negative_linestyle'] = 'solid'
# USEFUL FUNCTIONS
def create_dir(path):
try:
os.mkdir(path)
except:
pass
Settings¶
# SETTINGS
workdir = "_workdir/"
outputdir = "outputs/"
label = "indentation_2D"
create_dir(workdir)
create_dir(workdir + outputdir)
Model definition¶
#-------------------------------------------------------------------------------
# MESH DEFINITIONS
def element_map(mesh):
mesh.elements.loc[mesh.elements.type.argiope == "tri3", ("type", "solver", "")] = "CAX3"
mesh.elements.loc[mesh.elements.type.argiope == "quad4", ("type", "solver", "")] = "CAX4R"
return mesh
def sample_material_map(mesh):
mesh.elements["materials"] = "SAMPLE_MAT"
return mesh
def indenter_material_map(mesh):
mesh.elements["materials"] = "INDENTER_MAT"
return mesh
parts = {
"sample" : hd.models.Sample2D(lx = 1., ly = 1.,
r1 = 2., r2 = 3.,
Nx = 32, Ny = 16,
Nr = 2, Nt = 64,
gmsh_path = "gmsh",
file_name = "dummy",
workdir = workdir,
gmsh_space = 2,
gmsh_options = "-algo 'delquad'",
element_map = element_map,
material_map = sample_material_map),
"indenter" : hd.models.SpheroconicalIndenter2D(
R = 1.,
psi= 70.3,
r1 = 1.,
r2 = 3.,
r3 = 4.,
lc1 = .05,
lc2 = .5,
rigid = False,
gmsh_path = "gmsh",
file_name = "dummy",
workdir = workdir,
gmsh_space = 2,
gmsh_options = "-algo 'delquad'",
element_map = element_map,
material_map = indenter_material_map)}
materials = [ag.materials.Hollomon(label = "SAMPLE_MAT", strain_data_points = 100),
ag.materials.Hollomon(label = "INDENTER_MAT", strain_data_points = 100)]
#-------------------------------------------------------------------------------
# STEP DEFINTIONS
steps = [
hd.models.Step2D(name = "LOADING1",
control_type = "disp",
duration = 1.,
kind = "adaptative",
nframes = 50,
controlled_value = -0.2,
field_output_frequency = 99999),
hd.models.Step2D(name = "UNLOADING1",
control_type = "force",
duration = 1.,
kind = "adaptative",
nframes = 50,
controlled_value = 0.,
field_output_frequency = 99999),
hd.models.Step2D(name = "RELOADING1",
control_type = "disp",
duration = 1.,
kind = "adaptative",
nframes = 50,
controlled_value = -0.2,
field_output_frequency = 99999),
hd.models.Step2D(name = "LOADING2",
control_type = "disp",
duration = 1.,
kind = "adaptative",
nframes = 50,
controlled_value = -0.4,
field_output_frequency = 99999),
hd.models.Step2D(name = "UNLOADING2",
control_type = "force",
kind = "adaptative",
duration = 1.,
nframes = 50,
controlled_value = 0.,
field_output_frequency = 99999)
]
model0 = hd.models.Indentation2D(label = label,
parts = parts,
steps = steps,
materials = materials,
solver = "abaqus",
solver_path = local_settings.ABAQUS_PATH,
workdir = workdir,
verbose = True)
print("1: Preprocessing ----------------------------------")
%time model0.write_input()
print("2: Processing -------------------------------------")
%time model0.run_simulation()
print("3: Postprocessing ---------------------------------")
%time model0.postproc()
print("4: Saving model -----------------------------------")
%time model0.save(workdir + "model.pcklz")
1: Preprocessing ---------------------------------- CPU times: user 1.51 s, sys: 32 ms, total: 1.54 s Wall time: 2.79 s 2: Processing ------------------------------------- <Running "indentation_2D" using abaqus> (b'Abaqus JOB indentation_2DnAbaqus 6.13-1nBegin Analysis Input File ProcessornTue Jan 9 17:10:52 2018nRun prenTue Jan 9 17:10:55 2018nEnd Analysis Input File ProcessornBegin Abaqus/Standard AnalysisnTue Jan 9 17:10:55 2018nRun standardnTue Jan 9 17:12:33 2018nEnd Abaqus/Standard AnalysisnAbaqus JOB indentation_2D COMPLETEDn', None) <Ran indentation_2D: duration 104.45s> CPU times: user 4 ms, sys: 12 ms, total: 16 ms Wall time: 1min 44s 3: Postprocessing --------------------------------- <Post-Processing"indentation_2D" using abaqus> /opt/abaqus/scratch/Commands/abaqus viewer noGUI=indentation_2D_abqpp.py (b'', None) <Post-Processed indentation_2D: duration 5.33s> CPU times: user 324 ms, sys: 52 ms, total: 376 ms Wall time: 5.67 s 4: Saving model ----------------------------------- CPU times: user 1.2 s, sys: 0 ns, total: 1.2 s Wall time: 1.2 s
model = ag.utils.load(workdir + "model.pcklz")
Model checking¶
Mesh building and quality checking.
parts["indenter"].mesh.elements.head()
conn | materials | sets | type | surfaces | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
n0 | n1 | n2 | n3 | ALL_ELEMENTS | argiope | solver | SURFACE | |||||
f1 | f2 | f3 | f4 | |||||||||
element | ||||||||||||
79 | 465 | 455 | 412 | 442 | INDENTER_MAT | True | quad4 | CAX4R | False | False | False | False |
80 | 262 | 323 | 358 | 290 | INDENTER_MAT | True | quad4 | CAX4R | False | False | False | False |
81 | 440 | 419 | 395 | 437 | INDENTER_MAT | True | quad4 | CAX4R | False | False | False | False |
82 | 499 | 483 | 489 | 493 | INDENTER_MAT | True | quad4 | CAX4R | False | False | False | False |
83 | 441 | 413 | 458 | 454 | INDENTER_MAT | True | quad4 | CAX4R | False | False | False | False |
parts["sample"].mesh.elements.head()
conn | materials | sets | type | sets | surfaces | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
n0 | n1 | n2 | n3 | CORE | SHELL1 | SHELL2 | argiope | solver | ALL_ELEMENTS | SURFACE | |||||
f1 | f2 | f3 | f4 | ||||||||||||
element | |||||||||||||||
161 | 1 | 9 | 273 | 100 | SAMPLE_MAT | True | False | False | quad4 | CAX4R | True | False | False | False | True |
162 | 100 | 273 | 274 | 99 | SAMPLE_MAT | True | False | False | quad4 | CAX4R | True | False | False | False | True |
163 | 99 | 274 | 275 | 98 | SAMPLE_MAT | True | False | False | quad4 | CAX4R | True | False | False | False | True |
164 | 98 | 275 | 276 | 97 | SAMPLE_MAT | True | False | False | quad4 | CAX4R | True | False | False | False | True |
165 | 97 | 276 | 277 | 96 | SAMPLE_MAT | True | False | False | quad4 | CAX4R | True | False | False | False | True |
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 = .5, 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, 2, i)
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.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()
plt.title(name.title())
i+= 1
plt.show()
<IPython.core.display.Javascript object>
Simulation¶
Post-Processing¶
Time data¶
hist = model.data["history"]
hist.head()
Wes | Wf | RF | Wtot | dtot | dtip | Wei | CF | Wps | t | step | F | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.000000e+00 | 0.0 | -0.000000 | 0.000000e+00 | 0.000 | 0.000000 | 0.000000e+00 | 0.0 | 0.000000e+00 | 0.00 | 0 | 0.000000 |
1 | 1.212117e-07 | 0.0 | -0.000172 | 4.421582e-07 | -0.004 | -0.001550 | 1.233709e-07 | 0.0 | 0.000000e+00 | 0.02 | 0 | -0.000172 |
2 | 6.670477e-07 | 0.0 | -0.000491 | 1.847942e-06 | -0.008 | -0.003304 | 6.785313e-07 | 0.0 | 6.015316e-08 | 0.04 | 0 | -0.000491 |
3 | 1.686669e-06 | 0.0 | -0.000875 | 4.664802e-06 | -0.012 | -0.004641 | 1.736352e-06 | 0.0 | 3.642311e-07 | 0.06 | 0 | -0.000875 |
4 | 3.276133e-06 | 0.0 | -0.001324 | 9.063065e-06 | -0.016 | -0.006774 | 3.377875e-06 | 0.0 | 9.294579e-07 | 0.08 | 0 | -0.001324 |
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>
Fields¶
model.parts["sample"].mesh.fields_metadata()
frame | frame_value | label | part | position | step_label | step_num | |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | S | I_SAMPLE | node | LOADING1 | 0 |
1 | 0 | 0 | U | I_SAMPLE | node | LOADING1 | 0 |
2 | 1 | 1 | S | I_SAMPLE | node | LOADING1 | 0 |
3 | 1 | 1 | U | I_SAMPLE | node | LOADING1 | 0 |
4 | 0 | 0 | S | I_SAMPLE | node | UNLOADING1 | 1 |
5 | 0 | 0 | U | I_SAMPLE | node | UNLOADING1 | 1 |
6 | 1 | 1 | S | I_SAMPLE | node | UNLOADING1 | 1 |
7 | 1 | 1 | U | I_SAMPLE | node | UNLOADING1 | 1 |
8 | 0 | 0 | S | I_SAMPLE | node | RELOADING1 | 2 |
9 | 0 | 0 | U | I_SAMPLE | node | RELOADING1 | 2 |
10 | 1 | 1 | S | I_SAMPLE | node | RELOADING1 | 2 |
11 | 1 | 1 | U | I_SAMPLE | node | RELOADING1 | 2 |
12 | 0 | 0 | S | I_SAMPLE | node | LOADING2 | 3 |
13 | 0 | 0 | U | I_SAMPLE | node | LOADING2 | 3 |
14 | 1 | 1 | S | I_SAMPLE | node | LOADING2 | 3 |
15 | 1 | 1 | U | I_SAMPLE | node | LOADING2 | 3 |
16 | 0 | 0 | S | I_SAMPLE | node | UNLOADING2 | 4 |
17 | 0 | 0 | U | I_SAMPLE | node | UNLOADING2 | 4 |
18 | 1 | 1 | S | I_SAMPLE | node | UNLOADING2 | 4 |
19 | 1 | 1 | U | I_SAMPLE | node | UNLOADING2 | 4 |
model.parts["sample"].mesh.fields_metadata()
frame | frame_value | label | part | position | step_label | step_num | |
---|---|---|---|---|---|---|---|
0 | 0 | 0 | S | I_SAMPLE | node | LOADING1 | 0 |
1 | 0 | 0 | U | I_SAMPLE | node | LOADING1 | 0 |
2 | 1 | 1 | S | I_SAMPLE | node | LOADING1 | 0 |
3 | 1 | 1 | U | I_SAMPLE | node | LOADING1 | 0 |
4 | 0 | 0 | S | I_SAMPLE | node | UNLOADING1 | 1 |
5 | 0 | 0 | U | I_SAMPLE | node | UNLOADING1 | 1 |
6 | 1 | 1 | S | I_SAMPLE | node | UNLOADING1 | 1 |
7 | 1 | 1 | U | I_SAMPLE | node | UNLOADING1 | 1 |
8 | 0 | 0 | S | I_SAMPLE | node | RELOADING1 | 2 |
9 | 0 | 0 | U | I_SAMPLE | node | RELOADING1 | 2 |
10 | 1 | 1 | S | I_SAMPLE | node | RELOADING1 | 2 |
11 | 1 | 1 | U | I_SAMPLE | node | RELOADING1 | 2 |
12 | 0 | 0 | S | I_SAMPLE | node | LOADING2 | 3 |
13 | 0 | 0 | U | I_SAMPLE | node | LOADING2 | 3 |
14 | 1 | 1 | S | I_SAMPLE | node | LOADING2 | 3 |
15 | 1 | 1 | U | I_SAMPLE | node | LOADING2 | 3 |
16 | 0 | 0 | S | I_SAMPLE | node | UNLOADING2 | 4 |
17 | 0 | 0 | U | I_SAMPLE | node | UNLOADING2 | 4 |
18 | 1 | 1 | S | I_SAMPLE | node | UNLOADING2 | 4 |
19 | 1 | 1 | U | I_SAMPLE | node | UNLOADING2 | 4 |
parts = {k:part.mesh.copy() for k, part in model.parts.items() }
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.set_aspect("equal")
ax.set_xlim(0., 4.)
ax.set_ylim(-2., 2.)
field_num = 14
disp_num = 15
levels = np.linspace(-1.e-2, 1.e-2, 11)
for k, mesh in parts.items():
field = mesh.fields[field_num].data.v12
disp = mesh.fields[disp_num].data
mesh.nodes[("coords", "x")] += disp.v1
mesh.nodes[("coords", "y")] += disp.v2
tri = mesh.to_triangulation()
patches = mesh.to_polycollection(facecolor = "none",
edgecolor = "black",
linewidth = .5)
grad = ax.tricontourf(tri, field, levels, cmap = mpl.cm.jet, alpha = 1.)
ax.tricontour(tri, field, levels, colors = "white", linewidths = 1.)
ax.add_collection(patches)
cbar = plt.colorbar(grad)
cbar.set_label("Cauchy Stress, $\sigma_{12}$")
ax.axis("off")
plt.xlabel("$x$")
plt.ylabel("$y$")
#plt.grid()
<IPython.core.display.Javascript object>
<matplotlib.text.Text at 0x7fda4246bb00>