FEATool
v1.8 Finite Element Analysis Toolbox |

Problem Definition

FEATool uses a struct format with several fields to specify and set up problem definitions. The FEATool GUI will automatically manage these fields, however if the model is exported, modified on the command line, or built from scratch it is important to know how these fields are used, which is explained below.

The FEATool problem definition struct consists of the following main fields

Field | Description |
---|---|

geom | Geometry objects |

grid | Grid structure |

sdim | Cell array of space dimension names |

phys | Physics mode structs |

dvar | Cell array of dependent variable names |

sfun | Cell array of shape functions |

coef | Cell array of coefficient and expression definitions |

eqn | Equation specification struct |

bdr | Boundary specification struct |

pnt | Point source and constraint specification struct |

sol | Solution vector and list of solution times |

A cell array of geometry objects used for grid generation is contained in the **geom.objects** field. The geometry is only used by the automatic grid generation and can be omitted if a grid is constructed by other means (for example with the grid function primitives). For example, the following code defines a geometry with a unit circle

fea.geom.objects = { gobj_circle() };

The **grid** struct field, which defines the computational grid, is explained in the Grid section.

The **sdim** field contains a cell array of strings with names for the space dimensions. These can then be used in FEATool functions, and equation/boundary specification and postprocessing. Typically the field will take the following forms

fea.sdim = { 'x' }; % 1D. fea.sdim = { 'x' 'y' }; % 2D. fea.sdim = { 'r' 'z' }; % 2D - Axisymmetry. fea.sdim = { 'x' 'y' 'z' }; % 3D.

but the name strings can be substituted arbitrarily.

The optional **phys** struct contains predefined physics modes that have been added with the addphys function. After editing and setting the appropriate physics mode coefficients the parsephys command will expand the physics to the fea parent **dvar**, **sfun**, **coef**, **eqn**, and **bdr** fields.

The **dvar** field contains a cell array of strings with names of the dependent (equation) variables which should be solved for. For example

fea.dvar = { 'u' 'v' };

defines two dependent variables, labeled *u* and *v*.

Similarly, the **sfun** field contains a cell array of strings with function names of the finite element shape functions to use for each dependent variable. Shape functions are defined in the *ellib* directory. For example

fea.dvar = { 'sflag1' 'sflag2' };

defines 1st order conforming basis functions for the first dependent variable and 2nd order for the second one.

The **coef** field is a (n_coef, 4) sized cell array of coefficient expressions that can be used in equation definitions and postprocessing. The first column gives the coefficient names, second a short description, third a long description, and the fourth column is a sub cell array for the coefficient expression definitions in each subdomain. (If any of the fields *const*, *expr*, and *vars* exist they will be merged internally with the *coef* field.) The assignment

fea.coef = { 'rho' '' '' { 1 2 } ; 'miu' '' '' { 3 '4*pi*sin(x)' } };

here defines two coefficients *rho* with values *1* and *2* in two respective subdomains, and *miu* with values *3* and the expression *4*pi*sin(x)*.

The **eqn**, **bdr**, and **pnt** structs are used to specify equations, boundary conditions, and point constraints. The composition of these fields is explained below in the corresponding subsections.

After solving a problem the **sol** field will contain the solution column vector **u** with rows corresponding to the degrees of freedom (ordered according to the order of the dependent variables in *fea.dvar*). For time dependent problems the columns in **u** correspond to solutions at different times, and additionally the output times will be stored in the **tlist** vector.

The equation struct contains the following fields

Field | Description |
---|---|

eqn.m.form | Form specifications for temporal terms |

eqn.m.coef | Coefficient specifications for temporal terms |

Shape functions are inherited from eqn.a.sfun |

Field | Description |
---|---|

eqn.a.form | Bilinear form specifications |

eqn.a.coef | Coefficient specifications for bilinear forms |

eqn.a.sfun | Shape function specification for bilinear forms |

Field | Description |
---|---|

eqn.f.form | Linear form specifications for right hand side/load vector |

eqn.f.coef | Coefficient specifications for right hand side/load vector |

eqn.f.sfun | Shape function specifications for right hand side/load vector |

Field | Description |
---|---|

eqn.dofm | Degree of freedom n numbering map for each cell |

eqn.ndof | Numbers of degrees of freedom for each dependent variable |

The **eqn.m** field contains specifications for the time dependent term (with time derivative). Similarly the **eqn.a** field contains specifications for the bilinear forms used in the iteration (stiffness) matrix, and the **eqn.f** field specifies the linear forms in the right hand side/load vector.

The above struct fields contain the **form** field which specifies the (bi-)linear forms to build and assemble. For bilinear forms the first row corresponds to the trial function space, and the second row the test function space. Linear forms only need to contain one row. In the form specification a 1 indicates a function value, 2 x-derivative, 3 y-derivative, and 4 z-derivative. For example a form specification [2 3;2 3] indicates a bilinear form with two terms, one term with both x-derivatives for the test and trial function spaces, and one with y-derivatives for both spaces (which in this case is a typical two-dimensional diffusion operator). Second order derivatives can also be specified as 22 for the xx-derivative, 23 xy-derivative and so on.

The **coef** field, is a cell array with coefficient values or expressions used for each term in the **form** field.

