CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > OpenFOAM Programming & Development

Run time Selection Mechanism - Some help required to understand

Register Blogs Members List Search Today's Posts Mark Forums Read

Like Tree6Likes
  • 6 Post By jaswi

Reply
 
LinkBack Thread Tools Display Modes
Old   March 23, 2009, 14:39
Thumbs up Run time Selection Mechanism - Some help required to understand
  #1
Senior Member
 
Join Date: Mar 2009
Posts: 248
Rep Power: 9
jaswi is on a distinguished road
Dear Forum Users

Good Evening to all

Run Time Selection Mechanism is one of the wonderful features of OpenFOAM. Understanding how it works is a bit involved. I have tried to look into its implementation but need some help from experts. I hope I will be able to get some answers.

Lets start :-)

Certain Macros constitute the core of this implementation, namely:
  1. declareRunTimeSelectionTable
  2. defineRunTimeSelectionTable
  3. addToRunTimeSelectionTable
Classes which use this mechanism invoke:

  • the macro declareRunTimeSelectionTable in their header file
  • the other two macros in their cpp file.
For further discussion , I have used the class polyPatch. If we take a look at its header file, we find it has 2 definitions for run time selection tables. They read:

Code:
// Declare run-time constructor selection tables
  
         declareRunTimeSelectionTable
         (
             autoPtr,
             polyPatch,
             word,
             (
                 const word& name, const label size,
                 const label start, const label index,
                 const polyBoundaryMesh& bm
             ),
             (name, size, start, index, bm)
         );
 

         declareRunTimeSelectionTable
         (
             autoPtr,
             polyPatch,
             dictionary,
             (
                 const word& name, const dictionary& dict,
                 const label index,   const polyBoundaryMesh& bm
             ),
             (name, dict, index, bm)
         );
The cpp file - polyPatch.C invoke the other two macros in this way:

Macros when invoked lead to a simple string substitution and then it actually compiles. Listing just the macros will not add to the clarity of what it is doing so I have used the first definition of the selection table to rewrite what these macros are doing exactly.


macro - declareRunTimeSelectionTable:

The first macro reads (Note: syntax correctness requires forward slashes as macros cannot have line breaks) :

Code:
#define declareRunTimeSelectionTable\
(autoPtr,baseType,argNames,argList,parList)                                        

