# Kratos For Dummies OLD

(Difference between revisions)
 Revision as of 16:38, 22 February 2011 (view source)Gcasas (Talk | contribs) (→Element implementation methods file: poisson_2d.cpp)← Older edit Latest revision as of 09:34, 25 April 2012 (view source)Pablo (Talk | contribs) m (21 intermediate revisions by 2 users not shown) Line 387: Line 387: ///@name Member Variables ///@name Member Variables ///@{ ///@{ − boost::numeric::ublas::bounded_matrix msDN_DX; + '''boost::numeric::ublas::bounded_matrix msDN_DX; − boost::numeric::ublas::bounded_matrix msD; + '''boost::numeric::ublas::bounded_matrix msD;''' − array_1d msN; //dimension = number of nodes + '''array_1d msN; //dimension = number of nodes''' − array_1d ms_temp; //dimension = number of nodes + '''array_1d ms_temp; //dimension = number of nodes''' − array_1d point_sources; //dimension = number of nodes + '''array_1d point_sources; //dimension = number of nodes''' and to close the class definition: and to close the class definition: Line 569: Line 569: KRATOS_TRY KRATOS_TRY − boost::numeric::ublas::bounded_matrix msDN_DX; + '''boost::numeric::ublas::bounded_matrix msDN_DX;''' − boost::numeric::ublas::bounded_matrix msD; + '''boost::numeric::ublas::bounded_matrix msD;''' − array_1d msN; //dimension = number of nodes + '''array_1d msN; //dimension = number of nodes''' − array_1d ms_temp; //dimension = number of nodes + '''array_1d ms_temp; //dimension = number of nodes''' − array_1d point_sources; //dimension = number of nodes + '''array_1d point_sources; //dimension = number of nodes''' const unsigned int number_of_points = GetGeometry().size(); const unsigned int number_of_points = GetGeometry().size(); Line 1,169: Line 1,169: install install : '''KratosR1PoissonApplication''' : $(TOP)/libs ; install install : '''KratosR1PoissonApplication''' :$(TOP)/libs ; − ==== Customising the python variables file: kPoisson_python.cpp ==== + ==== Customising the python variables file: kPoisson_python_application.cpp ==== The following file basically indicates Kratos the variables to be used by the pyhton commands. Therefore, we have just to modify the name of the application ('''KratosR1PoissonApplication''') and to add the variables names ('''DUMMY_UNKNOWN''' for the unknown, '''DUMMY_MATERIAL''' for the material property and '''DUMMY_POINT_SOURCE''' for the source term). The following file basically indicates Kratos the variables to be used by the pyhton commands. Therefore, we have just to modify the name of the application ('''KratosR1PoissonApplication''') and to add the variables names ('''DUMMY_UNKNOWN''' for the unknown, '''DUMMY_MATERIAL''' for the material property and '''DUMMY_POINT_SOURCE''' for the source term). Line 1,233: Line 1,233: #include "includes/define.h" #include "includes/define.h" #include "'''kPoisson.h'''" #include "'''kPoisson.h'''" − #include "custom_python/add_custom_strategies_to_python.h" + //#include "custom_python/add_custom_strategies_to_python.h" − #include "custom_python/add_custom_utilities_to_python.h" + //#include "custom_python/add_custom_utilities_to_python.h" namespace Kratos namespace Kratos Line 1,271: Line 1,271: #endif // KRATOS_PYTHON defined #endif // KRATOS_PYTHON defined + + + ==== Creating a Custom Condition to incorporate the thermal loads: pointsource.h ; pointsource.cpp ==== + + The process of creating a custom condition is similar to creating an element, the easiest way is to copy the code from another condition and change it to suit our needs. Due to simplicity and similarities, the easiest files to start with are PointForce2D  from the structural application. The difference between our recently created element and the condition we are about to create is that in this case we'll be  loading data nodewisely. + + DUMMY_POINT_SOURCE is our variable containing the external thermal loads to our problem. + To include them we'll create a new condition called pointsource . KRATOS will call the condition and assign it node by node to the system of equations. + Since this is standard load, we only have to add the contribution to the right hand side (RHS) without any calculation. In pseudo code, our task is simply: + + RHS (node) + = DUMMY_POINT_SOURCE (node) + + Still, note that the structre of a condition, as well as the one in elements, includes both the RHS and the left hand side matrix (LHS). This gives us flexibility and thus we can incorporate operations that also affect the matrix. + We will create 2 files  (pointsource.h and pointsource.cpp ), preferably inside the custom_conditions folder . Bear in mind that conditions are a class called by the solver , so you have to respect the structure and subroutines required by it. Again, the same rules that apply to elements. + Again, in pseudocode: + + class pointsource + void CalculateLocalSystem + void CalculateRightHandSide + void EquationIdVector + void GetDofList + + Just as in the elements, to incorporate this condition we have to create it and register it in Kratos. To do so adding lines both in kPoisson.h and kPoisson.cpp is necessary. Once registered, the solver will be the one calling it and ensambling the RHS, so there's no need to call it in the problemtype. Also, do not forget to include the file in the jamfile of our problemtype. Below you can find both the .h and .cpp files: + + pointsource.h + #if !defined(KRATOS_PointSource_CONDITION_H_INCLUDED ) + #define  KRATOS_PointSource_CONDITION_H_INCLUDED + + // External includes + #include "boost/smart_ptr.hpp" + + // Project includes + #include "includes/define.h" + #include "includes/serializer.h" + #include "includes/condition.h" + #include "includes/ublas_interface.h" + #include "includes/variables.h" + + namespace Kratos + { + class PointSource + : public Condition + { + public: + ///@name Type Definitions + ///@{ + + /// Counted pointer of PointForce2D + KRATOS_CLASS_POINTER_DEFINITION(PointSource); + + /// Default constructor. + PointSource(IndexType NewId, GeometryType::Pointer pGeometry); + PointSource(IndexType NewId, GeometryType::Pointer pGeometry, + PropertiesType::Pointer pProperties); + + /// Destructor. + virtual ~PointSource(); + + + Condition::Pointer Create(IndexType NewId, NodesArrayType const& + ThisNodes,  PropertiesType::Pointer pProperties) const; + + void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& + rRightHandSideVector, ProcessInfo& rCurrentProcessInfo); + + void CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& + rCurrentProcessInfo); + //virtual void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo); + + void EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& + rCurrentProcessInfo); + + void GetDofList(DofsVectorType& ConditionalDofList,ProcessInfo& + CurrentProcessInfo); + + protected: + + + private: + + friend class Serializer; + + // A private default constructor necessary for serialization + PointSource(){}; + + virtual void save(Serializer& rSerializer) + { + rSerializer.save("Name","PointSource"); + KRATOS_SERIALIZE_SAVE_BASE_CLASS(rSerializer, Condition ); + } + + virtual void load(Serializer& rSerializer) + { + KRATOS_SERIALIZE_LOAD_BASE_CLASS(rSerializer, Condition ); + } + + + }; // Class PointForce2D + + } namespace kratos + + + + pointsource.cpp + + // Project includes + #include "includes/define.h" + #include "custom_conditions/pointsource.h" + #include "kPoisson.h" + #include "utilities/math_utils.h" + + namespace Kratos + { + //************************************************************************************ + //************************************************************************************ + PointSource::PointSource(IndexType NewId, GeometryType::Pointer + pGeometry) + : Condition(NewId, pGeometry) + { + //DO NOT ADD DOFS HERE!!! + } + + //************************************************************************************ + //************************************************************************************ + PointSource::PointSource(IndexType NewId, GeometryType::Pointer pGeometry,  PropertiesType::Pointer pProperties) + : Condition(NewId, pGeometry, pProperties) + { + } + Condition::Pointer PointSource::Create(IndexType NewId, NodesArrayType + const& ThisNodes,  PropertiesType::Pointer pProperties) const + { + return Condition::Pointer(new PointSource(NewId, + GetGeometry().Create(ThisNodes), pProperties)); + } + PointSource::~PointSource() + { + } + + //************************************************************************************ + //************************************************************************************ + void PointSource::CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo) + { + KRATOS_TRY + if(rRightHandSideVector.size() != 1) + rRightHandSideVector.resize(1,false); + + double load = GetGeometry()[0].GetSolutionStepValue(DUMMY_POINT_SOURCE); + rRightHandSideVector[0] = load; + KRATOS_CATCH("") + } + + //************************************************************************************ + //************************************************************************************ + void PointSource::CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo) + { + KRATOS_TRY + + if(rLeftHandSideMatrix.size1() != 1) + rLeftHandSideMatrix.resize(1,1,false); + noalias(rLeftHandSideMatrix) = ZeroMatrix(1,1); + if(rRightHandSideVector.size() != 1) + rRightHandSideVector.resize(1,false); + double load = GetGeometry()[0].GetSolutionStepValue(DUMMY_POINT_SOURCE); + rRightHandSideVector[0] = load; + KRATOS_CATCH("") + } + + + //************************************************************************************ + //************************************************************************************ + void PointSource::EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& CurrentProcessInfo) + { + int number_of_nodes = GetGeometry().PointsNumber(); + unsigned int index; + unsigned int dim = 1; + rResult.resize(number_of_nodes*dim); + for (int i=0;i.mdpa extension (see [[Input Data]] ). This format is more user friendly in case something has to be changed using a text editor. − Create a new text file with the name '''010_kPoisson.prop.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + We'll need to create our input file containing the materials, nodes, elements, Boundary conditions and Loads. Here's a simple example that is self explanatory: − For the materials properties, you have to translate the GiD material label (Dummy_Material) to our Kratos variable (DUMMY_MATERIAL), as follows: + example.mdpa − *loop materials + Begin ModelPartData − *format "%i%f" + // VARIABLE_NAME value − PROPERTIES[*MatNum]['''DUMMY_MATERIAL'''] = *MatProp('''Dummy_Material'''); + End ModelPartData − *end materials + − + − This code will generate a file with the different materials used in our problem, like this one: + − + − PROPERTIES[1][DUMMY_MATERIAL] = 1.000000; + − PROPERTIES[2][DUMMY_MATERIAL] = 1000.000000; + − + − ==== Element data file: 011_kPoisson.elem.bas ==== + − + − Create a new text file with the name '''011_kPoisson.elem.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + − + − Now you have to indicate the kind of Kratos element you are going to use for your problem, in order to create a list with the elements numbers, connectivities and assigned material. In this case is '''Poisson2D'''. + − + − // Reading Elements + − ElementsGroup = '''dummy_group'''; + //we start by looping only in the materials used, GID does this automatically + Begin Properties 1 + DUMMY_MATERIAL 1.0 + End Properties − *loop elems + Begin Nodes − *Set var i=0 + 1        0.15421        -2.88256        0.00000 − *set var j= ElemsNnode + 2        -3.37484        -2.88256        0.00000 − *format "%i%i%i%i%i%i%i%i" + 3        0.15421        2.12337        0.00000 − ELEMENTS[*ElemsNum] = '''Poisson2D'''([*\ + 4        -3.37484        2.12337        0.00000 − *for(i=1;i. − Create a new text file with the name '''012_kPoisson.cond.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + 01_kPoisson.mdpa.bas − + Begin ModelPartData − Remember that we have defined three conditions (two for the Dirichlet Boundary type and a third one for the point source), corresponding to fix the value of our '''DUMMY_UNKNOWN''' and our '''DUMMY_POINT_SOURCE''': + //  VARIABLE_NAME value − * Point_Fix_Value (Value) + End ModelPartData − * Line_Fix_Value (Value) + − * Point_Dummy_Load (Q) + − + − // Fixing degrees of freedom in nodes + − *Set cond '''Point_Fix_Value''' *nodes + //we start by looping only in the materials used, GID checks that automatically − *Add cond '''Line_Fix_Value''' *nodes + *loop materials − *loop nodes  *OnlyInCond + Begin Properties *matnum() − *format "%i%f" + DUMMY_MATERIAL *matprop(1) − NODES[*NodesNum].Fix('''DUMMY_UNKNOWN'''); + End Properties − *end nodes + *end − *Set cond '''Point_Dummy_Load''' *nodes + Begin Nodes − *loop nodes  *OnlyInCond + *loop nodes − NODES[*NodesNum].Fix('''DUMMY_POINT_SOURCE'''); + *format "%6i%15.5f%15.5f%15.5f" − *end nodes + *NodesNum *NodesCoord(1) *NodesCoord(2) *NodesCoord(3) − + *end − With this file, we are saying to Kratos what the conditions are (the fixed values or the source values), but '''not the specific value'''. This is done in this way for transient problems, where the value of a condition can change for each time step. + End Nodes − + − Assigning the following conditions to our model: + − + − [[Image:KPoisson.cnd.4.jpg]] [[Image:KPoisson.cnd.5.jpg]] + − + − this file will produce a data file like the following: + − + − // Fixing degrees of freedom in nodes + − NODES[1].Fix(DUMMY_UNKNOWN); + Begin Elements Poisson2D − NODES[2].Fix(DUMMY_UNKNOWN); + *loop elems − NODES[5].Fix(DUMMY_UNKNOWN); + *elemsnum *elemsmat *elemsConec − NODES[7].Fix(DUMMY_UNKNOWN); + *end elems − NODES[8].Fix(DUMMY_UNKNOWN); + End Elements − NODES[9].Fix(DUMMY_UNKNOWN); + − NODES[4].Fix(DUMMY_POINT_SOURCE); + Begin NodalData DUMMY_UNKNOWN          //be careful, variables are case sensitive! + *Set cond Point_Fix_Value *nodes + *Add cond Line_Fix_Value *nodes + *loop nodes  *OnlyInCond + *NodesNum 1 *cond(1,int) + *end + End NodalData − ==== Initial Values data file: 013_kPoisson.init.bas ==== + Using *Set cond and *Add cond and later *OnlyInCond creates a loop only on the restricted nodes. The same commands are used for the loads: − Create a new text file with the name '''013_kPoisson.init.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + Begin NodalData DUMMY_POINT_SOURCE              //now we loop the loads − + *Set cond Point_Dummy_Load *nodes − To indicate the initial values (the fix values for static problems), we have to create the following file: + − + − // Fixing degrees of freedom in nodes + − + − *Set cond '''Point_Fix_Value''' *nodes + − *Add cond '''Line_Fix_Value''' *nodes + *loop nodes  *OnlyInCond *loop nodes  *OnlyInCond − *format "%i%f" + *NodesNum   0   *cond(1) − NODES[*NodesNum]('''DUMMY_UNKNOWN''',0) = *cond('''Value'''); + *end nodes *end nodes − *Set cond '''Point_Dummy_Load''' *nodes + End NodalData − *loop nodes  *OnlyInCond + − NODES[*NodesNum]('''DUMMY_POINT_SOURCE''',0) = *cond('''Q'''); + − *end nodes + − + − That it will generate for the previous example: + − + − // Fixing degrees of freedom in nodes + − + − NODES[1](DUMMY_UNKNOWN,0) = 0.000000; + − NODES[2](DUMMY_UNKNOWN,0) = 0.000000; + − NODES[5](DUMMY_UNKNOWN,0) = 0.000000; + − NODES[7](DUMMY_UNKNOWN,0) = 7.000000; + − NODES[8](DUMMY_UNKNOWN,0) = 7.000000; + − NODES[9](DUMMY_UNKNOWN,0) = 7.000000; + − NODES[4](DUMMY_POINT_SOURCE,0) = 500.0; + − + − ==== Node data file: 014_kPoisson.node.bas ==== + − + − Create a new text file with the name '''014_kPoisson.node.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + − + − In general terms, you will not modify this file in your applications, because it is just the list of nodes' coordinates of your problem. + − + − *RealFormat "%10.5f" + − NODES = NodesList([ + − *set var i=1 + − *loop nodes + − *if(i>1) + − , + − *endif + − [*nodesnum,*NodesCoord(1),*NodesCoord(2),*NodesCoord(3)]*\ + − *set var i=i+1 + − *end + − + − ]) + − + − For our specific mesh, this file will generate something like: + − + − NODES = NodesList([ + − [1,  -8.57703,  -4.79186,  0.00000], + − [2,  -8.57703,  3.98651,  0.00000], + − [3,  6.08043,  -4.79186,  0.00000], + − [4,  6.08043,  3.98651,  0.00000], + − [5,  -8.57703,  12.76488,  0.00000], + − [6,  6.08043,  12.76488,  0.00000], + − [7,  20.73789,  -4.79186,  0.00000], + − [8,  20.73789,  3.98651,  0.00000], + − [9,  20.73789,  12.76488,  0.00000] + − ]) + === Batch files for your GiD kPoisson Problemtype === === Batch files for your GiD kPoisson Problemtype === Line 1,914: Line 2,046: Create a new text file with the name '''kPoisson.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). Create a new text file with the name '''kPoisson.bas''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). − This template file will create each python command line file customised to our specific GiD example and our Kratos application (with the kPoisson element and the selected solver). Note that once again the '''bold''' characters indicates those lines you should modify, using our specific class, methods or variables denomination. + This template file will create each python command line file customised to our specific GiD example and our Kratos application (with the kPoisson element and the selected solver). Note that once again the '''bold''' characters indicates those lines you should modify, using our specific class, methods or variables denomination. Notice the lines that tell Kratos we're using the new format, in case you've downloaded an old version of the python script. ################################################################## ################################################################## Line 1,964: Line 2,096: write_conditions = WriteConditionsFlag.WriteElementsOnly write_conditions = WriteConditionsFlag.WriteElementsOnly gid_io = GidIO("*tcl(file tail [GiD_Info project  modelname])",gid_mode,multifile,deformed_mesh_flag,write_conditions) gid_io = GidIO("*tcl(file tail [GiD_Info project  modelname])",gid_mode,multifile,deformed_mesh_flag,write_conditions) − gid_io.ReadModelPart(model_part) + #gid_io.ReadModelPart(model_part)           #this line was replaced by the following 2 to use the .mdpa file (singlefile) instead of the old multifile format + model_part_io = ModelPartIO("*tcl(file tail [GiD_Info project modelname])")    #new line 1 + model_part_io.ReadModelPart(model_part) #new line 2 mesh_name = 0.0 mesh_name = 0.0 Line 2,042: Line 2,176: write_conditions = WriteConditionsFlag.WriteElementsOnly write_conditions = WriteConditionsFlag.WriteElementsOnly gid_io = GidIO("'''our_example'''",gid_mode,multifile,deformed_mesh_flag,write_conditions) gid_io = GidIO("'''our_example'''",gid_mode,multifile,deformed_mesh_flag,write_conditions) − gid_io.ReadModelPart(model_part) + #gid_io.ReadModelPart(model_part)           #this line was replaced by the following 2 to use the .mdpa file (singlefile) instead of the old multifile format + model_part_io = ModelPartIO("*tcl(file tail [GiD_Info project modelname])")    #new line 1 + model_part_io.ReadModelPart(model_part) #new line 2 mesh_name = 0.0 mesh_name = 0.0 Line 2,074: Line 2,210: ==== MS Window Batch file: kPoisson.win.bat ==== ==== MS Window Batch file: kPoisson.win.bat ==== − Create a new text file with the name '''kPoisson.win.bat''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). + You'll have to make a new text file with the name '''kPoisson.win.bat''' in your GiD kPoisson problemtype directory ('''kPoisson.gid'''). This file contains instructions to rename files and call Kratos. − No special comments are needed for this file. Just take cure about where your python bin is located. For Linux or Unix systems is almost the same. + When creating the input files starting from the .bas files, GID will not read the .mdpa extension between the dots (it is only used for the user's clarity) . It simply starts with kPoisson.bas, naming it example.dat and then proceeds to create the others ommiting the "01_" and adding -1 at the end, -2 for the next and so on. The .bat file will be in charge of deleting the ones from the last run and renaming the new ones properly. example.dat will contain the python commands  and therefore we'll have to change the extension later to .py . This file also executes the python script at the end. + + kPoisson.win.bat @ECHO OFF @ECHO OFF rem OutputFile: %1.log rem OutputFile: %1.log − − del %2\%1.info − del %2\%1.flavia.res − del %2\%1.flavia.dat − del %2\%1.err del %2\%1.py del %2\%1.py − + del %2\%1.mdpa − del %2\%1.prop + − del %2\%1.elem + − del %2\%1.cond + − del %2\%1.init + − del %2\%1.node + − + ren %2\%1.dat %2\%1.py ren %2\%1.dat %2\%1.py − ren %2\%1-1.dat %2\%1.prop + ren %2\%1-1.dat %2\%1.mdpa − ren %2\%1-2.dat %2\%1.elem + − ren %2\%1-3.dat %2\%1.cond + − ren %2\%1-4.dat %2\%1.init + − ren %2\%1-5.dat %2\%1.node + '''C:\kratosR1\Python25\python''' %2\%1.py >%2\%1.log '''C:\kratosR1\Python25\python''' %2\%1.py >%2\%1.log Line 2,112: Line 2,235: #    OutputFile: $2/$1.info #    OutputFile: $2/$1.info #    ErrorFile: $2/$1.err #    ErrorFile: $2/$1.err − #delete previous result file + #delete previous files − rm -f  $2/$1.flavia.res + rm $2/$1.mdpa − rm $2/$1.info + − rm $2/$1.flavia.dat + − rm $2/$1.err + − rm $2/$1.node + − rm $2/$1.prop + − rm $2/$1.elem + − rm $2/$1.cond + − rm $2/$1.init + rm $2/$1.py rm $2/$1.py mv $2/$1.dat $2/$1.py mv $2/$1.dat $2/$1.py − mv $2/$1-1.dat $2/$1.prop + mv $2/$1-1.dat $2/$1.mdpa − mv $2/$1-2.dat $2/$1.elem + python $2/$1.py >$2/$1.log − mv $2/$1-3.dat $2/$1.cond + − mv $2/$1-4.dat $2/$1.init + − mv $2/$1-5.dat $2/$1.node + − '''python $2/$1.py >$2/$1.log''' + − rm $2/$1.post.res + − rm $2/$1_0.post.bin $2/$1.post.res + === Source Files for your GiD-Kratos Application Problem Type === === Source Files for your GiD-Kratos Application Problem Type === Line 2,183: Line 2,292: a set of new files are generated: a set of new files are generated: − * our_example.cond + * our_example.mdpa − * our_example.elem + − * our_example.init + − * our_example.node + − * our_example.prop + * our_example.py * our_example.py * our_example.log * our_example.log * our_example.post.res * our_example.post.res − The first six files have been already explained. + The first two files have been already explained. The log file contains the details about how the simulation have been performed, including warnings or errors (if there is something). The log file contains the details about how the simulation have been performed, including warnings or errors (if there is something).

