Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controlling Geant4 smart voxelization from the detector constructor #1361

Closed
atolosadelgado opened this issue Dec 4, 2024 · 5 comments · Fixed by #1367
Closed

Controlling Geant4 smart voxelization from the detector constructor #1361

atolosadelgado opened this issue Dec 4, 2024 · 5 comments · Fixed by #1367
Assignees

Comments

@atolosadelgado
Copy link
Contributor

atolosadelgado commented Dec 4, 2024

Hi,

If I understand correctly, the DD4hep class Volume [link] is the equivalent to Logical Volume in Geant4. I was wondering if it would be possible to expose the following functions [link] of G4LogicalVolume from the DD4hep Volume:

    // File: source/geometry/management/include/G4LogicalVolume.hh, line 294 
    inline G4double GetSmartless() const;
    inline void SetSmartless(G4double s);
    inline G4bool IsToOptimise() const;
    inline void SetOptimisation(G4bool optim);

In my case I am dealing with the full stereo drift chamber, which may be very extreme when creating the voxelization because of the twisted geometry. I would like to investigate if it is possible to fine tune the granularity of the voxelization so it can be a better option to using hyperboloids as layers. With the Geant4 default settings, the voxelization causes the memory to explode: 4GB (60k wires placed directly into the main volume) [1] vs 2.7GB (60k placed in 112 different layers) [2].

Without the possibility of tuning the granularity of the smart voxelization, I guess the use of hyperboloids is preferred because of the smaller memory consumption, even if the tracking is slower.

Thank you for your time.

Best,
Alvaro

[1] When placing wires directly into the main gas volume, so the geometry tree looks like "main gas, cylinder" -> "wires" x60000

G4GeometryManager::ReportVoxelStats -- Voxel Statistics

    Total memory consumed for geometry optimisation:   1476755 kByte
    Total CPU time elapsed for geometry optimisation: 92 seconds

    Voxelisation: top CPU users:
    Percent   Total CPU    System CPU       Memory  Volume
    -------   ----------   ----------     --------  ----------
      99.74        91.32         0.64      1476756k DCH_v2_gas

    Voxelisation: top memory users:
    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume
    -------   --------     ------   ------   --------   ----------    ----------
     100.00    1476755k    892233 23403932   40571076        91.32    DCH_v2_gas

[2] When using hyperboloids as layers, so the geometry tree looks like "main gas, cylinder" -> "gas layer, hyperboloid" x112 -> "wires" x60000

G4GeometryManager::ReportVoxelStats -- Voxel Statistics

    Total memory consumed for geometry optimisation:   539877 kByte
    Total CPU time elapsed for geometry optimisation: 27 seconds

    Voxelisation: top CPU users:
    Percent   Total CPU    System CPU       Memory  Volume
    -------   ----------   ----------     --------  ----------
       2.12         0.58         0.01        11597k DCH_v2_layer109
       2.12         0.58         0.01        11626k DCH_v2_layer111
       2.12         0.58         0.00        11544k DCH_v2_layer107
       2.04         0.56         0.01        11550k DCH_v2_layer105
       1.93         0.53         0.01        10561k DCH_v2_layer99
       1.82         0.50         0.00        10623k DCH_v2_layer103
       1.82         0.50         0.00        10577k DCH_v2_layer101
       1.79         0.49         0.00         8578k DCH_v2_layer112
       1.79         0.49         0.01         9983k DCH_v2_layer91
       1.79         0.49         0.01         9979k DCH_v2_layer93

    Voxelisation: top memory users:
    Percent     Memory      Heads    Nodes   Pointers    Total CPU    Volume
    -------   --------     ------   ------   --------   ----------    ----------
       2.15      11625k      5651   189804     298392         0.58    DCH_v2_layer111
       2.15      11596k      5665   189230     297988         0.58    DCH_v2_layer109
       2.14      11549k      5713   188264     297336         0.56    DCH_v2_layer105
       2.14      11543k      5679   188248     296992         0.58    DCH_v2_layer107
       1.97      10623k      4919   174206     270288         0.50    DCH_v2_layer103
       1.96      10577k      4933   173348     269412         0.50    DCH_v2_layer101
       1.96      10561k      4951   173008     269256         0.53    DCH_v2_layer99
       1.95      10506k      4951   171986     268388         0.49    DCH_v2_layer97
       1.86      10020k      4333   164900     254204         0.49    DCH_v2_layer95
       1.85       9994k      4375   164290     254212         0.47    DCH_v2_layer89
