00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "G4SmartVoxelHeader.hh"
00046
00047 #include "G4ios.hh"
00048
00049 #include "G4LogicalVolume.hh"
00050 #include "G4VPhysicalVolume.hh"
00051 #include "G4VoxelLimits.hh"
00052
00053 #include "voxeldefs.hh"
00054 #include "G4AffineTransform.hh"
00055 #include "G4VSolid.hh"
00056 #include "G4VPVParameterisation.hh"
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
00067 G4int pSlice)
00068 : fminEquivalent(pSlice),
00069 fmaxEquivalent(pSlice),
00070 fparamAxis(kUndefined)
00071 {
00072 G4int nDaughters = pVolume->GetNoDaughters();
00073 G4VoxelLimits limits;
00074
00075
00076
00077 if ((nDaughters!=1) || (!pVolume->GetDaughter(0)->IsReplicated()))
00078 {
00079
00080
00081
00082 BuildVoxels(pVolume);
00083 }
00084 else
00085 {
00086
00087
00088 BuildReplicaVoxels(pVolume);
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 G4SmartVoxelHeader::G4SmartVoxelHeader(G4LogicalVolume* pVolume,
00101 const G4VoxelLimits& pLimits,
00102 const G4VolumeNosVector* pCandidates,
00103 G4int pSlice)
00104 : fminEquivalent(pSlice),
00105 fmaxEquivalent(pSlice),
00106 fparamAxis(kUndefined)
00107 {
00108 #ifdef G4GEOMETRY_VOXELDEBUG
00109 G4cout << "**** G4SmartVoxelHeader::G4SmartVoxelHeader" << G4endl
00110 << " Limits " << pLimits << G4endl
00111 << " Candidate #s = " ;
00112 for (size_t i=0;i<pCandidates->size();i++)
00113 {
00114 G4cout << (*pCandidates)[i] << " ";
00115 }
00116 G4cout << G4endl;
00117 #endif
00118
00119 BuildVoxelsWithinLimits(pVolume,pLimits,pCandidates);
00120 }
00121
00122
00123
00124
00125
00126
00127 G4SmartVoxelHeader::~G4SmartVoxelHeader()
00128 {
00129
00130
00131
00132 G4int node, proxy, maxNode=fslices.size();
00133 G4SmartVoxelProxy *lastProxy=0;
00134 G4SmartVoxelNode *dyingNode, *lastNode=0;
00135 G4SmartVoxelHeader *dyingHeader, *lastHeader=0;
00136
00137 for (node=0; node<maxNode; node++)
00138 {
00139 if (fslices[node]->IsHeader())
00140 {
00141 dyingHeader = fslices[node]->GetHeader();
00142 if (lastHeader!=dyingHeader)
00143 {
00144 lastHeader = dyingHeader;
00145 lastNode = 0;
00146 delete dyingHeader;
00147 }
00148 }
00149 else
00150 {
00151 dyingNode = fslices[node]->GetNode();
00152 if (dyingNode!=lastNode)
00153 {
00154 lastNode=dyingNode;
00155 lastHeader=0;
00156 delete dyingNode;
00157 }
00158 }
00159 }
00160
00161
00162 for (proxy=0; proxy<maxNode; proxy++)
00163 {
00164 if (fslices[proxy]!=lastProxy)
00165 {
00166 lastProxy = fslices[proxy];
00167 delete lastProxy;
00168 }
00169 }
00170
00171
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 G4bool G4SmartVoxelHeader::operator == (const G4SmartVoxelHeader& pHead) const
00184 {
00185 if ( (GetAxis() == pHead.GetAxis())
00186 && (GetNoSlices() == pHead.GetNoSlices())
00187 && (GetMinExtent() == pHead.GetMinExtent())
00188 && (GetMaxExtent() == pHead.GetMaxExtent()) )
00189 {
00190 G4int node, maxNode;
00191 G4SmartVoxelProxy *leftProxy, *rightProxy;
00192 G4SmartVoxelHeader *leftHeader, *rightHeader;
00193 G4SmartVoxelNode *leftNode, *rightNode;
00194
00195 maxNode=GetNoSlices();
00196 for (node=0; node<maxNode; node++)
00197 {
00198 leftProxy = GetSlice(node);
00199 rightProxy = pHead.GetSlice(node);
00200 if (leftProxy->IsHeader())
00201 {
00202 if (rightProxy->IsNode())
00203 {
00204 return false;
00205 }
00206 else
00207 {
00208 leftHeader = leftProxy->GetHeader();
00209 rightHeader = rightProxy->GetHeader();
00210 if (!(*leftHeader==*rightHeader))
00211 {
00212 return false;
00213 }
00214 }
00215 }
00216 else
00217 {
00218 if (rightProxy->IsHeader())
00219 {
00220 return false;
00221 }
00222 else
00223 {
00224 leftNode = leftProxy->GetNode();
00225 rightNode = rightProxy->GetNode();
00226 if (!(*leftNode==*rightNode))
00227 {
00228 return false;
00229 }
00230 }
00231 }
00232 }
00233 return true;
00234 }
00235 else
00236 {
00237 return false;
00238 }
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void G4SmartVoxelHeader::BuildVoxels(G4LogicalVolume* pVolume)
00248 {
00249 G4VoxelLimits limits;
00250 G4int nDaughters = pVolume->GetNoDaughters();
00251
00252 G4VolumeNosVector targetList;
00253 targetList.reserve(nDaughters);
00254 for (G4int i=0; i<nDaughters; i++)
00255 {
00256 targetList.push_back(i);
00257 }
00258 BuildVoxelsWithinLimits(pVolume, limits, &targetList);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267 void G4SmartVoxelHeader::BuildReplicaVoxels(G4LogicalVolume* pVolume)
00268 {
00269 G4VPhysicalVolume *pDaughter=0;
00270
00271
00272
00273 EAxis axis;
00274 G4int nReplicas;
00275 G4double width,offset;
00276 G4bool consuming;
00277
00278
00279
00280 if ( (pVolume->GetNoDaughters()==1)
00281 && (pVolume->GetDaughter(0)->IsReplicated()==true) )
00282 {
00283
00284
00285 pDaughter=pVolume->GetDaughter(0);
00286 pDaughter->GetReplicationData(axis,nReplicas,width,offset,consuming);
00287 fparamAxis = axis;
00288 if ( consuming==false )
00289 {
00290 G4VoxelLimits limits;
00291 G4VolumeNosVector targetList;
00292 targetList.reserve(nReplicas);
00293 for (G4int i=0; i<nReplicas; i++)
00294 {
00295 targetList.push_back(i);
00296 }
00297 if (axis != kUndefined)
00298 {
00299
00300
00301 G4ProxyVector* pSlices=BuildNodes(pVolume,limits,&targetList,axis);
00302 faxis = axis;
00303 fslices = *pSlices;
00304 delete pSlices;
00305
00306
00307
00308 const G4AffineTransform origin;
00309 pVolume->GetSolid()->CalculateExtent(faxis, limits, origin,
00310 fminExtent, fmaxExtent);
00311
00312
00313 BuildEquivalentSliceNos();
00314 CollectEquivalentNodes();
00315 }
00316 else
00317 {
00318
00319
00320
00321 BuildVoxelsWithinLimits(pVolume, limits, &targetList);
00322 }
00323 }
00324 else
00325 {
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 switch (axis)
00338 {
00339 case kXAxis:
00340 case kYAxis:
00341 case kZAxis:
00342 fminExtent = -width*nReplicas*0.5;
00343 fmaxExtent = width*nReplicas*0.5;
00344 break;
00345 case kRho:
00346 fminExtent = offset;
00347 fmaxExtent = width*nReplicas+offset;
00348 break;
00349 case kPhi:
00350 fminExtent = offset;
00351 fmaxExtent = offset+width*nReplicas;
00352 break;
00353 default:
00354 G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels()",
00355 "GeomMgt0002", FatalException, "Illegal axis.");
00356 break;
00357 }
00358 faxis = axis;
00359 BuildConsumedNodes(nReplicas);
00360 if ( (axis==kXAxis) || (axis==kYAxis) || (axis==kZAxis) )
00361 {
00362
00363
00364 G4double emin = kInfinity, emax = -kInfinity;
00365 G4VoxelLimits limits;
00366 G4AffineTransform origin;
00367 pVolume->GetSolid()->CalculateExtent(axis, limits, origin, emin, emax);
00368 if ( (std::fabs((emin-fminExtent)/fminExtent) +
00369 std::fabs((emax-fmaxExtent)/fmaxExtent)) > 0.05)
00370 {
00371 std::ostringstream message;
00372 message << "Sanity check: wrong solid extent." << G4endl
00373 << " Replicated geometry, logical volume: "
00374 << pVolume->GetName();
00375 G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels",
00376 "GeomMgt0002", FatalException, message);
00377 }
00378 }
00379 }
00380 }
00381 else
00382 {
00383 G4Exception("G4SmartVoxelHeader::BuildReplicaVoxels", "GeomMgt0002",
00384 FatalException, "Only one replicated daughter is allowed !");
00385 }
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395 void G4SmartVoxelHeader::BuildConsumedNodes(G4int nReplicas)
00396 {
00397 G4int nNode, nVol;
00398 G4SmartVoxelNode *pNode;
00399 G4SmartVoxelProxy *pProxyNode;
00400
00401
00402
00403 G4NodeVector nodeList;
00404 nodeList.reserve(nReplicas);
00405 for (nNode=0; nNode<nReplicas; nNode++)
00406 {
00407 pNode=new G4SmartVoxelNode(nNode);
00408 if (!pNode)
00409 {
00410 G4Exception("G4SmartVoxelHeader::BuildConsumedNodes()", "GeomMgt0003",
00411 FatalException, "Node allocation error.");
00412 }
00413 nodeList.push_back(pNode);
00414 }
00415 for (nVol=0; nVol<nReplicas; nVol++)
00416 {
00417 nodeList[nVol]->Insert(nVol);
00418 }
00419
00420
00421
00422 fslices.clear();
00423 for (nNode=0; nNode<nReplicas; nNode++)
00424 {
00425 pProxyNode = new G4SmartVoxelProxy(nodeList[nNode]);
00426 if (!pProxyNode)
00427 {
00428 G4Exception("G4SmartVoxelHeader::BuildConsumedNodes()", "GeomMgt0003",
00429 FatalException, "Proxy node allocation error.");
00430 }
00431 fslices.push_back(pProxyNode);
00432 }
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442 void
00443 G4SmartVoxelHeader::BuildVoxelsWithinLimits(G4LogicalVolume* pVolume,
00444 G4VoxelLimits pLimits,
00445 const G4VolumeNosVector* pCandidates)
00446 {
00447
00448
00449
00450
00451 G4ProxyVector *pGoodSlices=0, *pTestSlices, *tmpSlices;
00452 G4double goodSliceScore=kInfinity, testSliceScore;
00453 EAxis goodSliceAxis = kXAxis;
00454 EAxis testAxis = kXAxis;
00455 G4int node, maxNode, iaxis;
00456 G4VoxelLimits noLimits;
00457
00458
00459
00460 for (iaxis=0; iaxis<3; iaxis++)
00461 {
00462 switch(iaxis)
00463 {
00464 case 0:
00465 testAxis = kXAxis;
00466 break;
00467 case 1:
00468 testAxis = kYAxis;
00469 break;
00470 case 2:
00471 testAxis = kZAxis;
00472 break;
00473 }
00474 if (!pLimits.IsLimited(testAxis))
00475 {
00476 pTestSlices = BuildNodes(pVolume,pLimits,pCandidates,testAxis);
00477 testSliceScore = CalculateQuality(pTestSlices);
00478 if ( (!pGoodSlices) || (testSliceScore<goodSliceScore) )
00479 {
00480 goodSliceAxis = testAxis;
00481 goodSliceScore = testSliceScore;
00482 tmpSlices = pGoodSlices;
00483 pGoodSlices = pTestSlices;
00484 pTestSlices = tmpSlices;
00485 }
00486 if (pTestSlices)
00487 {
00488
00489
00490 maxNode=pTestSlices->size();
00491 for (node=0; node<maxNode; node++)
00492 {
00493 delete (*pTestSlices)[node]->GetNode();
00494 }
00495 G4SmartVoxelProxy* tmpProx;
00496 while (pTestSlices->size()>0)
00497 {
00498 tmpProx = pTestSlices->back();
00499 pTestSlices->pop_back();
00500 for (G4ProxyVector::iterator i=pTestSlices->begin();
00501 i!=pTestSlices->end(); )
00502 {
00503 if (*i==tmpProx)
00504 {
00505 i = pTestSlices->erase(i);
00506 }
00507 else
00508 {
00509 ++i;
00510 }
00511 }
00512 if ( tmpProx ) { delete tmpProx; }
00513 }
00514 delete pTestSlices;
00515 }
00516 }
00517 }
00518
00519
00520
00521 if (!pGoodSlices)
00522 {
00523 G4Exception("G4SmartVoxelHeader::BuildVoxelsWithinLimits()",
00524 "GeomMgt0002", FatalException,
00525 "Cannot select more than 3 axis for optimisation.");
00526 return;
00527 }
00528
00529
00530
00531
00532
00533
00534
00535 fslices=*pGoodSlices;
00536 delete pGoodSlices;
00537
00538 faxis=goodSliceAxis;
00539
00540 #ifdef G4GEOMETRY_VOXELDEBUG
00541 G4cout << G4endl << " Volume = " << pVolume->GetName()
00542 << G4endl << " Selected axis = " << faxis << G4endl;
00543 for (size_t islice=0; islice<fslices.size(); islice++)
00544 {
00545 G4cout << " Node #" << islice << " = {";
00546 for (G4int j=0; j<fslices[islice]->GetNode()->GetNoContained(); j++)
00547 {
00548 G4cout << " " << fslices[islice]->GetNode()->GetVolume(j);
00549 }
00550 G4cout << " }" << G4endl;
00551 }
00552 G4cout << G4endl;
00553 #endif
00554
00555
00556
00557 G4VSolid* outerSolid = pVolume->GetSolid();
00558 const G4AffineTransform origin;
00559 if(!outerSolid->CalculateExtent(faxis,pLimits,origin,fminExtent,fmaxExtent))
00560 {
00561 outerSolid->CalculateExtent(faxis,noLimits,origin,fminExtent,fmaxExtent);
00562 }
00563
00564
00565
00566 BuildEquivalentSliceNos();
00567 CollectEquivalentNodes();
00568 RefineNodes(pVolume,pLimits);
00569
00570
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 void G4SmartVoxelHeader::BuildEquivalentSliceNos()
00584 {
00585 G4int sliceNo, minNo, maxNo, equivNo;
00586 G4int maxNode = fslices.size();
00587 G4SmartVoxelNode *startNode, *sampleNode;
00588 for (sliceNo=0; sliceNo<maxNode; sliceNo++)
00589 {
00590 minNo = sliceNo;
00591
00592
00593
00594 startNode = fslices[minNo]->GetNode();
00595
00596
00597
00598 for (equivNo=minNo+1; equivNo<maxNode; equivNo++)
00599 {
00600 sampleNode = fslices[equivNo]->GetNode();
00601 if (!((*startNode) == (*sampleNode))) { break; }
00602 }
00603 maxNo = equivNo-1;
00604 if (maxNo != minNo)
00605 {
00606
00607
00608 for (equivNo=minNo; equivNo<=maxNo; equivNo++)
00609 {
00610 sampleNode = fslices[equivNo]->GetNode();
00611 sampleNode->SetMinEquivalentSliceNo(minNo);
00612 sampleNode->SetMaxEquivalentSliceNo(maxNo);
00613 }
00614
00615
00616 sliceNo = maxNo;
00617 }
00618 }
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630 void G4SmartVoxelHeader::CollectEquivalentNodes()
00631 {
00632 G4int sliceNo, maxNo, equivNo;
00633 G4int maxNode=fslices.size();
00634 G4SmartVoxelNode *equivNode;
00635 G4SmartVoxelProxy *equivProxy;
00636
00637 for (sliceNo=0; sliceNo<maxNode; sliceNo++)
00638 {
00639 equivProxy=fslices[sliceNo];
00640
00641
00642
00643 equivNode = equivProxy->GetNode();
00644 maxNo = equivNode->GetMaxEquivalentSliceNo();
00645 if (maxNo != sliceNo)
00646 {
00647 #ifdef G4GEOMETRY_VOXELDEBUG
00648 G4cout << "**** G4SmartVoxelHeader::CollectEquivalentNodes" << G4endl
00649 << " Collecting Nodes = "
00650 << sliceNo << " - " << maxNo << G4endl;
00651 #endif
00652
00653
00654 for (equivNo=sliceNo+1; equivNo<=maxNo; equivNo++)
00655 {
00656 delete fslices[equivNo]->GetNode();
00657 delete fslices[equivNo];
00658 fslices[equivNo] = equivProxy;
00659 }
00660 sliceNo = maxNo;
00661 }
00662 }
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 void G4SmartVoxelHeader::CollectEquivalentHeaders()
00678 {
00679 G4int sliceNo, maxNo, equivNo;
00680 G4int maxNode = fslices.size();
00681 G4SmartVoxelHeader *equivHeader, *sampleHeader;
00682 G4SmartVoxelProxy *equivProxy;
00683
00684 for (sliceNo=0; sliceNo<maxNode; sliceNo++)
00685 {
00686 equivProxy = fslices[sliceNo];
00687 if (equivProxy->IsHeader())
00688 {
00689 equivHeader = equivProxy->GetHeader();
00690 maxNo = equivHeader->GetMaxEquivalentSliceNo();
00691 if (maxNo != sliceNo)
00692 {
00693
00694
00695
00696
00697 #ifdef G4GEOMETRY_VOXELDEBUG
00698 G4cout << "**** G4SmartVoxelHeader::CollectEquivalentHeaders" << G4endl
00699 << " Collecting Headers =";
00700 #endif
00701 for (equivNo=sliceNo+1; equivNo<=maxNo; equivNo++)
00702 {
00703 sampleHeader = fslices[equivNo]->GetHeader();
00704 if ( (*sampleHeader) == (*equivHeader) )
00705 {
00706 #ifdef G4GEOMETRY_VOXELDEBUG
00707 G4cout << " " << equivNo;
00708 #endif
00709
00710
00711 delete sampleHeader;
00712 delete fslices[equivNo];
00713 fslices[equivNo] = equivProxy;
00714 }
00715 else
00716 {
00717
00718
00719
00720 equivProxy = fslices[equivNo];
00721 equivHeader = equivProxy->GetHeader();
00722 }
00723
00724 }
00725 #ifdef G4GEOMETRY_VOXELDEBUG
00726 G4cout << G4endl;
00727 #endif
00728
00729
00730 sliceNo = maxNo;
00731 }
00732 }
00733 }
00734 }
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 G4ProxyVector* G4SmartVoxelHeader::BuildNodes(G4LogicalVolume* pVolume,
00751 G4VoxelLimits pLimits,
00752 const G4VolumeNosVector* pCandidates,
00753 EAxis pAxis)
00754 {
00755 G4double motherMinExtent= kInfinity, motherMaxExtent= -kInfinity,
00756 targetMinExtent= kInfinity, targetMaxExtent= -kInfinity;
00757 G4VPhysicalVolume *pDaughter=0;
00758 G4VPVParameterisation *pParam=0;
00759 G4VSolid *targetSolid;
00760 G4AffineTransform targetTransform;
00761 G4bool replicated;
00762 G4int nCandidates = pCandidates->size();
00763 G4int nVol, nNode, targetVolNo;
00764 G4VoxelLimits noLimits;
00765
00766 #ifdef G4GEOMETRY_VOXELDEBUG
00767 G4cout << "**** G4SmartVoxelHeader::BuildNodes" << G4endl
00768 << " Limits = " << pLimits << G4endl
00769 << " Axis = " << pAxis << G4endl
00770 << " Candidates = " << nCandidates << G4endl;
00771 #endif
00772
00773
00774
00775
00776 G4VSolid* outerSolid = pVolume->GetSolid();
00777 const G4AffineTransform origin;
00778 if( !outerSolid->CalculateExtent(pAxis, pLimits, origin,
00779 motherMinExtent, motherMaxExtent) )
00780 {
00781 outerSolid->CalculateExtent(pAxis, noLimits, origin,
00782 motherMinExtent, motherMaxExtent);
00783 }
00784 G4VolumeExtentVector minExtents(nCandidates,0.);
00785 G4VolumeExtentVector maxExtents(nCandidates,0.);
00786
00787 if ( (pVolume->GetNoDaughters()==1)
00788 && (pVolume->GetDaughter(0)->IsReplicated()==true) )
00789 {
00790
00791
00792
00793 pDaughter = pVolume->GetDaughter(0);
00794 pParam = pDaughter->GetParameterisation();
00795 if (!pParam)
00796 {
00797 std::ostringstream message;
00798 message << "PANIC! - Missing parameterisation." << G4endl
00799 << " Replicated volume with no parameterisation object !";
00800 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0003",
00801 FatalException, message);
00802 return 0;
00803 }
00804
00805
00806
00807 targetTransform = G4AffineTransform(pDaughter->GetRotation(),
00808 pDaughter->GetTranslation());
00809 replicated = true;
00810 }
00811 else
00812 {
00813 replicated = false;
00814 }
00815
00816
00817
00818 for (nVol=0; nVol<nCandidates; nVol++)
00819 {
00820 targetVolNo=(*pCandidates)[nVol];
00821 if (replicated == false)
00822 {
00823 pDaughter=pVolume->GetDaughter(targetVolNo);
00824
00825
00826
00827 targetTransform = G4AffineTransform(pDaughter->GetRotation(),
00828 pDaughter->GetTranslation());
00829
00830
00831 targetSolid = pDaughter->GetLogicalVolume()->GetSolid();
00832 }
00833 else
00834 {
00835
00836
00837 targetSolid = pParam->ComputeSolid(targetVolNo,pDaughter);
00838
00839
00840
00841 targetSolid->ComputeDimensions(pParam,targetVolNo,pDaughter);
00842
00843
00844
00845 pParam->ComputeTransformation(targetVolNo,pDaughter);
00846 targetTransform = G4AffineTransform(pDaughter->GetRotation(),
00847 pDaughter->GetTranslation());
00848 }
00849
00850
00851 if(!targetSolid->CalculateExtent(pAxis, pLimits, targetTransform,
00852 targetMinExtent, targetMaxExtent))
00853 {
00854 targetSolid->CalculateExtent(pAxis, noLimits, targetTransform,
00855 targetMinExtent,targetMaxExtent);
00856 }
00857 minExtents[nVol] = targetMinExtent;
00858 maxExtents[nVol] = targetMaxExtent;
00859
00860 #ifdef G4GEOMETRY_VOXELDEBUG
00861 G4cout << "---------------------------------------------------" << G4endl
00862 << " Volume = " << pDaughter->GetName() << G4endl
00863 << " Min Extent = " << targetMinExtent << G4endl
00864 << " Max Extent = " << targetMaxExtent << G4endl
00865 << "---------------------------------------------------" << G4endl;
00866 #endif
00867
00868
00869
00870 if ( (!pLimits.IsLimited()) && ((targetMaxExtent<=motherMinExtent)
00871 ||(targetMinExtent>=motherMaxExtent)) )
00872 {
00873 std::ostringstream message;
00874 message << "PANIC! - Overlapping daughter with mother volume." << G4endl
00875 << " Daughter physical volume "
00876 << pDaughter->GetName() << G4endl
00877 << " is entirely outside mother logical volume "
00878 << pVolume->GetName() << " !!";
00879 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0002",
00880 FatalException, message);
00881 }
00882
00883 #ifdef G4GEOMETRY_VOXELDEBUG
00884
00885
00886
00887
00888 if (!pLimits.IsLimited())
00889 {
00890 G4double width;
00891 G4int kStraddlePercent=5;
00892 width = maxExtents[nVol]-minExtents[nVol];
00893 if ( (((motherMinExtent-minExtents[nVol])*100/width) > kStraddlePercent)
00894 ||(((maxExtents[nVol]-motherMaxExtent)*100/width) > kStraddlePercent) )
00895 {
00896 G4cout << "**** G4SmartVoxelHeader::BuildNodes" << G4endl
00897 << " WARNING : Daughter # " << nVol
00898 << " name = " << pDaughter->GetName() << G4endl
00899 << " Crosses mother boundary of logical volume, name = "
00900 << pVolume->GetName() << G4endl
00901 << " by more than " << kStraddlePercent
00902 << "%" << G4endl;
00903 }
00904 }
00905 #endif
00906 }
00907
00908
00909
00910
00911
00912 G4double minWidth = kInfinity;
00913 G4double currentWidth;
00914 for (nVol=0; nVol<nCandidates; nVol++)
00915 {
00916
00917
00918
00919
00920 currentWidth = std::abs(maxExtents[nVol]-minExtents[nVol]);
00921 if ( (currentWidth<minWidth)
00922 && (maxExtents[nVol]>=pLimits.GetMinExtent(pAxis))
00923 && (minExtents[nVol]<=pLimits.GetMaxExtent(pAxis)) )
00924 {
00925 minWidth = currentWidth;
00926 }
00927 }
00928
00929
00930
00931
00932 G4double noNodesExactD = ((motherMaxExtent-motherMinExtent)*2.0/minWidth)+1.0;
00933
00934
00935
00936
00937 G4double smartlessComputed = noNodesExactD / nCandidates;
00938 G4double smartlessUser = pVolume->GetSmartless();
00939 G4double smartless = (smartlessComputed <= smartlessUser)
00940 ? smartlessComputed : smartlessUser;
00941 G4double noNodesSmart = smartless*nCandidates;
00942 G4int noNodesExactI = G4int(noNodesSmart);
00943 G4int noNodes = ((noNodesSmart-noNodesExactI)>=0.5)
00944 ? noNodesExactI+1 : noNodesExactI;
00945 if( noNodes == 0 ) { noNodes=1; }
00946
00947 #ifdef G4GEOMETRY_VOXELDEBUG
00948 G4cout << " Smartless computed = " << smartlessComputed << G4endl
00949 << " Smartless volume = " << smartlessUser
00950 << " => # Smartless = " << smartless << G4endl;
00951 G4cout << " Min width = " << minWidth
00952 << " => # Nodes = " << noNodes << G4endl;
00953 #endif
00954
00955 if (noNodes>kMaxVoxelNodes)
00956 {
00957 noNodes=kMaxVoxelNodes;
00958 #ifdef G4GEOMETRY_VOXELDEBUG
00959 G4cout << " Nodes Clipped to = " << kMaxVoxelNodes << G4endl;
00960 #endif
00961 }
00962 G4double nodeWidth = (motherMaxExtent-motherMinExtent)/noNodes;
00963
00964
00965
00966 G4NodeVector* nodeList = new G4NodeVector();
00967 if (!nodeList)
00968 {
00969 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0003",
00970 FatalException, "NodeList allocation error.");
00971 return 0;
00972 }
00973 nodeList->reserve(noNodes);
00974
00975 for (nNode=0; nNode<noNodes; nNode++)
00976 {
00977 G4SmartVoxelNode *pNode;
00978 pNode = new G4SmartVoxelNode(nNode);
00979 if (!pNode)
00980 {
00981 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0003",
00982 FatalException, "Node allocation error.");
00983 return 0;
00984 }
00985 nodeList->push_back(pNode);
00986 }
00987
00988
00989
00990
00991
00992 for (nVol=0; nVol<nCandidates; nVol++)
00993 {
00994 G4int nodeNo, minContainingNode, maxContainingNode;
00995 minContainingNode = G4int((minExtents[nVol]-motherMinExtent)/nodeWidth);
00996 maxContainingNode = G4int((maxExtents[nVol]-motherMinExtent)/nodeWidth);
00997
00998
00999
01000 if ( (maxContainingNode>=0) && (minContainingNode<noNodes) )
01001 {
01002
01003
01004
01005 if (maxContainingNode>=noNodes)
01006 {
01007 maxContainingNode = noNodes-1;
01008 }
01009
01010
01011
01012 if (minContainingNode<0)
01013 {
01014 minContainingNode=0;
01015 }
01016 for (nodeNo=minContainingNode; nodeNo<=maxContainingNode; nodeNo++)
01017 {
01018 (*nodeList)[nodeNo]->Insert((*pCandidates)[nVol]);
01019 }
01020 }
01021 }
01022
01023
01024
01025
01026
01027
01028 G4ProxyVector* proxyList = new G4ProxyVector();
01029 if (!proxyList)
01030 {
01031 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0003",
01032 FatalException, "Proxy list allocation error.");
01033 return 0;
01034 }
01035 proxyList->reserve(noNodes);
01036
01037
01038
01039
01040 for (nNode=0; nNode<noNodes; nNode++)
01041 {
01042
01043
01044 ((*nodeList)[nNode])->Shrink();
01045 G4SmartVoxelProxy* pProxyNode = new G4SmartVoxelProxy((*nodeList)[nNode]);
01046 if (!pProxyNode)
01047 {
01048 G4Exception("G4SmartVoxelHeader::BuildNodes()", "GeomMgt0003",
01049 FatalException, "Proxy node allocation failed.");
01050 return 0;
01051 }
01052 proxyList->push_back(pProxyNode);
01053 }
01054 delete nodeList;
01055 return proxyList;
01056 }
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073 G4double G4SmartVoxelHeader::CalculateQuality(G4ProxyVector *pSlice)
01074 {
01075 G4double quality;
01076 G4int nNodes = pSlice->size();
01077 G4int noContained, maxContained=0, sumContained=0, sumNonEmptyNodes=0;
01078 G4SmartVoxelNode *node;
01079
01080 for (G4int i=0; i<nNodes; i++)
01081 {
01082 if ((*pSlice)[i]->IsNode())
01083 {
01084
01085
01086 node = (*pSlice)[i]->GetNode();
01087 noContained = node->GetNoContained();
01088 if (noContained)
01089 {
01090 sumNonEmptyNodes++;
01091 sumContained += noContained;
01092
01093
01094
01095 if (noContained>maxContained)
01096 {
01097 maxContained = noContained;
01098 }
01099 }
01100 }
01101 else
01102 {
01103 G4Exception("G4SmartVoxelHeader::CalculateQuality()", "GeomMgt0001",
01104 FatalException, "Not applicable to replicated volumes.");
01105 }
01106 }
01107
01108
01109
01110 if (sumNonEmptyNodes)
01111 {
01112 quality = sumContained/sumNonEmptyNodes;
01113 }
01114 else
01115 {
01116 quality = kInfinity;
01117 }
01118
01119 #ifdef G4GEOMETRY_VOXELDEBUG
01120 G4cout << "**** G4SmartVoxelHeader::CalculateQuality" << G4endl
01121 << " Quality = " << quality << G4endl
01122 << " Nodes = " << nNodes
01123 << " of which " << sumNonEmptyNodes << " non empty" << G4endl
01124 << " Max Contained = " << maxContained << G4endl;
01125 #endif
01126
01127 return quality;
01128 }
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139 void G4SmartVoxelHeader::RefineNodes(G4LogicalVolume* pVolume,
01140 G4VoxelLimits pLimits)
01141 {
01142 G4int refinedDepth=0, minVolumes;
01143 G4int maxNode = fslices.size();
01144
01145 if (pLimits.IsXLimited())
01146 {
01147 refinedDepth++;
01148 }
01149 if (pLimits.IsYLimited())
01150 {
01151 refinedDepth++;
01152 }
01153 if (pLimits.IsZLimited())
01154 {
01155 refinedDepth++;
01156 }
01157
01158
01159
01160 switch (refinedDepth)
01161 {
01162 case 0:
01163 minVolumes=kMinVoxelVolumesLevel2;
01164 break;
01165 case 1:
01166 minVolumes=kMinVoxelVolumesLevel3;
01167 break;
01168 default:
01169 minVolumes=10000;
01170 break;
01171 }
01172
01173 if (refinedDepth<2)
01174 {
01175 G4int targetNo, noContainedDaughters, minNo, maxNo, replaceNo, i;
01176 G4double sliceWidth = (fmaxExtent-fminExtent)/maxNode;
01177 G4VoxelLimits newLimits;
01178 G4SmartVoxelNode* targetNode;
01179 G4SmartVoxelProxy* targetNodeProxy;
01180 G4SmartVoxelHeader* replaceHeader;
01181 G4SmartVoxelProxy* replaceHeaderProxy;
01182 G4VolumeNosVector* targetList;
01183 G4SmartVoxelProxy* lastProxy;
01184
01185 for (targetNo=0; targetNo<maxNode; targetNo++)
01186 {
01187
01188
01189 targetNodeProxy = fslices[targetNo];
01190 targetNode = targetNodeProxy->GetNode();
01191
01192 if (targetNode->GetNoContained() >= minVolumes)
01193 {
01194 noContainedDaughters = targetNode->GetNoContained();
01195 targetList = new G4VolumeNosVector();
01196 if (!targetList)
01197 {
01198 G4Exception("G4SmartVoxelHeader::RefineNodes()",
01199 "GeomMgt0003", FatalException,
01200 "Target volume node list allocation error.");
01201 return;
01202 }
01203 targetList->reserve(noContainedDaughters);
01204 for (i=0; i<noContainedDaughters; i++)
01205 {
01206 targetList->push_back(targetNode->GetVolume(i));
01207 }
01208 minNo = targetNode->GetMinEquivalentSliceNo();
01209 maxNo = targetNode->GetMaxEquivalentSliceNo();
01210
01211 #ifdef G4GEOMETRY_VOXELDEBUG
01212 G4cout << "**** G4SmartVoxelHeader::RefineNodes" << G4endl
01213 << " Refining nodes " << minNo
01214 << " - " << maxNo << " inclusive" << G4endl;
01215 #endif
01216 if (minNo > maxNo)
01217 {
01218 delete targetNode;
01219 delete targetList;
01220 return;
01221 }
01222
01223
01224
01225 lastProxy=0;
01226 for (replaceNo=minNo; replaceNo<=maxNo; replaceNo++)
01227 {
01228 if (lastProxy != fslices[replaceNo])
01229 {
01230 lastProxy=fslices[replaceNo];
01231 delete lastProxy;
01232 }
01233 }
01234
01235
01236 delete targetNode;
01237
01238
01239
01240 newLimits = pLimits;
01241 newLimits.AddLimit(faxis,fminExtent+sliceWidth*minNo,
01242 fminExtent+sliceWidth*(maxNo+1));
01243 replaceHeader = new G4SmartVoxelHeader(pVolume,newLimits,
01244 targetList,replaceNo);
01245 if (!replaceHeader)
01246 {
01247 G4Exception("G4SmartVoxelHeader::RefineNodes()", "GeomMgt0003",
01248 FatalException, "Refined VoxelHeader allocation error.");
01249 return;
01250 }
01251 replaceHeader->SetMinEquivalentSliceNo(minNo);
01252 replaceHeader->SetMaxEquivalentSliceNo(maxNo);
01253 replaceHeaderProxy = new G4SmartVoxelProxy(replaceHeader);
01254 if (!replaceHeaderProxy)
01255 {
01256 G4Exception("G4SmartVoxelHeader::RefineNodes()", "GeomMgt0003",
01257 FatalException, "Refined VoxelProxy allocation error.");
01258 return;
01259 }
01260 for (replaceNo=minNo; replaceNo<=maxNo; replaceNo++)
01261 {
01262 fslices[replaceNo] = replaceHeaderProxy;
01263 }
01264
01265
01266 delete targetList;
01267 targetNo=maxNo;
01268 }
01269 }
01270 }
01271 }
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281 G4bool G4SmartVoxelHeader::AllSlicesEqual() const
01282 {
01283 G4int noSlices = fslices.size();
01284 G4SmartVoxelProxy* refProxy;
01285
01286 if (noSlices>1)
01287 {
01288 refProxy=fslices[0];
01289 for (G4int i=1; i<noSlices; i++)
01290 {
01291 if (refProxy!=fslices[i])
01292 {
01293 return false;
01294 }
01295 }
01296 }
01297 return true;
01298 }
01299
01300
01301
01302
01303
01304 std::ostream& operator << (std::ostream& os, const G4SmartVoxelHeader& h)
01305 {
01306 os << "Axis = " << G4int(h.faxis) << G4endl;
01307 G4SmartVoxelProxy *collectNode=0, *collectHead=0;
01308 G4int collectNodeNo=0;
01309 G4int collectHeadNo=0;
01310 size_t i, j;
01311 G4bool haveHeaders=false;
01312
01313 for (i=0; i<h.fslices.size(); i++)
01314 {
01315 os << "Slice #" << i << " = ";
01316 if (h.fslices[i]->IsNode())
01317 {
01318 if (h.fslices[i]!=collectNode)
01319 {
01320 os << "{";
01321 for (G4int k=0; k<h.fslices[i]->GetNode()->GetNoContained(); k++)
01322 {
01323 os << " " << h.fslices[i]->GetNode()->GetVolume(k);
01324 }
01325 os << " }" << G4endl;
01326 collectNode = h.fslices[i];
01327 collectNodeNo = i;
01328 }
01329 else
01330 {
01331 os << "As slice #" << collectNodeNo << G4endl;
01332 }
01333 }
01334 else
01335 {
01336 haveHeaders=true;
01337 if (h.fslices[i] != collectHead)
01338 {
01339 os << "Header" << G4endl;
01340 collectHead = h.fslices[i];
01341 collectHeadNo = i;
01342 }
01343 else
01344 {
01345 os << "As slice #" << collectHeadNo << G4endl;
01346 }
01347 }
01348 }
01349
01350 if (haveHeaders)
01351 {
01352 collectHead=0;
01353 for (j=0; j<h.fslices.size(); j++)
01354 {
01355 if (h.fslices[j]->IsHeader())
01356 {
01357 os << "Header at Slice #" << j << " = ";
01358 if (h.fslices[j] != collectHead)
01359 {
01360 os << G4endl
01361 << (*(h.fslices[j]->GetHeader()));
01362 collectHead = h.fslices[j];
01363 collectHeadNo = j;
01364 }
01365 else
01366 {
01367 os << "As slice #" << collectHeadNo << G4endl;
01368 }
01369 }
01370 }
01371 }
01372 return os;
01373 }