## Latest revision as of 09:34, 25 April 2012

 Warning. Please, note that: If you have some questions, comments or suggestions, you can use the "discussion" tab to include them.

## The Most Basic Finite Element Method Formulation

### Suggested Prerequisites

• Linear algebra
• Partial differential equations
• ... ...

### Our Partial Differential Equation: Poisson's equation

As our first example, we will use the Poisson's Equation in two-dimensional Cartesian coordinates, that it takes the form:

$\left[ \frac{\partial}{\partial x}\cdot \left( K_{x} \cdot \frac{\partial}{\partial x}\right) + \frac{\partial}{\partial y}\cdot \left(K_{y} \cdot \frac{\partial}{\partial y} \right) \right]\varphi(x,y) = f(x,y)$

for a domain Ω, equivalent to write:

$\nabla \cdot (K \nabla \varphi )= f$

where K is the material property, $\varphi$ is the unknown to obtain and f is a source term.

### Boundary Conditions

Two different boundary conditions will be considered:

#### Dirichlet boundary condition

The first type boundary condition specifies the values the solution needs to take $(\varphi_{0})$ on a boundary $({\Gamma_{\varphi}})$ of the domain:

$\varphi(x,y)\mid_{\Gamma_{\varphi}} = \varphi_{0}$

#### Neumann boundary condition

The second type boundary condition specifies the values that the derivative of a solution (q0) is to take on the boundary (Γq) of the domain:

$K \nabla \varphi(x,y)\mid_{\Gamma_{q}} = q_{0}$

### Finite Element Method Formulation

The Weak formulation using the Weighted Residual Form (Galerkin Method) of Poisson equation can be written as follows:

${ \int_{\Omega} W [\nabla^T D \nabla \varphi + \rho_v]\partial \Omega + \oint_{\Gamma_q}\overline{W}[n^T D \nabla \varphi + \overline{q}]\partial \Gamma_q=0 }$

with $W, \overline{W}$ the weights for each differential equation. If $\overline{W}=W$ and using the integration by parts, this equation becomes:

