NAME
BasisFuncGrid - basis function modification of a GridFE object
(mixed FEM)
INCLUDE
include "BasisFuncGrid.h"
SYNTAX
class BasisFuncGrid : public GridWithPts
{
friend class FieldFE; // for efficient interpolation
Handle(GridFE) geomt_grid;
bool isop; // true: isoparm. elm. => all info from grid
int nsd;
int nsd_phys;
// note that the present implementation of BasisFuncGrid is restricted
// to meshes where all the elements are of the same type!
// these variables replace those in GridFE when isop==false, in case
// of isoparametric elements, none of the variables below are used
int nno; // no of basis function nodes
int nbf; // total no of basis functions
int nbe; // total no of basis functions in an element
int nne; // no of basis function nodes in an element
int nbind;
Handle(Indicators) essbind;
MatSimple(real) coor;
String elm_tp;
HandleElmDefs elmdef;
MatSimple(int) nodel;
// loc2glob_arr(e,j): global dof corresponding to the local dof j in elm e
MatSimple(int) loc2glob_arr;
VecSimple(int) node2dof_arr;
int current_node; // used in the grid iterator functions
bool incorrect_coor; // true if coor is not moved in move()
void generateMesh (); // compute new basis function nodes and dofs
public:
BasisFuncGrid ();
BasisFuncGrid (const GridFE& grid);
~BasisFuncGrid ();
void redim (const GridFE& grid);
const GridFE& grid () const { return geomt_grid(); }
GridFE& grid () { return geomt_grid(); }
void setElmType (const String& old_tp, const String& new_tp);
void setElmType (const String& new_tp);
bool update ();
bool ok () const;
bool isoparametric () const { return isop; }
int loc2glob (int e, int dof) const;
void loc2glob (VecSimple(int)& l2g, int e) const;
int getNoNodesInElm (int e =1) const; // basis func. nodes in elm e
int getNoBasisFuncInElm (int e =1) const; // equals no of dof in elm e
int getNoBasisFuncAtBasisNodeInElm (int elm_node, int e = 1) const;
int getBasisFuncNoInElm (int elm_node, int basis_func_no_at_this_node,
int e = 1) const;
int getBasisFuncNode (int global_basis_func_no) const;
int node2dof (int node) const; // global node -> global basis func no
int getNoNodes () const;
int getTotalNoDof () const;
int getNoSpaceDim () const { return nsd; }
int getNoPhysicalSpaceDim () const { return nsd_phys; }
real getCoor (int node, int dir) const;
Ptv(real) getCoor (int node) const;
void getCoor (Ptv(real)& point, int node) const;
void getMinMaxCoord (Ptv(real)& mincoord, Ptv(real)& maxcoord) const;
String getElmType (int e =1) const; // this version: independent of e!
bool allElmsOfSameType () const;
const Indicators& getEssBoInds () const { return essbind.getRef(); }
Indicators& getEssBoInds () { return essbind.getRef(); }
void setBoInd (int node, int indno);
void clearBoInd (int node, int indno);
void attach (Indicators& essboinds, bool automatic_fill = true);
void fillIndicators (Indicators& bfind);
bool notEqual (const BasisFuncGrid& bfnodes);
// only essential conditions are handled here (natural conditions are
// related to sides, i.e., the geometry and are handled by GridFE::BoNode)
bool essBoNode (int node, int indno) const;
bool essBoNode (int node) const;
bool essBoNodesInElm (int elm_no, int indno) const;
void print (Os os) const;
void scan (Is is);
// iterate through all the grid points:
virtual void startIterator ();
virtual bool nextPt (Ptv(real)& x);
bool nextPt (Ptv(real)& x, int& node);
// other virtual functions defined in base classes:
virtual int getNoPoints () const;
int isNode (const Ptv(real)& point);
virtual int nearestPoint
(const Ptv(real)& point, real& distance, bool& exact);
virtual void scale (); // scale the nodal coordinates
virtual void unscale (); // unscale the nodal coordinates
void attachScale (const SpaceTimeScale& scale);
virtual void isToBeChanged (); // redefined here (inherited from Grid)
void move (const FieldsFE& displacement, real scale_factor = 1.0);
// re-generate basis function grid:
void move (bool do_not_move_basis_function_nodes);
CLASS_INFO
VIRTUAL_CAST(BasisFuncGrid)
};
// a class VecSimplest(BasisFuncGrid) is defined
KEYWORDS
trial function nodes, mixed finite elements, finite elements,
grid
DESCRIPTION
Finite element basis functions are usually defined in terms of a
standard finite element grid where the expansion of the
unknown(s) and the geometric transformation of a standard element
utilize the same basis functions. We refer to such elements as
"isoparametric". In the isoparametric case, GridFE represents
the complete information about the grid.
In mixed finite element methods one often utilizes non-isopara
metric elements, that is, elements where the geometric mapping
and the expansion of the unknown(s) are based on different basis
functions. One will then often have a set of nodes defining the
geometry and an additional set of nodes related to the basis
functions for the unknown. We will refer to the functions used
for approximating the unknown(s) as "basis functions". The corre
sponding functions used to map an element from the local element
coordinate system to the physical domain are called "geometry
functions".
The description of various elements is represented as subclasses
in the ElmDef hierarchy. Every element has a definition of its
geometry functions (geomtFunc in ElmDef) and basis functions
(basisFunc in ElmDef). The nodes that are related to the geome
try functions are represented in a GridFE object. Our idea is to
introduce an additional class, BasisFuncGrid for representing the
nodes related to the basis functions. In case of isoparametric
elements, class BasisFuncGrid gets all its information from an
underlying GridFE object. However, for non-isoparametric ele
ments, BasisFuncGrid will have its own set of nodes.
Technically, class BasisFuncGrid has an indicator isop that is
true if all elements in the grid are isoparametric. Typical Bas
isFuncGrid member functions test if isop is true, in that case
the corresponding function in the associated GridFE is called, if
it is false, the function has to look up information in the
internal data structure of class BasisFuncGrid.
CONSTRUCTORS AND INITIALIZATION
There are two constructors. First one without arguments that does
nothing. Then there is a constructor taking an GridFE object as
argument. This second is identical to the empty constructor and
a redim call (this is standard in Diffpack). Hence, to initial
ize the BasisFuncGrid object, one must feed a GridFE object to
BasisFuncGrid, either using the constructor or the redim func
tion. If the elements are isoparametric, this is sufficient ini
tialization of the BasisFuncGrid object. For non-isoparametric
elements, one must assign the element type by call setElmType.
This version of class BasisFuncGrid can only work with one ele
ment type if non-isoparametric elements are wanted. The setElm
Type function will automatically initiate computations for manag
ing the degrees of freedom for a scalar field over the given non-
isoparametric element. Handling degrees of freedom for composite
fields is performed by class DegFreeFE.
MEMBER FUNCTIONS
grid - gives access to the underlying GridFE object.
update - updates the size of internal data structures if the grid
has been changed. For example, in adaptive methods, one should
call update every time the GridFE object has been manipulated.
Similar update functions are present in various fields, for
example, in FieldFE.
isoparametric - returns true if all elements in the grid are of
isoparametric type (that is, the same functions are used for
determining the shape of the element and the expansion of the
unknown over the element).
log2glob - returns the global node number corresponding to a
local node in an element. The term node here refers to a node
used for defining basis functions. Therefore this loc2glob func
tion is central for relating local degrees of freedom to global
degrees of freedom in the linear system that arises from the
finite element discretization.
log2glob(VecSimplest(int),int) - redims and fills a vector with
global node numbers for all local nodes in the element.
getNoNodesInElm - returns the number of basis function nodes in
an element. For example, if we have the four node quadrilateral
element with a constant shape function,
// we have a BasisFuncGrid bg
int m = bg.grid().getNoNodesInElm(e);
int n = bg.getNoNodesInElm(e);
Here m will be 4 while n will be 1.
getNoNodes - returns the number of basis function nodes. In the
example given under getNoNodesInElm, bg.getNoNodes() equals the
number of elements in the grid, that is, bg.grid().getNoElms().
getNoSpaceDim - gets the number of space dimensions.
getNoBasisFuncAtBasisNodeInElm - returns the number of basis
functions (degrees of freedom) at a basis function node in an
element. Normally this will be 1, but in p-FEM the basis function
nodes on the sides of the elements will have many associated
basis functions.
getBasisFuncNoInElm - the inverse function of "getNoBasisFuncAt
BasisNodeInElm.
getBasisFuncNode - given a global basis function number (degree
of freedom for a scalar field) global_basis_func_no, the function
returns the basis function node number that corresponds to this
degree of freedom. (At present, the function can only handle the
trivial case where the number of basis functions equals the num
ber of basis function nodes, otherwise an error message is
issued.)
node2dof - returns the basis function number (i.e. degree of
freedom number for the associated scalar field) of the first
basis function at a particular node. Convenient in, e.g.,
FieldFE::valueNode for a quick look-up of function value degrees
of freedom. If this application of the function is to be success
ful, one must follow a convention that when there are several
degrees of freedom (associated with a single scalar field) at a
basis function node, the first degree of freedom represents the
function value. If there is only one basis function (degree of
freedom) at each basis function node, the node2dof is an identity
mapping.
setElmType - sets the element type for an element. For example,
if you have generated a grid consisting of ElmB4n2D elements in a
preprocessor, you must apply the bilinear element for mapping the
element geometries, but the basis functions in each element can
be changed - for example to piecewise constants. One then simply
calls setElmType with the proper argument. If you do not know at
compile them the elements in the grid (old_tp), you can look up
the element type in the computed grid:
basis_func_grid->setElmType (new_tp);
or (the older)
basis_func_grid->setElmType (grid->getElmType(1),new_tp);
Note that getElmType(1) (i.e. look up type of element no. 1) is
okay since any use of BasisFuncGrid requires that all the ele
ments in the geometry grid are of the same type.
getEssBoInds - returns access to the Indicators object inside
this BasisFuncGrid object. Note that these indicators are used
for essential boundary conditions only (this is reflected in the
name, here getEssBoInds, while the corresponding function in
GridFE is boundaryData). Natural conditions are associated with
sides in elements and reflect hence geometry properties, i.e.,
GridFE must be responsible for this information. The indicators
in GridFE (accessed by boundaryData and clear/setBoInd functions)
cover natural condititions, and in the case of isoparametric ele
ments, also essential conditions.
attach - enables attachment of a new boundary indicator (for
essential conditions, see documentation of getEssBoInds). If one
attaches a new set of indicators in a GridFE object, one must
attach the corresponding Indicators objects in all BasisFuncGrid
classes that are connected to this GridFE object, if the elements
are non-isoparametric. That is, for non-isoparametric elements
the an indicator consists of a GridFE indicator and one corre
sponding indicator for all BasisFuncGrid objects. The GridFE
indicator will then determine the natural conditions along sides
(a geometric property), whereas the BasisFuncGrid indicators deal
with the essential conditions related to basis function degrees
of freedom. If a GridFE indicator is set and attached to the
GridFE object, one simply calls fillIndicators to compute the
corresponding BasisFuncGrid indicator and attaches the result
using attach. When the extra boolean argument to attach is true,
attach will first call fillIndicators to ensure that the indica
tor is updated according to the indicator information in the
underlying grid.
fillIndicators - computes a boundary indicator for the current
BasisFuncGrid object, using information about the current indica
tor in the underlying GridFE object. This function is normally
called from attach (see above).
setBoInd, clearBoInd - these functions are as described in
GridFE, but now the "nodes" are the nodes that are used in the
definition of the basis functions.
move - moves the basis function nodes if the basis function grid
consists of non-isoparametric elements. One function takes a dis
placement field and moves the nodes according to this field (see
also the similar move function in class GridFE). The other func
tion takes a do_not_move_basis_function_nodes argument, and if
this argument is false, it recomputes the coordinates of the
basis function nodes by executing the generateMesh function. This
latter version is slower than the former, but the basis function
coordinates will be consistent with their location in the refer
ence coordinate system (note that interpolating a displacement
field generally gives a small mismatch between the moved node and
its location computed by first moving the geometry and then map
ping a local node). If do_not_move_basis_function_nodes is true,
move does actually nothing except marking that the grid has
changed and must be restored the next time a field is dumped in
simres format. This is very efficient. The internal bool incor
rect_coor is then turned on to indicate that the values in coor
are incorrect. However, it is seldom that these values are actu
ally needed in a simulation (plotting velocity vectors at basis
function nodes is one example). Also, if the mesh is isoparamet
ric, move has no effect on coor anyway. Note that GridFE::move
must be called prior to any BasisFuncGrid::move!!
DEVELOPED BY
SINTEF Applied Mathematics, Oslo, Norway, and University of Oslo,
Dept. of Mathematics, Norway
AUTHOR
Hans Petter Langtangen, SINTEF/UiO