Skip to content

4. Applying boundary conditions in Florence

Roman edited this page Jun 30, 2023 · 10 revisions

In this section we will have a look on how to set up and apply essential and natural boundary conditions in Florence. Applying boundary conditions in Florence is facilitated through callback functions.

a) Applying essential/Dirichlet boundary conditions

Consider the following square domain meshed with quadrilateral elements showing node and element numbering.

Let us assume that we are solving an elasticity type problem and we would now like to apply the Dirichlet boundary conditions such that all nodes at (x=0) are fixed in x and y direction. To do this we need to first create our own function

def dirichlet_function(mesh):
    pass

The name of this function can be chosen arbitrarily and does not need to be dirichlet_function. Within the body of this function, we need to create an array of NaNs of size nnode x nvar where nnode is the number of nodes in the domain and nvar is the number of variable/DoFs per node. For Poisson type problems nvar=1, for structural mechanics problems nvar=ndim (where ndim is the the spatial dimension i.e. ndim=2 for 2D/plane strain/plane stress problems and ndim=3 for 3D problems) and for coupled electromechanics problems nvar=ndim+1.

def dirichlet_function(mesh):
    boundary_data = np.zeros((mesh.nnode,2)) + np.NAN

Now, to fix all nodes at (x=0) in x and y directions we can simply query using numpy which nodes lie at x=0 i.e. mesh.points[:,0]==0 or np.isclose(mesh.points[:,0],0.)

def dirichlet_function(mesh):
    boundary_data = np.zeros((mesh.nnode,2)) + np.NAN
    condition = np.isclose(mesh.points[:,0],0.)

If we wanted to fix all nodes at (y=0) then the function would have looked like

def dirichlet_function(mesh):
    boundary_data = np.zeros((mesh.nnode,2)) + np.NAN
    condition = np.isclose(mesh.points[:,1],0.)

Notice that 0 has changed to 1 while indexing mesh.points. Finally we are supposed to return the data from our function that is

def dirichlet_function(mesh):
    boundary_data = np.zeros((mesh.nnode,2)) + np.NAN
    condition = np.isclose(mesh.points[:,0],0.)
    return boundary_data

We now need to tell Florence to use this boundary condition for our mesh

boundary_condition = BoundaryCondition()
boundary_condition.SetDirichletCriteria(dirichlet_function,mesh)

Here, we initiate a boundary condition object and call it's method SetDirichletCriteria by giving it our function name dirichlet_function followed by the arguments that our function takes. In principle, our function can take as many arguments as needed.

a) Applying natural/Neumann boundary conditions

Applying nodal natural/Neumann boundary condition is exactly the same as applying Dirichlet boundary condition. the only difference is in telling Florence how to use it

boundary_condition = BoundaryCondition()
boundary_condition.SetNeumannCriteria(neumann_function,mesh)

Applying Neumann boundary condition on a face/region or even a curved region is also supported. In such case, we still need our user defined function, but we need to return two arrays from our function, one array of size mesh.faces.shape[0] and the other one of size mesh.faces.shape[0] x ndim. The first array will describe which mesh faces the boundary condition should be applied on. The second array describes the forces applied to each of those elements. Please refer to the hyperelastic explicit dyanmics example in Florence's main repository for an example of this type of boundary condition.