${ \int_{\Omega} \nabla^T W^T D \nabla \varphi \partial \Omega = \int_{\Omega} W^T \rho_v \partial \Omega - \oint_{\Gamma_q} W^T \overline{q_n} \partial \Gamma_q - \oint_{\Gamma_{\varphi}} W^T q_n \partial \Gamma_{\varphi} }$

for the two-dimensional Cartesian coordinates, each term can be written:

$D = \begin{bmatrix} K_x & 0 \\ 0 & K_y \end{bmatrix}$
$\partial \Omega = \partial x \partial y$
$x=[x,y]^T = \sum N_i[x_i,y_i]^T$

with N_i the shape forms of the element.

$\varphi = \sum N_i \varphi_i = N a^{(e)}$
$q=- D \nabla \varphi = - D \nabla N a^{(e)} = - D B a^{(e)}$

with B defined as:

$B = \begin{bmatrix} B_1... & B_n \end{bmatrix}$
$B_i = \begin{bmatrix} \frac{\partial N_i}{\partial x} \\ \frac{\partial N_i}{\partial y} \end{bmatrix}$

These system of equations can be written as the following matricial form:

$K \cdot a = f$

with K the stiffness matrix of the system, a the vector of nodal values to obatin (unknown vector), and f the source vector (independent forces or charges).

The superscript (e) refers to the equation applied for each element.

$K^{(e)} = { \int_{\Omega^{(e)}} B^T D B \partial \Omega^{(e)} }$
$f^{(e)} = { \int_{\Omega^{(e)}} N^T \rho_v \partial \Omega^{(e)} - \oint_{\Gamma_q^{(e)}} N^T \overline{q} \partial \Gamma_q^{(e)} - \oint_{\Gamma_{\varphi}^{(e)}} n^T N^T q_n \partial \Gamma_{\varphi}^({(e)} }$

A very symple example (to be prepared).

## A First Kratos Element

### Suggested Prerequisites:

• Finite Element Formulation for a PDE

### Introduction

An element in Kratos is the implementation code of the Elemental Finite Element Formulation for a PDE. An element can be used for any already existing application in Kratos, by including it in their corresponding files. The next section will explain the creation of a new application in Kratos. For simplicity reasons, we will focus now in the creation of the element, leaving the application's aspects in the next section.

Therefore, to check the element operation we will need to create the application, and we have not way to validate it here for the moment.

In this point we will need just to know the name of the application for their corresponding files ("kPoisson"), and the name of the application methods "PoissonApplication".

Our first element in Kratos will be the implementation of the Poisson's equation, so we will call it "poisson_2d". The class name for the element will be called "Poisson2D".

The most basic element implemented in Kratos only needs two files:

• poisson_2d.h
• poisson_2d.cpp

A quick way to create an element is to select one of the existing ones close to our formulation and modifying some specific parts. We are going to show the code of these two files with some comments in those lines you probably would want to customise.

The following code includes the most usual sections needed to operate with a Kratos element. Most of the code is common in all the elements and it doesn't need any change. Specific customisation is remarked using bold characters, therefore in general terms you should pay attention just to these parts and keep the rest unchanged.

First lines: legal issues

The first lines are just the typical legal issues related to Kratos as a framework to create simulation programs. You should keep them as they are. The only sentence to customise is the name of the application (in bold characters) in the third line, KratosR1PoissonApplication:

/*
==============================================================================
KratosR1PoissonApplication
A library based on:
Kratos
A General Purpose Software for Multi-Physics Finite Element Analysis
Version 1.0 (Released on march 05, 2007).

pooyan@cimne.upc.edu
rrossi@cimne.upc.edu
- CIMNE (International Center for Numerical Methods in Engineering),
Gran Capita' s/n, 08034 Barcelona, Spain

Permission is hereby granted, free  of charge, to any person obtaining
a  copy  of this  software  and  associated  documentation files  (the
"Software"), to  deal in  the Software without  restriction, including
without limitation  the rights to  use, copy, modify,  merge, publish,
distribute,  sublicense and/or  sell copies  of the  Software,  and to
permit persons to whom the Software  is furnished to do so, subject to
the following condition:

Distribution of this code for  any  commercial purpose  is permissible
ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNERS.

The  above  copyright  notice  and  this permission  notice  shall  be
included in all copies or substantial portions of the Software.

THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT  SHALL THE AUTHORS OR COPYRIGHT HOLDERS  BE LIABLE FOR ANY
CLAIM, DAMAGES OR  OTHER LIABILITY, WHETHER IN AN  ACTION OF CONTRACT,
TORT  OR OTHERWISE, ARISING  FROM, OUT  OF OR  IN CONNECTION  WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

==============================================================================
*/


The following lines (comments again) indicate the author's name (your name), date and hour of the last revision, and revision number, as usual in other codes.

//
//   Project Name:        Kratos
//   Last modified by:    $Author: it's me!$
//   Date:                $Date: 2008-08-08 23:58:38$
//   Revision:            $Revision: 1.0$
//
//


In order to avoid class redefinition, you have to define a label for your element definition, as follows:

#if !defined(KRATOS_POISSON_2D_ELEM_H_INCLUDED)
#define  KRATOS_POISSON_2D_ELEM_H_INCLUDED


the #endif is at the end of the code (the rest of the lines must be included between these ones):

#endif // KRATOS_POISSON_2D_ELEM_H_INCLUDED  defined


Now you have to add the "include" files (copy as it is):

// System includes

// External includes
#include "boost/smart_ptr.hpp"

// Project includes
#include "includes/define.h"
#include "includes/element.h"
#include "includes/ublas_interface.h"
#include "includes/variables.h"


Declare the namespace Kratos (copy at it is):

namespace Kratos
{

///@name Kratos Globals
///@{

///@}
///@name Type Definitions
///@{

///@}
///@name  Enum's
///@{

///@}
///@name  Functions
///@{

///@}
///@name Kratos Classes
///@{

/// Short class definition.
/** Detail class definition.
*/


The namespace is closed at the end of the file (just before the #endif):

}  // namespace Kratos.


Our class definition starts now. We will call it "Poisson2D":

 class Poisson2D
: public Element
{
public:
///@name Type Definitions
///@{

/// Counted pointer of Poisson2D
KRATOS_CLASS_POINTER_DEFINITION(Poisson2D);

///@}
///@name Life Cycle
///@{


Constructor and destructor declaration (you should just change the class name):

    /// Default constructor.
Poisson2D(IndexType NewId, GeometryType::Pointer pGeometry);
Poisson2D(IndexType NewId, GeometryType::Pointer pGeometry,  PropertiesType::Pointer pProperties);

/// Destructor.
virtual ~ Poisson2D();

///@}
///@name Operators
///@{

///@}
///@name Operations
///@{


And we add the class methods we need to perform the implementation of the element. By now we will just declare the methods, leaving a more detailed explanation in the implementation file (.cpp). Note that for this simple element you don't need change anything:

     Element::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes,  PropertiesType::Pointer pProperties) const;

void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo);

void CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo);

void EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& rCurrentProcessInfo);

void GetDofList(DofsVectorType& ElementalDofList,ProcessInfo& CurrentProcessInfo);

void InitializeSolutionStep(ProcessInfo& CurrentProcessInfo);


Additional lines not important for this element (you don't need to modify anything):

    ///@}
///@name Access
///@{

///@}
///@name Inquiry
///@{

///@}
///@name Input and output
///@{

///@}
///@name Friends
///@{

///@}

protected:
///@name Protected static Member Variables
///@{

///@}
///@name Protected member Variables
///@{

///@}
///@name Protected Operators
///@{

///@}
///@name Protected Operations
///@{

///@}
///@name Protected  Access
///@{

///@}
///@name Protected Inquiry
///@{

///@}
///@name Protected LifeCycle
///@{

///@}


The declaration of the class's attributes we will know to perform the element computation (note again the use of the class name):

   private:
///@name Member Variables
///@{
boost::numeric::ublas::bounded_matrix<double,3,2> msDN_DX;
boost::numeric::ublas::bounded_matrix<double,2,2> msD;
array_1d<double,3> msN; //dimension = number of nodes
array_1d<double,3> ms_temp; //dimension = number of nodes
array_1d<double,3> point_sources; //dimension = number of nodes


and to close the class definition:

     ///@}
///@name Member Variables
///@{

///@}
///@name Private Operators
///@{

///@}
///@name Private Operations
///@{

///@}
///@name Private  Access
///@{

///@}
///@name Private Inquiry
///@{

///@}
///@name Un accessible methods
///@{

/// Assignment operator.
// Poisson2D& operator=(const Poisson2D& rOther);

/// Copy constructor.
// Poisson2D(const Poisson2D& rOther);

///@}

}; // Class Poisson2D


To finalise the header code, we should add (no changes are needed):

 ///@}

///@name Type Definitions
///@{

///@}
///@name Input and output
///@{

/// input stream function

/// output stream function

///@}


### Element implementation methods file: poisson_2d.cpp

First lines: legal issues

The first lines are just again the typical legal issues related to Kratos as a framework to create simulation programs. You should keep them as they are. The only sentence to customise is the name of the application (in bold characters) in the third line, KratosR1PoissonApplication:

/*
==============================================================================
KratosR1PoissonApplication
A library based on:
Kratos
A General Purpose Software for Multi-Physics Finite Element Analysis
Version 1.0 (Released on march 05, 2007).

pooyan@cimne.upc.edu
rrossi@cimne.upc.edu
- CIMNE (International Center for Numerical Methods in Engineering),
Gran Capita' s/n, 08034 Barcelona, Spain

Permission is hereby granted, free  of charge, to any person obtaining
a  copy  of this  software  and  associated  documentation files  (the
"Software"), to  deal in  the Software without  restriction, including
without limitation  the rights to  use, copy, modify,  merge, publish,
distribute,  sublicense and/or  sell copies  of the  Software,  and to
permit persons to whom the Software  is furnished to do so, subject to
the following condition:

Distribution of this code for  any  commercial purpose  is permissible
ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNERS.

The  above  copyright  notice  and  this permission  notice  shall  be
included in all copies or substantial portions of the Software.

THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT  SHALL THE AUTHORS OR COPYRIGHT HOLDERS  BE LIABLE FOR ANY
CLAIM, DAMAGES OR  OTHER LIABILITY, WHETHER IN AN  ACTION OF CONTRACT,
TORT  OR OTHERWISE, ARISING  FROM, OUT  OF OR  IN CONNECTION  WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

==============================================================================
*/


The following lines (comments again) indicate the author's name (your name), date and hour of the last revision, and revision number, as usual in other codes.

//
//   Project Name:        Kratos
//   Last modified by:    $Author: it's me!$
//   Date:                $Date: 2008-08-08 23:58:38$
//   Revision:            $Revision: 1.0$
//
//


Now you have to add the "include" files. Note that you have to change the element header file name (poisson_2d.h) and the application header file name where you want to include your element (in this case, kPoisson.h, not yet created). The related subdirectories will be explained in the application section:

// System includes

// External includes

// Project includes
#include "includes/define.h"
#include "custom_elements/poisson_2d.h"
#include "kPoisson.h"
#include "utilities/math_utils.h"
#include "utilities/geometry_utilities.h"


Declare the namespace Kratos (copy at it is), and create the main class methods as follows. Just note that you have to be sure that you are using your element class name (Poisson2D in this example, in bold characters):

namespace Kratos
{
//************************************************************************************
//************************************************************************************
Poisson2D::Poisson2D(IndexType NewId, GeometryType::Pointer pGeometry)
: Element(NewId, pGeometry)
{
}

//************************************************************************************
//************************************************************************************
Poisson2D::Poisson2D(IndexType NewId, GeometryType::Pointer pGeometry,  PropertiesType::Pointer pProperties)
: Element(NewId, pGeometry, pProperties)
{

}

Element::Pointer Poisson2D::Create(IndexType NewId, NodesArrayType const& ThisNodes,  PropertiesType::Pointer pProperties) const

{
return Element::Pointer(new Poisson2D(NewId, GetGeometry().Create(ThisNodes), pProperties));
}

Poisson2D::~Poisson2D()
{
}



Remember to close the namespace at the end of the file.

}  // namespace Kratos.


Now, it's the critical moment to transfer your Finite Element Formulation to the Kratos code. Some preliminary comments are:

