61 : fminEquivalent(pSlice),
62 fmaxEquivalent(pSlice),
80 BuildReplicaVoxels(pVolume);
95 : fminEquivalent(pSlice),
96 fmaxEquivalent(pSlice),
99#ifdef G4GEOMETRY_VOXELDEBUG
100 G4cout <<
"**** G4SmartVoxelHeader::G4SmartVoxelHeader" <<
G4endl
101 <<
" Limits " << pLimits <<
G4endl
102 <<
" Candidate #s = " ;
103 for (
auto i=0; i<pCandidates->size(); ++i)
105 G4cout << (*pCandidates)[i] <<
" ";
110 BuildVoxelsWithinLimits(pVolume,pLimits,pCandidates);
122 std::size_t node, proxy, maxNode=fslices.size();
127 for (node=0; node<maxNode; ++node)
129 if (fslices[node]->IsHeader())
131 dyingHeader = fslices[node]->GetHeader();
132 if (lastHeader != dyingHeader)
134 lastHeader = dyingHeader;
141 dyingNode = fslices[node]->GetNode();
142 if (dyingNode != lastNode)
144 lastNode = dyingNode;
145 lastHeader =
nullptr;
152 for (proxy=0; proxy<maxNode; ++proxy)
154 if (fslices[proxy] != lastProxy)
156 lastProxy = fslices[proxy];
180 std::size_t node, maxNode;
186 for (node=0; node<maxNode; ++node)
198 if (!(*leftHeader == *rightHeader))
209 leftNode = leftProxy->
GetNode();
210 rightNode = rightProxy->
GetNode();
211 if (!(*leftNode == *rightNode))
235 targetList.reserve(nDaughters);
236 for (std::size_t i=0; i<nDaughters; ++i)
238 targetList.push_back((
G4int)i);
240 BuildVoxelsWithinLimits(pVolume, limits, &targetList);
251 G4VPhysicalVolume* pDaughter =
nullptr;
272 G4VoxelLimits limits;
274 targetList.reserve(nReplicas);
275 for (
auto i=0; i<nReplicas; ++i)
277 targetList.push_back(i);
290 const G4AffineTransform origin;
292 fminExtent, fmaxExtent);
295 BuildEquivalentSliceNos();
296 CollectEquivalentNodes();
303 BuildVoxelsWithinLimits(pVolume, limits, &targetList);
324 fminExtent = -width*nReplicas*0.5;
325 fmaxExtent = width*nReplicas*0.5;
329 fmaxExtent = width*nReplicas+
offset;
333 fmaxExtent =
offset+width*nReplicas;
336 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels()",
341 BuildConsumedNodes(nReplicas);
346 G4double emin = kInfinity, emax = -kInfinity;
347 G4VoxelLimits limits;
348 G4AffineTransform origin;
350 if ( (std::fabs((emin-fminExtent)/fminExtent) +
351 std::fabs((emax-fmaxExtent)/fmaxExtent)) > 0.05)
353 std::ostringstream message;
354 message <<
"Sanity check: wrong solid extent." <<
G4endl
355 <<
" Replicated geometry, logical volume: "
357 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels",
365 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels",
"GeomMgt0002",
377void G4SmartVoxelHeader::BuildConsumedNodes(
G4int nReplicas)
380 G4SmartVoxelNode* pNode;
381 G4SmartVoxelProxy* pProxyNode;
386 nodeList.reserve(nReplicas);
387 for (nNode=0; nNode<nReplicas; ++nNode)
389 pNode =
new G4SmartVoxelNode(nNode);
390 if (pNode ==
nullptr)
392 G4Exception(
"G4SmartVoxelHeader::BuildConsumedNodes()",
"GeomMgt0003",
395 nodeList.push_back(pNode);
397 for (nVol=0; nVol<nReplicas; ++nVol)
399 nodeList[nVol]->Insert(nVol);
405 for (nNode=0; nNode<nReplicas; ++nNode)
407 pProxyNode =
new G4SmartVoxelProxy(nodeList[nNode]);
408 if (pProxyNode ==
nullptr)
410 G4Exception(
"G4SmartVoxelHeader::BuildConsumedNodes()",
"GeomMgt0003",
413 fslices.push_back(pProxyNode);
434 G4double goodSliceScore=kInfinity, testSliceScore;
436 std::size_t node, maxNode;
437 G4VoxelLimits noLimits;
445 pTestSlices = BuildNodes(pVolume,pLimits,pCandidates,testAxis);
446 testSliceScore = CalculateQuality(pTestSlices);
447 if ( (pGoodSlices ==
nullptr) || (testSliceScore<goodSliceScore) )
449 goodSliceAxis = testAxis;
450 goodSliceScore = testSliceScore;
451 std::swap( pGoodSlices, pTestSlices);
453 if (pTestSlices !=
nullptr)
457 maxNode=pTestSlices->size();
458 for (node=0; node<maxNode; ++node)
460 delete (*pTestSlices)[node]->GetNode();
462 G4SmartVoxelProxy* tmpProx;
463 while (!pTestSlices->empty())
465 tmpProx = pTestSlices->back();
466 pTestSlices->pop_back();
467 for (
auto i=pTestSlices->cbegin(); i!=pTestSlices->cend(); )
471 i = pTestSlices->erase(i);
487 if (pGoodSlices ==
nullptr)
489 G4Exception(
"G4SmartVoxelHeader::BuildVoxelsWithinLimits()",
491 "Cannot select more than 3 axis for optimisation.");
501 fslices =* pGoodSlices;
504 faxis = goodSliceAxis;
506#ifdef G4GEOMETRY_VOXELDEBUG
509 for (
auto islice=0; islice<fslices.size(); ++islice)
511 G4cout <<
" Node #" << islice <<
" = {";
512 for (
auto j=0; j<fslices[islice]->GetNode()->GetNoContained(); ++j)
514 G4cout <<
" " << fslices[islice]->GetNode()->GetVolume(j);
523 G4VSolid* outerSolid = pVolume->
GetSolid();
524 const G4AffineTransform origin;
525 if(!outerSolid->
CalculateExtent(faxis,pLimits,origin,fminExtent,fmaxExtent))
527 outerSolid->
CalculateExtent(faxis,noLimits,origin,fminExtent,fmaxExtent);
532 BuildEquivalentSliceNos();
533 CollectEquivalentNodes();
534 RefineNodes(pVolume, pLimits);
549void G4SmartVoxelHeader::BuildEquivalentSliceNos()
551 std::size_t sliceNo, minNo, maxNo, equivNo;
552 std::size_t maxNode = fslices.size();
553 G4SmartVoxelNode *startNode, *sampleNode;
554 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
560 startNode = fslices[minNo]->GetNode();
564 for (equivNo=minNo+1; equivNo<maxNode; ++equivNo)
566 sampleNode = fslices[equivNo]->GetNode();
567 if (!((*startNode) == (*sampleNode))) {
break; }
574 for (equivNo=minNo; equivNo<=maxNo; ++equivNo)
576 sampleNode = fslices[equivNo]->GetNode();
596void G4SmartVoxelHeader::CollectEquivalentNodes()
598 std::size_t sliceNo, maxNo, equivNo;
599 std::size_t maxNode=fslices.size();
600 G4SmartVoxelNode* equivNode;
601 G4SmartVoxelProxy* equivProxy;
603 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
605 equivProxy=fslices[sliceNo];
609 equivNode = equivProxy->
GetNode();
611 if (maxNo != sliceNo)
613#ifdef G4GEOMETRY_VOXELDEBUG
614 G4cout <<
"**** G4SmartVoxelHeader::CollectEquivalentNodes" <<
G4endl
615 <<
" Collecting Nodes = "
616 << sliceNo <<
" - " << maxNo <<
G4endl;
620 for (equivNo=sliceNo+1; equivNo<=maxNo; ++equivNo)
622 delete fslices[equivNo]->GetNode();
623 delete fslices[equivNo];
624 fslices[equivNo] = equivProxy;
643void G4SmartVoxelHeader::CollectEquivalentHeaders()
645 std::size_t sliceNo, maxNo, equivNo;
646 std::size_t maxNode = fslices.size();
648 G4SmartVoxelProxy *equivProxy;
650 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
652 equivProxy = fslices[sliceNo];
657 if (maxNo != sliceNo)
663#ifdef G4GEOMETRY_VOXELDEBUG
664 G4cout <<
"**** G4SmartVoxelHeader::CollectEquivalentHeaders" <<
G4endl
665 <<
" Collecting Headers =";
667 for (equivNo=sliceNo+1; equivNo<=maxNo; ++equivNo)
669 sampleHeader = fslices[equivNo]->GetHeader();
670 if ( (*sampleHeader) == (*equivHeader) )
672#ifdef G4GEOMETRY_VOXELDEBUG
678 delete fslices[equivNo];
679 fslices[equivNo] = equivProxy;
686 equivProxy = fslices[equivNo];
691#ifdef G4GEOMETRY_VOXELDEBUG
721 G4double motherMinExtent= kInfinity, motherMaxExtent= -kInfinity,
722 targetMinExtent= kInfinity, targetMaxExtent= -kInfinity;
723 G4VPhysicalVolume* pDaughter =
nullptr;
724 G4VPVParameterisation* pParam =
nullptr;
725 G4VSolid *targetSolid;
726 G4AffineTransform targetTransform;
728 std::size_t nCandidates = pCandidates->size();
729 std::size_t nVol, nNode, targetVolNo;
730 G4VoxelLimits noLimits;
732#ifdef G4GEOMETRY_VOXELDEBUG
733 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
734 <<
" Limits = " << pLimits <<
G4endl
735 <<
" Axis = " << pAxis <<
G4endl
736 <<
" Candidates = " << nCandidates <<
G4endl;
742 G4VSolid* outerSolid = pVolume->
GetSolid();
743 const G4AffineTransform origin;
745 motherMinExtent, motherMaxExtent) )
748 motherMinExtent, motherMaxExtent);
761 if (pParam ==
nullptr)
763 std::ostringstream message;
764 message <<
"PANIC! - Missing parameterisation." <<
G4endl
765 <<
" Replicated volume with no parameterisation object !";
766 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
773 targetTransform = G4AffineTransform(pDaughter->
GetRotation(),
784 for (nVol=0; nVol<nCandidates; ++nVol)
786 targetVolNo = (*pCandidates)[nVol];
793 targetTransform = G4AffineTransform(pDaughter->
GetRotation(),
812 targetTransform = G4AffineTransform(pDaughter->
GetRotation(),
818 targetMinExtent, targetMaxExtent))
821 targetMinExtent,targetMaxExtent);
823 minExtents[nVol] = targetMinExtent;
824 maxExtents[nVol] = targetMaxExtent;
826#ifdef G4GEOMETRY_VOXELDEBUG
827 G4cout <<
"---------------------------------------------------" <<
G4endl
829 <<
" Min Extent = " << targetMinExtent <<
G4endl
830 <<
" Max Extent = " << targetMaxExtent <<
G4endl
831 <<
"---------------------------------------------------" <<
G4endl;
836 if ( (!pLimits.
IsLimited()) && ((targetMaxExtent<=motherMinExtent)
837 ||(targetMinExtent>=motherMaxExtent)) )
839 std::ostringstream message;
840 message <<
"PANIC! - Overlapping daughter with mother volume." <<
G4endl
841 <<
" Daughter physical volume "
843 <<
" is entirely outside mother logical volume "
844 << pVolume->
GetName() <<
" !!";
845 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0002",
849#ifdef G4GEOMETRY_VOXELDEBUG
857 G4int kStraddlePercent = 5;
858 width = maxExtents[nVol]-minExtents[nVol];
859 if ( (((motherMinExtent-minExtents[nVol])*100/width) > kStraddlePercent)
860 ||(((maxExtents[nVol]-motherMaxExtent)*100/width) > kStraddlePercent) )
862 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
863 <<
" WARNING : Daughter # " << nVol
865 <<
" Crosses mother boundary of logical volume, name = "
867 <<
" by more than " << kStraddlePercent
880 for (nVol=0; nVol<nCandidates; ++nVol)
886 currentWidth = std::abs(maxExtents[nVol]-minExtents[nVol]);
887 if ( (currentWidth<minWidth)
891 minWidth = currentWidth;
898 G4double noNodesExactD = ((motherMaxExtent-motherMinExtent)*2.0/minWidth)+1.0;
903 G4double smartlessComputed = noNodesExactD / nCandidates;
905 G4double smartless = (smartlessComputed <= smartlessUser)
906 ? smartlessComputed : smartlessUser;
907 G4double noNodesSmart = smartless*nCandidates;
908 auto noNodesExactI =
G4int(noNodesSmart);
909 G4long noNodes = ((noNodesSmart-noNodesExactI)>=0.5)
910 ? noNodesExactI+1 : noNodesExactI;
911 if( noNodes == 0 ) { noNodes=1; }
913#ifdef G4GEOMETRY_VOXELDEBUG
914 G4cout <<
" Smartless computed = " << smartlessComputed <<
G4endl
915 <<
" Smartless volume = " << smartlessUser
916 <<
" => # Smartless = " << smartless <<
G4endl;
917 G4cout <<
" Min width = " << minWidth
918 <<
" => # Nodes = " << noNodes <<
G4endl;
924#ifdef G4GEOMETRY_VOXELDEBUG
928 G4double nodeWidth = (motherMaxExtent-motherMinExtent)/noNodes;
933 if (nodeList ==
nullptr)
935 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
939 nodeList->reserve(noNodes);
941 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
943 G4SmartVoxelNode *pNode;
944 pNode =
new G4SmartVoxelNode((
G4int)nNode);
945 if (pNode ==
nullptr)
947 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
951 nodeList->push_back(pNode);
958 for (nVol=0; nVol<nCandidates; ++nVol)
960 G4long nodeNo, minContainingNode, maxContainingNode;
961 minContainingNode = (minExtents[nVol]-motherMinExtent)/nodeWidth;
962 maxContainingNode = (maxExtents[nVol]-motherMinExtent)/nodeWidth;
966 if ( (maxContainingNode>=0) && (minContainingNode<noNodes) )
971 if (maxContainingNode>=noNodes)
973 maxContainingNode = noNodes-1;
978 if (minContainingNode<0)
980 minContainingNode = 0;
982 for (nodeNo=minContainingNode; nodeNo<=maxContainingNode; ++nodeNo)
984 (*nodeList)[nodeNo]->Insert((*pCandidates)[nVol]);
995 if (proxyList ==
nullptr)
997 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1001 proxyList->reserve(noNodes);
1006 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
1010 ((*nodeList)[nNode])->Shrink();
1011 auto* pProxyNode =
new G4SmartVoxelProxy((*nodeList)[nNode]);
1012 if (pProxyNode ==
nullptr)
1014 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1018 proxyList->push_back(pProxyNode);
1042 std::size_t nNodes = pSlice->size();
1043 std::size_t noContained, maxContained=0, sumContained=0, sumNonEmptyNodes=0;
1044 G4SmartVoxelNode *node;
1046 for (std::size_t i=0; i<nNodes; ++i)
1048 if ((*pSlice)[i]->IsNode())
1052 node = (*pSlice)[i]->GetNode();
1054 if (noContained != 0)
1057 sumContained += noContained;
1061 if (noContained>maxContained)
1063 maxContained = noContained;
1069 G4Exception(
"G4SmartVoxelHeader::CalculateQuality()",
"GeomMgt0001",
1076 if (sumNonEmptyNodes != 0)
1078 quality = sumContained/sumNonEmptyNodes;
1082 quality = kInfinity;
1085#ifdef G4GEOMETRY_VOXELDEBUG
1086 G4cout <<
"**** G4SmartVoxelHeader::CalculateQuality" <<
G4endl
1087 <<
" Quality = " << quality <<
G4endl
1088 <<
" Nodes = " << nNodes
1089 <<
" of which " << sumNonEmptyNodes <<
" non empty" <<
G4endl
1090 <<
" Max Contained = " << maxContained <<
G4endl;
1108 std::size_t refinedDepth=0, minVolumes;
1109 std::size_t maxNode = fslices.size();
1126 switch (refinedDepth)
1141 std::size_t targetNo, noContainedDaughters, minNo, maxNo, replaceNo, i;
1142 G4double sliceWidth = (fmaxExtent-fminExtent)/maxNode;
1143 G4VoxelLimits newLimits;
1144 G4SmartVoxelNode* targetNode;
1145 G4SmartVoxelProxy* targetNodeProxy;
1147 G4SmartVoxelProxy* replaceHeaderProxy;
1149 G4SmartVoxelProxy* lastProxy;
1151 for (targetNo=0; targetNo<maxNode; ++targetNo)
1155 targetNodeProxy = fslices[targetNo];
1156 targetNode = targetNodeProxy->
GetNode();
1162 if (targetList ==
nullptr)
1166 "Target volume node list allocation error.");
1169 targetList->reserve(noContainedDaughters);
1170 for (i=0; i<noContainedDaughters; ++i)
1177#ifdef G4GEOMETRY_VOXELDEBUG
1178 G4cout <<
"**** G4SmartVoxelHeader::RefineNodes" <<
G4endl
1179 <<
" Refining nodes " << minNo
1180 <<
" - " << maxNo <<
" inclusive" <<
G4endl;
1192 for (replaceNo=minNo; replaceNo<=maxNo; ++replaceNo)
1194 if (lastProxy != fslices[replaceNo])
1196 lastProxy=fslices[replaceNo];
1206 newLimits = pLimits;
1207 newLimits.
AddLimit(faxis,fminExtent+sliceWidth*minNo,
1208 fminExtent+sliceWidth*(maxNo+1));
1210 targetList,(
G4int)replaceNo);
1211 if (replaceHeader ==
nullptr)
1213 G4Exception(
"G4SmartVoxelHeader::RefineNodes()",
"GeomMgt0003",
1219 replaceHeaderProxy =
new G4SmartVoxelProxy(replaceHeader);
1220 if (replaceHeaderProxy ==
nullptr)
1222 G4Exception(
"G4SmartVoxelHeader::RefineNodes()",
"GeomMgt0003",
1226 for (replaceNo=minNo; replaceNo<=maxNo; ++replaceNo)
1228 fslices[replaceNo] = replaceHeaderProxy;
1249 std::size_t noSlices = fslices.size();
1254 refProxy=fslices[0];
1255 for (std::size_t i=1; i<noSlices; ++i)
1257 if (refProxy!=fslices[i])
1274 std::size_t collectNodeNo = 0;
1275 std::size_t collectHeadNo = 0;
1277 G4bool haveHeaders =
false;
1279 for (i=0; i<h.fslices.size(); ++i)
1281 os <<
"Slice #" << i <<
" = ";
1282 if (h.fslices[i]->IsNode())
1284 if (h.fslices[i]!=collectNode)
1287 for (std::size_t k=0; k<h.fslices[i]->GetNode()->GetNoContained(); ++k)
1289 os <<
" " << h.fslices[i]->GetNode()->GetVolume((
G4int)k);
1292 collectNode = h.fslices[i];
1297 os <<
"As slice #" << collectNodeNo <<
G4endl;
1303 if (h.fslices[i] != collectHead)
1305 os <<
"Header" <<
G4endl;
1306 collectHead = h.fslices[i];
1311 os <<
"As slice #" << collectHeadNo <<
G4endl;
1318 collectHead=
nullptr;
1319 for (j=0; j<h.fslices.size(); ++j)
1321 if (h.fslices[j]->IsHeader())
1323 os <<
"Header at Slice #" << j <<
" = ";
1324 if (h.fslices[j] != collectHead)
1327 << (*(h.fslices[j]->GetHeader()));
1328 collectHead = h.fslices[j];
1333 os <<
"As slice #" << collectHeadNo <<
G4endl;
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4ThreadLocal T * G4GeomSplitter< T >::offset
G4GLOB_DLL std::ostream G4cout
G4LogicalVolume represents a leaf node or unpositioned subtree in the geometry hierarchy....
G4VSolid * GetSolid() const
std::size_t GetNoDaughters() const
G4double GetSmartless() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
const G4String & GetName() const
G4SmartVoxelNode defines a node in the smart voxel hierarchy, i.e. a 'slice' of space along a given a...
G4int GetMaxEquivalentSliceNo() const
G4int GetVolume(G4int pVolumeNo) const
void SetMaxEquivalentSliceNo(G4int pMax)
void SetMinEquivalentSliceNo(G4int pMin)
std::size_t GetNoContained() const
G4int GetMinEquivalentSliceNo() const
G4SmartVoxelProxy is a class for proxying smart voxels. The class represents either a header (in turn...
G4SmartVoxelNode * GetNode() const
G4SmartVoxelHeader * GetHeader() const
virtual void ComputeTransformation(const G4int no, G4VPhysicalVolume *pv) const =0
virtual G4VSolid * ComputeSolid(const G4int no, G4VPhysicalVolume *pv)
virtual G4bool IsReplicated() const =0
const G4RotationMatrix * GetRotation() const
const G4ThreeVector GetTranslation() const
G4LogicalVolume * GetLogicalVolume() const
virtual void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const =0
const G4String & GetName() const
virtual G4VPVParameterisation * GetParameterisation() const =0
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
virtual void ComputeDimensions(G4VPVParameterisation *p, const G4int n, const G4VPhysicalVolume *pRep)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
G4double GetMinExtent(const EAxis pAxis) const
G4bool IsYLimited() const
void AddLimit(const EAxis pAxis, const G4double pMin, const G4double pMax)
G4bool IsXLimited() const
G4double GetMaxExtent(const EAxis pAxis) const
G4bool IsZLimited() const
const axis_t axis_to_type< N >::axis
const G4int kMaxVoxelNodes
const G4int kMinVoxelVolumesLevel3
const G4int kMinVoxelVolumesLevel2