Tutorial

Mesh generation

A mesh is mainly composed by cells and nodes. in Amaru, a mesh is also composed by surface cells and surface edges and are computed at the time of mesh generation.

Nodes

A node is represented by an instance of the Node type. It contains the node coordinates, a identification number and a tag string that can be used to label a group of nodes.

using Amaru
node = Node(1.0, 2.0, 0.0, id=1, tag="vertex")
Node
    id: 1
    coord: [1.0, 2.0, 0.0]
    tag: "vertex"
    dofs: 0-element Vector{Dof}
    dofdict: OrderedDict{Symbol, Dof} with 0 entries

Cells

A mesh cell is represented by an instace of the Cell type. It is defined by a given shape object, a list of nodes, a identification number an a tag string. The shape object contains information related with the geometry of a finite element. For example, a TRI3 shape represents the shape of a linear triangular finite element.

using Amaru
node1 = Node(0.0, 0.0, id=1)
node2 = Node(1.0, 0.0, id=2)
node3 = Node(1.0, 1.0, id=3)
nodes = [ node1, node2, node3 ]

Cell(TRI3, nodes, id=1, tag="triangle")
Cell
    id: 1
    shape: CellShape  name="TRI3"
    nodes: 3-element Vector{Node}:
        1: Node  id=1
        2: Node  id=2
        3: Node  id=3
    tag: "triangle"
    quality: 0.0
    embedded: false
    crossed: false
    owner: nothing
    linked_elems: 0-element Vector{Amaru.AbstractCell}

There are many shapes defined in Amaru, for instance: LIN2, LIN3, TRI3, TRI6, QUAD4, QUAD8, QUAD9 TET4, TET10, PYR5, WED6, WED15, HEX8, HEX20, HEX27, etc.

Blocks

Blocks are entities used to aid the generation of structured meshes in 1D, 2D and 3D. A Block type represents a geometric segment, area (4 or 8 point quadrilateral) or volume (8 or 20 point hexahedron). An instance of the block type is generated from a coordinates matrix and predefined number of divisions divisions (nx, ny, nz) in the $x$, $y$ and $z$ directions of a local system. The block below represents a 2D Block with nx=7 and ny=5. The mplot function saves the block image to a file in svg format. Other formats as pdf and png can be used.