@andresailer
Copy link
Member

At what phase of Geant4 do these values have to be set?

@atolosadelgado
Copy link
Contributor Author

At what phase of Geant4 do these values have to be set?

These values are set when instantiating the logical volumes [link]. There is no UI command for later modification.

@andresailer
Copy link
Member

Why do you need to access

  • inline G4double GetSmartless() const;
  • inline G4bool IsToOptimise() const;
  • inline void SetOptimisation(G4bool optim);

?

Is the ability to SetSmartless(G4double s), enough?

@andresailer
Copy link
Member

The problem is to pass all that information from DD4hep volumes to G4LogicalVolumes, and maybe needing to expose more functions...

So maybe we can try this:

Create your own G4LogicalVolume plugin to create G4LogicalVolumes that you fully control.
See https://github.com/AIDASoft/DD4hep/blob/master/examples/DDG4/src/ChannelingCrystalVolume.cpp as an example, e.g. SmartlessLogicalVolume

In the c++ where you create your volumes then put something like this

    Volume vol = Volume("Volume", solid, material);
    // ...
    vol.addProperty("Geant4-plugin", "SmartlessLogicalVolume");

Then the Geant4Converter will use your code to create the G4LogicalVolume

G4LogicalVolume* g4vol = nullptr;
if ( _v.hasProperties() && !_v.getProperty(GEANT4_TAG_PLUGIN,"").empty() ) {
Detector* det = const_cast<Detector*>(&m_detDesc);
std::string plugin = _v.getProperty(GEANT4_TAG_PLUGIN,"");
g4vol = PluginService::Create<G4LogicalVolume*>(plugin, det, _v, g4solid, g4medium);
if ( !g4vol ) {
except("G4Cnv::volume["+name+"]","++ FATAL Failed to call plugin to create logical volume.");
}
}

See the release notes entry

* 2022-08-10 Markus Frank ([PR#950](https://github.com/aidasoft/dd4hep/pull/950))

@andresailer andresailer self-assigned this Dec 4, 2024
@atolosadelgado
Copy link
Contributor Author

atolosadelgado commented Dec 5, 2024

For the record,

This is the plugin I used:

// Framework include files
#include <DDG4/Factories.h>
// Geant4 include files
#include <G4Material.hh>
#include <G4LogicalVolume.hh>

#include <string>
#include <charconv> // For std::from_chars

// Forward declarations
namespace  {  class SmartlessLogicalVolume;  }

/// Namespace example name of the user
namespace dd4hep   {
  /** Class member specialization to create a a G4LogicalVolume specifying the Smartless parameter
   *  
   *  \author  A. Tolosa-Delgado
   *  \version 1.0
   *  \ingroup DD4HEP_SIMULATION
   */
  template <> G4LogicalVolume* 
  Geant4LogicalVolumeFactory<SmartlessLogicalVolume>::create(dd4hep::Detector& /* description */,
							      Volume      volume,
							      G4VSolid*   solid,
							      G4Material* material)
  {

    auto* ptr = new G4LogicalVolume(solid, material, volume.name());

    const std::string default_prop = "";
    std::string volume_prop  = volume.getProperty("SetSmartless",default_prop);
    if( default_prop != volume_prop)
    {
      // try conversion from string to integer
      auto s = volume_prop;
      int Smartless;
      bool IsConversionDone = std::from_chars(s.data(), s.data() + s.size(), Smartless).ec == std::errc{} ;
      if ( IsConversionDone )
      {
        ptr->SetSmartless(Smartless);
        printout(ALWAYS,"SmartlessLogicalVolume",
	     "====> Created specialize logical volume [SmartlessLogicalVolume] %s with Smartless parameter %d",
	     volume.name(), Smartless);
      }

    }
    return ptr;
  }
}      // End namespace dd4hep

DECLARE_GEANT4LOGICALVOLUME(SmartlessLogicalVolume)

And in the detector constructor, one has to setup 2 properties of the dd4hep::Volume object as follows:

        // detector constructor code
        dd4hep::Volume layer_v ( layer_name , layer_s, gasvolMat );
        // use SmartlessLogicalVolume plugin to translate dd4hep volumes into G4LogicalVolumes
        layer_v.addProperty("Geant4-plugin", "SmartlessLogicalVolume");
        // example of how to disable smart voxelization, Smartless parameter equals to 0
        layer_v.addProperty("SetSmartless", "0");

If you want, I can open a PR with this plugin so it is available for everybody.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants