284 targetList.reserve(nReplicas);
285 for (
auto i=0; i<nReplicas; ++i)
287 targetList.push_back(i);
346 G4Exception(
"G4SmartVoxelHeader::BuildReplicaVoxels()",
356 G4double emin = kInfinity, emax = -kInfinity;
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",
443 G4ProxyVector *pGoodSlices=
nullptr, *pTestSlices, *tmpSlices;
444 G4double goodSliceScore=kInfinity, testSliceScore;
447 std::size_t node, maxNode, iaxis;
452 for (iaxis=0; iaxis<3; ++iaxis)
468 pTestSlices =
BuildNodes(pVolume,pLimits,pCandidates,testAxis);
470 if ( (pGoodSlices ==
nullptr) || (testSliceScore<goodSliceScore) )
472 goodSliceAxis = testAxis;
473 goodSliceScore = testSliceScore;
474 tmpSlices = pGoodSlices;
475 pGoodSlices = pTestSlices;
476 pTestSlices = tmpSlices;
478 if (pTestSlices !=
nullptr)
482 maxNode=pTestSlices->size();
483 for (node=0; node<maxNode; ++node)
485 delete (*pTestSlices)[node]->GetNode();
488 while (!pTestSlices->empty())
490 tmpProx = pTestSlices->back();
491 pTestSlices->pop_back();
492 for (
auto i=pTestSlices->cbegin(); i!=pTestSlices->cend(); )
496 i = pTestSlices->erase(i);
512 if (pGoodSlices ==
nullptr)
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)
746 G4double motherMinExtent= kInfinity, motherMaxExtent= -kInfinity,
747 targetMinExtent= kInfinity, targetMaxExtent= -kInfinity;
753 std::size_t nCandidates = pCandidates->size();
754 std::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];
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;
933 auto noNodesExactI =
G4int(noNodesSmart);
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 std::size_t nNodes = pSlice->size();
1068 std::size_t noContained, maxContained=0, sumContained=0, sumNonEmptyNodes=0;
1071 for (std::size_t i=0; i<nNodes; ++i)
1073 if ((*pSlice)[i]->IsNode())
1077 node = (*pSlice)[i]->GetNode();
1079 if (noContained != 0)
1082 sumContained += noContained;
1086 if (noContained>maxContained)
1088 maxContained = noContained;
1094 G4Exception(
"G4SmartVoxelHeader::CalculateQuality()",
"GeomMgt0001",
1101 if (sumNonEmptyNodes != 0)
1103 quality = sumContained/sumNonEmptyNodes;
1107 quality = kInfinity;
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 std::size_t refinedDepth=0, minVolumes;
1134 std::size_t maxNode =
fslices.size();
1151 switch (refinedDepth)
1166 std::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)
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,(
G4int)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;