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.
Mesh.set_fields(fields=None, **kwargs)[source]

Sets the fields.

Verify
Mesh.check_elements()[source]

Checks element definitions.

Mesh.nvert()[source]

Returns the number of vertices of eache element according to its type/

Mesh.centroids_and_volumes(sort_index=True)[source]

Returns a dataframe containing volume and centroids of all the elements.

Mesh.angles(zfill=3)[source]

Returns the internal angles of all elements and the associated statistics

Mesh.edges(zfill=3)[source]

Returns the aspect ratio of all elements.

Mesh.stats()[source]

Returns mesh quality and geometric stats.

Mesh.fields_metadata()[source]

Returns fields metadata as a dataframe.

Modify
Mesh.element_set_to_node_set(tag)[source]

Makes a node set from an element set.

Mesh.node_set_to_surface(tag)[source]

Converts a node set to surface.

Mesh.surface_to_element_sets(tag)[source]

Creates elements sets corresponding to a surface.

Plot with Matplotlib
Mesh.to_polycollection(*args, **kwargs)[source]

Returns the mesh as matplotlib polygon collection. (tested only for 2D meshes)

Mesh.to_triangulation()[source]

Returns the mesh as a matplotlib.tri.Triangulation instance. (2D only)

Export
Mesh.write_inp(*args, **kwargs)[source]

Exports the mesh to the Abaqus INP format.

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.

metadata()[source]

Returns metadata as a dataframe.

save(path)

Saves the instance into a compressed serialized file.

class argiope.mesh.Field(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.

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.

Parsers

argiope.mesh.read_msh(path)[source]

Reads a GMSH msh file using MESHIO.

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.

write_inp()[source]

Returns the material definition as a string in Abaqus INP format.

class argiope.materials.ElasticPerfectlyPlastic(yield_stress=0.01, **kwargs)[source]

A elastic perfectly plastic material.

write_inp()[source]

Returns the material definition as a string in Abaqus INP format.

class argiope.materials.Hollomon(hardening_exponent=0.3, yield_stress=0.01, **kwargs)[source]

An Hollomon material.

get_plastic_table()[source]

Calculates the plastic data

write_inp()

Returns the material definition as a string in Abaqus INP format.

class argiope.materials.PowerLin(hardening_exponent=0.3, yield_stress=150.0, consistency=200.0, **kwargs)[source]

A Power Linear material : S = Sy + K (Ep)**n

get_plastic_table()[source]

Calculates the plastic data

write_inp()

Returns the material definition as a string in Abaqus INP format.

Models

Classes dedicated to model creation.

Model

The model meta class aims at being subclassed by actual model classes.

class argiope.models.Model(label, parts, steps, materials, amplitude=None, solver='abaqus', solver_path='', workdir='./workdir', verbose=False, cpus=1)[source]

Model meta class.

copy()

Returns a copy of self.

make_directories()[source]

Checks if required directories exist and creates them if needed.

run_postproc()[source]

Runs the post-proc script.

run_simulation()[source]

Runs the simulation.

save(path)

Saves the instance into a compressed serialized file.

Part

The part meta class helps creating part classes by providing useful methods.

class argiope.models.Part(gmsh_path='gmsh', file_name='dummy', workdir='./', gmsh_space=2, gmsh_options='', element_map=None, material_map=None)[source]
copy()

Returns a copy of self.

run_gmsh()[source]

Makes the mesh using gmsh.

save(path)

Saves the instance into a compressed serialized file.

Utils

Useful functions and classes.

Meta Classes

class argiope.utils.Container[source]

A container meta class with utilities

copy()[source]

Returns a copy of self.

save(path)[source]

Saves the instance into a compressed serialized file.