The **sfun** field is a cell array of shape function names used in the form assembly. This field is usually automatically constructed when calling the parseprob function.

**dofm** is an array specifying the local to global degree of freedom numbering for each dependent variable. The rows correspond to local degrees of freedoms on each cell and the columns give the cell numbers. (For linear conforming shape functions the dof mapping will be identical to the grid.c field.) This field is created when parseprob calls the mapdofbdr function.

**ndof** is simply an help array for the numbers of degrees of freedom for each dependent variable (equals to max(dofm(:)) and also automatically generated by mapdofbdr).

The boundary struct contains the following fields

Field | Description |
---|---|

bdr.d | Dirichlet boundary coefficients |

bdr.n | Neumann (flux) boundary coefficients |

bdr.bdrm | Boundary degree of freedom numbering maps |

Dirichlet boundary conditions are used to prescribe and fix a specific value for the dependent variables, while in contrast Neumann conditions represent a inward or outward directed flux (which are functions of the gradients of the dependent variables). Mixed Robin conditions are currently not available in FEATool. If a Dirichlet condition is prescribed on a boundary, the corresponding Neumann flux entry will be ignored. Alternatively, if a Dirichlet boundary coefficient entry is empty the Neumann flux contribution will be computed and added (however, all default Neumann contributions are zero corresponding to homogeneous do-nothing Neumann boundary conditions).

Dirichlet boundary coefficient values or string expressions for each boundary segment are specified in a cell array in the **bdr.d** field. Two syntaxes are supported, standard syntax where **d** is a cell array of size *n_dvar x n_bdr*, or extended syntax (supported in versions 1.5 or later) with **d** a *1 x n_dvar* cell array where each entry itself is a *n_bc_groups x n_bdr* cell array containing the coefficients. In the extended syntax the number of boundary condition groups *n_bc_groups* is due to the chosen finite element shape function (specifically the number of *nLDof* rows which is *1+n_sdim* for Hermite elements and *1* for all others). The extended syntax is used to prescribe separate conditions on the different local degrees of freedom (that is the basis function values and derivatives for Hermite elements). The Dirichlet boundary conditions are prescribed by the function bdrsetd.

If a Dirichlet boundary coefficient entry is empty, then Neumann (flux) conditions will be prescribed instead for the corresponding boundary segment. Similar to Dirichlet conditions, Neumann conditions are specified in the **n** field in either standard or extended syntax (bdrneu). An empty cell indicates homogeneous Neumann condition to be used (zero flux) for that boundary segment.

The **bdrm** arrays specifies the boundary condition mapping for each dependent variable. In an **bdrm** array the first row gives the global degree of freedom number, second the cell number, third cell edge number, fourth boundary section number, and fifth local degree of freedom number. While the **d** and **n** fields must be prescribed by the user or derived from the physics modes with a call to parsephys, the **bdrm** field is automatically created when parseprob calls the mapdofbdr function.

For example, assume a two dimensional time dependent problem with one dependent variable or unknown *u*, then the following standard boundary syntax

fea.bdr.d = { 1 'sin(pi*t*x)+u' [] [] }; fea.bdr.n = { [] 0 2 'nx*ux+ny*uy' };

will prescribe *u* constant *u = 1* on the first boundary, a string expression *u(x,t) = sin(pi*t*x)+u* on the second boundary, a constant flux Neumann condition *2* on the third boundary, and finally the flux expression *nx*ux+ny*uy* on the fourth and last boundary. Note that here in the string expressions it is perfectly valid to use constants, MATLAB and Octave functions, time *t*, function values and derivatives of the dependent variables, and also the normals, here *nx* and *ny*.

Assuming using a finite element basis functions with only one boundary condition group the equivalent extended syntax looks like the following

fea.bdr.d = { { 1 'sin(pi*t*x)+u' [] [] } }; fea.bdr.n = { { [] 0 2 'nx*ux+ny*uy' } };

If the default solvers *solvestat* and *solvetime* detects nonlinear Neumann boundary conditions they will attempt to linearize them by moving terms involving linear forms from the explicit right hand side to the implicit matrix (a boundary contribution to *eqn.a* instead of *eqn.f*). This is done by the bdrneu_lin function.

The point struct contains the following fields

Field | Description |
---|---|

pnt.index | Index to grid point (in grid.p) |

pnt.type | Specifies either sources or constraint |

pnt.dvar | Integer or string corresponding a dependent variable |

pnt.expr | scalar or string expression for constraint |

Point sources and Dirichlet point constraints can be specified in a **pnt** struct. The **type** field specifies either a point 'source' or 'constraint' for each point with a corresponding string value. Point sources are applied to the right hand side load vector *f* while constraints are applied to both *f* and the global matrix *A* with the information in the finite element problem struct (pntsetf and pntset). The sources or constraints will be applied to the degree of freedom closest to the grid point specified in the **index** field. The **dvar** field contains an integer or string expression pointing to a dependent variable in **dvar**. The sources or constraints are specified in the **expr** field either as a string expression or scalar so that *pnt.dvar(grid.p(:,pnt.index)) = pnt.expr*. (Note that a point constraint will override the usual Dirichlet boundary conditions at the given point).