25 #include "CreateSeedsOnSurface.hpp"
26 #include "Lattice.hpp"
27 #include "SkdTreeUtils.hpp"
42 m_name =
"mimmo.CreateSeedsOnSurface";
45 m_seed = {{0.0,0.0,0.0}};
47 m_seedbaricenter =
false;
48 m_randomFixed =
false;
49 m_randomSignature = 1;
50 m_bbox = std::unique_ptr<mimmo::OBBox> (
new mimmo::OBBox());
59 m_name =
"mimmo.CreateSeedsOnSurface";
62 m_seed = {{0.0,0.0,0.0}};
64 m_seedbaricenter =
false;
65 m_randomFixed =
false;
66 m_randomSignature = 1;
67 m_bbox = std::unique_ptr<mimmo::OBBox> (
new mimmo::OBBox());
69 std::string fallback_name =
"ClassNONE";
70 std::string input = rootXML.get(
"ClassName", fallback_name);
71 input = bitpit::utils::string::trim(input);
72 if(input ==
"mimmo.CreateSeedsOnSurface"){
89 m_points = other.m_points;
90 m_nPoints = other.m_nPoints;
91 m_minDist = other.m_minDist;
92 m_seed = other.m_seed;
93 m_engine = other.m_engine;
94 m_seedbaricenter = other.m_seedbaricenter;
95 m_randomFixed = other.m_randomFixed;
96 m_randomSignature = other.m_randomSignature;
97 m_sensitivity = other.m_sensitivity;
98 m_bbox = std::unique_ptr<mimmo::OBBox>(
new mimmo::OBBox(*(other.m_bbox.get())));
116 std::swap(m_points, x.m_points);
117 std::swap(m_nPoints, x.m_nPoints);
118 std::swap(m_minDist, x.m_minDist);
119 std::swap(m_seed, x.m_seed);
120 std::swap(m_engine, x.m_engine);
121 std::swap(m_seedbaricenter, x.m_seedbaricenter);
122 std::swap(m_randomFixed, x.m_randomFixed);
123 std::swap(m_randomSignature, x.m_randomSignature);
124 std::swap(m_deads, x.m_deads);
125 m_sensitivity.swap(x.m_sensitivity);
126 std::swap(m_bbox, x.m_bbox);
127 std::swap(m_final_sensitivity, x.m_final_sensitivity);
185 return static_cast<int>(m_engine);
206 return m_seedbaricenter;
227 return m_randomFixed;
238 return long(m_randomSignature);
247 m_nPoints = std::max(val,0);
265 if(eng <0 || eng >2) eng = 2;
287 m_seedbaricenter = flag;
298 if(geo ==
nullptr)
return;
299 if(geo->getType() != 1)
return;
329 m_randomSignature = signature;
341 m_sensitivity = *field;
352 m_seed = {{0.0,0.0,0.0}};
354 m_seedbaricenter =
false;
355 m_randomFixed =
false;
356 m_randomSignature =1;
358 m_sensitivity.
clear();
359 m_final_sensitivity.clear();
389 (*m_log)<<
"Error in " +
m_name +
" : nullptr pointer to linked geometry found"<<std::endl;
390 throw std::runtime_error(
m_name +
"nullptr pointer to linked geometry found");
401 (*m_log)<<
"Error in " +
m_name +
" : globally empty surface found, impossible to seed points "<<std::endl;
402 throw std::runtime_error(
m_name +
" : globally empty surface found, impossible to seed points ");
409 if(m_seedbaricenter) m_seed = m_bbox->getOrigin();
442 CreateSeedsOnSurface::solveLSet(
bool debug){
447 bitpit::log::Priority oldP =
m_log->getPriority();
448 m_log->setPriority(bitpit::log::Priority::NORMAL);
449 (*m_log)<<
"Warning in "<<
m_name<<
" : LevelSet option is not available in MPI version with np > 1. Switch to another engine."<<std::endl;
450 m_log->setPriority(oldP);
455 if(debug) (*m_log)<<
m_name<<
" : started LevelSet engine"<<std::endl;
459 m_deads.reserve(m_nPoints);
462 MimmoSharedPointer<MimmoObject> workgeo;
466 worksensitivity = &m_sensitivity_triangulated;
469 worksensitivity = &m_sensitivity;
472 workgeo->updateAdjacencies();
473 workgeo->buildSkdTree();
474 bitpit::SurfUnstructured * tri =
static_cast<bitpit::SurfUnstructured *
>(workgeo->getPatch());
478 long candidateIdv = bitpit::Vertex::NULL_ID;
480 double distance = std::numeric_limits<double>::max();
481 long cellId = bitpit::Cell::NULL_ID;
485 if(cellId != bitpit::Cell::NULL_ID){
486 bitpit::ConstProxyVector<long> cellVids = tri->getCell(cellId).getVertexIds();
487 double mindist = std::numeric_limits<double>::max();
489 for(
long idV : cellVids){
490 wdist = norm2(pseed - workgeo->getVertexCoords(idV));
499 if(candidateIdv != bitpit::Vertex::NULL_ID) m_deads.push_back(candidateIdv);
501 int deadSize = m_deads.size();
502 if(debug) (*m_log)<<
m_name<<
" : projected seed point"<<std::endl;
504 std::unordered_map<long,long> invConn = getInverseConn(*(workgeo->getPatch()));
505 if(debug) (*m_log)<<
m_name<<
" : created geometry inverse connectivity"<<std::endl;
507 while(deadSize < m_nPoints && deadSize != 0){
511 for(
const auto & dd : m_deads) field[dd] = 0.0;
513 solveEikonal(1.0,1.0, *(workgeo->getPatch()), invConn, field);
516 auto itSE=worksensitivity->end();
517 for(
auto itSX =worksensitivity->begin(); itSX != itSE; ++itSX){
518 field[itSX.getId()] *= *itSX;
521 double maxField= 0.0;
523 auto itE=field.end();
524 for(
auto itX =field.begin(); itX != itE; ++itX){
527 candMax = itX.getId();
531 m_deads.push_back(candMax);
533 deadSize = m_deads.size();
534 if(debug) (*m_log)<<
m_name<<
" : geodesic distance field for point "<<deadSize-1<<
" found"<<std::endl;
539 m_final_sensitivity.clear();
540 m_points.reserve(deadSize);
541 m_final_sensitivity.reserve(deadSize);
542 for(
const auto & val: m_deads){
543 m_points.push_back(tri->getVertexCoords(val));
544 m_final_sensitivity.push_back(worksensitivity->at(val));
547 m_minDist = std::numeric_limits<double>::max();
549 for(
int i=0; i<deadSize; ++i){
550 for(
int j=i+1; j<deadSize; ++j){
551 m_minDist = std::min(m_minDist,norm2(m_points[i] - m_points[j]));
556 m_sensitivity_triangulated.
clear();
557 if(debug) (*m_log)<<
m_name<<
" : distribution of point successfully found w/ LevelSet engine "<<std::endl;
568 CreateSeedsOnSurface::solveGrid(
bool debug){
571 if(debug) (*m_log)<<
m_name<<
" : started CartesianGrid engine"<<std::endl;
577 m_minDist = norm2(span)/2.0;
578 double perim = span[0]+span[1]+span[2];
580 for(
int i=0; i<3; ++i){
581 dim[i] = std::max(dim[i],
int(span[i]*m_nPoints/perim + 0.5));
590 grid->setOrigin(m_bbox->getOrigin());
591 grid->setSpan(m_bbox->getSpan());
592 grid->setRefSystem(m_bbox->getAxes());
593 grid->setDimension(dim);
599 dvecarr3E centroids = grid->getGlobalCellCentroids();
601 if(debug) (*m_log)<<
m_name<<
" : build volume cartesian grid wrapping 3D surface"<<std::endl;
606 dvecarr3E projCentroids(centroids.size());
607 dvector1D projSensitivity(centroids.size(), 1.0);
612 int currentRank = getRank();
613 skdTreeUtils::projectPointGlobal(
int(centroids.size()), centroids.data(),
getGeometry()->getSkdTree(), projCentroids.data(), ids.data(), ranks.data(), m_minDist,
true);
623 if(currentRank == ranks[count])
626 bitpit::ConstProxyVector<long> cellVids =
getGeometry()->getPatch()->getCell(ids[count]).getVertexIds();
628 listv.reserve(cellVids.size());
629 for(
long id: cellVids){
630 listv.push_back(
getGeometry()->getVertexCoords(
id));
633 bitpit::CGElem::computeGeneralizedBarycentric(p, listv, lambdas);
634 projSensitivity[count] = 0;
636 for(
long id: cellVids){
637 projSensitivity[count] += lambdas[ccvids] * m_sensitivity[id];
646 MPI_Allreduce(MPI_IN_PLACE, projSensitivity.data(),
int(projSensitivity.size()), MPI_DOUBLE, MPI_MIN, m_communicator);
650 if(debug) (*m_log)<<
m_name<<
" : found grid cell centers in the narrow band of 3D surface and projected them on it "<<std::endl;
657 std::vector<std::pair<double, int>> sortContainer;
658 sortContainer.reserve(projCentroids.size());
661 sortContainer.push_back(std::make_pair(norm2(m_seed - p), cc));
664 std::sort(sortContainer.begin(), sortContainer.end());
669 for(std::pair<double,int> & val : sortContainer){
670 tempP[cc] = projCentroids[val.second];
671 tempS[cc] = projSensitivity[val.second];
674 std::swap(projCentroids, tempP);
675 std::swap(projSensitivity, tempS);
678 decimatePoints(projCentroids, projSensitivity);
679 if(debug) (*m_log)<<
m_name<<
" : candidates decimated "<<std::endl;
682 std::swap(m_points, projCentroids);
683 std::swap(m_final_sensitivity, projSensitivity);
684 if(debug) (*m_log)<<
m_name<<
" : distribution of point successfully found w/ CartesianGrid engine "<<std::endl;
696 CreateSeedsOnSurface::solveRandom(
bool debug){
698 if(debug) (*m_log)<<
m_name<<
" : started Random engine"<<std::endl;
701 m_minDist = norm2(span)/ 2.0;
706 darray3E minP = m_bbox->getOrigin();
707 for(
int i=0; i<3; ++i) {minP += - 0.5*span[i]*axes[i];}
710 m_randomSignature = uint32_t(time(
nullptr));
713 MPI_Bcast(&m_randomSignature, 1, MPI_UINT32_T, 0, m_communicator);
716 rgen.seed(m_randomSignature);
717 double dist_rgen = double(rgen.max()-rgen.min());
718 double beg_rgen = double(rgen.min());
720 int nTent = 5*m_nPoints;
721 centroids.resize(nTent, minP);
723 for(
int i = 0; i<nTent; ++i){
724 for(
int j=0; j<3; ++j){
725 double valrand = (double(rgen())-beg_rgen)/dist_rgen;
726 centroids[i] += valrand * span[j]*axes[j];
731 if(debug) (*m_log)<<
m_name<<
" : found random points"<<std::endl;
735 dvecarr3E projCentroids(centroids.size());
736 dvector1D projSensitivity(centroids.size(), 1.0);
738 livector1D ids(centroids.size(), bitpit::Cell::NULL_ID);
741 int currentRank = getRank();
742 skdTreeUtils::projectPointGlobal(
int(centroids.size()), centroids.data(),
getGeometry()->getSkdTree(), projCentroids.data(), ids.data(), ranks.data(), m_minDist,
true);
752 if(currentRank == ranks[count])
755 bitpit::ConstProxyVector<long> cellVids =
getGeometry()->getPatch()->getCell(ids[count]).getVertexIds();
757 listv.reserve(cellVids.size());
758 for(
long id: cellVids){
759 listv.push_back(
getGeometry()->getVertexCoords(
id));
761 std::vector<double> lambdas;
762 bitpit::CGElem::computeGeneralizedBarycentric(p, listv, lambdas);
763 projSensitivity[count] = 0;
765 for(
long id: cellVids){
766 projSensitivity[count] += lambdas[ccvids] * m_sensitivity[id];
775 MPI_Allreduce(MPI_IN_PLACE, projSensitivity.data(),
int(projSensitivity.size()), MPI_DOUBLE, MPI_MIN, m_communicator);
779 if(debug) (*m_log)<<
m_name<<
" : projected points onto 3D surface "<<std::endl;
786 std::vector<std::pair<double, int>> sortContainer;
787 sortContainer.reserve(projCentroids.size());
790 sortContainer.push_back(std::make_pair(norm2(m_seed - p), cc));
793 std::sort(sortContainer.begin(), sortContainer.end());
798 for(std::pair<double,int> & val : sortContainer){
799 tempP[cc] = projCentroids[val.second];
800 tempS[cc] = projSensitivity[val.second];
803 std::swap(projCentroids, tempP);
804 std::swap(projSensitivity, tempS);
807 decimatePoints(projCentroids, projSensitivity);
808 if(debug) (*m_log)<<
m_name<<
" : candidates decimated "<<std::endl;
811 std::swap(m_points, projCentroids);
812 std::swap(m_final_sensitivity, projSensitivity);
813 if(debug) (*m_log)<<
m_name<<
" : distribution of point successfully found w/ Random engine "<<std::endl;
828 if(m_points.empty())
return;
836 bitpit::VTKFormat codex = bitpit::VTKFormat::ASCII;
837 if(binary){codex=bitpit::VTKFormat::APPENDED;}
840 for(
int i=0; i<m_nPoints; i++){
844 m_final_sensitivity.resize(m_nPoints, 1.0);
846 for(
int i=0; i<m_nPoints; ++i){
850 bitpit::VTKUnstructuredGrid vtk(dir, file, bitpit::VTKElementType::VERTEX);
851 vtk.setGeomData( bitpit::VTKUnstructuredField::POINTS, m_points) ;
852 vtk.setGeomData( bitpit::VTKUnstructuredField::CONNECTIVITY, conn) ;
853 vtk.setDimensions( m_nPoints, m_nPoints);
854 vtk.addData(
"sensitivity", bitpit::VTKFieldType::SCALAR, bitpit::VTKLocation::POINT, m_final_sensitivity);
855 vtk.addData(
"labels", bitpit::VTKFieldType::SCALAR, bitpit::VTKLocation::POINT,labels);
857 if(counter>=0){vtk.setCounter(counter);}
862 MPI_Barrier(m_communicator);
878 int listS = list.size();
883 for(
int j=0; j<listS; ++j){
884 listRefer[j] = (list[j] - list[0])*sens[j];
887 bitpit::KdTree<3,darray3E,long> kdT;
890 kdT.nodes.resize(listS + kdT.MAXSTK);
892 for(
auto & val : listRefer ){
893 kdT.insert(&val, label);
902 std::set<long> visited;
903 std::map<double, long> chooseCand;
906 finalCandidates.reserve(m_nPoints);
907 int candSize = finalCandidates.size();
908 while( candSize < m_nPoints){
910 finalCandidates.push_back(candidate);
912 visited.insert(candidate);
913 excl.insert(excl.end(), visited.begin(), visited.end());
914 kdT.hNeighbors(&listRefer[candidate], m_minDist, &neighs, & excl );
916 visited.insert(neighs.begin(), neighs.end());
918 int sizeN = visited.size();
923 while(sizeN == listS){
926 visited.insert(finalCandidates.begin(), finalCandidates.end());
927 for(
const auto & ind : finalCandidates){
928 excl.insert(excl.end(), visited.begin(), visited.end());
929 kdT.hNeighbors(&listRefer[ind], m_minDist, &neighs, & excl );
930 visited.insert(neighs.begin(), neighs.end());
932 sizeN = visited.size();
937 effective.reserve(list.size() - visited.size());
938 for(
int i=0; i< listS; ++i){
939 if( !visited.count(i) )
940 effective.push_back(i);
943 for(
const auto & ind : effective){
946 for(
const auto & indEx: finalCandidates){
947 norms[countNorms] = norm2(list[ind] - list[indEx]);
951 double norm = 0.0, variance=0.0;
952 for(
auto &val : norms) norm += val;
953 norm /= double(norms.size());
954 for(
auto &val : norms) val = std::abs(val/norm - 1.0);
955 maxval(norms, variance);
956 norm /= std::pow((variance+1.0),2);
958 chooseCand[norm] = ind;
961 candidate = (chooseCand.rbegin())->second;
967 dvecarr3E resultP(finalCandidates.size());
968 dvector1D resultS(finalCandidates.size());
970 for(
long index : finalCandidates){
971 resultP[counter] = list[index];
972 resultS[counter] = sens[index];
975 std::swap(list, resultP);
976 std::swap(sens, resultS);
994 CreateSeedsOnSurface::updateEikonal(
double g,
double s,
long tVert,
long tCell, bitpit::PatchKernel &tri, std::unordered_map<long int, short int> &flag,
dmpvector1D & field){
1004 double value(std::numeric_limits<double>::max());
1005 double dVU, dVW, dWU, dVP;
1006 std::array<double,3> eVU, eVW, eWU, eVP, P;
1009 double a, b, c, A, B, C, K, discr ;
1010 double phi_U, phi_W, phi_P;
1014 double tempVal1, tempVal2;
1017 value = std::abs(field[tVert]);
1023 bitpit::Cell & targetCell = tri.getCell(tCell);
1024 int locVert = targetCell.findVertex(tVert);
1025 if(locVert == bitpit::Vertex::NULL_ID)
return value;
1026 oneRing = tri.findCellVertexOneRing(tCell, locVert);
1030 for (
auto && oneIndex : oneRing) {
1034 bitpit::Cell & cellI = tri.getCell(I);
1035 long * connCellI = cellI.getConnect();
1036 k = cellI.findVertex(V);
1037 k = (k + 1) % cellI.getVertexCount();
1039 m = (k + 1) % cellI.getVertexCount();
1043 if ((flag[U] == 0) && (flag[W] == 0)) {
1047 if ((flag[U] == 0) || (flag[W] == 0)) {
1062 eVU = tri.getVertexCoords(V) - tri.getVertexCoords(U);
1064 value = std::min(value, std::abs(field[U]) + g*dVU);
1069 eVW = tri.getVertexCoords(V) - tri.getVertexCoords(W);
1072 eVU = tri.getVertexCoords(V) - tri.getVertexCoords(U);
1075 eWU = tri.getVertexCoords(W) - tri.getVertexCoords(U);
1080 phi_U = std::abs(field[U]);
1081 phi_W = std::abs(field[W]);
1084 b = -dWU*dVU*dotProduct(eWU, eVU);
1086 A = a*(pow(K, 2) - a);
1087 B = b*(pow(K, 2) - a);
1088 C = (pow(K, 2)*c - pow(b, 2));
1089 discr = pow(B, 2) - A*C;
1092 discrType = (discr < -1.0e-12) + 2*(std::abs(A) > 1.0e-12) +3*((std::abs(A) < 1.0e-12) && (std::abs(A) >= 0.0)) -1;
1096 discr = std::abs(discr);
1098 xi1 = (-B - sqrt(discr))/A;
1099 xi2 = (-B + sqrt(discr))/A;
1102 xi1 = std::min(1.0, std::max(0.0, xi1));
1103 xi2 = std::min(1.0, std::max(0.0, xi2));
1106 P = (1.0 - xi1) * tri.getVertexCoords(U) + xi1 * tri.getVertexCoords(W);
1107 eVP = tri.getVertexCoords(V) - P;
1110 phi_P = (1.0 - xi1) * phi_U + xi1 * phi_W;
1111 tempVal1 = phi_P + g * dVP;
1114 P = (1.0 - xi2) * tri.getVertexCoords(U) + xi2 * tri.getVertexCoords(W);
1115 eVP = tri.getVertexCoords(V) - P;
1118 phi_P = (1.0 - xi2) * phi_U + xi2 * phi_W;
1119 tempVal2 = phi_P + g * dVP;
1124 discr = std::abs(discr);
1127 P = tri.getVertexCoords(U);
1128 eVP = tri.getVertexCoords(V) - P;
1132 tempVal1 = phi_P + g*dVP;
1135 P = tri.getVertexCoords(W);
1136 eVP = tri.getVertexCoords(V) - P;
1140 tempVal2 = phi_P + g*dVP;
1151 value = std::min(value, std::min(tempVal1, tempVal2));
1175 CreateSeedsOnSurface::solveEikonal(
double g,
double s,bitpit::PatchKernel &tri, std::unordered_map<long,long> & invConn,
dmpvector1D & field ){
1178 long N(tri.getVertexCount());
1179 std::unordered_map<long int, short int> active;
1181 std::unordered_map<long, int> vmap;
1183 for(
const auto & vert: tri.getVertices()){
1184 vmap[vert.getId()] = countV;
1192 std::set<long> neighs;
1193 std::set<long>::iterator it, itend;
1197 for (
const auto &vertex : tri.getVertices() ){
1198 myId = vertex.getId() ;
1203 for (
const auto &vertex : tri.getVertices() ){
1204 myId = vertex.getId();
1207 if( isDeadFront(myId) ){
1214 neighs = findVertexVertexOneRing(tri,invConn[myId], myId);
1215 it = neighs.begin();
1216 itend = neighs.end();
1217 while(!check && it !=itend){
1219 check = s*field[*it] >= 0.0 && field[*it] < std::numeric_limits<double>::max();
1223 active[myId] = 2 - (int) check;
1230 long m(0), I(0), myId, J ;
1233 std::set<long> neighs;
1234 std::set<long>::iterator it,itbeg, itend;
1236 std::vector<std::array<int,2>> map(N), *mapPtr = ↦
1238 bitpit::MinPQueue<double, long> heap(N,
true, mapPtr);
1242 for(
const auto & vertex : tri.getVertices()){
1244 myId = vertex.getId();
1245 if(active[myId] == 1) {
1247 value = updateEikonal(s, g, myId, invConn[myId], tri, active, field);
1250 map[m][0] = vmap[myId];
1251 map[vmap[myId]][1] = m;
1253 heap.keys[m] = value;
1254 heap.labels[m] = myId;
1268 while (heap.heap_size > 0) {
1271 heap.extract(value, myId);
1275 field[myId] = value;
1281 neighs = findVertexVertexOneRing(tri, invConn[myId], myId);
1282 itbeg = neighs.begin();
1283 itend = neighs.end();
1285 for(it=itbeg; it != itend; ++it) {
1291 value = updateEikonal(s,g,J,invConn[J], tri, active, field);
1295 heap.modify( map[I][1],value,J );
1297 }
else if( active[J] == 2){
1300 value = updateEikonal(s,g,J, invConn[J],tri, active, field);
1307 map[heap.heap_size][0] = I ;
1308 map[I][1] = heap.heap_size;
1310 heap.insert(value, J);
1326 std::unordered_map<long,long>
1327 CreateSeedsOnSurface::getInverseConn(bitpit::PatchKernel & geo){
1329 std::unordered_map<long,long> invConn ;
1332 for(
const auto &cell : geo.getCells()){
1333 cellId = cell.getId();
1334 auto vList = cell.getVertexIds();
1335 for(
const auto & idV : vList) invConn[idV] = cellId;
1346 bool CreateSeedsOnSurface::isDeadFront(
const long int label){
1348 livector1D::iterator got = std::find(m_deads.begin(), m_deads.end(), label);
1349 if(got == m_deads.end())
return false;
1361 CreateSeedsOnSurface::findVertexVertexOneRing(bitpit::PatchKernel &geo,
const long & cellId,
const long & vertexId){
1363 std::set<long> result;
1364 bitpit::Cell &cell = geo.getCell(cellId);
1366 int loc_target = cell.findVertex(vertexId);
1367 if(loc_target == bitpit::Vertex::NULL_ID)
return result;
1369 livector1D list = geo.findCellVertexOneRing(cellId, loc_target);
1371 for(
const auto & index : list){
1372 bitpit::Cell & cell = geo.getCell(index);
1373 auto vList = cell.getVertexIds();
1374 for(
const auto & idV : vList){
1379 result.erase(vertexId);
1391 BITPIT_UNUSED(name);
1395 if(slotXML.hasOption(
"NPoints")){
1396 std::string input = slotXML.get(
"NPoints");
1397 input = bitpit::utils::string::trim(input);
1400 std::stringstream ss(input);
1402 value = std::max(value,0);
1407 if(slotXML.hasOption(
"Engine")){
1408 std::string input = slotXML.get(
"Engine");
1409 input = bitpit::utils::string::trim(input);
1412 std::stringstream ss(input);
1414 value = std::min(std::max(value,0),2);
1420 if(slotXML.hasOption(
"Seed")){
1421 std::string input = slotXML.get(
"Seed");
1422 input = bitpit::utils::string::trim(input);
1426 std::stringstream ss(input);
1427 ss >> temp[0]>>temp[1]>>temp[2];
1432 if(slotXML.hasOption(
"MassCenterAsSeed")){
1433 std::string input = slotXML.get(
"MassCenterAsSeed");
1434 input = bitpit::utils::string::trim(input);
1437 std::stringstream ss(input);
1443 if(slotXML.hasOption(
"RandomFixed")){
1444 std::string input = slotXML.get(
"RandomFixed");
1445 input = bitpit::utils::string::trim(input);
1448 std::stringstream ss(input);
1465 BITPIT_UNUSED(name);
1469 if(m_nPoints != 0 ){
1470 slotXML.set(
"NPoints", std::to_string(m_nPoints));
1475 slotXML.set(
"Engine", std::to_string(engint));
1479 if(norm2(seed) != 0.0 ){
1481 std::stringstream ss;
1482 ss<<std::scientific<<seed[0]<<
'\t'<<seed[1]<<
'\t'<<seed[2];
1483 slotXML.set(
"Seed", ss.str());
1487 slotXML.set(
"MassCenterAsSeed", std::to_string(1));
1492 slotXML.set(
"RandomFixed", std::to_string(signat));
1514 m_sensitivity = defaultField;
1517 m_sensitivity = defaultField;
1521 m_sensitivity = defaultField;
1536 double minSense=0.0,maxSense=0.0;
1539 double diff = maxSense - minSense;
1542 if(std::isnan(minSense) || std::isnan(maxSense) || diff <= std::numeric_limits<double>::min()){
1543 (*m_log)<<
"Warning in "<<
m_name<<
" : Not valid data of sensitivity field detected. Using default unitary field"<<std::endl;
1546 for(
auto &val: m_sensitivity){
1547 val += -1.0*minSense;
1562 bitpit::PatchKernel::CellIterator it =
getGeometry()->getPatch()->cellBegin();
1563 bitpit::PatchKernel::CellIterator itEnd =
getGeometry()->getPatch()->cellEnd();
1564 while(check && it != itEnd){
1565 check = ( (*it).getType() == bitpit::ElementType::TRIANGLE );
1579 m_sensitivity_triangulated = m_sensitivity;
1581 temp->triangulate();
1584 int nResidual = temp->getNVertices() -
getGeometry()->getNVertices();
1588 missingIds.reserve(nResidual);
1589 bitpit::PiercedVector<bitpit::Vertex> & originalPV =
getGeometry()->getVertices();
1590 for(
auto it=m_sensitivity_triangulated.begin(); it != m_sensitivity_triangulated.end(); ++it){
1591 if(!originalPV.exists(it.getId())) missingIds.push_back(it.getId());
1594 temp->updateAdjacencies();
1595 std::unordered_map<long,long> invConn = getInverseConn(*(temp->getPatch()));
1597 for(
long id : missingIds){
1598 pcoord = temp->getVertexCoords(
id);
1599 std::set<long> ring = findVertexVertexOneRing(*(temp->getPatch()), invConn[
id],
id);
1601 for(
long idR : ring){
1602 w = 1.0/norm2(pcoord - temp->getVertexCoords(idR));
1604 m_sensitivity_triangulated[id] += (w * m_sensitivity_triangulated[idR]);
1606 m_sensitivity_triangulated[id] /= wtot;