delete time for complex geometries

From: rhatcher@SLAC.stanford.edu
Date: Sat Apr 01 2000 - 02:34:30 MEST


I'm attempting to build a large geometry (484 x 193 = 93412 objects)
using TShape and TNode objects and I'm finding that while the
construction time is tolerable, the time to delete the object is
impossibly long (scales not linearly with the number of objects but
N^2 or N! ?).

Is there anything that can be done about this behaviour?

Also while everything appears to run fine for small numbers, at larger
numbers earlier attempts also generated a SEGV in the TGeometry deletion.
I don't think it was a coding error on my part, but I haven't run
to "completion" on this latest version.

-robert

========= running the macro =================================

  *   Version   2.23/12   1 February 2000   *
<on Linux (RedHat 5.2 I believe)>

Compiled with thread support.

CINT/ROOT C/C++ Interpreter version 5.14.25, Nov 25 1999

root [0] .L time_geom.C  
root [1] time_geom(48,0);

 build geometry  nplanes=48 nstrips=192
                  cummulative time
     basics       Real time 0:0:0, CP time 0.010
     matrices     Real time 0:0:0, CP time 0.010
     shapes       Real time 0:0:1, CP time 1.350
     nodes        Real time 0:0:10, CP time 10.440

 done building 

 shape list has 9266 entries 

 world node has 51 sub-nodes

 destroy geometry Real time 0:0:14, CP time 14.920
 done destruction 

root [2] time_geom(484,0);

 build geometry  nplanes=484 nstrips=192
                  cummulative time
     basics       Real time 0:0:0, CP time -0.000
     matrices     Real time 0:0:0, CP time -0.000
     shapes       Real time 0:0:13, CP time 13.660
     nodes        Real time 0:1:45, CP time 105.630

 done building 

 shape list has 93414 entries 

 world node has 487 sub-nodes

<hours pass.....>

========= time_geom.C =================================

void time_geom(int nplanes=48, int drawlevel=0)
{
  // Stuff to run this under root and see the result
  gROOT->Reset();
  gStyle->SetPalette(1,0);

  TStopwatch sw;

  int nstrips;
  float hwplane,dzpln,zpos;
  char *planename = "pXXX";
  char *stripname = "pXXXsXX";

  //  int nplanes;
  //  dbi_detinfo(nplanes);
  dbi_plninfo(nplanes-1,nstrips,hwplane,dzpln,zpos);

  sw.Start(true);
  cout << endl << " build geometry "
       << " nplanes=" << nplanes << " nstrips=" << nstrips << endl;
  cout << "                  cummulative time" << endl;

  cout << "     basics       ";
  TGeometry *mygeom = new TGeometry("mygeom","my detector");
  // define the world

  Float_t hxysize = hwplane * 1.1;
  Float_t hzsize  = (zpos+dzpln) * 1.25;
  TBRIK *worldvol = new TBRIK("worldvol","The world space","void",
                              hxysize,hxysize,hzsize);

  TNode *worldnode = new TNode("worldnode","The world node",worldvol);
  // passing 0 for TRotMatrix* produces a rotation matrix named "Identity"

  Float_t tmarkerxy = hwplane;
  Float_t tmarkerz  = (zpos+dzpln);

  // create little x,y,z markers
  TSPHE *sphere = new TSPHE("sphere","sphere","void",10.);
  TNode *xmarker = new TNode("xmarker","xmarker",sphere,tmarkerxy,0.,0.);
  TNode *ymarker = new TNode("ymarker","ymarker",sphere,0.,tmarkerxy,0.);
  TNode *zmarker = new TNode("zmarker","zmarker",sphere,0.,0.,tmarkerz);
  sw.Stop();
  sw.Print();
  sw.Continue();

  cout << "     matrices     ";
  build_matrices();
  sw.Stop();
  sw.Print();
  sw.Continue();

  cout << "     shapes       ";
  build_shapes(nplanes);
  sw.Stop();
  sw.Print();
  sw.Continue();

  cout << "     nodes        ";
  build_nodes(nplanes,worldnode,drawlevel);
  sw.Stop();
  sw.Print();
  sw.Continue();

  cout << endl << " done building " << endl << endl;
  sw.Stop();

  if (drawlevel) {
     sw.Start(true);
     cout << " draw geometry ";
     TCanvas *c1 = new TCanvas("c1","detector geometry",200,10,700,700);
     mygeom->Draw();
     c1->Update();
     sw.Stop();
     sw.Print();
     sw.Continue();
     cout << " done draw " << endl << endl;
     sw.Stop();
  }

  THashList *shapelist = mygeom->GetListOfShapes();
  Int_t entries_s = shapelist->GetSize();
  cout << " shape list has " << entries_s << " entries " << endl << endl;

  TList *planelist = worldnode->GetListOfNodes();
  Int_t entries_p = planelist->GetSize();
  cout << " world node has " << entries_p << " sub-nodes" << endl << endl;

  sw.Start(true);
  cout << " destroy geometry ";
  delete mygeom;
  sw.Stop();
  sw.Print();
  sw.Continue();
  cout << " done destruction " << endl << endl;
  sw.Stop();
}