/* Construct from argList function pointer type */                                
    typedef autoPtr<baseType> (*argNames##ConstructorPtr)argList;       
                                                                                                          
    /* Construct from argList function table type */                                    
    typedef HashTable<argNames##ConstructorPtr, word, string::hash>     
        argNames##ConstructorTable;                                     
                                                                        
    /* Construct from argList function pointer table pointer */                          
    static argNames##ConstructorTable* argNames##ConstructorTablePtr_; 
    /* Class to add constructor from argList to table */               
    template<class baseType##Type>                                      
    class add##argNames##ConstructorToTable                             
    {                                                                   
    public:                                                             
                                                                        
        static autoPtr<baseType> New argList                            
        {                                                               
            return autoPtr<baseType>(new baseType##Type parList);       
        }                                                               
                                                                        
        add##argNames##ConstructorToTable                               
        (                                                              
            const word& lookup = baseType##Type::typeName               
        )                                                               
        {                                                               
            construct##argNames##ConstructorTables();                   
            argNames##ConstructorTablePtr_->insert(lookup, New);       
        }                                                               
                                                                       
        ~add##argNames##ConstructorToTable()                            
        {                                                               
            destroy##argNames##ConstructorTables();                    
        }                                                              
    };                                                                 
                                                                        
    /* Table Constructor called from the table add function */          
    static void construct##argNames##ConstructorTables();             
    /* Table destructor called from the table add function destructor */
    static void destroy##argNames##ConstructorTables()
This macro has five arguments:
  1. autoPtr - name of the pointer. In OpenFOAM its always the smart pointer autoPtr<Type > templated over the type
  2. baseType - Name of the base class
  3. argNames Not sure what it means exactly
  4. argList - list of arguments
  5. parList - parameter list
Lets compare it with the invocation of this macro for polyPatch.
Code:
    declareRunTimeSelectionTable
         (
           autoPtr   autoPtr
           baseclass - polyPatch
           argNames  word
           argList - (const word& name,   
                         const label size,    
                         const label start,   
                         const label index,
                         const polyBoundaryMesh& bm),
           parList -  (name, size, start, index,bm)
         );
As a result invocation of this macro we will have the following code :
// it first defines a typedef for the construction of a function pointer type from argList.
Code:
  typedef autoPtr<polyPatch> (* wordConstructorPtr)  ( const word& name,   
                                                                                const label size,    
                                                                                const label start,   
                                                                                const label index,
                                                                                const polyBoundaryMesh& bm
                                                                               );
// Next a typedef is defined for the HashTable, given the argList. It reads:
Code:
 typedef HashTable < wordConstructorPtr,   word,  string::hash>  wordConstructorTable;
//it declares a static pointer to the constructor table.
Code:
static wordConstructorTable* wordConstructorTablePtr_;
// the template class reads :
Code:
 template<class polyPatchType>                                                                 
     class addwordConstructorToTable                                                  
     {                                                                                                                       
     public:     
      // static function
  
          static autoPtr<polyPatch> New  ( const word& name,   
                                                           const label size,    
                                                           const label start,   
                                                           const label index,
                                                           const polyBoundaryMesh& bm
                                                          )                                                      
             {   
                  return autoPtr<polyPatch> (new polyPatch (name, size, start, index, bm));              }
 
  // constructor
    addwordConstructorToTable ( const word& lookup = polyPatchType::typeName ) 
    {                                                                                                               
         constructwordConstructorTables();                                      
         wordConstructorTablePtr_->insert(lookup, New);                 
   }                                                                                                               
                                  
 // destructor                                                                                         
   ~addwordConstructorToTable()                                               
     {                                                                                                                
         destroywordConstructorTables();                                         
    }
};
Next these two static functions are declared. These two functions are used inside the template class. I am not sure about this but it seems that within a macro the order is not important. These two definitions could have been in the begining as well.
Code:
static void constructwordConstructorTables();
static void destroywordConstructorTables();

macro - defineRunTimeSelectionTable( )

Macro defineRunTimeSelectionTable(baseType, argNames) already expanded for the class polyPatch reads :
Code:
  #define defineRunTimeSelectionTable( polyPatch, word )            

     defineRunTimeSelectionTablePtr(polyPatch, word ); 
     defineRunTimeSelectionTableConstructor(polyPatch, word) 
     defineRunTimeSelectionTableDestructor(polyPatch,word)
The invocation of this macro , further invokes three macros , namely:
defineRunTimeSelectionTablePtr(polyPatch, word);

Code:
#define defineRunTimeSelectionTablePtr(polyPatch, word)                
                                                                          
/* Define the constructor function table and initialized to NULL */
polyPatch::wordConstructorTable*  polyPatch::wordConstructorTablePtr_ = NULL
defineRunTimeSelectionTableConstructor(polyPatch, word)
Code:
#define defineRunTimeSelectionTableConstructor(polyPatch, word)       
/* Table Constructor called from the table add function 
void polyPatch :: constructwordConstructorTables()              
     {                                                                   
           static bool constructed = false;                                 
           if (!constructed)                                                
                          {                                                               
                            polyPatch::wordConstructorTablePtr_                     
                            = new polyPatch::wordConstructorTable;              
                           constructed = true;                                          
                          }                                                               
                  }
defineRunTimeSelectionTableDestructor(polyPatch, word)
Code:
#define defineRunTimeSelectionTableDestructor(polyPatch, word)        
                                                                          
/* Table destructor called from the table add function destructor */
    void polyPatch::destroywordConstructorTables()                
     {                                                                   
           if (polyPatch::wordConstructorTablePtr_)                    
          {                                                                
               delete polyPatch::wordConstructorTablePtr_;             
               polyPatch::wordConstructorTablePtr_ = NULL;             
                       }                                                                
               }
The first among three macros declares a pointer to the hashtable and initializes it to NULL . The 2nd and 3rd macros implement the static functions, defined in the template class addwordConstructorToTable .


macro - addToRunTimeSelectionTable( ) -
this macro is pretty simple . it reads
Code:
 #define addToRunTimeSelectionTable(baseType,thisType,argNames)               
                                                                               
 /* Add the thisType constructor function to the table */                  
  baseType::add##argNames##ConstructorToTable<thisType>                    
  add##thisType##argNames##ConstructorTo##baseType##Table_
When invoked like this for polyPatch : addToRunTimeSelectionTable(polyPatch, polyPatch, word). it will read :
Code:
     polyPatch::addwordConstructorToTable<polyPatch>                   
      addpolyPatchwordConstructorTopolyPatchTable_

Now the questions :-))
1) How / where is the constructor
addwordConstructorToTable is called to construct the table . If the code
Code:
     polyPatch::addwordConstructorToTable<polyPatch>                   
      addpolyPatchwordConstructorTopolyPatchTable_
