The objectRegistry is a hierarchical database that OpenFOAM uses to organize its model-related data. It is complemented by IOobject, and regIOobject. IOobject is a class that provides standardized input / output support, as well as giving access to runTime, the root of the objectRegistry. regIOobject automatically manages the registration and deregistration of objects to the objectRegistry.
1 Why is it needed?
It is needed to simplify the communication between the solvers and their data. OpenFOAM implements many modelling solution methods such as:
- finite volume method;
- finite differencing method;
- finite area method; and
- Ordinary Differential Equation solvers.
It achieves this through abstraction and templating - or in other words - by chopping up its code into many small pieces that can be used by all these solution methods. To make this possible, all common elements of the modelling data are wrapped up into a single universal framework. This is the objectRegistry.
2 When do you need it?
Anytime you are working with modelling data. For example, this includes:
- physical models;
- field data;
- dictionaries; and
- the mesh itself.
It is hard to imagine a situation where you will not need it.
3 How do you use it?
4 How does it work?
The main components of the objectRegistry are:
- the IOobject;
- the regIOobject; and
- the objectRegistry.
The objectRegistry is a hash table with a few additional member variables and methods. It catalogues regIOobject pointers by IOobject::name_, and helps manage their read and write operations. Every object it catalogues exists in-memory and usually on-disk in some form, the nature of which is governed by read and write options carried out by the individual regIOobjects.
There are actually two hierarchies in effect with the objectRegistry:
- the hierarchy of objects held in-memory; and
- the hierarchy of objects on-disk.
4.2.1 Hierarchy in-memory
An objectRegistry is itself a regIOobject, which means it can be a registered member of another objectRegistry. This leads to hierarchies. For example, scalarTransportFoam creates this objectRegistry hierarchy when it initializes (in order of appearance):
runTime //Time (objectRegistry) |-controlDict //IOdictionary (regIOobject) `-mesh //fvMesh (objectRegistry) |-fvSchemes //IOdictionary (regIOobject) |-fvSolution //IOdictionary (regIOobject) |-points //pointIOField (regIOobject) |-faces //faceIOlist (regIOobject) |-owner //labelIOlist (regIOobject) |-neighbour //labelIOlist (regIOobject) |-boundary //polyBoundaryMesh (regIOobject) |-pointZones //pointZoneMesh (regIOobject) |-faceZones //faceZoneMesh (regIOobject) |-cellZones //cellZoneMesh (regIOobject) |-T //volScalarField (regIOobject) |-U //volVectorField (regIOobject) `-transportProperties //IOdictionary (regIOobject)
In-memory hierarchy of scalarTransportFoam objectRegistry, in order of appearance.
Every objectRegistry has:
- pointers to all its child regIOobjects;
- a reference to its parent objectRegistry; and
- a reference to the master objectRegistry;
- the master is always runTime.
4.2.2 Hierarchy on-disk
The on-disk hierarchy depends on the read / write behaviour of the objects. objectRegistry objects have different read and write behaviour than "regular" regIOobjects. During a typical write operation, a regIOobject only has to write its data to a file, whereas an objectRegistry cycles through all its child objects, and tells them each ot write themselves. Read operations are performed on an as-needed basis.
A regIOobject writes its file to
- instance_ can be:
* timeName() normally [caseDirectory]/[timeName] e.g. reactor/0.045 * system() normally [caseDirectory]/system e.g. reactor/system * constant() normally [caseDirectory]/constant e.g. reactor/constant * caseSystem() normally [caseDirectory]/system, but becomes ../system in parallel runs * caseConstant() normally [caseDirectory]/constant, but becomes ../constant in parallel runs
Functions above are given local to runTime
- local_ can be anything, and is optional; and
- name_ can be anything.
Similarly, read-only files placed in any of these paths can be read by the solver, provided it knows to look for it. The on-disk hierarchy written by scalarTransportFoam is:
caseDirectory // directory |-system // directory | |-controlDict // read-only | |-fvSchemes // read-only | `-fvSolution // read-only |-constant // directory | |-transportProperties // read-only | `-polyMesh // directory | |-boundary // read-only | |-faces // read-only | |-neighbour // read-only | |-owner // read-only | `-points // read-only `-[timeName, eg 1.5] // directory |-uniform // directory | `-time // read / write |-phi // read / write |-T // read / write `-U // read / write
On-disk hierarchy of scalarTransportFoam objectRegistry.
4.3 Read / write functions
The objectRegistry employs virtual functions to achieve a universal framework. When runTime.writeNow() is called, this is approximately what happens:
- runTime calls regIOobject::write()
- regIOobject calls the virtual function writeObject. Normally this would call objectRegistry::writeObject, but Time has overriden this:
- runTime::writeObject first writes an IOdictionary called time to the [caseName]/[timeName]/constant directory before calling the regular objectRegistry::writeObject
- objectRegistry::writeObject cycles through all its child regIOobjects and calls writeObject on each of them.
- If the child object is a "regular" regIOobject, regIOobject::writeObject will be called.
- regIOobject::writeObject will open the OFstream and call writeData, a function that must be defined in all regIOobjects.
Important write functions are:
- objectRegistry uses this to call writeObject on all its child regIOobjects
- regIOobject uses this to call writeData on itself
- Some derived objectRegistry classes override this one, such as Time.
- objectRegistry implements this as an error-throw. Should not be called.
- regIOobject purely virtual function (i.e. = 0). All derived classes must override this.
Important read functions are:
- objectRegistry can scan the case directory to find any modified files that need to be reread. It accomplishes this with:
- readIfModified; and
- read - opens file stream with readStream, reads data with readData, closes the file stream;
- readData - must be overridden by the derived class, otherwise returns a fail;
- readStream - opens file stream and checks its type.
IOobject handles other read and write operations such as reading and writing the header.
4.4 IOobject versus regIOobject
An IOobject can be thought of as a dormant regIOobject. It doesn't have data input / output, and it doesn't automatically register / deregister itself from its objectRegistry. In fact, IOobjects do not really exist - there isn't a single IOobject class that isn't also a <regIOobject</tt> (apart from IOobject itself). The separation between these two objects only comes into play when passing them as parameters:
- objects are passed as IOobject& almost exclusively; whereas
- regIOobject&s are passed only to register themselves in the objectRegistry (and in the constructor parameters for themselves).
An IOobject is a class that gives an object all the information that objectRegistry needs to catalogue it. This includes:
- name_ - this serves as both:
- its filename on the hard drive; and
- its key in the objectRegistry hash table;
- instance_ - the path to its file, not including the final backslash;
- local_ - an optional local path;
- db_ - the objectRegistry with which it will register or has registered;
- rOpt - its read option; and
- wOpt - its write option.
On the other hand, a regIOobject is an IOobject that also automatically registers and deregisters itself from its parent objectRegistry. It achieves this with its constructors and its destructor. Marupio 22:24, 2 March 2010 (UTC)