void build_matrices(void)
{

   TRotMatrix *rotX = 
      new TRotMatrix("rotX","X rotation", 90.,  0., 90., 90.,  0.,  0.);

   TRotMatrix *rotU = 
      new TRotMatrix("rotU","U rotation", 90.,-45., 90., 45.,  0.,  0.);

   TRotMatrix *rotV = 
      new TRotMatrix("rotV","Y rotation", 90., 45., 90.,135.,  0.,  0.);
}

void build_shapes(int nplanes)
{
   // Normally these dimensions would all come out of the 
   // detector construction database ... but for our purposes
   // we'll just use a fake DBI

   int istrip;
   int iplane;

   int nstrips;
   float hwplane,dzpln,zpos;
   char *planename = "pXXX";
   char *stripname = "pXXXsXX";
   float dx,dy,dz,x0,y0,z0;
   char *rotname = "rotX";

   //   int nplanes;
   //   dbi_detinfo(nplanes);

   // loop over all strips in all planes and construct the shape
   // using info from fake database interface

   TPGON *aplanevol;
   TBRIK *astripvol;

   for (iplane = 0; iplane != nplanes; iplane++) {

      // octogonal planes

      dbi_plnname(iplane,planename);
      dbi_plninfo(iplane,nstrips,hwplane,dzpln,zpos);
      Float_t rout = hwplane;
      Float_t rin  = (1-1.0e-6)*rout;

      Float_t deg2rad  = TMath::Pi()/180;
      Float_t cos22p5  = TMath::Cos(deg2rad*45/2);
      Float_t sin45    = TMath::Sin(deg2rad*45);
 
      rout = rout * sin45 / cos22p5;
      rin  = rin  * sin45 / cos22p5;

      aplanevol = new TPGON(planename,planename,"void",-22.5,360.,8,2);
      aplanevol->DefineSection(0,-dzpln,rin,rout);
      aplanevol->DefineSection(1,+dzpln,rin,rout);

      for (istrip = 0; istrip != nstrips; istrip++) {
         
         // individual strips

         dbi_stripname(iplane,istrip,stripname);
         dbi_stripinfo(iplane,istrip,dx,dy,dz,x0,y0,z0,rotname);

         astripvol = new TBRIK(stripname,stripname,"void",dx,dy,dz);
      }
   }
}