• Kratos allows different ways to implement the formulation, therefore don't worry if you find different Kratos elements with different implementation approaches, even if you leave some methods unused, or parts without contents. Just check the coherence of your formulation.
• Kratos has been designed to allow you to focus your attention to the element formulation. That is, again, don't worry about the other programming aspects of your simulation program, such as the matrix assembly, solvers, etc... Of course, you are able to customise them, but for basic applications is not necessary at all.

Copy the following code as it is, with two exceptions (in bold characters):

• use your element class name (Poisson2D in this example);
• your variable names (we will use DUMMY_UNKNOWN for the unknown, DUMMY_MATERIAL for the material property and DUMMY_POINT_SOURCE for the source term);
	//************************************************************************************
//************************************************************************************
void Poisson2D::CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo)
{
KRATOS_TRY

boost::numeric::ublas::bounded_matrix<double,3,2> msDN_DX;
boost::numeric::ublas::bounded_matrix<double,2,2> msD;
array_1d<double,3> msN; //dimension = number of nodes
array_1d<double,3> ms_temp; //dimension = number of nodes
array_1d<double,3> point_sources; //dimension = number of nodes

		const unsigned int number_of_points = GetGeometry().size();

if(rLeftHandSideMatrix.size1() != number_of_points)
rLeftHandSideMatrix.resize(number_of_points,number_of_points,false);

if(rRightHandSideVector.size() != number_of_points)
rRightHandSideVector.resize(number_of_points,false);

//getting data for the given geometry
double Area;
GeometryUtils::CalculateGeometryData(GetGeometry(), msDN_DX, msN, Area);

double dummy_material = GetProperties()[DUMMY_MATERIAL];
msD(0,0)=dummy_material;
msD(1,1)=dummy_material;
point_sources[0] = GetGeometry()[0].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);
point_sources[1] = GetGeometry()[1].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);
point_sources[2] = GetGeometry()[2].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);

// main loop
const GeometryType::IntegrationPointsArrayType& integration_points = GetGeometry().IntegrationPoints();

noalias(rLeftHandSideMatrix) = prod(msDN_DX,Matrix(prod(msD,trans(msDN_DX))));

rLeftHandSideMatrix *= Area;

//Point charge contribution
noalias(rRightHandSideVector) = point_sources;

//subtracting the dirichlet term
// RHS -= LHS*DUMMY_UNKNOWNs
for(unsigned int iii = 0; iii<number_of_points; iii++)
ms_temp[iii] = GetGeometry()[iii].FastGetSolutionStepValue(DUMMY_UNKNOWN);
noalias(rRightHandSideVector) -= prod(rLeftHandSideMatrix,ms_temp);

KRATOS_CATCH("");
}


The code is self-explanatory, but just a few comments to link it with our basic finite element formulation:

• CalculateGeometryData obtains msDN_DX, msN and the elemental Area, that is, the B and N matrix;
• msD is the material properties matrix (the D matrix);
• With prod(msDN_DX,Matrix(prod(msD,trans(msDN_DX)))) we obtain the stiffness matrix (the K matrix);
• With noalias(rRightHandSideVector) = point_sources we add the point_source contribution to the source vector f;
• Finally, with prod(rLeftHandSideMatrix,ms_temp) we compute the Dirichlet contribution to the source vector f;

The following code is not used for this specific element (keep at it is, just changing the class name):

	//************************************************************************************
//************************************************************************************
void Poisson2D::CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo)
{
KRATOS_ERROR(std::logic_error,  "method not implemented" , "");
}

//************************************************************************************
//************************************************************************************
// this subroutine calculates the nodal contributions for the explicit steps of the
// fractional step procedure
void Poisson2D::InitializeSolutionStep(ProcessInfo& CurrentProcessInfo)
{
KRATOS_TRY

KRATOS_CATCH("");
}


And, finally, the next lines give us the unknows (you have just change the class and variables' names):

	//************************************************************************************
//************************************************************************************
void Poisson2D::EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& CurrentProcessInfo)
{
unsigned int number_of_nodes = GetGeometry().PointsNumber();
if(rResult.size() != number_of_nodes)
rResult.resize(number_of_nodes,false);

for (unsigned int i=0;i<number_of_nodes;i++)
rResult[i] = GetGeometry()[i].GetDof(DUMMY_UNKNOWN).EquationId();
}

//************************************************************************************
//************************************************************************************
void Poisson2D::GetDofList(DofsVectorType& ElementalDofList,ProcessInfo& CurrentProcessInfo)
{
unsigned int number_of_nodes = GetGeometry().PointsNumber();
if(ElementalDofList.size() != number_of_nodes)
ElementalDofList.resize(number_of_nodes);

for (unsigned int i=0;i<number_of_nodes;i++)
ElementalDofList[i] = GetGeometry()[i].pGetDof(DUMMY_UNKNOWN);

}


### Tips for a basic Kratos Element creation

If you want to create the element from any existing one, you can also use the following quick steps:

1. copy the .h and .cpp original element in your working directory;
• for example, copy conv_diff_2d.h and conv_diff_2d.h to myKratos/my_elements;
2. rename the .h and .cpp copied files to your element name;
• for example: poisson_2d.h and poisson_2d.cpp;
• for example, edit your poisson_2d.h file;
1. search and replace the "KratosR1OriginalNameApplication" word to "KratosR1YourApplication";
• for example, search and replace KratosR1ConvectionDiffusionApplication for KratosR1PoissonApplication;
2. modify the authors, data and hour of the last creation/modification, and version of the code;
3. search and replace the KRATOS_elementType_2D_ELEM_H_INCLUDED string for your specific label;
• for example, search and replace KRATOS_TRIANGULAR_CONVDIFF_ELEM_H_INCLUDED for KRATOS_POISSON_2D_ELEM_H_INCLUDED;
4. search and replace the class name from the original to your new element;
• for example, search and replace ConvDiff2D for Poisson2D;
4. edit your element implementation (.cpp) file and:
• for example, edit your poisson_2d.cpp file;
1. search and replace the "KratosR1OriginalNameApplication" word to "KratosR1YourApplication";
• for example, search and replace KratosR1ConvectionDiffusionApplication for KratosR1PoissonApplication;
2. modify the authors, data and hour of the last creation/modification, and version of the code;
• for example, add #include "custom_elements/poisson_2d.h" and #include "kPoisson.h";
4. search and replace the class name from the original to your new element;
• for example, search and replace ConvDiff2D for Poisson2D;
5. search and replace variable's names from the original to your new element;
• for example, search and replace CONDUCTIVITY for DUMMY_MATERIAL;
• for example, search and replace conductivity for dummy_material;
• for example, search and replace TEMPERATURE for DUMMY_UNKNOWN;
6. create, if needed, new variables or equation terms (for example, the point_source contribution);
point_sources[0] = GetGeometry()[0].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);
point_sources[1] = GetGeometry()[1].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);
point_sources[2] = GetGeometry()[2].FastGetSolutionStepValue(DUMMY_POINT_SOURCE);
//Point charge contribution
noalias(rRightHandSideVector) = point_sources;

Excellent! Now you have your first basic element! To check it, you will now to include them in an application or to create a new one, the topic of the next section.

## A First Kratos Application

### Introduction

An application in Kratos is an specific customisation of the Kratos elements in order to perform an specific simulation. That means that you can combine already existing Kratos elements, solvers, strategies and so on to create your application.

In this section, we will create a new application to use our recently created element for our Poisson PDE example. It is almost the simplest application, but include a lot of tips that is highly convenient to know in order to properly work with Kratos. It is a kind of the Kratos' 'Hello world'.

Kratos's framework is implemented at two different levels: C++ and python programming. You will need to create or modify C++ code for low level operations, such as to implement the element, solvers or IO routines. You will use the python codes to combine these elements at a higher level, closer to the end-user, such as to select the elements or solvers, decide what are the variables you want to print, etc.

Coming from our Poisson element, remember that we have already selected the name:

• of our application: kPoisson;
• the application methods: PoissonApplication;
• our element: poisson_2d;
• class name for the element: Poisson2D;
• variables: DUMMY_UNKNOWN, DUMMY_MATERIAL, DUMMY_POINT_SOURCE;

Kratos is an open source code framework and that means that you can share, modify and freely use the code. You can also contribute with your code, your applications and examples in the growing of the Kratos' community.

For this reason, Kratos has been designed to work at other two development levels:

• Kratos kernel, that it is supposed to be the most inner part of Kratos, of common interest for all the Kratos' community;
• Kratos applications, with specific code for every each unique details of each problem, user profile or simulation case;

Basically, to classify and separate these two development levels, we will work with code in files located in different subdirectories. In this way, you can experiment with your application without worry about modifying important code in the Kratos Kernel. You can also share your code with the rest of the Kratos community, if you want, by using the CVS, but without provoking conflicts with the rest of the Kratos framework.

 Warning. Please, note that: if you have to change or modify anything of the Kratos kernel to improve your application, you can do it in your stand-alone Kratos installation, but you should contact the main Kratos developers (Dr. Pooyan Davdand or Dr. Riccardo Rossi) before updating it in the Kratos CVS.

### Basic Kratos Directory Tree

If you have successfully installed Kratos, you should have a directory's tree like this (minor changes are allowed, such as the location of the python files, etc):

/kratosR1
/applications
/bin
/CVS
/Debug
/doc
/external_libraries
/kratos
/libs
/Python25
/Release


Our main working directory will be our specific application's directory (to be created), in the applications subdirectory. Nevertheless, the rest of the structure is presented to indicate where are located other important files to work with Kratos.

### The files' structure for a Kratos application