using Amaru
block = Block([0 0; 4 0; 3 2; 1 2], nx=7, ny=5)
mplot(block, "block.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file block.svg saved

Blocks can be combined to define a complex geometry. To manipulate blocks, Amaru provides several operators as copy, move!, scale!, rotate, mirror, array, polar, extrude, etc.

For example, let's generate a square mesh with a central hole. We start with a quadratic quadrilateral block. Note that the vertex coordinates follow the same numbering as conventional finite elements. Thus, the corner nodes are listed first, and then the middle nodes. All the nodes are listed couterclockwise.

using Amaru

block1 = Block(
    [
        0.0      0.0
        0.7643   0.7643
        0.6667   1.0
        0.0      1.0
        0.38215  0.38215
        0.692    0.8724
        0.3333   1.0
        0.0      0.5
    ],
    cellshape=QUAD8, nx=5, ny=5
)
mplot(block1, "block1.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file block1.svg saved

A mirror operation can be applyed to this block to get a second one. Then, both blocks can be grouped in an array for further manipulation.

block2 = mirror(block1, base=[0, 0], axis=[0.7643, -0.7643])
blocks = [block1, block2]
mplot(blocks, "blocks.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file blocks.svg saved

The center of the circle that contains the arc is located at the coordinates (1,1). To place the center at the origin (0,0) we perform a move! operation.

move!(blocks, dx=-1.0, dy=-1.0)
mplot(blocks, "moved.svg", markers=true, axis=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file moved.svg saved

Next, we can apply a polar operation to the current geometry to obtain the square region with a central hole. Note that the original geometry was replicated four times (n=4) with different rotation angles. For this purpose a rotation axis and a base point were employed.

hole = polar(blocks, base=[0, 0], axis=[0, 0, 1], angle=360, n=4)
mplot(hole, "hole.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file hole.svg saved

Then, an extrude operation is used to obtain a volume following a defined axis and length. The argument n=4 represents the number of divisions intended along the new dimension.

solid = extrude(hole, axis=[0, 0, 1], length=1, n=4)
mplot(solid, "solid.svg", markers=true, dist=13)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file solid.svg saved

Note that, the solid variable is an array with four blocks, as shown in the figure. This array is used to generate the structured mesh.

mesh = Mesh(solid)
mplot(mesh, "mesh.svg", dist=13)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh.svg saved

Finally, a smooth operation can be applied to improve the cells quality.

smooth_mesh = smooth!(mesh)
mplot(smooth_mesh, "smooth_mesh.svg", dist=13)
Mesh Laplacian smoothing:
  it   qmin     q1     q2     q3   qmax   qavg     sdev       time  histogram (0:0.05:1]
   0  0.662  0.764  0.820  0.868  0.930  0.813  0.07626          -  [             ▂▄▆▇▅▆ ]
   1  0.688  0.770  0.838  0.909  0.956  0.834  0.07929  0m  0.14s  [             ▂▃▄▆▅▇▁]
   2  0.688  0.785  0.855  0.911  0.956  0.846  0.07911  0m  0.05s  [             ▁▃▄▃▅▇_]
   3  0.694  0.793  0.863  0.922  0.966  0.852  0.07937  0m  0.05s  [             ▁▃▃▂▅▇▁]
   4  0.700  0.799  0.872  0.929  0.973  0.856  0.07920  0m  0.06s  [              ▃▂▃▄▇▁]
   5  0.706  0.805  0.878  0.930  0.977  0.858  0.07879  0m  0.24s  [              ▃▁▅▄▇▁]
   6  0.712  0.810  0.883  0.929  0.981  0.860  0.07830  0m  0.05s  [              ▄▁▆▅▇▂]
   7  0.718  0.813  0.886  0.927  0.983  0.860  0.07784  0m  0.05s  [              ▄▁▇▅▇▃]

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file smooth_mesh.svg saved

Mesh generation examples

Below are presented some examples of structured mesh generation using Amaru.

Simple 2D mesh

using Amaru

block = Block([0 0 ; 2 2], nx=8, ny=6)
mesh  = Mesh(block)
mplot(mesh, "mesh-quad4.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-quad4.svg saved

Mesh with quadratic cells

using Amaru

block = Block([0 0 ; 2 2], nx=8, ny=6, cellshape=QUAD8)
mesh  = Mesh(block)
mplot(mesh, "mesh-quad8.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-quad8.svg saved

Simple 3D mesh

using Amaru
block = Block([0 0 0; 2 4 3], nx=3, ny=6, nz=6)
mesh = Mesh(block)
mplot(mesh, "mesh-hex8.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-hex8.svg saved

2D mesh constructed from two quadratic blocks

using Amaru
block1 = Block(
    [
        0.0      0.0
        0.7643   0.7643
        0.6667   1.0
        0.0      1.0
        0.38215  0.38215
        0.692    0.8724
        0.3333   1.0
        0.0      0.5
    ],
    cellshape=QUAD8, nx=5, ny=5
)
block2 = mirror(block1, base=[0, 0], axis=[0.7643, -0.7643])
mesh = Mesh(block1, block2)
mplot(mesh, "mesh-2d.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-2d.svg saved

Mesh with cells growing in the $x$ direction

using Amaru

R = 5.0
r = 1.0

block = BlockGrid(
    [ 0.0, r, R ],
    [ 0.0, R ],
    nx=[ 4, 8 ],
    ny=[ 8 ],
    rx=[ 1, 1.2] # elements growing rate in the x direction
)

mesh = Mesh(block)
mplot(mesh, "mesh-rate.svg", markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-rate.svg saved

3D mesh obtained revolving the last example

mesh = revolve(mesh, minangle=0, maxangle=90, base=[0,0,0], axis=[0,1,0])
changeaxes!(mesh, "xzy")
rotate!(mesh, axis=[0,0,1], angle=90)
mplot(mesh, "mesh-rev.svg", azim=-45)

  changeaxes!: mesh associated data was not reordered according to new axes.

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-rev.svg saved

Wire mesh

using Amaru

block1 = Block([0 0 0; 1 0 1; 0.7 0 0.3 ], n=7) # curved wire (quadratic)
block2 = Block([1 0 1; 1 0 2], n=5) # straight wire
mesh = Mesh(block1, block2)

mplot(mesh, "mesh-arc.svg", azim=-90, elev=0, markers=true)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-arc.svg saved

3D mesh obtained revolving the last example

mesh = revolve(mesh, n=24, axis=[0,0,1], base=[0,0,0]) # surface by revolution
mplot(mesh, "mesh-surf.svg", elev=15)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id

  Available element fields:

    quality, elem-id, cell-type, tag

  file mesh-surf.svg saved

Finite element model

To performe a finite element analysis, an instance of the Model type is required. This represents the domain model and contains nodes and finite elements. The element instances are different from the cells in a Mesh object since the elements are constructed according to the analysis problem. To instantiate a Model object a mesh and a list of material models objects are needed. The Model type is used for all analysis problems, e.g. mechanical, thermal, seepage, etc. Thus, for a particular problem, a consistent list of materials should be used. For example, in a mechanical analysis, all elements should be associated to mechanical material types. Based on the choosen materials, the Model object will setup the corresponding finite elements and degrees of freedom.

Material definitions

There are several material models implemented in Amaru and are associated to a corresponding type, e.g. ElasticSolid, DruckerPrager, VonMises, ElasticRod, etc. A particular material instance is defined by calling the construcor with set of corresponding parameters.

using Amaru

steel = ElasticSolid(E=2e8, nu=0.2) # E in kPa
rock = DruckerPrager(E=2e8, nu=0.2, alpha=0.4, kappa=2500, H=1e4)
rebar = ElasticRod(E=2e8, A=1e-4)

Model generation

The following example shows the walk through of creating a Model object. Note that the list of materials contains a pair relating a domain region to material instance.

using Amaru

# Mesh generation
block = Block([0 0 0; 1 0.1 0.1], nx=20, ny=2, nz=2, cellshape=HEX20)
mesh = Mesh(block)

# Analysis model
steel = ElasticSolid(E=2e8, nu=0.2) # E in kPa

materials = [
    :(x>=0) => steel,
]
model = Model(mesh, materials)
Model setup
  setting elements...
  3D model 3d model
    621 nodes
     80 elements
    168 faces
    336 edges
      1 materials
      0 loggers

Boundary conditions

The boundary conditions are given by objects that define the quantities that should be applied to nodes, faces, edges or even elements (NodeBC, SurfaceBC, EdgeBC and ElementBC).

The example below shows a nodal boundary condition where all displacements are set to zero.

using Amaru

fixed_end = NodeBC(ux=0, uy=0, uz=0)
NodeBC
    conds: Base.Pairs(:ux => 0, :uy => 0, :uz => 0)
    filter: Expr ()
    nodes: 0-element Vector{Node}

This other example shows a face boudary condition where a traction is applied in the negative $z$ direction.

using Amaru

load = SurfaceBC(tz=-10)
SurfaceBC
    conds: Base.Pairs(:tz => -10)
    filter: Expr ()
    faces: 0-element Vector{Cell}

The keys (e.g. ux, tz, etc.) to be set in a boundary condition are related to the analysis problem, and ultimately to the material types in use. For example, in a mechanical analysis, the keys for nodal boundary conditions are ux, uy, uz, fx, fy and fz where ux represents displacement and fx concentrated force, both in the $x$ direction. Similarly, the keys for a face boudary condition are ux, uy, uz, tx, ty and tz, where tx is a traction (force per area) in the $x$ direction. Besides, the tn key can be used to apply traction normal to the face.

Analysis example

This example shows a mechanical analysis in a steel beam. The left end was clamped, thus all displacements at x==0 are set to zero. Also, a vertical traction is applied at the right end. The solve! function performs the calculations of a Model instance subjected to a set of boundary conditions. The function also updates the state variables at the elements' integration points.

For post-processing in a visualization software (e.g. Paraview), the model can save the current per node and per element values (e.g. displacements, stresses, etc.) in "vtk" and "vtu" formats. To save the full state of a domain model, the output in "xml" format is also supported; thus, the model can be reused in future analyses.

using Amaru

# Mesh generation
block = Block([0 0 0; 1 0.1 0.1], nx=20, ny=2, nz=2, cellshape=HEX8)
mesh = Mesh(block)

# Analysis model
steel = ElasticSolid(E=200e6, nu=0.2) # E in kPa

materials = [
    :(x>=0) => steel,
]
model = Model(mesh, materials)

bcs = [
    :(x==0) => NodeBC(ux=0, uy=0, uz=0)
    :(x==1) => SurfaceBC(tz=-1000)
]

addstage!(model, bcs)

solve!(model, quiet=true)
save(model, "beam.vtu")
Model setup
  setting elements...
  3D model 3d model
    189 nodes
     80 elements
    168 faces
    336 edges
      1 materials
      0 loggers
Mechanical solver
  active threads: 1
  model type: 3d
  file beam.vtu saved 

The mplot function allow to save a plot of the domain in several formats (e.g. "pdf", "svg", "png", etc.). In this case, the deformed state is plot using a mangnification scale of 100. Also the $u_y$ field is displayed and the corresponding label is placed next to the colorbar. To adjunst the point of view, the azim, elev and dist parameters can be set. They represent, respectively, the azimut, elevation angle and distance to the rendered domain.

mplot(model, "beam.svg", warpscale=100, field=:uz, colorbarlabel=raw"$u_z$", colorbarscale=0.4, azim=-90, elev=30, dist=7)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id, ux, fx, uy, fy, uz, fz, sxx, syy, szz, syz, sxz, sxy, s1, s2, s3,
    exx, eyy, ezz, eyz, exz, exy, U

  Available element fields:

    elem-id, cell-type

  file beam.svg saved

Nonlinear analysis

The use of material models with nonlinear behavior lead to a nonlinear analyses. For example, the VonMises material type represents a nonlinear material model. For the analysis, the number of increments can be adjusted using the nincs parameter. Also, the autoinc parameter can be set to true to le the solve! function to automatically compute and recompute the increment sizes. The tol paramter specifies the maximum force discrepancy between internal and external forces.

using Amaru

# Mesh generation
block = Block([0 0 0; 1 0.1 0.1], nx=20, ny=2, nz=4, cellshape=HEX8)
mesh = Mesh(block)

# Analysis model
steel1 = ElasticSolid(E=2e8, nu=0.2) # E in kPa
steel2 = VonMises(E=2e8, nu=0.2, fy=500e3, H=1e4)

materials = [
    :(x>=0.5) => steel1,
    :(x<=0.5) => steel2
]
model = Model(mesh, materials)

bcs = [
    :(x==0) => NodeBC(ux=0, uy=0, uz=0)
    :(x==1) => SurfaceBC(uz=-0.04)
]

addstage!(model, bcs)

solve!(model, tol=0.01, autoinc=true, quiet=true)
Model setup
  setting elements...
  3D model 3d model
    315 nodes
    160 elements
    256 faces
    512 edges
      2 materials
      0 loggers
Mechanical solver
  active threads: 1
  model type: 3d
mplot(model, "beam-vm.svg", warpscale=10, field=:sxx, fieldmult=1e-3, colorbarlabel=raw"$\sigma_{xx}$", colorbarscale=0.4, azim=-90, dist=7)

Mesh plotting

  Optional arguments:

    axis, lw, markers, nodelabels, celllabels, opacity, field,
     fieldmult, fieldlims, vectorfield, arrowscale, colormap, colorbarscale,
     colorbarlabel, colorbarlocation, colorbarorientation, colorbarpad,
     warpscale, hicells, elev, azim, dist, outline, outlineangle,
     figsize, leaveopen, quiet

  Available node fields:

    node-id, ux, fx, uy, fy, uz, fz, sxx, syy, szz, syz, sxz, sxy, s1, s2, s3,
    exx, eyy, ezz, eyz, exz, exy, epa, j1, srj2d, U

  Available element fields:

    elem-id, cell-type

  file beam-vm.svg saved

Loggers

Loggers are objects designed to track the information of nodes, integration points, faces, edges, points and segments. That information is updated at every increment and can be saved to a file.

using Amaru

nodelog = NodeLogger("nodelog.table")
iplog = IpLogger("nodelog.table")
facelog = FacesSumLogger("nodelog.table")
nodeslog = NodeGroupLogger("nodes.book")

The loggers need to be associated to the entity they track by using a filter expression, coordinates or a tag string. Finally, the loggers have to be linked to a Model object by using the setloggers! function.

using Amaru

# Mesh generation
block = Block([0 0 0; 1 0.1 0.1], nx=20, ny=2, nz=3, cellshape=HEX8)
mesh = Mesh(block)

# Analysis model
steel1 = ElasticSolid(E=2e8, nu=0.2) # E in kPa
steel2 = VonMises(E=2e8, nu=0.2, fy=500e3, H=1e4)

materials = [
    :(x>=0.5) => steel1,
    :(x<=0.5) => steel2
]
model = Model(mesh, materials)

bcs = [
    :(x==0) => NodeBC(ux=0, uy=0, uz=0)
    :(x==1) => SurfaceBC(uz=-0.04)
]

loggers = [
    :(x==1) => FacesSumLogger("tip.table"),
    [0.05, 0.05, 0.1] => IpLogger("ip.table"),
    :(y==0.1 && z==0.1) => NodeGroupLogger("topgroup.book"),
    [0 0.05 0.1; 1 0.05 0.1] => SegmentLogger("top.book", n=40),
    [0 0.05 0.0; 1 0.05 0.0] => SegmentLogger("bottom.book", n=40),
]

setloggers!(model, loggers)
addstage!(model, bcs, nouts=2)

solve!(model, tol=0.01, autoinc=true, quiet=true)
Model setup
  setting elements...
  3D model 3d model
    252 nodes
    120 elements
    212 faces
    424 edges
      2 materials
      0 loggers

  setup_logger: No ip found at [0.05, 0.05, 0.1]. Picking the nearest at
  [0.039434, 0.039434, 0.092956]
Mechanical solver
  active threads: 1
  model type: 3d
  file ./top.book written
  file ./bottom.book written
  file ./top.book written
  file ./bottom.book written
  file ./top.book written
  file ./bottom.book written

The loggers are classified single loggers and group loggers. Single loggers record a table of data. Group loggers record a book, which is a set of tables. Once the analysis is finished, the loggers data can be recovered in another script calling the constructors of the types DataTable and DataBook.

using Amaru

tip = DataTable("tip.table")

 │       ux │       uy │         uz │       fx │       fy │       fz │ out │ 
 │  0.0e+00 │  0.0e+00 │        0.0 │  0.0e+00 │  0.0e+00 │      0.0 │ 0.0 │ 
 │ -8.1e-20 │  8.1e-16 │    -0.0004 │ -5.9e-13 │  5.2e-13 │ -2.22233 │ 0.0 │ 
 │  5.8e-19 │  1.1e-15 │    -0.0012 │ -1.1e-12 │  6.5e-13 │   -6.667 │ 0.0 │ 
 │  1.3e-18 │  2.1e-15 │    -0.0028 │ -1.0e-12 │  7.1e-13 │ -15.5563 │ 0.0 │ 
 │  3.5e-18 │  4.8e-15 │     -0.006 │  6.4e-13 │  2.6e-12 │  -33.335 │ 0.0 │ 
 │  1.8e-18 │  8.6e-15 │    -0.0124 │ -5.4e-12 │  3.9e-12 │ -68.8924 │ 0.0 │ 
 │  4.6e-18 │  9.7e-15 │      -0.02 │ -6.1e-12 │  9.0e-12 │ -111.117 │ 1.0 │ 
 │ -9.9e-20 │ -6.1e-18 │   -0.02128 │  5.7e-14 │  2.2e-15 │ -117.705 │ 1.0 │ 
 │ -1.2e-19 │ -6.7e-18 │  -0.022688 │  7.0e-13 │  9.4e-15 │ -123.521 │ 1.0 │ 
 │ -1.4e-19 │ -6.9e-18 │ -0.0242368 │ -3.2e-14 │ -1.4e-14 │ -129.086 │ 1.0 │ 
 │ -1.3e-19 │ -7.8e-18 │ -0.0259405 │ -2.9e-14 │  3.6e-14 │ -134.693 │ 1.0 │ 
 │ -1.3e-19 │ -8.8e-18 │ -0.0278145 │ -2.8e-13 │  1.6e-14 │ -140.261 │ 1.0 │ 
 │ -1.3e-19 │ -1.0e-17 │  -0.029876 │ -2.6e-13 │  2.0e-14 │ -144.938 │ 1.0 │ 
 │ -8.1e-20 │ -1.2e-17 │ -0.0321436 │  6.8e-14 │  6.6e-14 │ -148.669 │ 1.0 │ 
 │ -9.9e-20 │ -1.2e-17 │ -0.0346379 │ -1.3e-13 │  1.0e-14 │ -152.093 │ 1.0 │ 
 │ -9.9e-20 │ -1.3e-17 │ -0.0373817 │ -5.8e-13 │  9.1e-15 │ -155.302 │ 1.0 │ 
 │ -1.5e-19 │ -1.4e-17 │      -0.04 │  3.7e-13 │  8.5e-14 │  -157.96 │ 2.0 │ 
using Amaru

long = DataBook("topgroup.book").tables[end]

 │    x │   y │   z │         ux │       fx │       uy │       fy │       uz │       fz │ 
 │  0.0 │ 0.1 │ 0.1 │        0.0 │ -3.2e+02 │  0.0e+00 │  1.1e+02 │  0.0e+00 │  1.1e+02 │ 
 │ 0.05 │ 0.1 │ 0.1 │ 0.00032737 │  2.9e-03 │ -1.4e-04 │  1.0e-03 │ -1.9e-04 │ -1.9e-03 │ 
 │  0.1 │ 0.1 │ 0.1 │ 0.00072704 │  2.9e-03 │ -1.5e-04 │  4.4e-03 │ -7.1e-04 │ -4.9e-04 │ 
 │ 0.15 │ 0.1 │ 0.1 │  0.0010785 │ -7.2e-04 │ -1.1e-04 │  1.5e-03 │ -1.6e-03 │  1.3e-04 │ 
 │  0.2 │ 0.1 │ 0.1 │  0.0013472 │ -3.6e-04 │ -6.6e-05 │  1.0e-04 │ -2.9e-03 │ -1.3e-04 │ 
 │ 0.25 │ 0.1 │ 0.1 │  0.0015526 │  1.8e-06 │ -4.5e-05 │ -8.6e-07 │ -4.3e-03 │  1.2e-05 │ 
 │  0.3 │ 0.1 │ 0.1 │  0.0017239 │ -1.3e-06 │ -3.2e-05 │ -9.9e-07 │ -6.0e-03 │ -1.2e-07 │ 
 │ 0.35 │ 0.1 │ 0.1 │  0.0018695 │ -1.2e-07 │ -2.5e-05 │ -7.0e-07 │ -7.8e-03 │ -8.7e-09 │ 
 │  0.4 │ 0.1 │ 0.1 │  0.0020028 │  2.6e-14 │ -2.4e-05 │  1.0e-13 │ -9.7e-03 │  2.6e-13 │ 
 │ 0.45 │ 0.1 │ 0.1 │  0.0021251 │  6.3e-14 │ -2.2e-05 │  1.1e-15 │ -1.2e-02 │  1.0e-13 │ 
 │  0.5 │ 0.1 │ 0.1 │  0.0022369 │ -2.2e-15 │ -2.0e-05 │  1.7e-13 │ -1.4e-02 │ -6.8e-14 │ 
 │ 0.55 │ 0.1 │ 0.1 │   0.002338 │  1.8e-14 │ -1.8e-05 │  2.1e-13 │ -1.6e-02 │  8.2e-14 │ 
 │  0.6 │ 0.1 │ 0.1 │  0.0024285 │ -8.2e-14 │ -1.6e-05 │ -3.2e-14 │ -1.9e-02 │ -5.8e-13 │ 
 │ 0.65 │ 0.1 │ 0.1 │  0.0025083 │  6.4e-14 │ -1.4e-05 │ -7.7e-14 │ -2.1e-02 │  3.1e-13 │ 
 │  0.7 │ 0.1 │ 0.1 │  0.0025775 │ -1.0e-13 │ -1.2e-05 │ -3.2e-13 │ -2.4e-02 │ -1.8e-12 │ 
 │ 0.75 │ 0.1 │ 0.1 │   0.002636 │  1.0e-13 │ -9.8e-06 │ -1.1e-13 │ -2.6e-02 │ -4.4e-13 │ 
 │  0.8 │ 0.1 │ 0.1 │  0.0026839 │ -6.6e-14 │ -7.9e-06 │ -4.1e-13 │ -2.9e-02 │ -4.0e-13 │ 
 │ 0.85 │ 0.1 │ 0.1 │  0.0027212 │  1.5e-13 │ -5.9e-06 │ -1.2e-13 │ -3.2e-02 │  7.9e-13 │ 
 │  0.9 │ 0.1 │ 0.1 │  0.0027478 │ -2.1e-13 │ -3.9e-06 │ -1.5e-13 │ -3.4e-02 │  1.6e-15 │ 
 │ 0.95 │ 0.1 │ 0.1 │  0.0027638 │  2.8e-14 │ -1.9e-06 │ -1.2e-13 │ -3.7e-02 │  6.6e-13 │ 
 │  1.0 │ 0.1 │ 0.1 │  0.0027693 │  1.1e-13 │ -7.0e-07 │ -8.9e-14 │ -4.0e-02 │ -4.8e+00 │ 

Plotting

Amaru provides a chart ploting function cplot to ease the visualization of the data stored in DataTable and DataBook objects.

using Amaru

tip = DataTable("tip.table")
cplot(
    (x=tip.uz, y=tip.fz, marker="o"),
    "uz_vs_fz.svg",
    xmult  = 1e3,
    xlabel = raw"$u_z$ [mm]",
    ylabel = raw"$f_z$ [kN]",
)

topgroup = DataBook("topgroup.book").tables[end]
cplot(
    (x=topgroup.x, y=topgroup.uz, marker="o"),
    "x_vs_uz.svg",
    ymult  = 1e3,
    xlabel = raw"$x$ [m]",
    ylabel = raw"$u_z$ [mm]",
)

top = DataBook("top.book").tables[end]
bottom = DataBook("bottom.book").tables[end]
cplot(
    (x=top.x, y=top.sxx, marker="o", label="top"),
    (x=bottom.x, y=bottom.sxx, marker="o", label="bottom"),
    "x_vs_sxx.svg",
    ymult  = 1e-3,
    xlabel = raw"$x$ [m]",
    ylabel = raw"$\sigma_{xx}$ [MPa]",
)

Chart plotting

  generating plot u_z$ [mm] vs f_z$ [kN]

  Arguments:

    args: plot data and optional filename

  Optional named arguments:

    xlabel, ylabel, xbins, ybins, showgrid, ticklength, figsize, legendloc,
    legendexpand, bbox_to_anchor, ncol, xlim, ylim, equalaspect, xscale,
    yscale, xmult, ymult, ticksinside, axis, arrowaxis, xticks, xticklabels,
    yticks, yticklabels, fontsize, legendfontsize, textfontsize, labelspacing,
    annotations, tagpos, tagloc, tagdist, tagfontsize, tagcolor, tagalign,
    x2label, y2label, x2mult, y2mult, y2bins, x2lim, y2lim, y2scale, copypath,
    quiet

  Optional named arguments per curve:

    x, y, color, ls, lw, marker, ms, mfc, label, tag, tagpos, tagloc, tagdist,
    tagfontsize, tagcolor, tagalign

  file uz_vs_fz.svg saved

Chart plotting

  generating plot x$ [m] vs u_z$ [mm]

  Arguments:

    args: plot data and optional filename

  Optional named arguments:

    xlabel, ylabel, xbins, ybins, showgrid, ticklength, figsize, legendloc,
    legendexpand, bbox_to_anchor, ncol, xlim, ylim, equalaspect, xscale,
    yscale, xmult, ymult, ticksinside, axis, arrowaxis, xticks, xticklabels,
    yticks, yticklabels, fontsize, legendfontsize, textfontsize, labelspacing,
    annotations, tagpos, tagloc, tagdist, tagfontsize, tagcolor, tagalign,
    x2label, y2label, x2mult, y2mult, y2bins, x2lim, y2lim, y2scale, copypath,
    quiet

  Optional named arguments per curve:

    x, y, color, ls, lw, marker, ms, mfc, label, tag, tagpos, tagloc, tagdist,
    tagfontsize, tagcolor, tagalign

  file x_vs_uz.svg saved

Chart plotting

  generating plot x$ [m] vs \sigma_{xx}$ [MPa]

  Arguments:

    args: plot data and optional filename

  Optional named arguments:

    xlabel, ylabel, xbins, ybins, showgrid, ticklength, figsize, legendloc,
    legendexpand, bbox_to_anchor, ncol, xlim, ylim, equalaspect, xscale,
    yscale, xmult, ymult, ticksinside, axis, arrowaxis, xticks, xticklabels,
    yticks, yticklabels, fontsize, legendfontsize, textfontsize, labelspacing,
    annotations, tagpos, tagloc, tagdist, tagfontsize, tagcolor, tagalign,
    x2label, y2label, x2mult, y2mult, y2bins, x2lim, y2lim, y2scale, copypath,
    quiet

  Optional named arguments per curve:

    x, y, color, ls, lw, marker, ms, mfc, label, tag, tagpos, tagloc, tagdist,
    tagfontsize, tagcolor, tagalign

  file x_vs_sxx.svg saved