void build_nodes(int nplanes, TNode *worldnode, int drawlevel)
{
   // Normally these positions would all come out of the 
   // detector construction database ... but for our purposes
   // we'll just use a fake DBI

   // if "drawlevel" = 0 set everything invisible
   //                  1 draw some strips of first/last plane
   //                  2 all strips

   int istrip;
   int iplane;

   int nstrips;
   float hwplane,dzpln,zpos;
   char *planename = "pXXX";
   char *stripname = "pXXXsXX";
   float dx,dy,dz,x0,y0,z0;
   char *rotname = "rotX";

   //   int nplanes;
   //   dbi_detinfo(nplanes);

   // loop over all strips in all planes and construct the shape
   // using info from fake database interface

   TNode *aplanenode;
   TNode *astripnode;

   for (iplane = 0; iplane != nplanes; iplane++) {

      dbi_plnname(iplane,planename);
      dbi_plninfo(iplane,nstrips,hwplane,dzpln,zpos);

      worldnode->cd();

      aplanenode = new TNode(planename,planename,
                             planename,0,0,zpos,"Identity");
      
      switch (drawlevel)
         {
            
         case 0: // everything invisible
            aplanenode->SetVisibility(-1);
            break;
         case 1: // most are invisible (neither node nor sons)
            aplanenode->SetVisibility(-1); 
            if (iplane==0 || iplane == nplanes-1) aplanenode->SetVisibility(1);
            break;
         case 2: // everything visible
            aplanenode->SetVisibility(1);
            break;
         }

      for (istrip = 0; istrip != nstrips; istrip++) {
         
         // individual strips

         dbi_stripname(iplane,istrip,stripname);
         dbi_stripinfo(iplane,istrip,dx,dy,dz,x0,y0,z0,rotname);
         aplanenode->cd();
         
         astripnode = 
            new TNode(stripname,stripname,stripname,x0,y0,z0,rotname);

         switch (drawlevel)
            {
               
            case 0: // everything invisible
               astripnode->SetVisibility(0);
               break;
            case 1: // draw every 4th of first/last plane)
               astripnode->SetVisibility(0); 
               if (iplane==0 || iplane == nplanes-1) {
                  if (istrip%4 == 0) astripnode->SetVisibility(1);
                  astripnode->SetLineColor(51+istrip/4);
               }
               break;
            case 2: // everything visible
               astripnode->SetVisibility(1);
               break;
            }

      }
   }
}


void dbi_detinfo(int &nplanes)
{
   // number of planes in the detector
   nplanes = 24;
   nplanes = 48;
   //   nplanes = 484;
}

void dbi_plnname(int ipln, char *planename)
{
   sprintf(planename,"p%3.3x",ipln);
}
void dbi_stripname(int ipln, int istrip, char *stripname)
{
   sprintf(stripname,"p%3.3xs%2.2x",ipln,istrip);
}


void dbi_plninfo(int ipln, 
                 int &nstrips, float &hwplane, float &dzpln, float &zpos)
{
   // info about each plane ... for now they're all the same

   nstrips = 192;
   hwplane = 400;
   dzpln   = 0.5 * 1.1;
   zpos    = dzpln + ipln*5.25;

}
      
void dbi_stripinfo(int ipln, int istrip,
                   float &dx, float &dy, float &dz,
                   float &x0, float &y0, float &z0,
                   char *rotname)
{
   int nstrips;
   float hwplane,dzpln,zpos;

   dbi_plninfo(ipln,nstrips,hwplane,dzpln,zpos);
   
   // constraint  nstrips*(2*dy) + (nstrips-1)*(2*hgap) = 2*hwplane
   Float_t hgap = 0.033; // average .66mm gap between strips
   dy = (hwplane - (nstrips-1)*hgap) / nstrips;

   Float_t deltat = 2.0 * (dy+hgap);
   Float_t toffset = (float)(nstrips-1)/2. * (-deltat);

   z0 = 0.; // no offset within the plane

   Float_t t, tabs, tcut;
   tcut = hwplane * TMath::Tan(22.5*TMath::Pi()/180.);

   t = toffset + istrip*deltat;
   tabs = TMath::Abs(t);

   dx = hwplane;
   if ((tabs+dy) > tcut) {
      dx = tcut + hwplane-(tabs+dy);
   }

   Float_t dxdy;
   if ((ipln&1) == 0) {
      sprintf(rotname,"rotU");
      dxdy = +1;
   } else {
      sprintf(rotname,"rotV");
      dxdy = -1;
   }

   Float_t rsqrt2 = 1./TMath::Sqrt(2.);
   y0 = t * rsqrt2;
   x0 = dxdy * y0;

}



This archive was generated by hypermail 2b29 : Tue Jan 02 2001 - 11:50:22 MET