61 : fminEquivalent(pSlice),
62 fmaxEquivalent(pSlice),
96 : fminEquivalent(pSlice),
97 fmaxEquivalent(pSlice),
100#ifdef G4GEOMETRY_VOXELDEBUG
101 G4cout <<
"**** G4SmartVoxelHeader::G4SmartVoxelHeader" <<
G4endl
102 <<
" Limits " << pLimits <<
G4endl
103 <<
" Candidate #s = " ;
104 for (
auto i=0; i<pCandidates->size(); ++i)
106 G4cout << (*pCandidates)[i] <<
" ";
124 size_t node, proxy, maxNode=
fslices.size();
129 for (node=0; node<maxNode; ++node)
133 dyingHeader =
fslices[node]->GetHeader();
134 if (lastHeader != dyingHeader)
136 lastHeader = dyingHeader;
143 dyingNode =
fslices[node]->GetNode();
144 if (dyingNode != lastNode)
146 lastNode = dyingNode;
147 lastHeader =
nullptr;
154 for (proxy=0; proxy<maxNode; ++proxy)
156 if (
fslices[proxy] != lastProxy)
182 size_t node, maxNode;
188 for (node=0; node<maxNode; ++node)
202 if (!(*leftHeader == *rightHeader))
216 leftNode = leftProxy->
GetNode();
217 rightNode = rightProxy->
GetNode();
218 if (!(*leftNode == *rightNode))
245 targetList.reserve(nDaughters);
246 for (
size_t i=0; i<nDaughters; ++i)
248 targetList.push_back(i);
280 if ( consuming ==
false )
284 targetList.reserve(nReplicas);
285 for (
auto i=0; i<nReplicas; ++i)
287 targetList.push_back(i);
346 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels()",
363 std::ostringstream message;
364 message <<
"Sanity check: wrong solid extent." <<
G4endl
365 <<
" Replicated geometry, logical volume: "
367 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels",
375 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels",
"GeomMgt0002",
396 nodeList.reserve(nReplicas);
397 for (nNode=0; nNode<nReplicas; ++nNode)
400 if (pNode ==
nullptr)
402 G4Exception(
"G4SmartVoxelHeader::BuildConsumedNodes()",
"GeomMgt0003",
405 nodeList.push_back(pNode);
407 for (nVol=0; nVol<nReplicas; ++nVol)
409 nodeList[nVol]->Insert(nVol);
415 for (nNode=0; nNode<nReplicas; ++nNode)
420 G4Exception(
"G4SmartVoxelHeader::BuildConsumedNodes()",
"GeomMgt0003",
443 G4ProxyVector *pGoodSlices=
nullptr, *pTestSlices, *tmpSlices;
447 size_t node, maxNode, iaxis;
452 for (iaxis=0; iaxis<3; ++iaxis)
468 pTestSlices =
BuildNodes(pVolume,pLimits,pCandidates,testAxis);
470 if ( (!pGoodSlices) || (testSliceScore<goodSliceScore) )
472 goodSliceAxis = testAxis;
473 goodSliceScore = testSliceScore;
474 tmpSlices = pGoodSlices;
475 pGoodSlices = pTestSlices;
476 pTestSlices = tmpSlices;
482 maxNode=pTestSlices->size();
483 for (node=0; node<maxNode; ++node)
485 delete (*pTestSlices)[node]->GetNode();
488 while (pTestSlices->size()>0)
490 tmpProx = pTestSlices->back();
491 pTestSlices->pop_back();
492 for (
auto i=pTestSlices->cbegin(); i!=pTestSlices->cend(); )
496 i = pTestSlices->erase(i);
503 if ( tmpProx ) {
delete tmpProx; }
514 G4Exception(
"G4SmartVoxelHeader::BuildVoxelsWithinLimits()",
516 "Cannot select more than 3 axis for optimisation.");
529 faxis = goodSliceAxis;
531#ifdef G4GEOMETRY_VOXELDEBUG
534 for (
auto islice=0; islice<
fslices.size(); ++islice)
536 G4cout <<
" Node #" << islice <<
" = {";
537 for (
auto j=0; j<
fslices[islice]->GetNode()->GetNoContained(); ++j)
576 size_t sliceNo, minNo, maxNo, equivNo;
577 size_t maxNode =
fslices.size();
579 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
585 startNode =
fslices[minNo]->GetNode();
589 for (equivNo=minNo+1; equivNo<maxNode; ++equivNo)
591 sampleNode =
fslices[equivNo]->GetNode();
592 if (!((*startNode) == (*sampleNode))) {
break; }
599 for (equivNo=minNo; equivNo<=maxNo; ++equivNo)
601 sampleNode =
fslices[equivNo]->GetNode();
623 size_t sliceNo, maxNo, equivNo;
628 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
634 equivNode = equivProxy->
GetNode();
636 if (maxNo != sliceNo)
638#ifdef G4GEOMETRY_VOXELDEBUG
639 G4cout <<
"**** G4SmartVoxelHeader::CollectEquivalentNodes" <<
G4endl
640 <<
" Collecting Nodes = "
641 << sliceNo <<
" - " << maxNo <<
G4endl;
645 for (equivNo=sliceNo+1; equivNo<=maxNo; ++equivNo)
647 delete fslices[equivNo]->GetNode();
670 size_t sliceNo, maxNo, equivNo;
671 size_t maxNode =
fslices.size();
675 for (sliceNo=0; sliceNo<maxNode; ++sliceNo)
682 if (maxNo != sliceNo)
688#ifdef G4GEOMETRY_VOXELDEBUG
689 G4cout <<
"**** G4SmartVoxelHeader::CollectEquivalentHeaders" <<
G4endl
690 <<
" Collecting Headers =";
692 for (equivNo=sliceNo+1; equivNo<=maxNo; ++equivNo)
694 sampleHeader =
fslices[equivNo]->GetHeader();
695 if ( (*sampleHeader) == (*equivHeader) )
697#ifdef G4GEOMETRY_VOXELDEBUG
716#ifdef G4GEOMETRY_VOXELDEBUG
753 size_t nCandidates = pCandidates->size();
754 size_t nVol, nNode, targetVolNo;
757#ifdef G4GEOMETRY_VOXELDEBUG
758 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
759 <<
" Limits = " << pLimits <<
G4endl
760 <<
" Axis = " << pAxis <<
G4endl
761 <<
" Candidates = " << nCandidates <<
G4endl;
770 motherMinExtent, motherMaxExtent) )
773 motherMinExtent, motherMaxExtent);
786 if (pParam ==
nullptr)
788 std::ostringstream message;
789 message <<
"PANIC! - Missing parameterisation." <<
G4endl
790 <<
" Replicated volume with no parameterisation object !";
791 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
809 for (nVol=0; nVol<nCandidates; ++nVol)
811 targetVolNo = (*pCandidates)[nVol];
812 if (replicated ==
false)
828 targetSolid = pParam->
ComputeSolid(targetVolNo,pDaughter);
843 targetMinExtent, targetMaxExtent))
846 targetMinExtent,targetMaxExtent);
848 minExtents[nVol] = targetMinExtent;
849 maxExtents[nVol] = targetMaxExtent;
851#ifdef G4GEOMETRY_VOXELDEBUG
852 G4cout <<
"---------------------------------------------------" <<
G4endl
854 <<
" Min Extent = " << targetMinExtent <<
G4endl
855 <<
" Max Extent = " << targetMaxExtent <<
G4endl
856 <<
"---------------------------------------------------" <<
G4endl;
861 if ( (!pLimits.
IsLimited()) && ((targetMaxExtent<=motherMinExtent)
862 ||(targetMinExtent>=motherMaxExtent)) )
864 std::ostringstream message;
865 message <<
"PANIC! - Overlapping daughter with mother volume." <<
G4endl
866 <<
" Daughter physical volume "
868 <<
" is entirely outside mother logical volume "
869 << pVolume->
GetName() <<
" !!";
870 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0002",
874#ifdef G4GEOMETRY_VOXELDEBUG
882 G4int kStraddlePercent = 5;
883 width = maxExtents[nVol]-minExtents[nVol];
884 if ( (((motherMinExtent-minExtents[nVol])*100/width) > kStraddlePercent)
885 ||(((maxExtents[nVol]-motherMaxExtent)*100/width) > kStraddlePercent) )
887 G4cout <<
"**** G4SmartVoxelHeader::BuildNodes" <<
G4endl
888 <<
" WARNING : Daughter # " << nVol
890 <<
" Crosses mother boundary of logical volume, name = "
892 <<
" by more than " << kStraddlePercent
905 for (nVol=0; nVol<nCandidates; ++nVol)
911 currentWidth = std::abs(maxExtents[nVol]-minExtents[nVol]);
912 if ( (currentWidth<minWidth)
916 minWidth = currentWidth;
923 G4double noNodesExactD = ((motherMaxExtent-motherMinExtent)*2.0/minWidth)+1.0;
928 G4double smartlessComputed = noNodesExactD / nCandidates;
930 G4double smartless = (smartlessComputed <= smartlessUser)
931 ? smartlessComputed : smartlessUser;
932 G4double noNodesSmart = smartless*nCandidates;
934 G4long noNodes = ((noNodesSmart-noNodesExactI)>=0.5)
935 ? noNodesExactI+1 : noNodesExactI;
936 if( noNodes == 0 ) { noNodes=1; }
938#ifdef G4GEOMETRY_VOXELDEBUG
939 G4cout <<
" Smartless computed = " << smartlessComputed <<
G4endl
940 <<
" Smartless volume = " << smartlessUser
941 <<
" => # Smartless = " << smartless <<
G4endl;
942 G4cout <<
" Min width = " << minWidth
943 <<
" => # Nodes = " << noNodes <<
G4endl;
949#ifdef G4GEOMETRY_VOXELDEBUG
953 G4double nodeWidth = (motherMaxExtent-motherMinExtent)/noNodes;
958 if (nodeList ==
nullptr)
960 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
964 nodeList->reserve(noNodes);
966 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
970 if (pNode ==
nullptr)
972 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
976 nodeList->push_back(pNode);
983 for (nVol=0; nVol<nCandidates; ++nVol)
985 G4long nodeNo, minContainingNode, maxContainingNode;
986 minContainingNode = (minExtents[nVol]-motherMinExtent)/nodeWidth;
987 maxContainingNode = (maxExtents[nVol]-motherMinExtent)/nodeWidth;
991 if ( (maxContainingNode>=0) && (minContainingNode<noNodes) )
996 if (maxContainingNode>=noNodes)
998 maxContainingNode = noNodes-1;
1003 if (minContainingNode<0)
1005 minContainingNode = 0;
1007 for (nodeNo=minContainingNode; nodeNo<=maxContainingNode; ++nodeNo)
1009 (*nodeList)[nodeNo]->Insert((*pCandidates)[nVol]);
1020 if (proxyList ==
nullptr)
1022 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1026 proxyList->reserve(noNodes);
1031 for (nNode=0;
G4long(nNode)<noNodes; ++nNode)
1035 ((*nodeList)[nNode])->Shrink();
1037 if (pProxyNode ==
nullptr)
1039 G4Exception(
"G4SmartVoxelHeader::BuildNodes()",
"GeomMgt0003",
1043 proxyList->push_back(pProxyNode);
1067 size_t nNodes = pSlice->size();
1068 size_t noContained, maxContained=0, sumContained=0, sumNonEmptyNodes=0;
1071 for (
size_t i=0; i<nNodes; ++i)
1073 if ((*pSlice)[i]->IsNode())
1077 node = (*pSlice)[i]->GetNode();
1082 sumContained += noContained;
1086 if (noContained>maxContained)
1088 maxContained = noContained;
1094 G4Exception(
"G4SmartVoxelHeader::CalculateQuality()",
"GeomMgt0001",
1101 if (sumNonEmptyNodes)
1103 quality = sumContained/sumNonEmptyNodes;
1110#ifdef G4GEOMETRY_VOXELDEBUG
1111 G4cout <<
"**** G4SmartVoxelHeader::CalculateQuality" <<
G4endl
1112 <<
" Quality = " << quality <<
G4endl
1113 <<
" Nodes = " << nNodes
1114 <<
" of which " << sumNonEmptyNodes <<
" non empty" <<
G4endl
1115 <<
" Max Contained = " << maxContained <<
G4endl;
1133 size_t refinedDepth=0, minVolumes;
1134 size_t maxNode =
fslices.size();
1151 switch (refinedDepth)
1166 size_t targetNo, noContainedDaughters, minNo, maxNo, replaceNo, i;
1176 for (targetNo=0; targetNo<maxNode; ++targetNo)
1180 targetNodeProxy =
fslices[targetNo];
1181 targetNode = targetNodeProxy->
GetNode();
1187 if (targetList ==
nullptr)
1191 "Target volume node list allocation error.");
1194 targetList->reserve(noContainedDaughters);
1195 for (i=0; i<noContainedDaughters; ++i)
1197 targetList->push_back(targetNode->
GetVolume(i));
1202#ifdef G4GEOMETRY_VOXELDEBUG
1203 G4cout <<
"**** G4SmartVoxelHeader::RefineNodes" <<
G4endl
1204 <<
" Refining nodes " << minNo
1205 <<
" - " << maxNo <<
" inclusive" <<
G4endl;
1217 for (replaceNo=minNo; replaceNo<=maxNo; ++replaceNo)
1219 if (lastProxy !=
fslices[replaceNo])
1231 newLimits = pLimits;
1235 targetList,replaceNo);
1236 if (replaceHeader ==
nullptr)
1238 G4Exception(
"G4SmartVoxelHeader::RefineNodes()",
"GeomMgt0003",
1245 if (replaceHeaderProxy ==
nullptr)
1247 G4Exception(
"G4SmartVoxelHeader::RefineNodes()",
"GeomMgt0003",
1251 for (replaceNo=minNo; replaceNo<=maxNo; ++replaceNo)
1253 fslices[replaceNo] = replaceHeaderProxy;
1274 size_t noSlices =
fslices.size();
1280 for (
size_t i=1; i<noSlices; ++i)
1299 G4int collectNodeNo = 0;
1300 G4int collectHeadNo = 0;
1302 G4bool haveHeaders =
false;
1304 for (i=0; i<h.
fslices.size(); ++i)
1306 os <<
"Slice #" << i <<
" = ";
1309 if (h.
fslices[i]!=collectNode)
1312 for (
size_t k=0; k<h.
fslices[i]->GetNode()->GetNoContained(); ++k)
1314 os <<
" " << h.
fslices[i]->GetNode()->GetVolume(k);
1322 os <<
"As slice #" << collectNodeNo <<
G4endl;
1328 if (h.
fslices[i] != collectHead)
1330 os <<
"Header" <<
G4endl;
1336 os <<
"As slice #" << collectHeadNo <<
G4endl;
1343 collectHead=
nullptr;
1344 for (j=0; j<h.
fslices.size(); ++j)
1348 os <<
"Header at Slice #" << j <<
" = ";
1349 if (h.
fslices[j] != collectHead)
1352 << (*(h.
fslices[j]->GetHeader()));
1358 os <<
"As slice #" << collectHeadNo <<
G4endl;
static const G4double emax
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4GLOB_DLL std::ostream G4cout
G4VSolid * GetSolid() const
size_t GetNoDaughters() const
G4double GetSmartless() const
G4VPhysicalVolume * GetDaughter(const G4int i) const
const G4String & GetName() const
G4int GetMaxEquivalentSliceNo() const
G4int GetVolume(G4int pVolumeNo) const
void SetMaxEquivalentSliceNo(G4int pMax)
void SetMinEquivalentSliceNo(G4int pMin)
std::size_t GetNoContained() const
G4int GetMinEquivalentSliceNo() const
G4SmartVoxelNode * GetNode() const
G4SmartVoxelHeader * GetHeader() const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
virtual void ComputeTransformation(const G4int, G4VPhysicalVolume *) const =0
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)
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
std::ostream & operator<<(std::ostream &, const BasicVector3D< float > &)
static const G4double kInfinity
const G4int kMaxVoxelNodes
const G4int kMinVoxelVolumesLevel3
const G4int kMinVoxelVolumesLevel2