corresponds to the call to constructor for this template class (which i doubt that it is ) then what about the ctor argument (const word& lookup = polyPatchType::typeName).

Now If I am wrong in asking the first question and we assume that ctor is indeed called then the static function call - constructwordConstructorTables() will create a new HashTable and return a pointer to it. The next statement
Code:
wordConstructorTablePtr_->insert(lookup, New);
inserts an entry into the HashTable based on the value returned by the lookup and the call to the static function New.

2) As I understand from the second code statement in the ctor body, a key is inserted into the HashTable corresponding to the base class. How are the other types of patches entered into this table.

3) Finally what troubles me most is that I am unable to grasp when / where are these tables created during the creational process of fvMesh.

Thanks a lot for your attention.

Best Regards
Jaswi
duckfly, MichiB, sharonyue and 3 others like this.
jaswi is offline   Reply With Quote

Old   August 26, 2013, 22:28
Default
  #2
Senior Member
 
Dongyue Li
Join Date: Jun 2012
Location: Torino, Italy
Posts: 676
Rep Power: 8
sharonyue is on a distinguished road
Very Neat!! But Really tough tough for a newbie though...
sharonyue is offline   Reply With Quote

Old   April 18, 2014, 07:44
Default
  #3
Member
 
xuhe-openfoam
Join Date: Aug 2013
Location: DaLian,china
Posts: 82
Rep Power: 4
bieshuxuhe is on a distinguished road
hi,
maybe macro - addToRunTimeSelectionTable( )
Code:
#define addToRunTimeSelectionTable(baseType,thisType,argNames)               
                                                                               
 /* Add the thisType constructor function to the table */                  
  baseType::add##argNames##ConstructorToTable<thisType>                    
  add##thisType##argNames##ConstructorTo##baseType##Table_
for polyPatch should be
Code:
polyPatch::addwordConstructorToTable<thisType>                   
      addthisTypewordConstructorTopolyPatchTable_
The thread is so good for us newcomer to learn runtimeselection Mechanism ! thanks a lot !
bieshuxuhe is offline   Reply With Quote

Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Differences between serial and parallel runs carsten OpenFOAM Bugs 11 September 12, 2008 11:16
Convergence moving mesh lr103476 OpenFOAM Running, Solving & CFD 30 November 19, 2007 15:09
Total run time Dominic Main CFD Forum 0 August 24, 2006 23:12
local time scale factor selection mike CFX 0 April 19, 2006 08:52
Physical Reason for stability of Implicit Schemes? radhakrishnan Main CFD Forum 25 December 7, 2000 16:25


All times are GMT -4. The time now is 18:18.