Thoughts on implementing AgML geometry in starvmc application for embedding

Embedding jobs typically run simulation and reconstruction within a single job.  As we migrate away from starsim towards a virtual MC framework, we need to consider the constraints that this imposes.  At present, the AgML support library does not support multiple instances of a geometry.  This blog entry is to summarize the known reasons for this limitation, and what some of the proposed solutions are.

  1. AgML Module variables are in global scope in each module.cxx file
    • Module variables will be shared between multiple instances of each geometry
    • At present there is no Reset() function to initialize the state of these variables to their initial value
    • Solution:
      • AgML export should add a Reset function to the module, which returns all user variables to their initial state
      • Optionally, user-variables should be added to a TTable for persistence and run-time inspection
  2. Implementation of structures
    • The implementation of AgML structures relies on a ROOT TFolder.  When users Fill the data structure, the data is posted to a TFolder.  When multiple geometries are instantiated, the possibility of a namespace clash exists.
    • Solution:
      • Refactor the code to use or TTable instead of TFolder. 
      • Introduce a top-level TDataSet for each instance of the geometry.  All geometry modules and data structures to be hung off of that object.
      • Namespace collisions possible for creating two instances of the same geometry.  Hash the second instance (e.g. _2).
      • Will need to work around the c++ / fortran indexing of arrays at the AgML export level
      • Need solution for storing character data.  (Pointer to TString?  Fixed-length character array?)
  3. Reliance on the ROOT dictionary, conflicts with namespaces...
    • All modules, blocks, data structures are stored within a namespace
    • When a module is created, the command "using namespace Module;" is entered into the CINT interpreter, in order to make all objects within that namespace accessible without referencing the namespace
    • This creates a problem when instantiating multiple versions of the geometry.  Consider two tags with different versions of BTOF.  In the first tag we declare "using namespace BtofGeo6;".  In the second, we declare "using namespace BtofGeo7;" .  On the second geometry tag, ROOT will not know which namespace to reference when creating the geomtry.  Likely it will pickup the first instance of an object in its list.
    • Solution:
      • Move away from using dictionary to instantiate AgBlock and AgModule objects.  Instead, create instances of these objects at runtime, look them up (via a LUT in AgModule for instance) when needed, and execute user-code defined on that object.
      • User code can be factored into either a ROOT macro, or a functor declared as a friend of the module.
      • etc...
  4. Material DB will be redefined on creation of new geometry
    • Solution:
      • Refactor the Material DB.  Make it a TTable, whose parent is the TDataSet which corresponds to the current geometry.
  5. Heavy reliance on ROOT dictionary when comparing shapes... (not critical, but a bit of a code cleanup issue).
    • Solution:
      • Refactor shapes to store parameters inside of a TTable or TDataSet...


This is a large change to the code which has to be performed during operations with AgML.  We will need to break the job down into multiple phases, and run validation tests after every phase.  Proposed work will proceed as follows:

  1. Phase 1 -- Implement a top-level TDataSet to hold geometry information for a given geometry tag.  No change to the geometry model, no validation required.
  2. Phase 2 -- Add reinitialization of AgML module variables.  No validation required.
  3. Phase 3 -- Material DB switches to a TTable.  Run validation.  Sufficient to run validation on one or two geometry tags.
  4. Phase 4 -- Implement AgML structures as TTable.  Run full validation.
  5. Phase 5 -- Refactor AgBlock creation in AgModule.  Instead of relying on ROOT dictionary, create AgBlock and add it to the block lookup table.  Full validation.
#define AddBlock(B) { \
   mBlockTable[ ##B ] = Module::B::New(); /* Create new instance of block an insert into LUT */ \
   Module::B::instance() -> Init(); \
   Module::B::instance() -> SetModule( this ); \
  1. Phase 6 -- Refactor Geometry.cxx to remove use of ROOT dictionaries.  Complete validaton.

Effort involved --

Phase 1, 2 are straightforward and easy.  One day FTE.

Phase 3 should also be straightforward.  (1) Define the TTable structure.  (2) Create adaptor for AgMaterial.  (3)  Validate.  Should be 2-3 days FTE.

Phase 4 should take a bit longer. 1-2 weeks.

  • AgML export should create a POD c-struct for each AgML structure
  • Arrays in structures will need to be mapped into a function... e.g.
  • character strings need to be handled... perhaps as a pointer to a TString...

Phase 5 should be about 1-2 weeks.

Total time: ~1 month full effort.  This will increase if a validation test fails along the way.