Introduction
In the first step of our analysis, which is detailed in step-1, we defined the mesh. However, additional information is required to conduct a basic finite element analysis. As such, we will proceed by defining the degrees of freedom (DoFs) and the model in this step. Finally, we will apply the relevant boundary conditions to obtain the desired solution.
The poisson equation
The issue we want to solve is the linear Poisson equation that reads as follows: $$ \begin{equation} \sigma\nabla^{2}\phi=f \label{eq:poisson} \tag{1} \end{equation} $$ where \(\sigma\) and \(f\) denote the model's coefficients. Below are the related boundary conditions: $$ \begin{equation} \sigma\nabla\phi\cdot\vec{n}=0\qquad\mathrm{on}\quad\partial\Omega_{N} \label{eq:neumann} \tag{2} \end{equation} $$ and $$ \begin{equation} \phi=\phi_{g}\qquad\mathrm{on}\quad\partial\Omega_{D} \label{eq:dirichlet} \tag{3} \end{equation} $$ where the Dirichlet boundary condition and Neumann boundary condition are represented by the subscripts \(D\) and \(N\).
Define the degree of freedom (DoF)
The degree of freedom (DoF) or the degrees of freedom (DoFs) can be used to define the name of each DoF and also to apply the necessary boundary conditions ([bcs]
), elements ([elmts]
), and so on. The [dofs]
block looks like below:
The degrees of freedom (DoF), or DoFs, are used to assign names to each DoF and to apply the required boundary conditions (bcs
) and elements (elements
). The block of code defining the DoFs is presented below as dofs
:
"dofs":{
"names":["dof-a","dof-b","dof-c",...,"dof-x"]
}
Options
The dofs
block includes an option called names, which is used to specify the name of each degree of freedom. It is important to note that the order in which the names are listed corresponds to the index of each degree of freedom. For example, in a 2D elastic analysis, two displacement degrees of freedom are required, namely disp_x
and disp_y
. The dofs
block should thus be defined as follows:
"dofs":{
"names":["disp_x","disp_y"]
}
In this specific case, disp_x
is assigned as the first degree of freedom with an index of 1, while disp_y
is assigned as the second degree of freedom with an index of 2. Note that the only option available in the dofs
block is names
, with no additional options
Since the Poisson equation involves only a single degree of freedom, the final expression for the dofs
block is as follows
"dofs":{
"names":["phi"]
}
Element for Poisson equation
With the degree of freedom established, we now need to define the model in Eq.\(\eqref{eq:poisson}\). To accomplish this, we use the elements
block, which is defined as follows:
"elements":{
"elmt1":{
"type":"poisson",
"dofs":["phi"],
"material":{
"type":"constpoisson",
"parameters":{
"sigma":1.0,
"f":1.0e1
}
}
}
}
The type
option specifies the element or model to be used, which may be one of the built-in elements in AsFem or a user-defined element (UEL
). The degrees of freedom to be used in the element are defined by the dofs
option, while the material option specifies the name of the material sub-block to be used. Once the elements
block is defined, the model described in Eq.\(\eqref{eq:poisson}\) is complete.
Material properties
The coefficients \(k\) and \(F\), which correspond to the material properties in Eq.\(\eqref{eq:poisson}\), can be calculated or defined using the material
sub-block, as shown below:
"material":{
"type":"constpoisson",
"parameters":{
"sigma":1.0,
"f":1.0e1
}
}
The material
sub-block includes the type
option, which specifies the name of the material type defined in AsFem. The parameters option is used to define the parameters that will be used in our model. In this case, we will use \(\sigma=1.0\) and \(f=10.0\)
Boundary conditions
The boundary conditions described in Eq.\(\eqref{eq:dirichlet}\) and \(\eqref{eq:neumann}\) can be applied using the bcs
block. In our case, the Neumann boundary condition in Eq.\(\eqref{eq:neumann}\) is zero, and thus, only the Dirichlet boundary condition needs to be taken into account:
"bcs":{
"left":{
"type":"dirichlet",
"dofs":["phi"],
"bcvalue":0.1,
"side":["left"]
},
"right":{
"type":"dirichlet",
"dofs":["phi"],
"bcvalue":0.5,
"side":["right"]
}
}
The left
and right
sub-block is used to specify different boundary conditions for the left and right boundaries. The type
option within each sub-block is used to specify the type of boundary condition, which is supported by AsFem. The dof
option denotes the name of the DoF to which the given boundary conditions will be applied. In our case, we constrain the value of \(\phi\) on the left and right sides of a rectangular domain to be 0.1 and 0.5, respectively.
Static analysis
Now that the model and boundary conditions have been defined, we are ready to begin the FEM calculation. To specify the type of analysis we want to perform, we use the job
block. In this case, since we are conducting a static analysis, the block can be defined as follows:
"job":{
"type":"static",
"print":"on",
}
If you want to observe how the iteration information changes during the analysis, you can use the following:
"job":{
"type":"static",
"print":"dep",
"restart":true
}
The print
option is used to enable basic information output in the terminal. If you prefer to see fewer outputs, you can use "print":"off"
.
Run it in AsFem
To proceed with the second example in AsFem, create a new text file and name it step2.json
, or a name of your choosing. Next, copy the following lines into your input file:
{
"mesh":{
"type":"asfem",
"dim":2,
"nx":50,
"ny":50,
"meshtype":"quad4",
"savemesh":true
},
"dofs":{
"names":["phi"]
},
"elements":{
"elmt1":{
"type":"poisson",
"dofs":["phi"],
"material":{
"type":"constpoisson",
"parameters":{
"sigma":1.0,
"f":1.0e1
}
}
}
},
"projection":{
"type":"default",
"vectormate":["gradu"]
},
"bcs":{
"left":{
"type":"dirichlet",
"dofs":["phi"],
"bcvalue":0.1,
"side":["left"]
},
"right":{
"type":"dirichlet",
"dofs":["phi"],
"bcvalue":0.5,
"side":["right"]
}
},
"nlsolver":{
"type":"newton",
"solver":"gmres",
"maxiters":50,
"abs-tolerance":5.0e-7,
"rel-tolerance":5.0e-10,
"s-tolerance":0.0,
"preconditioner":"jacobi"
},
"output":{
"type":"vtu",
"interval":1
},
"qpoints":{
"bulk":{
"type":"gauss-legendre",
"order":2
}
},
"job":{
"type":"static",
"print":"dep",
"restart":true
}
}
You can also find the complete input file in examples/tutorial
.
If everything goes well, you can see the following image in your Paraview:
Wait a second, what should I do if I want to solve a Poisson equation in 3D?
The solution is straightforward - you just need to modify your mesh to be 3D. Here is an example of how you can do this using the input file step2-3d.json
:
"mesh":{
"type":"asfem",
"dim":3,
"nx":50,
"ny":50,
"nz":50,
"meshtype":"hex8",
"savemesh":true
}
then you will see: