How to Create New Element
How to implement a new element
The practical way to write an element is to look at some element exists there in Kratos. one of these elements is LinearElement that is plane-strain two dimensional three nodded element. In .h file of this element after some "includes", the element class is defined. constructor and creat functions in this part are cmmon for all elements and just need to be renamed by the name of your element.i.e in the case of LinearElement the constructors are
LinearElement(IndexType NewId, GeometryType::Pointer pGeometry); LinearElement(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties);
and the Create is
Element::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes, PropertiesType::Pointer pProperties) const;
After these functions, some more familiar functions, for a FEM code, like are presented
The implementation of a new element is a standard operation in the FEM and an effort was made to simplify
LinearElement::LinearElement(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties): Element(NewId, pGeometry, pProperties)
The basic interface to the element is provided in the class element.h which defines the interface for all the public functions allowed on a generic element.
The minimal informations needed at the moment of the construction of a new element are:
- Id: a unique identifier of the element
- Properties::Pointer: it is the pointer to the container of data which are common to a group of elements
- Geometry::Pointer: pointer to the entity which represents the topology of the element (tetrahedra, exahedra...). In its easiest instance the geometry is simply a list of pointers to the nodes of the element, but it may contain many more informations (described in a specific tutorial)
All of the informations above need to be given at the moment of construction. Additional info may be provided for the construction of specific element, however in general the kratos will have no direct access to them.
To conclude the element contains a pointer to a "DataValueContainer" which allows to store VARIABLES per each element. This implies that an empty element will store
1 unsigned int, a minimum of 3 "Shared Pointers" Having thus a non negligible memory occupation.
Telling to the kratos that a new element exists
After implementing and compiling an element, it is necessary to "teach" to the kratos how to recognize the new element. The idea is here to create a "model element" from which all the other elements will be creates. This is done in the "application.h" and "application.cpp" where an object is created and a Name is associated to it. This process for LinearElement is presented here. At the moment of reading a datafile the kratos parses the Value of the Element, asks the kernel for the model element with the corresponding Value and creates the new elements by creating copies of the model (calling internally the function Create)
The aim of this section is to provide a brief introduction to the main functions provided by the element interface.
Most of the elemental functions accept a parameter "CurrentProcessInfo". The basic use of this object is to carry informations about the current state of the process, for example the current TIME or DELTA\_TIME. This object is however a flexible container of variables and can be used to pass any variable to the element. An example is the implementation of a fractional step process where the element has to provide a different behaviour depending of the step in execution. This can be achieved easily by passing a variable FRACTIONAL\_STEP with the number of the current step. Note that the type of the variable passed ia free: as an example different backword differencing schemes can be implemented by simply passing a vector with the correct values of the BDF coefficients (see the element Fluid2D in the "incompressible\_fluid\_application" as example).
The "Degrees Of Freedom" (DOF):
The first step needed to solve a given problem is of course to define the variables we are trying to determine. Those unknowns are called degrees of freedom. The constructor of the element should provide the list of dofs for all of the nodes which compose the element. An example follows: ... Note that if the reactions are needed it is necessary to associate to each dof its action. This can be obtained by the following code: ...
Calculation of the Right Hand Side (RHS):
The kratos requires the elements to return A RESIDUA as RHS. This may not represent the natural choice for linear problems but allows to mix linear and non linear elements.
The residua is defined as RHS = dWext - dWint (note that indeed this corresponds to the standard definition changed of sign)
For linear problems, if the vector of external "forces" fext is known, The RHS can be calculated as RHS=fext-K*xp Where K is the "standard" stiffness matrix and xp is a vector containing the last known values of the dofs (note that the prescribed values are all known here)
Clearly the residual form is natural for non linear problems and requires no further explanation. The "tangent" stiffness matrix, called here LHS should be introduce with its natural sign. Note that for linear elements the "tangent" coincides with the "standard" stiffness matrix.
returns the elemental unique id. WARNING: unpredictable results may occur if different elements are constructed with the same Id. (generally speaking just one of the elements with the same Id will be preserved)
this function is called during the build phase and performs the calculation of RHS and LHS at the same time. As described above the RHS is a residua.
This function returns a vector with the list of dofs in the element. This list has to follow the same ordering used in the construction of the LHS and RHS.
This function returns a vector with the list of "EquationIds" associated to each element. Those ids are intended as the position of the corresnding dof in the global system matrix. This list has to follow the same ordering used in the construction of the LHS and RHS.
Function called ONCE at the first time a solving strategy is used.
InitalizeSolutionStep and FinalizeSolutionStep
Functions called ONCE at the beginning and end of a given solution process (a call of the Solve function of the solving strategy)
InitializeNonLinIteration and FinalizeNonLinIteration
Functions called once at the beginning and end of each non linear iteration. (they are called inside the Build process)
MassMatrix and DampMatrix
Return the elemental matrices with the same name
Gets the vectors of values corresponding to the first and second time derivatives for the elemental unknowns (at the time step desired)
This function exists with different overloads to accept variables of different type. The element can overload it as needed to calculate a given value or to perform a given operation. Returns a result of type "VariableType"
Similar to the function above but performs at once the calculation of the desired var on all the integration points. Returns Vector<VariableType>