Argiope: pythonic FEM data management toolbox¶
Install¶
pip install argiope
Tutorials:¶
Notebooks¶
Mesh¶
Note
This notebook can be downloaded here: mesh_tutorial.ipynb
Mesh tutorial¶
%load_ext autoreload
%autoreload 2
import argiope as ag
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
from string import Template
%matplotlib nbagg
Geometry setup¶
geom_template = """
lc = $lc;
Point(1) = {0,0,0,lc};
Point(2) = {.5,0,0,lc};
Point(3) = {.5,.5,0,lc};
Point(4) = {1,.5,0,lc};
Point(5) = {1,1,0,lc};
Point(6) = {0,1,0,lc};
Point(7) = {.5,.25,0,lc};
Point(8) = {.5,.75,0,lc};
Point(9) = {.125,.875,0,lc};
Point(10) = {.125,.875-.05,0,lc};
Point(11) = {.125,.875+.05,0,lc};
Line(1) = {1,2};
Circle(2) = {2,3,4};
Line(3) = {4,5};
Line(4) = {5,6};
Line(5) = {6,1};
Circle(6) = {7,3,8};
Circle(7) = {8,3,7};
Circle(8) = {10,9,11};
Circle(9) = {11,9,10};
Line Loop(1) = {6,7}; // interior loop
Line Loop(2) = {1,2,3,4,5}; // exterior loop
Line Loop(3) = {8,9};// hole
Plane Surface(2) = {2,1,3}; // exterior surface (with a hole)
Recombine Surface {2};
Physical Surface("SURFACE") = {2};
"""
open("./_workdir/mesh.geo", "w").write(Template(geom_template).substitute(lc = 0.025))
725
Mesh creation¶
GMSH can be run directly as a shell command.
!gmsh -2 ./_workdir/mesh.geo -algo 'delquad'
Info : Running 'gmsh -2 ./_workdir/mesh.geo -algo delquad' [Gmsh 3.0.6, 1 node, max. 1 thread]
Info : Started on Fri Mar 2 16:03:33 2018
Info : Reading './_workdir/mesh.geo'...
Info : Done reading './_workdir/mesh.geo'
Info : Finalized high order topology of periodic connections
Info : Meshing 1D...
Info : Meshing curve 1 (Line)
Info : Meshing curve 2 (Circle)
Info : Meshing curve 3 (Line)
Info : Meshing curve 4 (Line)
Info : Meshing curve 5 (Line)
Info : Meshing curve 6 (Circle)
Info : Meshing curve 7 (Circle)
Info : Meshing curve 8 (Circle)
Info : Meshing curve 9 (Circle)
Info : Done meshing 1D (0.004 s)
Info : Meshing 2D...
Info : Meshing surface 2 (Plane, Frontal Quad)
Info : Blossom: 3586 internal 232 closed
Info : Blossom completed (0.08 s): 1227 quads 0 triangles 0 invalid quads 0 quads with Q < 0.1 Avg Q = 0.904 Min Q 0.451
Info : Done meshing 2D (0.304 s)
Info : 2856 vertices 1470 elements
Info : Writing './_workdir/mesh.msh'...
Info : Done writing './_workdir/mesh.msh'
Info : Stopped on Fri Mar 2 16:03:34 2018
It is even simpler to use the dedicated function in argiope.utils.
ag.utils.run_gmsh(gmsh_path = "gmsh",
gmsh_space = 2,
gmsh_options = "-algo 'del2d'",
name = "./_workdir/mesh.geo")
Mesh reading¶
mesh = ag.mesh.read_msh("./_workdir/mesh.msh")
mesh.nodes.head()
coords | sets | |||
---|---|---|---|---|
x | y | z | all | |
node | ||||
1 | 0.0 | 0.0 | 0.0 | True |
2 | 0.5 | 0.0 | 0.0 | True |
3 | 1.0 | 0.5 | 0.0 | True |
4 | 1.0 | 1.0 | 0.0 | True |
5 | 0.0 | 1.0 | 0.0 | True |
mesh.elements.head()
conn | materials | sets | type | ||||||
---|---|---|---|---|---|---|---|---|---|
n0 | n1 | n2 | n3 | SURFACE | all | argiope | solver | ||
element | |||||||||
1 | 428 | 1689 | 767 | 766 | True | True | quad4 | ||
2 | 344 | 743 | 693 | 1542 | True | True | quad4 | ||
3 | 426 | 864 | 237 | 699 | True | True | quad4 | ||
4 | 1392 | 815 | 254 | 1246 | True | True | quad4 | ||
5 | 872 | 679 | 438 | 1479 | True | True | quad4 |
Putting it all together¶
Let’s now do all these operations in a single function and do fun stuff.
def make_mesh(lc, algorithm = "del2d"):
"""
A mesh function that creates a mesh.
"""
open("./_workdir/mesh.geo", "w").write(Template(geom_template).substitute(lc = lc))
ag.utils.run_gmsh(gmsh_path = "gmsh",
gmsh_space = 2,
gmsh_options = "-algo '{0}'".format(algorithm),
name = "./_workdir/mesh.geo")
mesh = ag.mesh.read_msh("./_workdir/mesh.msh")
return mesh
mesh = make_mesh(0.02, "meshadapt")
mesh
<Mesh, 2665 nodes, 2522 elements, 0 fields>
fig = plt.figure()
algos = ["frontal", "del2d", "delquad", "meshadapt"]
for i in range(len(algos)):
mesh = make_mesh(0.03, algos[i])
patches = mesh.to_polycollection(edgecolor = "black", linewidth = .5, alpha = 1.)
stats = mesh.stats()
#patches.set_array( stats.stats.max_abs_angular_deviation )
patches.set_array( stats.stats.aspect_ratio )
patches.set_cmap(mpl.cm.terrain)
ax = fig.add_subplot(2, 2, i+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.add_collection(patches)
cbar = plt.colorbar(patches, orientation = "vertical")
cbar.set_label("Max Abs. Ang. Dev. [$^o$]")
ax.set_title(algos[i])
#plt.xlabel("$x$")
#plt.ylabel("$y$")
#plt.grid()
ax.axis('off')
plt.show()
<IPython.core.display.Javascript object>
Mesh quality investigation¶
For example, let’s investigate the effect of the mesh algorithm on the overall quality of the mesh.
stats = mesh.stats()
stats.stats.describe().loc[["min", "max", "mean", "std"]][["max_angular_deviation", "aspect_ratio"]]
max_angular_deviation | aspect_ratio | |
---|---|---|
min | 0.812189 | 1.005641 |
max | 57.488325 | 2.633344 |
mean | 21.067222 | 1.342344 |
std | 11.070150 | 0.234528 |
Package documentation:¶
Mesh¶
Mesh processing tools.
Mesh class¶
-
class
argiope.mesh.
Mesh
(**kwargs)[source]¶ A single class to handle meshes and associated data. The class constructor only a redirection to the following methods:
A simple example is given below.
import numpy as np import argiope as ag # NODE COORDINATES coords = np.array([[0., 0., 0.], #1 [1., 0., 0.], #2 [2., 0., 0.], #3 [1., 1., 0.], #4 [0., 1., 0.], #5 [0., 0., 1.], #6 [1., 0., 1.], #7 [2., 0., 1.], #8 [1., 1., 1.], #9 [0., 1., 1.], #10 [0., 0., 2.], #11 [1., 0., 2.], #12 [2., 0., 2.], #13 [1., 1., 2.], #14 [0., 1., 2.], #15 [1., 0., 3.], #16 ]) # NODE LABELS nlabels = np.arange(len(coords)) +1 # NODE SETS nsets = {"nset1": nlabels > 2} # CONNECTIVITY : # Warning = nothing, only used to ensure renctangularity of the table. conn = [[ 1, 2, 4, 5, 0, 0, 0, 0], #1 = QUAD4 [ 2, 3, 4, 0, 0, 0, 0, 0], #2 = TRI3 [ 6, 7, 9, 10, 11, 12, 14, 15], # 3 = HEXA8 [ 7, 8, 9, 12, 13, 14, 0, 0], # 4 = PRISM6 [12, 13, 14, 16, 0, 0, 0, 0], # 5 = TETRA4 ] elabels = np.arange(1, len(conn) + 1) types = np.array(["quad4", "tri3", "hexa8", "prism6", "tetra4"]) stypes = np.array(["CPS4", "CAX3", "C3D8", "C3D6", "C3D4"]) # Abaqus element naming convention. esets = {"eset1": elabels < 2} materials = np.array(["mat1", "mat2", "mat2", "mat2", "mat2"]) mesh = ag.mesh.Mesh(nlabels = nlabels, coords = coords, nsets = nsets, conn = conn, elabels = elabels, esets = esets, types = types, stypes = stypes, )
For more complex examples, follow the notebook tutorials.
Set¶
-
Mesh.
set_nodes
(nlabels=[], coords=[], nsets={}, **kwargs)[source]¶ Sets the node data.
Parameters: - nlabels (1D uint typed array-like) – node labels. Items be strictly positive and int typed in 1D array-like with shape \((N_n)\).
- coords (2D float typed array-like) – node coordinates. Must be float typed 2D array-like of shape \((N_n \times 3)\).
- nsets (dict) – node sets. Contains boolean array-like of shape \((N_n)\).
-
Mesh.
set_elements
(elabels=None, types=None, stypes='', conn=None, esets={}, surfaces={}, materials='', **kwargs)[source]¶ Sets the element data.
Parameters: - elabels (1D uint typed array-like) – element labels. Items be strictly positive and int typed in 1D array-like with shape \((N_e)\).
- types (str typed array-like) – element types chosen among argiope specific element types.
- stypes (str typed array-like) – element types chosen in solver (depends on the chosen solver) specific element types.
- conn (uint typed array-like) – connectivity table. In order to deal with non rectangular tables, \(0\) can be used to fill missing data.
- esets (dict) – element sets. Contains boolean array-like of shape \((N_e)\).
- surfaces (dict) – surfaces. Contains boolean array-like of shape \((N_e, N_s )\) with \(N_s\) being the maximum number of faces on a single element.
- materials (str typed array-like) – material keys. Any number a of materials can be used.
Verify¶
-
Mesh.
centroids_and_volumes
(sort_index=True)[source]¶ Returns a dataframe containing volume and centroids of all the elements.
Modify¶
Fields¶
Meta classes¶
-
class
argiope.mesh.
MetaField
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ A field mother class.
Parameters: - label (str) – field label
- position (in ["node", "element"]) – physical position
-
copy
()¶ Returns a copy of self.
-
save
(path)¶ Saves the instance into a compressed serialized file.
Field classes¶
-
class
argiope.mesh.
ScalarField
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ -
copy
()¶ Returns a copy of self.
-
metadata
()¶ Returns metadata as a dataframe.
-
save
(path)¶ Saves the instance into a compressed serialized file.
-
-
class
argiope.mesh.
Vector2Field
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ 2D vector field.
-
copy
()¶ Returns a copy of self.
-
metadata
()¶ Returns metadata as a dataframe.
-
save
(path)¶ Saves the instance into a compressed serialized file.
-
-
class
argiope.mesh.
Vector3Field
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ 3D vector field.
-
copy
()¶ Returns a copy of self.
-
metadata
()¶ Returns metadata as a dataframe.
-
save
(path)¶ Saves the instance into a compressed serialized file.
-
-
class
argiope.mesh.
Tensor4Field
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ Second order symmetric 2D tensor field.
-
copy
()¶ Returns a copy of self.
-
metadata
()¶ Returns metadata as a dataframe.
-
save
(path)¶ Saves the instance into a compressed serialized file.
-
-
class
argiope.mesh.
Tensor6Field
(label=None, position='node', step_num=None, step_label=None, part=None, frame=None, frame_value=None, data=None, **kwargs)[source]¶ Second order symmetric tensor field.
-
copy
()¶ Returns a copy of self.
-
metadata
()¶ Returns metadata as a dataframe.
-
save
(path)¶ Saves the instance into a compressed serialized file.
-
Mesh generation¶
-
argiope.mesh.
structured_mesh
(shape=(2, 2, 2), dim=(1.0, 1.0, 1.0))[source]¶ Returns a structured mesh.
Parameters: - shape (tuple) – 2 or 3 integers (eg: shape = (10, 10, 10)).
- dim (tuple) – 2 or 3 floats (eg: dim = (4., 2., 1.))
Note
This function does not use GMSH for mesh generation.
>>> import argiope as ag >>> mesh = ag.mesh.structured_mesh(shape =(10,10,10), dim=(1.,1.,1.)))
Materials¶
Materials useable for FEM simulations.
Materials¶
-
class
argiope.materials.
Elastic
(young_modulus=1.0, poisson_ratio=0.3, **kwargs)[source]¶ An isotropic elastic material class.
-
class
argiope.materials.
ElasticPerfectlyPlastic
(yield_stress=0.01, **kwargs)[source]¶ A elastic perfectly plastic material.
Models¶
Classes dedicated to model creation.
Model¶
The model meta class aims at being subclassed by actual model classes.
Part¶
The part meta class helps creating part classes by providing useful methods.