Self-Configuration Recipe
This recipe is incomplete and out-of-date and needs to be adapted
Purpose
The purpose of this recipe is to show the use of the following features of the COOLFluiD framework:
- CFLogFacility
- Framework Exceptions
- Self-Registering Objects
At the end of this recipe you should be able to understand the various print levels in CFLogFacility. You should be able to catch the exceptions thrown by the framework or the libraries that compose COOLFluiD. You should also be able to initialize a PhysicalModel and create a GeometricEntity, though the appropriate factory.
!!Step 1!! Go to the "Recipes" directory. Go into the "Recipe01" directory. Edit the file "main.cxx" and verify the following code is present in the file.
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> #include "Framework/CFLog.hh"
using namespace std; using namespace COOLFluiD;
int main() {
CFLogLevel::set(DEBUG_MAX);
CFLog(INFO, "COOLFluiD Recipe 1 starting: " << endl);
return 0;
} </span> [</html>]
The first line in the main() sets the print level of the CFLogFacility to DEBUG_MAX. The second line will print to output with the priority INFO, some sentence.
You can compile it with some special options because you must inform the compiler you are using the COOLFluid framework, where it is, and which libraries of it should it use.
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> g++ -ggdb -DHAVE_CONFIG_H -L$HOME/COOLFluiD/lib -I$HOME/COOLFluiD/include/coolfluid -lFramework -lUtils -lMathTools -lParallel -lMPI *.cxx -o program </span> [</html>]
A "program" executable should be compiled now. To run it, first you must inform the system where the COOLFluiD libraries are. Do this by setting the enviromental variable "LD_LIBRARY_PATH".
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$HOME/COOLFluiD/lib" </span> [</html>]
The result should be:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> COOLFluiD Recipe 1 starting: </span> [</html>]
!!Step 2!!
Add the following lines to the main(), just after the print message, before the return statement.
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;">
PhysicalModel::setPhysicalModelImpl("Euler2D");
VolumeIntegrator::getInstance().setIntegrationForAllGeo(GAUSSLEGENDRE,ORDER1);
const CFString cellProviderName = "LagrangeTriagP1P1";
BaseGeometricEntityProvider<Cell>* cellProvider = GeometricEntityFactory<Cell>::getProvider(cellProviderName);
</span> [</html>]
You shouldn't care much about what they mean at this point. Just take them for granted. In any case, the first line initializes the PhysicalModel to Euler2D, the second sets the volume integrations on all GeometricEntity's to be a GaussLegendre of first order. The thir line creates a name which is used in the fourth line get the provider of GeometricEntity of type "LagrangeTriagP1P1".
!!Step 3!!
If you would try to compile, all sort of errors would appear. That's because the inclusion of the header files are missing.
Include the following lines along with the other #include directives:
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> #include "Framework/PhysicalModel.hh" #include "Framework/VolumeIntegrator.hh" #include "Framework/Cell.hh" #include "Framework/BaseGeometricEntityProvider.hh" </span> [</html>]
If you try to compile now, you should get an error stating that Physical model is unknown. Well, that's because is in its own namespace. You must open the namespace for using.
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> using namespace COOLFluiD::Framework; </span> [</html>]
Now you should be able to compile it with no errors or warnings. Try to run it. It will print out the following output:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: Aborted (core dumped) </span> [</html>]
!!Step 4!!
Something wrong happened. Probably we did something incorrect but we don't know what. The framework uses exceptions to communicate problems to the upper applications, in this case you "main.cxx" program. You should change your main and prepare it ot receive exceptions. Edit the main.cxx and place around the code, a try-catch block, in the following way:
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> int main() {
CFLogLevel::set(DEBUG_MAX);
CFLog(INFO, "COOLFluiD Recipe 1 starting: " << endl);
try {
PhysicalModel::setPhysicalModelImpl("Euler2D");
VolumeIntegrator::getInstance().setIntegrationForAllGeo(GAUSSLEGENDRE,ORDER1);
const CFString cellProviderName = "LagrangeTriagP1P1";
BaseGeometricEntityProvider<Cell>* cellProvider =
GeometricEntityFactory<Cell>::getProvider(cellProviderName);
} catch (exception& e) {
cerr << e.what() << endl; cerr << "Aborting ... " << endl;
} catch (...) {
cerr << "Unknown exception thrown and not caught !!!" << endl; cerr << "Aborting ... " << endl; throw; // re-throw
}
return 0;
} </span> [</html>]
It should compile. Try to run it afterwards, and you should get the following output: [<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: NoSuchValueException: Factory<PhysicalModelImpl>::getProvider() Euler2D not registered Aborting ... </span> [</html>]
There was one exception thrown, and it informs the application that there is no known PhysicalModel known as "Euler2D". So the problem is in the first line when you try to set the PhysicalModel. The problem is, that in the compilation command, we did not include a linking to the EulerModel library. Do it now by addind to the command the following switch:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> -lEulerModel </span> [</html>]
Compile and run again. The output should now be:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: Set PhysicalModel to: Euler2D Integrator<INTEGRATORIMPL>::setIntegrationForAllGeo() : begin Integrator<INTEGRATORIMPL>::activateIntegrators() : begin Integrator<INTEGRATORIMPL>::activateIntegrators() : end Integrator<INTEGRATORIMPL>::setIntegrationForAllGeo() : end NoSuchValueException: GeometricEntityFactory<TYPE>::getProvider() LagrangeTriagP1P1 not registered Aborting ... Integrator<INTEGRATORIMPL>::unsetUp() : begin Integrator<INTEGRATORIMPL>::unsetUp() : end </span> [</html>]
This means that you've set the PhysicalModel properly to "Euler2D". Further, there was some work done by setting up the Integrator properties, and activating the integrators. You should not care much about it now. But there is another exception being thrown. It seems that the "LagrangeTriagP1P1" GeometricEntity was not registered in the factory.
!!Step 5!!
Factories are a way to build objects without having to know about their details. Moreover, combined with self registration, it allows to build a certain concrete type of object just by specifying the name of the type. In this case we are planning to build a GeometricEntity of the type "LagrangeTriagP1P1". The assumption of this method is that the type is somehow known by the factory. This is done by a special object called a Provider which regists himself to the correct factory, on start up of the application. Even before the main() starts to be executed. That's why there is the need to get the Provider from the Factory.
This call to the factory failed because the Provider of the object you are trying to create does not exist in the libraires you selected in the compilation command. To include it, you must include the COOLFluiD module "ShapeFunctions". Add to the compilation command line:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> -lShapeFunctions </span> [</html>]
Compile it and run. The output should be:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: Set PhysicalModel to: Euler2D Integrator<INTEGRATORIMPL>::setIntegrationForAllGeo() : begin Integrator<INTEGRATORIMPL>::activateIntegrators() : begin Integrator<INTEGRATORIMPL>::activateIntegrators() : end Integrator<INTEGRATORIMPL>::setIntegrationForAllGeo() : end Integrator<INTEGRATORIMPL>::unsetUp() : begin Integrator<INTEGRATORIMPL>::unsetUp() : end </span> [</html>]
Changing the level set to CFLog to VERBOSE, and recompiling should yield a briefer result, by removing the output which is of debug level:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: Set PhysicalModel to: Euler2D </span> [</html>]
!! Step 6 !!
After the creation of the cellProvider, we are in a position to create a GeometricEntity of the type we chose before. Implement the following lines just after the call to the factory:
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;">
const CFluint nbStatesInCell = 3; const CFluint nbNodesInCell = 3;
vector<State*> statesInCell(nbStatesInCell); vector<Node*> nodesInCell(nbNodesInCell);
GeometricEntity * cell = cellProvider->create(statesInCell,nodesInCell);
</span> [</html>]
Compile and run it. You should get an error saying:
[<html>] <SPAN style="color:#000000;background-color:#FFFFCC;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;"> prompt:Recipe01> ./program COOLFluiD Recipe 1 starting: Set PhysicalModel to: Euler2D program: /home/tlmq/workspace/COOLFluiD/src/Framework/GeometricEntity.cxx:28: COOLFluiD::Framework::GeometricEntity::GeometricEntity(const std::vector<COOLFluiD::Framework::State*, std::allocator<COOLFluiD::Framework::State*> >&, const std::vector<COOLFluiD::Framework::Node*, std::allocator<COOLFluiD::Framework::Node*> >&): Assertion `*its != 0' failed. Aborted (core dumped) </span> [</html>]
This is not an exception being thrown. Its an code assertation which failed. Assertations are conditions put into the code, only in debug mode, that imediatly order the code to abort if the condition is not satisfied. This means we did something wrong in the new lines introduced.
Ah! The vecotr of nodes and states put as parameters of the constructor of the GeometricEntity were empty, hence the constructor is unable to build it. Lets change the code to reflect the building of the nodes and states, and do not forget to initialize the boolean, onMesh to indicate these nodes are not hanging loose, but are part of an GeometricEntity.
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;">
const CFluint nbStatesInCell = 3; const CFluint nbNodesInCell = 3; const CFbool onMesh = true;
vector<State*> statesInCell(nbStatesInCell); vector<Node*> nodesInCell(nbNodesInCell);
for(CFluint i =0; i < 3; ++i) {
nodesInCell [i] = new Node(onMesh); statesInCell[i] = new State(); statesInCell[i]->setSpaceCoordinates(nodesInCell[i]);
}
GeometricEntity * cell = cellProvider->create(statesInCell,nodesInCell);
</span> [</html>]
Compiling and running this program will work, having the same output has before, but there is a conceptual problem in the program. The nodes and states have been allocated dynamically, with the new operator, but have noe been deallocated, and since the program will not do it automatically for dynamic allocated memory we need to do it explicitly. This should be done when they are not used anymore:
[<html>] <SPAN style="color:#333333;background-color:#cccccc;font-size:10px;border: 1px solid gray;padding:5px 5px 5px 5px;white-space: pre; display:block;">
GeometricEntity * cell = cellProvider->create(statesInCell,nodesInCell);
deletePtr(cell); for(CFluint i =0; i < 3; ++i) {
deletePtr(statesInCell[i]); deletePtr(nodesInCell[i]);
}
</span> [</html>]
Compile it and run. The output should be the same, but now you have built a GeometricEntity, which concretly is a Triangle with Lagrange interpolation functions of the first order.
Congratulations!! You're done with this recipe'''
!!!See also!!! This recipe continues in SelfConfigurationRecipe
