Kratos For Dummies OLD
(→Element implementation methods file: poisson_2d.cpp) |
(→Element implementation methods file: poisson_2d.cpp) |
||
Line 570: | Line 570: | ||
boost::numeric::ublas::bounded_matrix<double,3,2> msDN_DX; | boost::numeric::ublas::bounded_matrix<double,3,2> msDN_DX; | ||
− | + | bboost::numeric::ublas::bounded_matrix<double,2,2> msD; | |
− | + | barray_1d<double,3> msN; //dimension = number of nodes | |
− | + | barray_1d<double,3> ms_temp; //dimension = number of nodes | |
− | + | barray_1d<double,3> point_sources; //dimension = number of nodes | |
− | + | bboost::numeric::ublas::bounded_matrix<double,3,2> point_sources_DX; //dimension = number of nodes | |
Revision as of 16:09, 22 February 2011
|
|
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:
for a domain Ω, equivalent to write:
where K is the material property, 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 on a boundary
of the domain:
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:
Finite Element Method Formulation
The Weak formulation using the Weighted Residual Form (Galerkin Method) of Poisson equation can be written as follows:
with the weights for each differential equation. If
and using the integration by parts, this equation becomes:
for the two-dimensional Cartesian coordinates, each term can be written:
with N_i the shape forms of the element.
with B defined as:
These system of equations can be written as the following matricial form:
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.
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.
Element header file: poisson_2d.h
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). 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. ============================================================================== */
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 Static 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 ///@}
This code can be downloaded here: poisson_2d.h
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). 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. ============================================================================== */
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). List the static variables, 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) { //DO NOT ADD DOFS HERE!!! } //************************************************************************************ //************************************************************************************ 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;
bboost::numeric::ublas::bounded_matrix<double,2,2> msD; barray_1d<double,3> msN; //dimension = number of nodes barray_1d<double,3> ms_temp; //dimension = number of nodes barray_1d<double,3> point_sources; //dimension = number of nodes bboost::numeric::ublas::bounded_matrix<double,3,2> point_sources_DX; //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); //reading properties and conditions 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:
- 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;
- rename the .h and .cpp copied files to your element name;
- for example: poisson_2d.h and poisson_2d.cpp;
- edit your element header (.h) file and:
- for example, edit your poisson_2d.h file;
- search and replace the "KratosR1OriginalNameApplication" word to "KratosR1YourApplication";
- for example, search and replace KratosR1ConvectionDiffusionApplication for KratosR1PoissonApplication;
- modify the authors, data and hour of the last creation/modification, and version of the code;
- 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;
- search and replace the class name from the original to your new element;
- for example, search and replace ConvDiff2D for Poisson2D;
- edit your element implementation (.cpp) file and:
- for example, edit your poisson_2d.cpp file;
- search and replace the "KratosR1OriginalNameApplication" word to "KratosR1YourApplication";
- for example, search and replace KratosR1ConvectionDiffusionApplication for KratosR1PoissonApplication;
- modify the authors, data and hour of the last creation/modification, and version of the code;
- add your specific include files (your element header file and your application header file);
- for example, add #include "custom_elements/poisson_2d.h" and #include "kPoisson.h";
- search and replace the class name from the original to your new element;
- for example, search and replace ConvDiff2D for Poisson2D;
- 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;
- create, if needed, new variables or equation terms (for example, the point_source contribution);
- for example, add in your CalculateLocalSystem method, the following lines:
- 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
Suggested Prerequisites
- Kratos installed. If not, check How to Compile Kratos
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.
|
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
- 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
- for example copy the files from /kratosR1/applications/convection_diffusion_application to /kratosR1/applications/kPoisson;
- Copy your element's code (poisson_2d.h, poisson_2d.cpp) in your custom_elements subdirectory (/kratosR1/applications/kPoisson/custom_elements);
- 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
- for example copy the content from /kratosR1/applications/convection_diffusion_application/custom_python to /kratosR1/applications/kPoisson/custom_python;
- 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
- for example copy the content from /kratosR1/applications/convection_diffusion_application/python_scripts to /kratosR1/applications/kPoisson/python_scripts;
- 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"; } /// Print information about this object. 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 <link>shared ; ################################################################################# ################################################################################# ##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 add_custom_strategies_to_python.cpp add_custom_utilities_to_python.cpp #kratos library ##/kratos-prj/kratos//libkratos/<link>static /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.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
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 = True 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') 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 <threading>multi <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:<linkflags>"/NODEFAULTLIB:libcmt" <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 ; #ATTENTION: "this requires adding threading=multi to the bjam call" 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.
|
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.
The other files can be also download here (please download, unzip and copy in their each specific Kratos directory, as it is indicated):
- Applications interface.zip in /kratosR1/applications directory;
- Jamroot.zip in /kratosR1 directory;
- Variables.zip in /kratosR1/kratos/includes directory;
- Variables.cpp.zip in /kratosR1/kratos/sources directory;
|
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 CONDITION: Point_Dummy_Load 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.
Properties data file: 010_kPoisson.prop.bas
Create a new text file with the name 010_kPoisson.prop.bas in your GiD kPoisson problemtype directory (kPoisson.gid).
For the materials properties, you have to translate the GiD material label (Dummy_Material) to our Kratos variable (DUMMY_MATERIAL), as follows:
*loop materials *format "%i%f" PROPERTIES[*MatNum][DUMMY_MATERIAL] = *MatProp(Dummy_Material); *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; *loop elems *Set var i=0 *set var j= ElemsNnode *format "%i%i%i%i%i%i%i%i" ELEMENTS[*ElemsNum] = Poisson2D([*\ *for(i=1;i<j;i=i+1)*\ *ElemsConec(*i),*\ *end*\ *ElemsConec(*ElemsNnode)],*ElemsMat); *end elems
This template file will generate something like:
// Reading Elements ElementsGroup = dummy_group; ELEMENTS[1] = Poisson2D([2,1,3],1); ELEMENTS[2] = Poisson2D([3,4,2],1); ELEMENTS[3] = Poisson2D([4,3,7],2); ELEMENTS[4] = Poisson2D([7,8,4],2); ELEMENTS[5] = Poisson2D([5,2,4],1); ELEMENTS[6] = Poisson2D([4,6,5],1); ELEMENTS[7] = Poisson2D([6,4,8],2); ELEMENTS[8] = Poisson2D([8,9,6],2);
This is a file generated with a GiD mesh like the following:
Conditions data file: 012_kPoisson.cond.bas
Create a new text file with the name 012_kPoisson.cond.bas in your GiD kPoisson problemtype directory (kPoisson.gid).
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:
- Point_Fix_Value (Value)
- Line_Fix_Value (Value)
- Point_Dummy_Load (Q)
// Fixing degrees of freedom in nodes *Set cond Point_Fix_Value *nodes *Add cond Line_Fix_Value *nodes *loop nodes *OnlyInCond *format "%i%f" NODES[*NodesNum].Fix(DUMMY_UNKNOWN); *end nodes *Set cond Point_Dummy_Load *nodes *loop nodes *OnlyInCond NODES[*NodesNum].Fix(DUMMY_POINT_SOURCE); *end nodes
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.
Assigning the following conditions to our model:
this file will produce a data file like the following:
// Fixing degrees of freedom in nodes NODES[1].Fix(DUMMY_UNKNOWN); NODES[2].Fix(DUMMY_UNKNOWN); NODES[5].Fix(DUMMY_UNKNOWN); NODES[7].Fix(DUMMY_UNKNOWN); NODES[8].Fix(DUMMY_UNKNOWN); NODES[9].Fix(DUMMY_UNKNOWN); NODES[4].Fix(DUMMY_POINT_SOURCE);
Initial Values data file: 013_kPoisson.init.bas
Create a new text file with the name 013_kPoisson.init.bas in your GiD kPoisson problemtype directory (kPoisson.gid).
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 *format "%i%f" NODES[*NodesNum](DUMMY_UNKNOWN,0) = *cond(Value); *end nodes *Set cond Point_Dummy_Load *nodes *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
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.
################################################################## ################################################################## #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 static_poisson_solver.AddVariables(model_part) #reading a model 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) 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 static_poisson_solver.AddDofs(model_part) #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 static_poisson_solver.AddVariables(model_part) #reading a model 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) 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 static_poisson_solver.AddDofs(model_part) #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
Create a new text file with the name kPoisson.win.bat in your GiD kPoisson problemtype directory (kPoisson.gid).
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.
@ECHO OFF 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.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-1.dat %2\%1.prop 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 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 result file rm -f $2/$1.flavia.res 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 mv $2/$1.dat $2/$1.py mv $2/$1-1.dat $2/$1.prop mv $2/$1-2.dat $2/$1.elem 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
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.cond
- our_example.elem
- our_example.init
- our_example.node
- our_example.prop
- our_example.py
- our_example.log
- our_example.post.res
The first six 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:
"kerneal entered in AddApplication" : kerneal entered in AddApplication
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 reading nodes temp : Node #9 : (20.7379 , 12.7649 , 0) Nodes succesfully read reading Properties Properties succesfully read reading Elements Properties succesfully read reading Conditions Properties succesfully read reading Initial Values reading initiali values finished reading initial values Initial Values succesfully read Reading completed succesfully 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: