Skip to content
Roman Poya edited this page Jun 28, 2018 · 8 revisions

A detailed walkthrough of Florence

In this tutorial we are going to have a look at some of Florence's core functionality. To use Florence in your project, you typically add the following line at the top of your python scripts

from Florence import *

1. Generating meshes in Florence

a) Basics of meshing and predefined shapes

We are going to have a look at generating and preparing meshes in Florence for finite element analysis. Florence offers the possibility to define meshes on a set of predefined shapes/geometries. As of version 0.1.4, Florence supports 5 types of elements. In Florence's terminology these are

  1. line
  2. tri
  3. quad
  4. tet
  5. hex

For instance, to create a mesh on a unit square domain, we simply define a Mesh instance and call the Square method on it, as follows

mesh = Mesh()
mesh.Square(nx=2, ny=2, element_type="quad")

This will create a quadrilateral mesh on a unit square domain with 4 elements. We can access the nodal coordinates and element connectivity of the mesh simply by

print(mesh.points)
print(mesh.elements)

For a more general rectangular shapes, we can define a Rectangle mesh as follows

mesh = Mesh()
mesh.Rectangle(lower_left_point=(0,0), upper_right_point=(2,1), nx=20, ny=10, element_type="tri")

This will create a triangular mesh on the specified rectangular domain with 400 elements. Finally, if we want to mesh a quadrilateral region such as parallelogram, trapezium etc, we can call the generic and rather low level map mesher from Florence called QuadrilateralProjection

mesh = Mesh().QuadrilateralProjection(c1=(0,0), c2=(2,0), c3=(2,3), c4=(1,2), npoints=10)

This will map mesh all four sides of the quadrilateral domain using 10 elements. Other predefined shapes include (not limited to)

mesh.Circle(radius=2., nrad=10, ncirc=30)

mesh.Arc(start_angle=0, end_angle=PI/2., radius=2., nrad=10, ncirc=30)

# plate with a hole
mesh.CircularPlate(side_length=30, radius=10, center=(0.,0.), ncirc=5, nrad=5, element_type="tri")

Three-dimensional meshes can be generated in a similar fashion for instance

mesh.Cube(nx=10, ny=10, nz=10, element_type="hex")

mesh.Parallelepiped(lower_left_rear_point=(0,0,0), upper_right_front_point=(2,4,10),
        nx=2, ny=4, nz=10, element_type="hex")

# for general 8 noded regions 
mesh = Mesh().HexahedralProjection(c1=(0,0,0), c2=(2,0,0), c3=(2,2,0), c4=(0,2,0.),
        c5=(0,1.8,3.), c6=(0.2,0,3.), c7=(2,0.2,3.), c8=(1.8,2,3.), npoints=6, equally_spaced=True)

mesh.Cylinder()
mesh.HollowCylinder()
mesh.Sphere()

b) Generating higher order elements

Support for arbitrary order nodal Lagrange and Lagrange Gauss-Lobatto as well as modal hierarchic elements is available. For instance, to get a 4th order Lagrange element on any type of mesh, we can call the generic function

# 4th order Lagrange Gauss-Lobatto elements
mesh.GetHighOrderMesh(p=4)
# 4th order Lagrange elements
mesh.GetHighOrderMesh(p=4, equally_spaced=True)

c) Mesh properties and attributes

Inquiring mesh edges/faces, boundary edges/faces is as simple as

all_edges = mesh.GetEdges()
boundary_edges = mesh.GetBoundaryEdges()
interior_edges = mesh.GetInteriorEdges()

all_faces = mesh.GetFaces()
boundary_faces = mesh.GetBoundaryFaces()
interior_faces = mesh.GetInteriorFaces()

Associativity of elements with edges/faces can also be enquired using

edge_to_element_map = mesh.GetElementsWithBoundaryEdges()
face_to_element_map = mesh.GetElementsWithBoundaryFaces()

Finding which nodes are shared between which elements can be done as follows

elements_sharing_nodes = mesh.GetNodeCommonality()

d) Mesh refinement and smoothing

Uniform mesh refinement on all kinds of meshes is supported through the generic function Refine

mesh.Refine(level=3)

Mesh smoothing (or rather non-uniform refinement) based on a given criterion is also supported. For example, to smooth out all elements with aspect ratio 2 and above we can do

mesh.Smooth(criteria={'aspect_ratio':2})

e) Mesh partitioning for parallel processing

Low and high order meshes can be partitioned for parallel processing using the built-in Partition call

partioned_mesh, partitioned_element_indices, partitioned_nodes_indices = mesh.Partition(n=12)

e) Mesh cutting operations

Low and high order meshes can be cut through using either the RemoveElements or GetLocalisedMesh functions

# geometric cuts
new_mesh = mesh.RemoveElements(xyz_min_max_array)
# algebraic cuts
new_mesh = mesh.GetLocalisedMesh(elements_indices_to_remove)

f) Mesh boolean operations

Meshes can be merged together simply through the +, - calls

mesh = Mesh().Square() + Mesh().Square(lower_left_point=(1,0))

g) Reading external meshes

The Mesh class of Florence supports reading meshes written in different formats such as Gmsh (.msh), .obj, GID, Salome, FRO, HDF5 etc

mesh.ReadGmsh("mesh_file_name.msh", element_type="tet")
mesh.ReadOBJ("mesh_file_name.obj", element_type="tri")
# or simply call
mesh.Read(filename, reader_type="gmsh", element_type="tet")