In the /KratosR1/applications directory you have to create a new directory (let's go to call it "kPoisson"). You have to create a set of custom directories for your application (basically /custom_elements, /custom_python, /python_scripts and /test_examples):

/KratosR1
/applications
/kPoisson
/custom_elements
/custom_python
/python_scripts
/test_examples


Each of these subdirectories will contain the specific C++ or python code needed for our application. We will focus our attention in using our customised element, therefore, the other needed code will be, simply, copied from other already existing applications.

Note that if you want to use a new strategy or solver, then you have to create other typical customisation directories or files such as /custom_strategies, etc...

### Creation of our Kratos application files: copying already existing files

1. Copy the header (.h), implementation (.cpp) C++ file and Jamfile from other application to your main application subdirectory (kPoisson);
• for example copy the files from /kratosR1/applications/convection_diffusion_application to /kratosR1/applications/kPoisson;
• convection_diffusion_application.h
• convection_diffusion_application.cpp
• Jamfile
2. Copy your element's code (poisson_2d.h, poisson_2d.cpp) in your custom_elements subdirectory (/kratosR1/applications/kPoisson/custom_elements);
3. Copy the custom_python files from other application to your custom_python subdirectory;
• for example copy the content from /kratosR1/applications/convection_diffusion_application/custom_python to /kratosR1/applications/kPoisson/custom_python;
• kratos_convection_diffusion_python_application.cpp
4. Copy the python_scripts files from other application to your python_scripts subdirectory;
• for example copy the content from /kratosR1/applications/convection_diffusion_application/python_scripts to /kratosR1/applications/kPoisson/python_scripts;
• convection_diffusion_solver.py
• nonlinear_convection_diffusion_solver.py
• As you can see, in this directory the python file to run the solver is saved; therefore, you have to select the most appropriate solver for your application from those already existing ones;
• For this application (the Poisson equation), we recommend to use the strategy and solver coming from the structural application (a very similar problem); therefore, copy from \kratosR1\applications\structural_application\python_scripts to your local directory (\kratosR1\applications\kPoisson\python_scripts) the following files:
• structural_solver_static.py
• strategy_python.py
5. Depending on your interest, you can also copy an example from other application in your test_examples directory;

The following files (above in bold characters) are those that you will have to modify, that we will review later. The rest of them, in principle, you can keep as they are.

• convection_diffusion_application.h
• convection_diffusion_application.cpp
• Jamfile
• kratos_convection_diffusion_python_application.cpp
• structural_solver_static.py

In addition, you have to indicate to the Kratos Kernel that you have created a new application, in order to be included in the whole Kratos. To do this, you will have also to modify the following files:

• in the main applications' directory (/kratosR1/applications/applications_interface.py);
• in the Kratos root (/kratosR1/Jamroot);

### Customisation of our Application files

In summary, we have to modify:

• /kratosR1/applications/kPoisson/convection_diffusion_application.h
• /kratosR1/applications/kPoisson/convection_diffusion_application.cpp
• /kratosR1/applications/kPoisson/Jamfile
• /kratosR1/applications/kPoisson/custom_python/kratos_convection_diffusion_python_application.cpp
• /kratosR1/applications/kPoisson/python_scripts/structural_solver_static.py
• /kratosR1/applications/applications_interface.py
• /kratosR1/Jamroot

The first thing to do is to rename the other application files (convection_diffusion_application or structural in this case) to our specific application name (kPoisson), for example by doing:

• /kratosR1/applications/kPoisson/kPoisson.h
• /kratosR1/applications/kPoisson/kPoisson.cpp
• /kratosR1/applications/kPoisson/Jamfile
• /kratosR1/applications/kPoisson/custom_python/kPoisson_python_application.cpp
• /kratosR1/applications/kPoisson/python_scripts/static_poisson_solver.py
• /kratosR1/applications/applications_interface.py
• /kratosR1/Jamroot

Let's go to edit these files (note that we have three C++ files and three python files):

#### Customising the header application file: kPoisson.h

The first lines (comments) indicate the author's name (your name), date and hour of the last revision, and revision number, as usual in other codes.

//
//   Project Name:        Kratos
//   Last modified by:    $Author: it's me!$
//   Date:                $Date: 2008-08-08 23:58:38$
//   Revision:            $Revision: 1.0$
//
//


In order to avoid class redefinition, you have to define a label for your application definition, as follows:

#if !defined(KRATOS_POISSON__H_INCLUDED)
#define  KRATOS_POISSON_H_INCLUDED


the #endif is at the end of the code (the rest of the lines must be included between these ones):

#endif // KRATOS_POISSON_H_INCLUDED  defined


Now you have to add the "include" files (note that here you define the element to be used, poisson_2d.h, for the rest of include files you can copy as it is):

// System includes
#include <string>
#include <iostream>

// External includes

// Project includes
#include "includes/define.h"
#include "includes/kratos_application.h"

#include "custom_elements/poisson_2d.h"

#include "includes/variables.h"
#include "includes/condition.h"
#include "includes/ublas_interface.h"


Declare the namespace Kratos (copy at it is):

namespace Kratos
{

///@name Kratos Globals
///@{

// Variables definition

///@}
///@name Type Definitions
///@{

///@}
///@name  Enum's
///@{

///@}
///@name  Functions
///@{

///@}
///@name Kratos Classes
///@{

/// Short class definition.
/** Detail class definition.
*/


Now, coming from the element definition, remember that we have called our application KratosR1PoissonApplication, the name we have to use in the following lines:

	class KratosR1PoissonApplication : public KratosApplication
{
public:
///@name Type Definitions
///@{

/// Pointer definition of KratosR1PoissonApplication
KRATOS_CLASS_POINTER_DEFINITION(KratosR1PoissonApplication);

///@}
///@name Life Cycle
///@{

/// Default constructor.
KratosR1PoissonApplication();

/// Destructor.
virtual ~KratosR1PoissonApplication(){}

///@}
///@name Operators
///@{

///@}
///@name Operations
///@{

virtual void Register();

///@}
///@name Access
///@{

///@}
///@name Inquiry
///@{

///@}
///@name Input and output
///@{

/// Turn back information as a string.
virtual std::string Info() const
{
return "KratosR1PoissonApplication";
}

virtual void PrintInfo(std::ostream& rOStream) const
{
rOStream << Info();
PrintData(rOStream);
}

///// Print object's data.
virtual void PrintData(std::ostream& rOStream) const
{
KRATOS_WATCH("in KratosR1PoissonApplication");
KRATOS_WATCH(KratosComponents<VariableData>::GetComponents().size() );
rOStream << "Variables:" << std::endl;
KratosComponents<VariableData>().PrintData(rOStream);
rOStream << std::endl;
rOStream << "Elements:" << std::endl;
KratosComponents<Element>().PrintData(rOStream);
rOStream << std::endl;
rOStream << "Conditions:" << std::endl;
KratosComponents<Condition>().PrintData(rOStream);
}

///@}
///@name Friends
///@{

///@}

protected:
///@name Protected static Member Variables
///@{

///@}
///@name Protected member Variables
///@{

///@}
///@name Protected Operators
///@{

///@}
///@name Protected Operations
///@{

///@}
///@name Protected  Access
///@{

///@}
///@name Protected Inquiry
///@{

///@}
///@name Protected LifeCycle
///@{

///@}


Now we have to declare our element class name (Poisson2D):

	private:
///@name Static Member Variables
///@{

//       static const ApplicationCondition  msApplicationCondition;

///@}
///@name Member Variables
///@{
const Poisson2D  mPoisson2D;

///@}
///@name Private Operators
///@{

///@}
///@name Private Operations
///@{

///@}
///@name Private  Access
///@{

///@}
///@name Private Inquiry
///@{

///@}
///@name Un accessible methods
///@{


And, finally, we have to declare the assignment operator and constructor method (remember to close the namespace definition and #endif label if you had not done it before):

		/// Assignment operator.
KratosR1PoissonApplication& operator=(KratosR1PoissonApplication const& rOther);

/// Copy constructor.
KratosR1PoissonApplication(KratosR1PoissonApplication const& rOther);

///@}

}; // Class KratosR1PoissonApplication

///@}

///@name Type Definitions
///@{

///@}
///@name Input and output
///@{

///@}

}  // namespace Kratos.

#endif // KRATOS_POISSON_H_INCLUDED  defined


#### Customising the implementation application file: kPoisson.cpp

The implementation file really doesn't need any comment. Just note that your customising parts are remarked in bold characters:

//
//   Project Name:        Kratos
//   Last Modified by:    $Author: it's me$
//   Date:                $Date: 2008-08-08$
//   Revision:            $Revision: 1.0$
//
//

// System includes

// External includes

// Project includes
#include "includes/define.h"
#include "geometries/triangle_2d_3.h"
#include "geometries/triangle_3d_3.h"
#include "geometries/tetrahedra_3d_4.h"
#include "geometries/line_2d.h"
#include "kPoisson.h"
#include "includes/variables.h"

namespace Kratos
{
KratosR1PoissonApplication::KratosR1PoissonApplication():
mPoisson2D(0, Element::GeometryType::Pointer(new Triangle2D3<Node<3> >(Element::GeometryType::PointsArrayType(3, Node<3>()))))
{}

void KratosR1PoissonApplication::Register()
{
// calling base class register to register Kratos components
KratosApplication::Register();
std::cout << "Initializing KratosR1PoissonApplication... " << std::endl;

// Registering elements and conditions here
KRATOS_REGISTER_ELEMENT("Poisson2D", mPoisson2D);
}

}  // namespace Kratos


#### Customising the python compiling application file: Jamfile

This file indicates Kratos where to find all the specific application files, therefore basically you should include your custom directories and files (note again that you have just to pay attention to the bold characters). Take care while modifying this file because python is highly sensitive to spaces and tab characters.

project PoissonApplication
:
source-location
.
custom_elements
custom_python
custom_utilities
external_includes
:
requirements <include>.
<define>KRATOS_PYTHON
;

#################################################################################
#################################################################################
##definition of "dependencies for the project"
# no libs needed for this application ... have a look to PFEMapplication for examples
# of use in a more general case

#################################################################################
#################################################################################
## list of files to be build, including dependencies to other libraries
import python ;
python-extension KratosR1PoissonApplication
:
#list of sources
kPoisson.cpp
kPoisson_python_application.cpp
poisson_2d.cpp

#kratos library
/KratosProject//libkratos_static

#"system" includes
/KratosProject//pythonlib
/KratosProject//boost_python_lib
;

#################################################################################
#################################################################################
## rules to install ... and to remove the prefix "lib"

install install : KratosR1PoissonApplication : <location>$(TOP)/libs ;  #### Customising the python variables file: kPoisson_python_application.cpp The following file basically indicates Kratos the variables to be used by the pyhton commands. Therefore, we have just to modify the name of the application (KratosR1PoissonApplication) and to add the variables names (DUMMY_UNKNOWN for the unknown, DUMMY_MATERIAL for the material property and DUMMY_POINT_SOURCE for the source term). Legal issues /* ============================================================================== KratosR1PoissonApplication A library based on: Kratos A General Purpose Software for Multi-Physics Finite Element Analysis Version 1.0 (Released on march 05, 2007). Copyright 2008 Pooyan Dadvand, Riccardo Rossi pooyan@cimne.upc.edu rrossi@cimne.upc.edu - CIMNE (International Center for Numerical Methods in Engineering), Gran Capita' s/n, 08034 Barcelona, Spain Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following condition: Distribution of this code for any commercial purpose is permissible ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNERS. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ============================================================================== */  // // Project Name: Kratos // Last modified by:$Author: it's me! $// Date:$Date: 2008-08-08 23:58:38 $// Revision:$Revision: 1.0 $// //  // System includes #if defined(KRATOS_PYTHON) // External includes #include <boost/python.hpp> // Project includes #include "includes/define.h" #include "kPoisson.h" //#include "custom_python/add_custom_strategies_to_python.h" //#include "custom_python/add_custom_utilities_to_python.h" namespace Kratos { namespace Python { using namespace boost::python; BOOST_PYTHON_MODULE(KratosR1PoissonApplication) { class_<KratosR1PoissonApplication, KratosR1PoissonApplication::Pointer, bases<KratosApplication>, boost::noncopyable >("KratosR1PoissonApplication") ; AddCustomStrategiesToPython(); AddCustomUtilitiesToPython(); //registering variables in python KRATOS_REGISTER_IN_PYTHON_VARIABLE(DUMMY_UNKNOWN) KRATOS_REGISTER_IN_PYTHON_VARIABLE(DUMMY_MATERIAL) KRATOS_REGISTER_IN_PYTHON_VARIABLE(DUMMY_POINT_SOURCE) } } // namespace Python. } // namespace Kratos. #endif // KRATOS_PYTHON defined  #### Creating a Custom Condition to incorporate the thermal loads: pointsource.h ; pointsource.cpp The process of creating a custom condition is similar to creating an element, the easiest way is to copy the code from another condition and change it to suit our needs. Due to simplicity and similarities, the easiest files to start with are PointForce2D from the structural application. The difference between our recently created element and the condition we are about to create is that in this case we'll be loading data nodewisely. DUMMY_POINT_SOURCE is our variable containing the external thermal loads to our problem. To include them we'll create a new condition called pointsource . KRATOS will call the condition and assign it node by node to the system of equations. Since this is standard load, we only have to add the contribution to the right hand side (RHS) without any calculation. In pseudo code, our task is simply: RHS (node) + = DUMMY_POINT_SOURCE (node)  Still, note that the structre of a condition, as well as the one in elements, includes both the RHS and the left hand side matrix (LHS). This gives us flexibility and thus we can incorporate operations that also affect the matrix. We will create 2 files (pointsource.h and pointsource.cpp ), preferably inside the custom_conditions folder . Bear in mind that conditions are a class called by the solver , so you have to respect the structure and subroutines required by it. Again, the same rules that apply to elements. Again, in pseudocode: class pointsource void CalculateLocalSystem void CalculateRightHandSide void EquationIdVector void GetDofList  Just as in the elements, to incorporate this condition we have to create it and register it in Kratos. To do so adding lines both in kPoisson.h and kPoisson.cpp is necessary. Once registered, the solver will be the one calling it and ensambling the RHS, so there's no need to call it in the problemtype. Also, do not forget to include the file in the jamfile of our problemtype. Below you can find both the .h and .cpp files: pointsource.h #if !defined(KRATOS_PointSource_CONDITION_H_INCLUDED ) #define KRATOS_PointSource_CONDITION_H_INCLUDED // External includes #include "boost/smart_ptr.hpp" // Project includes #include "includes/define.h" #include "includes/serializer.h" #include "includes/condition.h" #include "includes/ublas_interface.h" #include "includes/variables.h" namespace Kratos { class PointSource : public Condition { public: ///@name Type Definitions ///@{ /// Counted pointer of PointForce2D KRATOS_CLASS_POINTER_DEFINITION(PointSource); /// Default constructor. PointSource(IndexType NewId, GeometryType::Pointer pGeometry); PointSource(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties); /// Destructor. virtual ~PointSource(); Condition::Pointer Create(IndexType NewId, NodesArrayType const& ThisNodes, PropertiesType::Pointer pProperties) const; void CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo); void CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo); //virtual void CalculateLeftHandSide(MatrixType& rLeftHandSideMatrix, ProcessInfo& rCurrentProcessInfo); void EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& rCurrentProcessInfo); void GetDofList(DofsVectorType& ConditionalDofList,ProcessInfo& CurrentProcessInfo); protected: private: friend class Serializer; // A private default constructor necessary for serialization PointSource(){}; virtual void save(Serializer& rSerializer) { rSerializer.save("Name","PointSource"); KRATOS_SERIALIZE_SAVE_BASE_CLASS(rSerializer, Condition ); } virtual void load(Serializer& rSerializer) { KRATOS_SERIALIZE_LOAD_BASE_CLASS(rSerializer, Condition ); } }; // Class PointForce2D } namespace kratos  pointsource.cpp // Project includes #include "includes/define.h" #include "custom_conditions/pointsource.h" #include "kPoisson.h" #include "utilities/math_utils.h" namespace Kratos { //************************************************************************************ //************************************************************************************ PointSource::PointSource(IndexType NewId, GeometryType::Pointer pGeometry) : Condition(NewId, pGeometry) { //DO NOT ADD DOFS HERE!!! } //************************************************************************************ //************************************************************************************ PointSource::PointSource(IndexType NewId, GeometryType::Pointer pGeometry, PropertiesType::Pointer pProperties) : Condition(NewId, pGeometry, pProperties) { } Condition::Pointer PointSource::Create(IndexType NewId, NodesArrayType const& ThisNodes, PropertiesType::Pointer pProperties) const { return Condition::Pointer(new PointSource(NewId, GetGeometry().Create(ThisNodes), pProperties)); } PointSource::~PointSource() { } //************************************************************************************ //************************************************************************************ void PointSource::CalculateRightHandSide(VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo) { KRATOS_TRY if(rRightHandSideVector.size() != 1) rRightHandSideVector.resize(1,false); double load = GetGeometry()[0].GetSolutionStepValue(DUMMY_POINT_SOURCE); rRightHandSideVector[0] = load; KRATOS_CATCH("") } //************************************************************************************ //************************************************************************************ void PointSource::CalculateLocalSystem(MatrixType& rLeftHandSideMatrix, VectorType& rRightHandSideVector, ProcessInfo& rCurrentProcessInfo) { KRATOS_TRY if(rLeftHandSideMatrix.size1() != 1) rLeftHandSideMatrix.resize(1,1,false); noalias(rLeftHandSideMatrix) = ZeroMatrix(1,1); if(rRightHandSideVector.size() != 1) rRightHandSideVector.resize(1,false); double load = GetGeometry()[0].GetSolutionStepValue(DUMMY_POINT_SOURCE); rRightHandSideVector[0] = load; KRATOS_CATCH("") } //************************************************************************************ //************************************************************************************ void PointSource::EquationIdVector(EquationIdVectorType& rResult, ProcessInfo& CurrentProcessInfo) { int number_of_nodes = GetGeometry().PointsNumber(); unsigned int index; unsigned int dim = 1; rResult.resize(number_of_nodes*dim); for (int i=0;i<number_of_nodes;i++) { index = i*dim; rResult[index] = (GetGeometry()[i].GetDof(DUMMY_UNKNOWN).EquationId()); } } //************************************************************************************ //************************************************************************************ void PointSource::GetDofList(DofsVectorType& ConditionalDofList,ProcessInfo& CurrentProcessInfo) { unsigned int dim = 1; ConditionalDofList.resize(GetGeometry().size()*dim); unsigned int index; for (unsigned int i=0;i<GetGeometry().size();i++) { index = i*dim; ConditionalDofList[index] = (GetGeometry()[i].pGetDof(DUMMY_UNKNOWN)); } } } // Namespace Kratos  #### Customising the python solver file: static_poisson_solver.py The following file customise the Kratos solvers and strategies for our specific application. This file purpose is just to put together our variable names and solvers to be used, as follows (bold characters indicates the lines to be modified for each application): #importing the Kratos Library from Kratos import * from KratosR1PoissonApplication import * def AddVariables(model_part): model_part.AddNodalSolutionStepVariable(DUMMY_UNKNOWN); model_part.AddNodalSolutionStepVariable(DUMMY_POINT_SOURCE); def AddDofs(model_part): for node in model_part.Nodes: #adding dofs node.AddDof(DUMMY_UNKNOWN); print "variables for the Poisson solver added correctly" class StaticPoissonSolver: ####################################################################### def __init__(self,model_part,domain_size): self.model_part = model_part self.time_scheme = ResidualBasedIncrementalUpdateStaticScheme() #definition of the solvers self.poisson_linear_solver = SkylineLUFactorizationSolver() #definition of the convergence criteria self.conv_criteria = DisplacementCriteria(1e-6,1e-9) ####################################################################### def Initialize(self): #creating the solution strategy CalculateReactionFlag = False ReformDofSetAtEachStep = False MoveMeshFlag = False import strategy_python self.solver = strategy_python.SolvingStrategyPython(self.model_part,self.time_scheme,self.poisson_linear_solver,self.conv_criteria,CalculateReactionFlag,ReformDofSetAtEachStep,MoveMeshFlag) ####################################################################### def Solve(self): (self.solver).Solve() ####################################################################### def SetEchoLevel(self,level): (self.solver).SetEchoLevel(level)  #### Customising the python applications interface: applications_interface.py The python file for the applications (applications_interface.py) registers the applications' names and paths in order to load them from our specific simulation program. You have to edit this file and delete the applications_interface.pyc file. Remember that our new application is called PoissonApplication with a class named KratosR1PoissonApplication in the path /kPoisson. We need to add our specific application name and paths, as follows (note that the new lines are written in bold characters). #path for applications s import sys Import_ALEApplication = False Import_IncompressibleFluidApplication = False Import_StructuralApplication = False Import_ConvectionDiffusionApplication = False Import_FSIApplication = False Import_PFEMApplication = False Import_ExternalSolversApplication = False Import_ULFApplication = False Import_MeshingApplication = False Import_PoissonApplication = False print "Applications Available:" print "Import_ALEApplication: False" print "Import_IncompressibleFluidApplication: False" print "Import_StructuralApplication: False" print "Import_ConvectionDiffusionApplication: False" print "Import_FSIApplication: False" print "Import_ExternalSolversApplication: False" print "Import_ULFApplication: False" print "Import_MeshingApplication: False" print "Import_PoissonApplication: False" def ImportApplications(kernel, applications_path): ########################################################################## ##importing the applications print "Applications Available:" print "Import_ALEApplication: "+str(Import_ALEApplication) print "Import_IncompressibleFluidApplication: "+str(Import_IncompressibleFluidApplication) print "Import_StructuralApplication: "+str(Import_StructuralApplication) print "Import_ConvectionDiffusionApplication: "+str(Import_ConvectionDiffusionApplication) print "Import_FSIApplication: "+str(Import_FSIApplication) print "Import_ExternalSolversApplication: "+str(Import_ExternalSolversApplication) print "Import_ULFApplication: "+str(Import_ULFApplication) print "Import_ULFApplication: "+str(Import_MeshingApplication) print "Import_ PoissonApplication: "+str(Import_PoissonApplication) if(Import_ALEApplication == True): print "importing KratosR1ALEApplication ..." sys.path.append(applications_path + '/ALEapplication/python_scripts' ) sys.path.append(applications_path + '/ALEapplication/Linux') from KratosR1ALEApplication import * ale_app = KratosR1ALEApplication() kernel.AddApplication(ale_app) print "KratosR1ALEApplication Succesfully imported" if(Import_IncompressibleFluidApplication == True): print "importing KratosR1IncompressibleFluidApplication ..." sys.path.append(applications_path + '/incompressible_fluid_application/python_scripts') sys.path.append(applications_path + '/incompressible_fluid_application/Linux') from KratosR1IncompressibleFluidApplication import * print "KratosR1IncompressibleFluidApplication lib loaded" incompressible_fluid_application = KratosR1IncompressibleFluidApplication() print "KratosR1IncompressibleFluidApplication application created" kernel.AddApplication(incompressible_fluid_application) print "KratosR1IncompressibleFluidApplication Succesfully imported" if(Import_StructuralApplication == True): print "importing KratosR1StructuralApplication ..." sys.path.append(applications_path + '/structural_application/python_scripts') sys.path.append(applications_path + '/structural_application/Linux') from KratosR1StructuralApplication import * structural_application = KratosR1StructuralApplication() kernel.AddApplication(structural_application) print "KratosR1StructuralApplication Succesfully imported" if(Import_ConvectionDiffusionApplication == True): print "importing KratosR1ConvectionDiffusionApplication ..." sys.path.append(applications_path + '/convection_diffusion_application/python_scripts') sys.path.append(applications_path + '/convection_diffusion_application/Linux') from KratosR1ConvectionDiffusionApplication import * convection_diffusion_application = KratosR1ConvectionDiffusionApplication() kernel.AddApplication(convection_diffusion_application) print "KratosR1ConvectionDiffusionApplication Succesfully imported" if(Import_FSIApplication == True): print "importing FSIapplication ..." sys.path.append(applications_path + '/FSIapplication/python_scripts') sys.path.append(applications_path + '/FSIapplication/Linux') from KratosR1FSIApplication import * fsi_application = KratosR1FSIApplication() kernel.AddApplication(fsi_application) print "FSIapplication Succesfully imported" if(Import_PFEMApplication == True): print "importing KratosR1PFEMApplication ..." sys.path.append(applications_path + '/PFEMapplication/python_scripts') sys.path.append(applications_path + '/PFEMapplication/Linux') from KratosR1PFEMApplication import * pfkElectrostatic = KratosR1PFEMApplication() kernel.AddApplication(pfkElectrostatic) print "KratosR1PFEMApplication Succesfully imported" if(Import_ExternalSolversApplication == True): print "importing KratosExternalSolversApplication ..." sys.path.append(applications_path + '/ExternalSolversApplication/python_scripts') sys.path.append(applications_path + '/ExternalSolversApplication/Linux') from KratosR1ExternalSolversApplication import * external_solvers_application = KratosR1ExternalSolversApplication() kernel.AddApplication(external_solvers_application) print "KratosExternalSolversApplication sucessfully imported" if(Import_ULFApplication == True): print "importing KratosR1ULFApplication ..." sys.path.append(applications_path + '/ULFapplication/python_scripts') sys.path.append(applications_path + '/ULFapplication/Linux') from KratosR1ULFApplication import * ulf_application = KratosR1ULFApplication() kernel.AddApplication(ulf_application) print "KratosULFApplication sucessfully imported" if(Import_MeshingApplication == True): print "importing KratosR1MeshingApplication ..." sys.path.append(applications_path + '/MeshingApplication/python_scripts') from KratosR1MeshingApplication import * meshing_application = KratosR1MeshingApplication() kernel.AddApplication(meshing_application) print "KratosMeshingApplication sucessfully imported" if(Import_PoissonApplication == True): print "importing KratosR1PoissonApplication ..." sys.path.append(applications_path + '/kPoisson/python_scripts') sys.path.append(applications_path + '/kPoisson/Linux') from KratosR1PoissonApplication import * kPoisson = KratosR1PoissonApplication() kernel.AddApplication(kPoisson) print "Kratos PoissonApplication sucessfully imported" ########################################################################## ##dynamic renumbering of variables to ensure the consistency kernel.Initialize() if(Import_ALEApplication == True): kernel.InitializeApplication(ale_app); if(Import_IncompressibleFluidApplication == True): kernel.InitializeApplication(incompressible_fluid_application); if(Import_StructuralApplication == True): kernel.InitializeApplication(structural_application); if(Import_ConvectionDiffusionApplication == True): kernel.InitializeApplication(convection_diffusion_application); if(Import_FSIApplication == True): kernel.InitializeApplication(fsi_application); if(Import_PFEMApplication == True): kernel.InitializeApplication(pfkElectrostatic); if(Import_ExternalSolversApplication == True): kernel.InitializeApplication(external_solvers_application); if(Import_ULFApplication == True): kernel.InitializeApplication(ulf_application); if(Import_MeshingApplication == True): kernel.InitializeApplication(meshing_application); if(Import_PoissonApplication == True): kernel.InitializeApplication(kPoisson);  #### Customising the main Kratos python compiling file: Jamroot The last file to modify is the python guide to compile Kratos, the Jamroot file in the Kratos root. The only lines to include are those related to your application, that is, at the end of the file, the list of applications included in the compilation. Note that if you don't want to load any specific application, you can remove it from this file or also just simply comment it using the "#" character: using gcc ; using intel : : : <cxxflags>"-fPIC -ansi -funroll-loops -cxxlib-gcc -openmp -wd654 -wd10010" ; using msvc ; using python ; ################################################################################# ## defining "common includes" and external libraries path-constant TOP : . ; project KratosProject : ############################################################################# ############### TO BE CUSTOMARIZED -- LINUX VERSION EXAMPLE!! ############### ##requirements <include>/usr/include/boost #to be customarized ## <include>/usr/include/python2.5/ #to be customarized ## <include>$(TOP)/kratos
##	     <include>$(TOP)/external_libraries ############################################################################# ############################################################################# ############### TO BE CUSTOMARIZED -- WINDOWS VERSION EXAMPLE!! ############### requirements <include>"D:/kratosR1/external_libraries/boost_1_34_1/" #to be customarized <include>"D:/kratosR1/Python25/include" #to be customarized <include>$(TOP)/kratos
<include>$(TOP)/external_libraries ############################################################################# ##omptl - necessary for parallelism <include>$(TOP)/external_libraries/omptl

#basic configurations
<define>NDEBUG

#compiler settings - can be customarized by the user
#WARNING -fPIC is NEEDED to compile on 64bit systems - it has to be specified here in order to include it in the
#kratos "static" library
<warnings>on

#gcc settings
<toolset>gcc:<cflags>"-fPIC -funroll-loops" ##settings for external libraries
<toolset>gcc:<cxxflags>"-fPIC -ansi -funroll-loops -ffast-math"

#msvc settings
<toolset>msvc:<cxxflags>"/D_SCL_SECURE_NO_DEPRECATE  /wd4335"

#intel settings
##	<toolset>intel:<cxxflags>"-fPIC -ansi -funroll-loops -ffast-math"
:
default-build release
;

#################################################################################
## defining "common external libraries"
## the user should adapt this depending on the installations directories on his system

#############################################################################
############### TO BE CUSTOMARIZED -- LINUX VERSION EXAMPLE!! ###############
##lib pythonlib : : <name>python2.5 ;
##lib boost_python_lib : : <variant>debug <name>boost_python-mt-d ;
##lib boost_python_lib : : <variant>release <name>boost_python-mt ;
##lib boost_python_lib : : <variant>debug <name>boost_python-gcc-mt-d-1_34_1 ;
##lib boost_python_lib : : <variant>release <name>boost_python-gcc-mt-1_34_1 ;
##lib gidpost : : <name>gidpost <search>$(TOP)/external_libraries/gidpost/unix/release ; ############################################################################# ############################################################################# ############### TO BE CUSTOMARIZED -- WINDOWS VERSION EXAMPLE!! ############### lib pythonlib : : <name>python25 <search>"D:/kratosR1/Python25/libs" ; lib boost_python_lib : : <variant>release <name>boost_python-vc80-mt-1_34_1 <search>"D:/kratosR1/external_libraries/boost_1_34_1/lib" ; lib boost_python_lib : : <variant>debug <name>boost_python-vc80-mt-gd-1_34_1 <search>"D:/kratosR1/external_libraries/boost_1_34_1/lib" ; lib gidpost : : <name>gidpost <search>$(TOP)/external_libraries/gidpost/win/Release/ ;
#############################################################################

#intel omp library...
lib intelomp  : : <name>guide  ;

alias libomp : intelomp : <toolset>intel ;
alias libomp : : <toolset>gcc ;
alias libomp : : <toolset>msvc ;

#################################################################################
# IN PRINCIPLE THIS SHOULD REQUIRE NO CUSTOMARIZATION .. apart for compiling new applications
## defining "ids" for the different projects
use-project /kratos-prj : . ;

##kratos base library and python interfaces
use-project /kratos-prj/kratos : kratos ;

##applications included in the compilation
use-project /kratos-prj/PFEMapplication : $(TOP)/applications/PFEMapplication ; use-project /kratos-prj/incompressible_fluid_application :$(TOP)/applications/incompressible_fluid_application ;
use-project /kratos-prj/structural_application : $(TOP)/applications/structural_application ; use-project /kratos-prj/convection_diffusion_application :$(TOP)/applications/convection_diffusion_application ;
use-project /kratos-prj/ExternalSolversApplication : $(TOP)/applications/ExternalSolversApplication ; use-project /kratos-prj/ULFapplication :$(TOP)/applications/ULFapplication ;
use-project /kratos-prj/ALEapplication : $(TOP)/applications/ALEapplication ; use-project /kratos-prj/FSIapplication :$(TOP)/applications/FSIapplication ;
use-project /kratos-prj/kPoisson : $(TOP)/applications/kPoisson ; alias libkratos_static : /kratos-prj/kratos//libkratos/<link>static ; ################################################################################# ## installation alias install : /kratos-prj//kratos /kratos-prj/PFEMapplication//install /kratos-prj/incompressible_fluid_application//install /kratos-prj/structural_application//install /kratos-prj/convection_diffusion_application//install # /kratos-prj/ExternalSolversApplication//install /kratos-prj/ULFapplication//install /kratos-prj/ALEapplication//install # /kratos-prj/FSIapplication//install /kratos-prj/kPoisson//install ; ECHO$(TOP) ;


### Rebuilding Kratos

Now it is the moment to compile all our new files. It's expected to find minor errors, and we will include in this section the most frequent problems found. Please, use the discussion tab to include your questions or difficulties.

 Things to do: Include the most frequent compilation errors.

One typical error is to use something not yet undefined in Kratos. The most evident case is the variables' name: DUMMY_UNKNOWN, DUMMY_MATERIAL, DUMMY_POINT_SOURCE for your application.

The variables are defined, created and registered in the variables.h file in the kratosR1\kratos\includes directory and in the variables.cpp file in the kratosR1\kratos\sources directory (see How_to_Add_a_variable).

In variables.h, check if the following lines are included (if not, please include them):

	KRATOS_DEFINE_VARIABLE(double, DUMMY_UNKNOWN)
KRATOS_DEFINE_VARIABLE(double, DUMMY_MATERIAL)
KRATOS_DEFINE_VARIABLE(double, DUMMY_POINT_SOURCE)


In variables.cpp, check if the following lines are included (if not, please include them):

	KRATOS_CREATE_VARIABLE(double, DUMMY_UNKNOWN)
KRATOS_CREATE_VARIABLE(double, DUMMY_MATERIAL)
KRATOS_CREATE_VARIABLE(double, DUMMY_POINT_SOURCE)


and:

	KRATOS_REGISTER_VARIABLE(DUMMY_UNKNOWN)
KRATOS_REGISTER_VARIABLE(DUMMY_MATERIAL)
KRATOS_REGISTER_VARIABLE(DUMMY_POINT_SOURCE)


### Source Files for this Kratos Application

The kPoisson directory with all their files can be found in KPoisson.dir.zip. Please download, unzip and copy the whole directory in your /kratosR1/applications directory.

 Warning. Please, note that: Do not copy these files inside your KratosR1 directory, because doing this would imply destroying the CVS. You should instead merge manually the differences.

## A First GiD - Kratos Interface

### Suggested Prerequisites

• Kratos application
• Basic knowledge about GiD customisation (an excellent introduction can be found in the GiD's Reference Manual

We will use GiD as our favourite pre and post-processor. To customise GiD for our Kratos kPoisson application, we will create two kind of files:

• code to customise the GiD windows for input data (files with .mat, .cnd and .prb extensions);
• code to get the user's input data from the windows and translate them to Kratos input data (files with .bas extension);

For our kPoisson application, it is enough to create two data files: the materials and the conditions windows.

Go to the GiD's problemtype directory (in MS Windows typically in something like "C:\Archivos de programa\GiD\GiD 8.2.0b\problemtypes\") and create a new folder with the name of your application, for example, kPoisson.gid.

### Customising GiD input data Windows

#### Materials GiD window: kPoisson.mat

Create a new text file with the name kPoisson.mat in your GiD kPoisson problemtype directory (kPoisson.gid).

Defining the materials' properties in GiD requires just to indicate the variable name and value of the property, for example:

MATERIAL: Air
QUESTION: Dummy_Material
VALUE: 1.0
END MATERIAL


This will generate in GiD:

If you want to include different material values, you can add them by simply copying the same lines:

MATERIAL: Air
QUESTION: Dummy_Material
VALUE: 1.0
END MATERIAL
MATERIAL: Aluminium
QUESTION: Dummy_Material
VALUE: 1000.0
END MATERIAL


#### Conditions GiD window: kPoisson.cnd

Create a new text file with the name kPoisson.cnd in your GiD kPoisson problemtype directory (kPoisson.gid).

We will define just two conditions: the Dirichlet boundary condition to be applied on points or lines, and a point source condition (to be applied on points). We will split both conditions by using the "BOOK" tab of GiD:

BOOK: Dirichlet_Conditions
CONDITION: Point_Fix_Value
CONDTYPE: over points
CONDMESHTYPE: over nodes
QUESTION: Value
VALUE: 0.0
END CONDITION


This will generate in GiD the window:

To include the same boundary condition on lines, we add the following lines:

CONDITION: Line_Fix_Value
CONDTYPE: over lines
CONDMESHTYPE: over nodes
QUESTION: Value
VALUE: 0.0
END CONDITION


And for the point source condition:

BOOK: Dummy_Sources
CONDTYPE: over points
CONDMESHTYPE: over nodes
QUESTION: Q
VALUE: 0.0
END CONDITION


with the result of:

### Transferring GiD input data to Kratos input data files

All the data in GiD (geometrical data, mesh information, material and conditions assigned to our model) will be transferred to Kratos by using .bas files. Basically, you have to translate the GiD labels to the Kratos variable name's.

The new input format requires only one file with .mdpa extension (see Input Data ). This format is more user friendly in case something has to be changed using a text editor.

We'll need to create our input file containing the materials, nodes, elements, Boundary conditions and Loads. Here's a simple example that is self explanatory:

example.mdpa

Begin ModelPartData
//  VARIABLE_NAME value
End ModelPartData

//we start by looping only in the materials used, GID does this automatically
Begin Properties 1
DUMMY_MATERIAL 1.0
End Properties

Begin Nodes
1         0.15421        -2.88256         0.00000
2        -3.37484        -2.88256         0.00000
3         0.15421         2.12337         0.00000
4        -3.37484         2.12337         0.00000
5        -6.90389        -2.88256         0.00000
6        -6.90389         2.12337         0.00000
7       -10.43295        -2.88256         0.00000
8       -10.43295         2.12337         0.00000
9       -13.96200        -2.88256         0.00000
10       -13.96200         2.12337         0.00000
End Nodes

Begin Elements Poisson2D
1 1 3 4 1
2 1 6 8 5
3 1 9 7 8
4 1 5 2 4
5 1 2 1 4
6 1 4 6 5
7 1 8 10 9
8 1 7 5 8
End Elements

Begin NodalData DUMMY_UNKNOWN          //be careful, variables are case sensitive!
9     1    0
10   1    0
End NodalData

Begin NodalData DUMMY_POINT_SOURCE              //now we loop the loads
1    0    453534
3    0    453534
End NodalData


GID will create the .mdpa starting from a .bas file. In our case we'll name it Kpoisson.mdpa.bas . This file will have the instructions to write Kratos' input file. The commands to tell GID what to do are quite simple and begin with a *, the words not used by the commands will be printed directly in the created file. A manual can be downloaded from this link <http://gid.cimne.upc.es/>.

01_kPoisson.mdpa.bas

Begin ModelPartData
//  VARIABLE_NAME value
End ModelPartData

//we start by looping only in the materials used, GID checks that automatically
*loop materials
Begin Properties *matnum()
DUMMY_MATERIAL *matprop(1)
End Properties
*end

Begin Nodes
*loop nodes
*format "%6i%15.5f%15.5f%15.5f"
*NodesNum *NodesCoord(1) *NodesCoord(2) *NodesCoord(3)
*end
End Nodes

Begin Elements Poisson2D
*loop elems
*elemsnum *elemsmat *elemsConec
*end elems
End Elements

Begin NodalData DUMMY_UNKNOWN          //be careful, variables are case sensitive!
*Set cond Point_Fix_Value *nodes
*loop nodes  *OnlyInCond
*NodesNum 1 *cond(1,int)
*end
End NodalData


Using *Set cond and *Add cond and later *OnlyInCond creates a loop only on the restricted nodes. The same commands are used for the loads:

Begin NodalData DUMMY_POINT_SOURCE              //now we loop the loads
*loop nodes  *OnlyInCond
*NodesNum    0    *cond(1)
*end nodes
End NodalData


### Batch files for your GiD kPoisson Problemtype

We have almost customised our GiD problemtype. We only need to create two additional files:

• the template file kPoisson.bas to generate the python command lines for running our problem in Kratos;
• the MS Windows (or Linux) batch file kPoisson.win.bat, basically to clean our working directory, to rename our files and to do some stuff previously to run python with our problem;

#### Python application file: kPoisson.bas

Create a new text file with the name kPoisson.bas in your GiD kPoisson problemtype directory (kPoisson.gid).

This template file will create each python command line file customised to our specific GiD example and our Kratos application (with the kPoisson element and the selected solver). Note that once again the bold characters indicates those lines you should modify, using our specific class, methods or variables denomination. Notice the lines that tell Kratos we're using the new format, in case you've downloaded an old version of the python script.

##################################################################
##################################################################
#setting the domain size for the problem to be solved
domain_size = 2

##################################################################
##################################################################
## ATTENTION: here the order is important

#including kratos path
kratos_libs_path = '../../../../libs' ##kratos_root/libs
kratos_applications_path = '../../../../applications' ##kratos_root/applications
import sys
sys.path.append(kratos_libs_path)
sys.path.append(kratos_applications_path)

print "before importing kratos"

#importing Kratos main library
from Kratos import **
print "Kratos library imported"
kernel = Kernel()   #defining kernel
print "kernel created"
#importing applications
import applications_interface
applications_interface.Import_PoissonApplication = True

applications_interface.ImportApplications(kernel, kratos_applications_path)

## from now on the order is not anymore crucial
##################################################################
##################################################################

from KratosR1PoissonApplication import **

#defining a model part
model_part = ModelPart("PoissonPart");

#adding of Variables to Model Part
import static_poisson_solver

gid_mode = GiDPostMode.GiD_PostBinary
multifile = MultiFileFlag.MultipleFiles
deformed_mesh_flag = WriteDeformedMeshFlag.WriteUndeformed
write_conditions = WriteConditionsFlag.WriteElementsOnly
gid_io = GidIO("*tcl(file tail [GiD_Info project  modelname])",gid_mode,multifile,deformed_mesh_flag,write_conditions)
#gid_io.ReadModelPart(model_part)           #this line was replaced by the following 2 to use the .mdpa file (singlefile) instead of the old multifile format
model_part_io = ModelPartIO("*tcl(file tail [GiD_Info project modelname])")     #new line 1

mesh_name = 0.0
gid_io.InitializeMesh( mesh_name );
gid_io.WriteMesh((model_part).GetMesh());
gid_io.FinalizeMesh()
print model_part

#the buffer size should be set up here after the mesh is read for the first time
model_part.SetBufferSize(3)

#importing the solver files

#creating a solver object
solver = static_poisson_solver.StaticPoissonSolver(model_part,domain_size)
solver.time_order = 1
solver.linear_solver = SkylineLUFactorizationSolver();
solver.echo_level = 0
solver.Initialize()

gid_io.InitializeResults(mesh_name,(model_part).GetMesh())

solver.Solve()

gid_io.WriteNodalResults(DUMMY_UNKNOWN,model_part.Nodes,0,0)
gid_io.FinalizeResults()


This file will create for our specific problem the following our_example.py file:

##################################################################
##################################################################
#setting the domain size for the problem to be solved
domain_size = 2

##################################################################
##################################################################
## ATTENTION: here the order is important

#including kratos path
kratos_libs_path = '../../../../libs' ##kratos_root/libs
kratos_applications_path = '../../../../applications' ##kratos_root/applications
import sys
sys.path.append(kratos_libs_path)
sys.path.append(kratos_applications_path)

print "before importing kratos"

#importing Kratos main library
from Kratos import *
print "Kratos library imported"
kernel = Kernel()   #defining kernel
print "kernel created"
#importing applications
import applications_interface
applications_interface.Import_PoissonApplication = True

applications_interface.ImportApplications(kernel, kratos_applications_path)

## from now on the order is not anymore crucial
##################################################################
##################################################################

from KratosR1PoissonApplication import *

#defining a model part
model_part = ModelPart("PoissonPart");

#adding of Variables to Model Part
import static_poisson_solver

gid_mode = GiDPostMode.GiD_PostBinary
multifile = MultiFileFlag.MultipleFiles
deformed_mesh_flag = WriteDeformedMeshFlag.WriteUndeformed
write_conditions = WriteConditionsFlag.WriteElementsOnly
gid_io = GidIO("our_example",gid_mode,multifile,deformed_mesh_flag,write_conditions)
#gid_io.ReadModelPart(model_part)           #this line was replaced by the following 2 to use the .mdpa file (singlefile) instead of the old multifile format
model_part_io = ModelPartIO("*tcl(file tail [GiD_Info project modelname])")     #new line 1

mesh_name = 0.0
gid_io.InitializeMesh( mesh_name );
gid_io.WriteMesh((model_part).GetMesh());
gid_io.FinalizeMesh()
print model_part

#the buffer size should be set up here after the mesh is read for the first time
model_part.SetBufferSize(3)

#importing the solver files

#creating a solver object
solver = static_poisson_solver.StaticPoissonSolver(model_part,domain_size)
solver.time_order = 1
solver.linear_solver = SkylineLUFactorizationSolver();
solver.echo_level = 0
solver.Initialize()

gid_io.InitializeResults(mesh_name,(model_part).GetMesh())

solver.Solve()

gid_io.WriteNodalResults(DUMMY_UNKNOWN,model_part.Nodes,0,0)
gid_io.FinalizeResults()



that is almost the same, but with the specific reference to the name of our example.

#### MS Window Batch file: kPoisson.win.bat

You'll have to make a new text file with the name kPoisson.win.bat in your GiD kPoisson problemtype directory (kPoisson.gid). This file contains instructions to rename files and call Kratos.

When creating the input files starting from the .bas files, GID will not read the .mdpa extension between the dots (it is only used for the user's clarity) . It simply starts with kPoisson.bas, naming it example.dat and then proceeds to create the others ommiting the "01_" and adding -1 at the end, -2 for the next and so on. The .bat file will be in charge of deleting the ones from the last run and renaming the new ones properly. example.dat will contain the python commands and therefore we'll have to change the extension later to .py . This file also executes the python script at the end.

kPoisson.win.bat

@ECHO OFF

rem OutputFile: %1.log

del %2\%1.py
del %2\%1.mdpa
ren %2\%1.dat %2\%1.py
ren %2\%1-1.dat %2\%1.mdpa

C:\kratosR1\Python25\python %2\%1.py >%2\%1.log

del %2\%1.post.res
ren %2\%1_0.post.bin %2\%1.post.res


A possible Linux version could be kPoisson.unix.bat:

#!/bin/csh -f
#    OutputFile: $2/$1.info
#    ErrorFile: $2/$1.err
#delete previous files
rm $2/$1.mdpa
rm $2/$1.py
mv $2/$1.dat $2/$1.py
mv $2/$1-1.dat $2/$1.mdpa
python $2/$1.py >$2/$1.log


### Source Files for your GiD-Kratos Application Problem Type

The kPoisson.gid directory with all their files can be found in KPoisson.gid.zip. Please download, unzip and copy the whole directory in your GiD problemtype directory.

### Files and Results in GiD

If everything is ok, now you can create your geometry, assign materials and conditions with GiD, launch your Kratos application and see the results.

#### Data files in GiD

After selecting our GiD problemtype (kPoisson),

we can create our geometry,

assign materials and conditions,

If we save now this problem with the name our_example, GiD will automatically generate the following files:

• our_example.cnd
• our_example.geo
• our_example.lin
• our_example.mat
• our_example.png
• our_example.rdr
• our_example.vv

Now we can mesh our model, generating the already presented mesh:

and creating the files:

• our_example.msh

If now we run our Kratos application, by doing:

a set of new files are generated:

• our_example.mdpa
• our_example.py
• our_example.log
• our_example.post.res

The first two files have been already explained.

The log file contains the details about how the simulation have been performed, including warnings or errors (if there is something).

#### Results files in GiD

our_example.log

Relevant aspects are indicated with bold characters:

Initializing KratosR1PoissonApplication...
"Application Registered" : Application Registered
"Variables Registered Registered" : Variables Registered Registered
"Elements Registered" : Elements Registered
"Conditions Registered" : Conditions Registered
our_example opened for io
our_example.node opened for io
our_example.prop opened for io
our_example.elem opened for io
our_example.cond opened for io
our_example.init opened for io
initializing result files
temp : Node #9 : (20.7379 , 12.7649 , 0)
writing a 2D mesh
"setting up the dofs" : setting up the dofs
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 0.0206048;  expected ratio = 1e-006absolute tol = 0.194195
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 0.00405189;  expected ratio = 1e-006absolute tol = 0.0380348
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 0.000159258;  expected ratio = 1e-006absolute tol = 0.00149484
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 2.82165e-005;  expected ratio = 1e-006absolute tol = 0.000264855
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 1.42173e-006;  expected ratio = 1e-006absolute tol = 1.33451e-005
Building Time : 0
LU factorization solver finished.

System Solve Time : 0
DISPLACEMENT CRITERIA :: obtained tol = 2.80121e-007;  expected ratio = 1e-006absolute tol = 2.62936e-006
"convergence is achieved" : convergence is achieved
before importing kratos
Kratos library imported
kernel created
Applications Available:
Import_ALEApplication: False
Import_IncompressibleFluidApplication: False
Import_StructuralApplication: False
Import_ConvectionDiffusionApplication: False
Import_FSIApplication: False
Import_ExternalSolversApplication: False
Import_ULFApplication: False
Import_MeshingApplication: False
Import_ElectrostaticApplication: False
Import_PoissonApplication: False
Applications Available:
Import_ALEApplication: False
Import_IncompressibleFluidApplication: False
Import_StructuralApplication: False
Import_ConvectionDiffusionApplication: False
Import_FSIApplication: False
Import_ExternalSolversApplication: False
Import_ULFApplication: False
Import_ULFApplication: False
Import_ ElectrostaticApplication: False
Import_ PoissonApplication: True
importing KratosR1PoissonApplication ...
Kratos PoissonApplication1 sucessfully imported
PoissonPart model part
Buffer Size : 1
Current solution step index : 0

Mesh 0 :
Number of Nodes      : 9
Number of Properties : 2
Number of Elements   : 8
Number of Conditions : 0

variables for the Poisson solver added correctly



The file our_example.post.res contains the results of the simulation, that is, the value of the unknowns for each node. It is written in binary format according to the GiD standards, and we can see the results by using the GiD post-processor:

If you want to get the results in a readable format, you can ask Gid to write them in an ascii format:

If we write results_ascii as the name to write the results in ascii format, we will obtain two files: results_ascii.msh and results_ascii.res.

Mesh file: results_ascii.msh

# encoding utf-8
MESH "Kratos Triangle2D3 Mesh" dimension 3 ElemType Triangle Nnode 3
Coordinates
1 -8.5770302 -4.7918601 0
2 -8.5770302 3.98651 0
3 6.08043 -4.7918601 0
4 6.08043 3.98651 0
5 -8.5770302 12.76488 0
6 6.08043 12.76488 0
7 20.73789 -4.7918601 0
8 20.73789 3.98651 0
9 20.73789 12.76488 0
end coordinates

Elements
1 2 1 3 1
2 3 4 2 1
5 5 2 4 1
6 4 6 5 1
end elements
MESH "Kratos Triangle2D3 Mesh 2" dimension 3 ElemType Triangle Nnode 3
Coordinates
end coordinates

Elements
3 4 3 7 2
4 7 8 4 2
7 6 4 8 2
8 8 9 6 2
end elements



Results file: results_ascii.res

GiD Post Results File 1.0

# encoding utf-8
Result "DUMMY UNKNOWN" "Kratos" 0 Scalar OnNodes
ComponentNames "DUMMY UNKNOWN"
Values
1 0
2 0
3 8.92342
4 9.84336
5 0
6 9.37023
7 7
8 7
9 7
End values


### Data Files for an Specific Example with Kratos in GiD

The our_example.gid directory with all their files can be found in our_example.gid.zip. Please download, unzip and copy the whole directory in your examples directory.

## Use and Validation of Our First Kratos Simulation Program

Suggested Prerequisites: