How to use Serialization
(→Serialization of a Polymorphic Class) |
(→Serialization of a Non-polymorphic Class) |
||
Line 100: | Line 100: | ||
* Now the class is ready for adding the serialization statements in order to serialize its data. There are two overloaded methods of Serializer which in charge of saving and loading the internal data of the class: | * Now the class is ready for adding the serialization statements in order to serialize its data. There are two overloaded methods of Serializer which in charge of saving and loading the internal data of the class: | ||
− | Serializer::save(std::string rTag, TDataType const& Data) | + | Serializer::save(std::string rTag, TDataType const& Data) const |
Serializer::load(std::string rTag, TDataType& Data) | Serializer::load(std::string rTag, TDataType& Data) |
Revision as of 13:03, 2 March 2011
The serialization consist of storing the state of an object into a storage format like data file or memory buffer and also retrieving the object from such a media. The idea of serialization is based on saving all object's data consecutively in the file or buffer and then load it in the same order. In Kratos a serialization mechanism is used for creating the restart file. So for storing an object into restart file and retrieve it afterward on must add the necessary component used by serialization. In the following section we will specify the necessary steps for making an object serializable in Kratos.
Preparing a Class for Serialization
The following steps are necessary in order to prepare a class for serialization:
- Including the includes/serializer.h
// Project includes #include "includes/define.h" #include "includes/serializer.h"
- Adding a doxygen statement for documentation of the serialization methods by adding following comment in the private section of the class: (A good option is after the Member Variables section)
private: ///@name Static Member Variables ///@{ ///@} ///@name Member Variables ///@{ ///@} ///@name Serialization ///@{ ///@} ///@name Private Operators ///@{
- making the Serializer a friend of the class by adding a friend statement in the private part of the
private: ///@name Static Member Variables ///@{ ///@} ///@name Member Variables ///@{ ///@} ///@name Serialization ///@{ friend class Serializer; ///@} ///@name Private Operators ///@{
- If the class dos not provide a default constructor (an empty constructor) you have to provide one in the serialization part as follow:
///@} ///@name Serialization ///@{ friend class Serializer; // A private default constructor necessary for serialization ClassName() : BaseClassName() { } ///@} ///@name Private Operators ///@{
Serialization of a Non-polymorphic Class
A non-polymorphic class is the one which is not belong to any inheritance. In other word it means a class which is not derived from other classes and is not the base for the other classes. Making the non-polymorphic classes consist in following steps:
- The first step is adding the serialization save and load methods as follow:
///@} ///@name Serialization ///@{ friend class Serializer; // A private default constructor necessary for serialization ClassName() : BaseClassName() { } virtual void save(Serializer& rSerializer) const { } virtual void load(Serializer& rSerializer) { } ///@} ///@name Private Operators ///@{
- Now the class is ready for adding the serialization statements in order to serialize its data. There are two overloaded methods of Serializer which in charge of saving and loading the internal data of the class:
Serializer::save(std::string rTag, TDataType const& Data) const Serializer::load(std::string rTag, TDataType& Data)
Where the Tag string is the tag given to the save or loaded data. This tag is only for text format and debugging purpose, and actually won't be written in binary format buffers and files. Here is an example of using these methods in a class with two member variables:
///@} ///@name Member Variables ///@{ int mMyInteger; Vector mMyVector; ///@} ///@name Serialization ///@{ friend class Serializer; // A private default constructor necessary for serialization ClassName() { } virtual void save(Serializer& rSerializer) const { rSerializer.save("My Integer", mMyInteger); rSerializer.save("My Vector", mMyVector); } virtual void load(Serializer& rSerializer) { rSerializer.load("My Integer", mMyInteger); rSerializer.load("My Vector", mMyVector); } ///@} ///@name Private Operators ///@{
It is VERY IMPORTANT to have the SAME CONSEQUENCE of variables in the save and load method. Altering this order results in corrupted loaded object or even crash of the program! |
Serialization of a Polymorphic Class
Serializing of a polymorphic class is similar to the non-polymorphic one with following three additional steps:
- First it is necessary to save the name of the class and this MUST BE the first step in your save method as follow:
virtual void save(Serializer& rSerializer) { rSerializer.save("Name","ClassName"); } virtual void load(Serializer& rSerializer) { }
The name of the class must be ONLY stored in save method and NOT LOADED in the load method as can be seen in the example. |
The difult constructor mentioned in non-Polymorphic part have to be added in public section to be able to be accesed from heritaed classes . |
- In general it is necessary to call the base class save and load in the derived class. This can be done using the following defined macro:
KRATOS_SERIALIZE_SAVE_BASE_CLASS(Serializer, BaseType) KRATOS_SERIALIZE_LOAD_BASE_CLASS(Serializer, BaseType)
Here is an example of use for TotalLagrangian element derived from Element:
virtual void save(Serializer& rSerializer) { rSerializer.save("Name","TotalLagrangian"); KRATOS_SERIALIZE_SAVE_BASE_CLASS(rSerializer, Element ); } virtual void load(Serializer& rSerializer) { KRATOS_SERIALIZE_LOAD_BASE_CLASS(rSerializer, Element ); }
- Finally the class must be registered in serializer using the Register() method. For elements and conditions the registeration is done via KRATOS_REGISTER_ELEMENT and KRATOS_REGISTER_CONDITION with the name of the class (NOT the given name respect to its geometry). Here is an example:
KRATOS_REGISTER_ELEMENT( "TotalLagrangian", mTotalLagrangian )
This is equivalent to write:
Serializer::Register("TotalLagrangian", mTotalLagrangian);
The above form can be used to register other polymorphic classes in Kratos if is necessary.