MRBF.cpp
1 /*---------------------------------------------------------------------------*\
2  *
3  * mimmo
4  *
5  * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6  *
7  * -------------------------------------------------------------------------
8  * License
9  * This file is part of mimmo.
10  *
11  * mimmo is free software: you can redistribute it and/or modify it
12  * under the terms of the GNU Lesser General Public License v3 (LGPL)
13  * as published by the Free Software Foundation.
14  *
15  * mimmo is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with mimmo. If not, see <http://www.gnu.org/licenses/>.
22  *
23  \ *---------------------------------------------------------------------------*/
24 
25 #include "MRBF.hpp"
26 
27 namespace mimmo{
28 
29  //TODO study how to manipulate supportRadius of RBF to define a local/global smoothing of RBF
30 
33  m_name = "mimmo.MRBF";
34  setMode(mode);
35  m_maxFields=-1;
36  m_tol = 1.0E-06;
37  m_bfilter = false;
38  m_supportRadiusValue = -1.0;
39  m_srIsReal = false;
40  m_functype = -1;
41  m_isCompact = false;
42  m_rbfgeometry = nullptr;
43  m_rbfdispl = nullptr;
44  m_rbfScalarDispl = nullptr;
45  m_rbfSupportRadii = nullptr;
46  m_diagonalFactor = 1.0;
47  m_areScalarResults = false;
48 };
49 
54 MRBF::MRBF(const bitpit::Config::Section & rootXML){
55 
56  m_name = "mimmo.MRBF";
57  m_maxFields=-1;
58  m_tol = 1.0E-06;
59  m_bfilter = false;
60  m_supportRadiusValue = -1.0;
61  m_srIsReal = false;
62  m_functype = -1;
63  m_isCompact = false;
64  m_rbfgeometry = nullptr;
65  m_rbfdispl = nullptr;
66  m_rbfScalarDispl = nullptr;
67  m_rbfSupportRadii = nullptr;
68  m_diagonalFactor = 1.0;
69  m_areScalarResults = false;
70 
72 
73  std::string fallback_name = "ClassNONE";
74  std::string input = rootXML.get("ClassName", fallback_name);
75  input = bitpit::utils::string::trim(input);
76  if(input == "mimmo.MRBF"){
77  std::string fallback_mode = "0";
78  std::string input2 = rootXML.get("Mode", fallback_mode);
79  input2 = bitpit::utils::string::trim(input2);
80  int mode_int = std::stoi(input2);
81  mode_int = std::min(2, std::max(0, mode_int));
82  setMode(static_cast<MRBFSol>(mode_int));
83  absorbSectionXML(rootXML);
84  }else{
86  };
87 }
88 
91 
95 MRBF::MRBF(const MRBF & other):BaseManipulation(other), bitpit::RBF(other){
96  m_tol = other.m_tol;
97  m_solver = other.m_solver;
98  m_bfilter = other.m_bfilter;
100  m_srIsReal = other.m_srIsReal;
102  m_functype = other.m_functype;
103  m_isCompact = other.m_isCompact;
104  if(m_bfilter) m_filter = other.m_filter;
106  m_rbfdispl = other.m_rbfdispl;
111 };
112 
117  swap(other);
118  return *this;
119 };
120 
125 void MRBF::swap(MRBF & x) noexcept
126 {
127  std::swap(m_tol, x.m_tol);
128  std::swap(m_solver, x.m_solver);
129  m_filter.swap(x.m_filter);
130  std::swap(m_bfilter, x.m_bfilter);
131  std::swap(m_supportRadiusValue , x.m_supportRadiusValue);
132  std::swap(m_srIsReal, x.m_srIsReal);
133  std::swap(m_supportRadii, x.m_supportRadii);
134  std::swap(m_functype, x.m_functype);
135  std::swap(m_isCompact, x.m_isCompact);
136  m_displ.swap(x.m_displ);
137  m_scalarDispl.swap(x.m_scalarDispl);
138  std::swap(m_effectiveSR, x.m_effectiveSR);
139  std::swap(m_rbfgeometry, x.m_rbfgeometry);
140  std::swap(m_rbfdispl, x.m_rbfdispl);
141  std::swap(m_rbfScalarDispl, x.m_rbfScalarDispl);
142  std::swap(m_rbfSupportRadii, x.m_rbfSupportRadii);
143  std::swap(m_diagonalFactor, x.m_diagonalFactor);
144  std::swap(m_areScalarResults, x.m_areScalarResults);
145 
146  RBF::swap(x);
147 
149 }
150 
153 void
155  bool built = true;
156  built = (built && createPortIn<MimmoSharedPointer<MimmoObject>, MRBF>(&m_geometry, M_GEOM, true));
157  built = (built && createPortIn<dvecarr3E, MRBF>(this, &mimmo::MRBF::setNode, M_COORDS));
158  built = (built && createPortIn<dvecarr3E, MRBF>(this, &mimmo::MRBF::setDisplacements, M_DISPLS));
159  built = (built && createPortIn<std::vector<double>, MRBF>(this, &mimmo::MRBF::setScalarDisplacements, M_DATAFIELD));
160  built = (built && createPortIn<std::vector<double>, MRBF>(this, &mimmo::MRBF::setVariableSupportRadii, M_DATAFIELD2));
161  built = (built && createPortIn<dmpvector1D*, MRBF>(this, &mimmo::MRBF::setFilter, M_FILTER));
162  built = (built && createPortIn<MimmoSharedPointer<MimmoObject>, MRBF>(this, &mimmo::MRBF::setNode, M_GEOM2));
163  built = (built && createPortIn<dmpvecarr3E*, MRBF>(this, &mimmo::MRBF::setDisplacements, M_VECTORFIELD));
164  built = (built && createPortIn<dmpvector1D*, MRBF>(this, &mimmo::MRBF::setScalarDisplacements, M_SCALARFIELD));
165  built = (built && createPortIn<dmpvector1D*, MRBF>(this, &mimmo::MRBF::setVariableSupportRadii, M_SCALARFIELD2));
166 
167  built = (built && createPortOut<dmpvecarr3E*, MRBF>(this, &mimmo::MRBF::getDisplacements, M_GDISPLS));
168  built = (built && createPortOut<dmpvector1D*, MRBF>(this, &mimmo::MRBF::getScalarDisplacements, M_SCALARFIELD));
169  built = (built && createPortOut<MimmoSharedPointer<MimmoObject>, MRBF>(this, &BaseManipulation::getGeometry, M_GEOM));
170  m_arePortsBuilt = built;
171 };
172 
176 dvecarr3E*
178  return(&m_node);
179 }
180 
186 MRBFSol
188  return m_solver;
189 };
190 
196  return &m_filter;
197 };
198 
205 bool
207  return m_srIsReal;
208 }
209 
215 bool
217  return !m_supportRadii.empty();
218 }
219 
225 dvector1D &
227  return m_effectiveSR;
228 }
229 
235 double
237  return m_diagonalFactor;
238 }
239 
243 int
245  if(m_functype < 0){
246  return static_cast<int>(RBF::getFunctionType());
247  }else{
248  return m_functype;
249  }
250 }
251 
252 
263  if(m_areScalarResults) return nullptr;
264  else return &m_displ;
265 };
266 
277  if(m_areScalarResults) return &m_scalarDispl ;
278  else return nullptr;
279 };
280 
281 
290 bool
292  return m_areScalarResults;
293 }
294 
295 
300 bool
302  return m_isCompact;
303 }
304 
310 int
312  return(RBF::addNode(node));
313 };
314 
320 std::vector<int>
322  return(RBF::addNode(nodes));
323 };
324 
328 void
330  removeAllNodes();
331  RBF::addNode(node);
332  m_rbfgeometry = nullptr;
333 };
334 
338 void
340  removeAllNodes();
341  RBF::addNode(nodes);
342  m_rbfgeometry = nullptr;
343 };
344 
349 void
351  if(!geometry) return ;
352  m_rbfgeometry = geometry;
353 };
354 
359 void
361  if(!filter) return;
362  m_filter.clear();
363  m_bfilter = !(filter->empty());
364  m_filter = *filter;
365 };
366 
372 ivector1D
374  ivector1D marked;
375  int sizeEff = getTotalNodesCount();
376  if( sizeEff == 0 ) return marked;
377 
378  bvector1D check(sizeEff, false);
379 
380  for(int i=0; i<sizeEff; ++i){
381  for(int j=i+1; j<sizeEff; ++j){
382  double dist = norm2(m_node[j] - m_node[i]);
383  if(!check[j] && dist <= tol){
384  marked.push_back(i);
385  check[j] = true;
386  }
387  }
388  }
389  return(marked);
390 }
391 
397 bool
399  ivector1D marked;
400  if(list==nullptr){
401  marked = checkDuplicatedNodes();
402  list = &marked;
403  }
404  return(removeNode(*list));
405 }
406 
407 
418 void
420  suppR_ = std::max(-1.0,suppR_);
421  m_supportRadiusValue = suppR_;
422  m_srIsReal = false;
423  m_supportRadii.clear();
424 }
425 
426 
435 void
437  suppR_ = std::max(-1.0,suppR_);
438  m_supportRadiusValue = suppR_;
439  m_srIsReal = true;
440  m_supportRadii.clear();
441 }
442 
446 void
448  setSupportRadiusReal(suppR_);
449 }
450 
461 void
463  if(sradii.empty() || m_solver != MRBFSol::NONE) return;
464  m_supportRadii = sradii;
465  m_supportRadiusValue = -1.0;
466  m_srIsReal = false;
467 }
468 
475 void
477  if(!sradii || m_solver != MRBFSol::NONE) return;
478  m_rbfSupportRadii = sradii;
479  m_supportRadiusValue = -1.0;
480  m_srIsReal = false;
481 }
482 
488 void
489 MRBF::setDiagonalFactor(double diagonalFactor){
490  m_diagonalFactor = std::min(std::max(diagonalFactor, 0.), 1.);
491 }
492 
497 void
498 MRBF::setTol(double tol){
499  m_tol = tol;
500 }
501 
513 void
515  int size = displ.size();
516 
517  removeAllData();
518 
519  dvector1D temp(size);
520  for(int loc=0; loc<3; ++loc){
521  for(int i=0; i<size; ++i){
522  temp[i] = displ[i][loc];
523  }
524  addData(temp);
525  }
526 
527  m_rbfdispl = nullptr;
528  m_areScalarResults = false;
529 }
530 
542 void
544  if (!displ) return;
545  m_rbfdispl = displ;
546  m_areScalarResults = false;
547 }
548 
549 
561 void
563  removeAllData();
564  addData(displ);
565 
566  m_rbfScalarDispl = nullptr;
567  m_areScalarResults = true;
568 
569 }
570 
582 void
584  if (!displ) return;
585  m_rbfScalarDispl = displ;
586 }
587 
593 void
594 MRBF::setFunction( const MRBFBasisFunction &bfunc, bool isCompact )
595 {
596  switch(bfunc){
597 
599  RBF::setFunction(heaviside10);
600  m_functype = static_cast<int>(MRBFBasisFunction::HEAVISIDE10);
601  break;
602 
604  RBF::setFunction(heaviside50);
605  m_functype = static_cast<int>(MRBFBasisFunction::HEAVISIDE50);
606  break;
607 
609  RBF::setFunction(heaviside100);
610  m_functype = static_cast<int>(MRBFBasisFunction::HEAVISIDE100);
611  break;
612 
614  RBF::setFunction(heaviside1000);
615  m_functype = static_cast<int>(MRBFBasisFunction::HEAVISIDE1000);
616  break;
617 
619  RBF::setFunction(dsigmoid);
620  m_functype = static_cast<int>(MRBFBasisFunction::DSIGMOID);
621  break;
622 
623  default:
624  bitpit::RBF::setFunction(bitpit::RBFBasisFunction::WENDLANDC2);
625  m_functype = -1;
626  break;
627  }
628 
630 }
631 
637 void
638 MRBF::setFunction( const bitpit::RBFBasisFunction &bfunc, bool isCompact)
639 {
640  bitpit::RBF::setFunction(bfunc);
641  m_functype = -1;
643 }
644 
649 void
650 MRBF::setCompactSupport(bool isCompact)
651 {
653 }
654 
656 void
659  clearFilter();
660  m_tol = 0.00001;
661  m_supportRadiusValue = -1.0;
662  m_srIsReal = false;
663  m_supportRadii.clear();
664 };
665 
667 void
669  m_filter.clear();
670  m_bfilter = false;
671 };
672 
673 
674 
680 void
682 
684  if(container == nullptr){
685  (*m_log)<<m_name + " : nullptr pointer to linked geometry found"<<std::endl;
686  throw std::runtime_error(m_name + "nullptr pointer to linked geometry found");
687  }
688 
689  // If RBF nodes passed by MimmoObject initialize RBFs
690  if (m_rbfgeometry){
691  if (!initRBFwGeometry())
692  {
693  // Initialization not valid (log message written in method). Skip execution.
694  return;
695  }
696  }
697 
698  //prepare m_displ or m_scalarDispl according to m_areScalarResults;
699  m_displ.clear();
701  if(m_areScalarResults){
703  m_scalarDispl.reserve(getGeometry()->getNVertices());
705  }else{
707  m_displ.reserve(getGeometry()->getNVertices());
709  }
710 
711  //resize displacements.
712  int size = 0;
713  int sizeF = getDataCount();
714 
715  for (int i=0; i<sizeF; i++){
716 
717  if(m_solver == MRBFSol::NONE) size = m_weight[i].size();
718  else size = m_value[i].size();
719 
720  if(size != getTotalNodesCount()){
721  (*m_log) << "warning: " << getName() << " has displacements of " << i << " field with size (" << size << ") that does not fit number of RBF nodes ("<< getTotalNodesCount() << ")" << std::endl;
722  fitDataToNodes(i);
723  }
724  }
725 
726  //compute the support radius in m_effectiveSR
727  //and push homogeneous support radius info to the base class,
728  //in case of Mode WHOLE/GREEDY
730 
731  //calculate weights for interpolation modes. This is not required
732  // in parameterization mode MRBFSol::NONE.
733  if (m_solver == MRBFSol::WHOLE) solve();
734  if (m_solver == MRBFSol::GREEDY) greedy(m_tol);
735 
736 
737  // Prepare the list of vertices to be used during rbf evaluations
738  std::unordered_set<long> activeMeshVertices;
739 
740  // Use bounding box to decide if use the whole geometry or filter the vertices
741  std::array<double,3> boxmin, boxmax;
742  container->getBoundingBox(boxmin, boxmax);
743  // Use diagonal length vs. maximum support radius
744  double dlength = norm2(boxmax-boxmin);
745  double maximumRadius = 0.;
746  for (double radius : getEffectivelyUsedSupportRadii())
747  {
748  if (radius > maximumRadius){
749  maximumRadius = radius;
750  }
751  }
752  bool useWholeGeometry = false;
753  // Use the whole geometry if maximum radius is greater than the diagonal of bounding box multiplied for a custom factor
754  if (maximumRadius > (m_diagonalFactor*dlength))
755  {
756  useWholeGeometry = true;
757  }
758 
759  // Set the active vertices of target geometry
760  if (isCompact() && !useWholeGeometry){
761  // Fill the list of vertices with them included in rbf radii
762  if(container->getKdTreeSyncStatus() != SyncStatus::SYNC){
763  container->buildKdTree();
764  }
765  int nnodes = getTotalNodesCount();
766  std::vector<long> ids;
767  bitpit::KdTree<3,bitpit::Vertex,long>* tree = container->getKdTree();
768  for(int i=0; i<nnodes; ++i){
769  bitpit::Vertex vertexNode(bitpit::Vertex::NULL_ID, m_node[i]);
770  tree->hNeighbors(&vertexNode, m_effectiveSR[i], &ids, nullptr);
771  activeMeshVertices.insert(ids.begin(), ids.end());
772  }
773  }
774  else{
775  // Use all the geometry vertices
776  std::vector<long> ids = container->getVerticesIds();
777  activeMeshVertices.insert(ids.begin(), ids.end());
778  }
779 
780  // get deformation using own class evalRBF.
781  std::array<double,3> tempValue;
782  std::vector<double> resultValue;
783  for(const long &id: activeMeshVertices){
784  bitpit::Vertex & vertex = container->getPatch()->getVertex(id);
785  resultValue =evalRBF(vertex.getCoords());
786  if(m_areScalarResults) {
787  m_scalarDispl.insert(id, resultValue[0]);
788  }else{
789  std::copy_n(resultValue.begin(), 3,tempValue.begin());
790  m_displ.insert(id, tempValue);
791  }
792  }
793 
794  //apply m_filter if it's active;
795  if(m_bfilter){
796  checkFilter();
797  if(m_areScalarResults){
798  for (auto it=m_scalarDispl.begin(); it!=m_scalarDispl.end(); ++it){
799  (*it) *= m_filter.at(it.getId());
800  }
801  }else{
802  for (auto it=m_displ.begin(); it!=m_displ.end(); ++it){
803  (*it) *= m_filter.at(it.getId());
804  }
805  }
806  }
807 
808 
809  if(m_areScalarResults){
811  }else{
812  m_displ.completeMissingData({{0.0,0.0,0.0}});
813  }
814 };
815 
819 void
821  if(m_geometry == nullptr) return;
822 
823  if(m_areScalarResults){
824 
825  //I can directly apply the "scalar" displacement field only in case of surface meshes.
826  // check it out if targeted geometry is a surface.
827  if(m_geometry->getType() != 1){
828  (*m_log)<<"WARNING "<<m_name<<" : while in SCALAR mode, the class can apply a displacement field only in case of surface geometry (MimmoObject type 1). Skip apply(). "<<std::endl;
829  return;
830  }
831  m_geometry->updateAdjacencies();
832  //retrieve local normals and recover 3D comp m_displ
833  // multiplying them for the scalar field input vertex by vertex.
834  bitpit::SurfaceKernel* skernel = static_cast<bitpit::SurfaceKernel*>(m_geometry->getPatch());
835  m_displ.clear();
836  m_displ.reserve(m_geometry->getNVertices());
837  bitpit::ConstProxyVector<long> verts;
838  std::size_t size;
839  long idN;
840  for(const bitpit::Cell & cell: m_geometry->getCells()){
841  verts = cell.getVertexIds();
842  size = verts.size();
843  for(std::size_t i=0; i<size; ++i){
844  idN = verts[i];
845  if(!m_displ.exists(idN)){
846  m_displ.insert(idN, skernel->evalVertexNormal(cell.getId(), i));
847  m_displ[idN] *= m_scalarDispl[idN];
848  }
849  }
850  }
851  }//endif m_areScalarResults;
852 
853  _apply(m_displ); //base manipulation utility method.
854 
856 }
857 
858 
864 void
865 MRBF::absorbSectionXML(const bitpit::Config::Section & slotXML, std::string name){
866 
867  BITPIT_UNUSED(name);
868 
869  std::string input;
870 
871  BaseManipulation::absorbSectionXML(slotXML, name);
872 
873  m_tol = 1.0E-6;
874  if(slotXML.hasOption("Tolerance")){
875  input = slotXML.get("Tolerance");
876  input = bitpit::utils::string::trim(input);
877  double value = m_tol;
878  if(!input.empty()){
879  std::stringstream ss(bitpit::utils::string::trim(input));
880  ss >> value;
881  if(value > 0.0) setTol(value);
882  }
883  };
884 
885  if(slotXML.hasOption("RBFShape")){
886  input = slotXML.get("RBFShape");
887  int value =1;
888  if(!input.empty()){
889  std::stringstream ss(bitpit::utils::string::trim(input));
890  ss>>value;
891  }
892  value = std::max(1, value);
893  if(value > 100){
894  if (value > 105){
895  value = 105;
896  }
897  MRBFBasisFunction shapetype = static_cast<MRBFBasisFunction>(value);
898  setFunction(shapetype);
899  }
900  else{
901  if(value > 13){
902  value =1;
903  }
904  bitpit::RBFBasisFunction shapetype = static_cast<bitpit::RBFBasisFunction>(value);
905  setFunction(shapetype);
906  }
907  };
908 
909  if(slotXML.hasOption("SupportRadiusLocal")){
910  input = slotXML.get("SupportRadiusLocal");
911  double value = -1.0;
912  if(!input.empty()){
913  std::stringstream ss(bitpit::utils::string::trim(input));
914  ss >> value;
915  setSupportRadiusLocal(value);
916  }
917  };
918  //LEGACY ENTRY old version of SupportRadiusLocal
919  if(slotXML.hasOption("SupportRadius")){
920  input = slotXML.get("SupportRadius");
921  double value = -1.0;
922  if(!input.empty()){
923  std::stringstream ss(bitpit::utils::string::trim(input));
924  ss >> value;
925  setSupportRadiusLocal(value);
926  }
927  };
928 
929  if(slotXML.hasOption("SupportRadiusReal")){
930  input = slotXML.get("SupportRadiusReal");
931  double value = -1.0;
932  if(!input.empty()){
933  std::stringstream ss(bitpit::utils::string::trim(input));
934  ss >> value;
935  setSupportRadiusReal(value);
936  }
937  };
938 
939  if(slotXML.hasOption("Compact")){
940  std::string input = slotXML.get("Compact");
941  input = bitpit::utils::string::trim(input);
942  bool value = false;
943  if(!input.empty()){
944  std::stringstream ss(input);
945  ss >> value;
946  }
947  setCompactSupport(value);
948  }
949 
950  m_diagonalFactor = 1.0;
951  if(slotXML.hasOption("DiagonalFactor")){
952  input = slotXML.get("DiagonalFactor");
953  input = bitpit::utils::string::trim(input);
954  double value = m_diagonalFactor;
955  if(!input.empty()){
956  std::stringstream ss(bitpit::utils::string::trim(input));
957  ss >> value;
958  if(value >= 0.0 && value <=1.0) setDiagonalFactor(value);
959  }
960  };
961 
962 }
963 
969 void
970 MRBF::flushSectionXML(bitpit::Config::Section & slotXML, std::string name){
971 
972  BITPIT_UNUSED(name);
973 
974  BaseManipulation::flushSectionXML(slotXML, name);
975 
976  slotXML.set("Mode", std::to_string(static_cast<int>(m_solver)));
977 
978  if(m_tol != 1.0E-6){
979  std::stringstream ss;
980  ss<<std::scientific<<m_tol;
981  slotXML.set("Tolerance", ss.str());
982  }
983  int type = getFunctionType();
984  if(type != static_cast<int>(bitpit::RBFBasisFunction::CUSTOM)){
985  slotXML.set("RBFShape", std::to_string(type));
986  }
987 
988  if(m_supportRadii.empty()){
989  std::stringstream ss;
990  ss<<std::scientific<<m_supportRadiusValue;
991  if(m_srIsReal){
992  slotXML.set("SupportRadiusReal", ss.str());
993  }else{
994  slotXML.set("SupportRadiusLocal", ss.str());
995  }
996  }
997 
998  if(isCompact()){
999  slotXML.set("Compact", std::to_string(1));
1000  }
1001 
1002  if(m_diagonalFactor != 1.0){
1003  std::stringstream ss;
1004  ss<<std::scientific<<m_diagonalFactor;
1005  slotXML.set("DiagonalFactor", ss.str());
1006  }
1007 
1008 }
1009 
1014 void
1017  check = check && m_filter.completeMissingData(0.0);
1018  check = check && m_filter.getGeometry() == getGeometry();
1019 
1020  if (!check){
1021  m_log->setPriority(bitpit::log::Verbosity::DEBUG);
1022  (*m_log)<<"Not valid filter found in "<<m_name<<". Proceeding with default unitary field"<<std::endl;
1023  m_log->setPriority(bitpit::log::Verbosity::NORMAL);
1024 
1025  m_filter.clear();
1028  m_filter.reserve(getGeometry()->getNVertices());
1029  for (const auto & vertex : getGeometry()->getVertices()){
1030  m_filter.insert(vertex.getId(), 1.0);
1031  }
1032  }
1033 }
1034 
1042 void
1044  if(m_solver != MRBFSol::NONE) return;
1045 
1046  int size = value.size();
1047 
1048  removeAllData();
1049 
1050  dvector1D temp(size);
1051  int sizeLoc = 0;
1052  if(!(value.empty())) sizeLoc = value[0].size();
1053  for(int loc=0; loc<sizeLoc; ++loc){
1054  for(int i=0; i<size; ++i){
1055  temp[i] = value[i][loc];
1056  }
1057  addData(temp);
1058  }
1059 }
1060 
1068 void
1069 MRBF::plotCloud(std::string directory, std::string filename, int counterFile, bool binary, bool deformed){
1070 
1071  if(deformed && m_areScalarResults){
1072  (*m_log)<<"WARNING "<<m_name<<": plotCloud skipping print of deformed RBF cloud, while the class is in Scalar mode"<<std::endl;
1073  return;
1074  }
1075 
1076  int nnodes = getTotalNodesCount();
1077  dvecarr3E* nodes_ = getNodes();
1078  dvecarr3E nodes(nnodes);
1079  if(deformed){
1080  dvecarr3E data(nnodes);
1081  for(int i=0; i<nnodes; ++i){
1082  for(int j=0; j<3; ++j){
1083  if(m_solver == MRBFSol::NONE) data[i][j] = m_weight[j][i];
1084  else data[i][j] = m_value[j][i];
1085  }
1086  }
1087  for(int i=0; i<nnodes; ++i){
1088  nodes[i] = (*nodes_)[i] + data[i];
1089  }
1090  }else{
1091  for(int i=0; i<nnodes; ++i){
1092  nodes[i] = (*nodes_)[i];
1093  }
1094  }
1095 
1096  bitpit::VTKFormat codex = bitpit::VTKFormat::ASCII;
1097  if(binary){codex=bitpit::VTKFormat::APPENDED;}
1098 
1099  ivector1D conn(nnodes);
1100  {
1101  int counter = 0;
1102  for(auto & val: conn){
1103  val = counter;
1104  ++counter;
1105  }
1106  }
1107  bitpit::VTKUnstructuredGrid vtk(directory, filename, bitpit::VTKElementType::VERTEX);
1108 
1109 #if MIMMO_ENABLE_MPI
1110  // only rank 0 writes (nodes are shared!)
1111  if (getRank() == 0){
1112 #endif
1113  vtk.setGeomData( bitpit::VTKUnstructuredField::POINTS, nodes) ;
1114  vtk.setGeomData( bitpit::VTKUnstructuredField::CONNECTIVITY, conn) ;
1115  vtk.setDimensions(conn.size(), nnodes);
1116  //use connectivity as node labels also;
1117  vtk.addData("labels",bitpit::VTKFieldType::SCALAR, bitpit::VTKLocation::POINT, conn) ;
1118  vtk.setCodex(codex);
1119  if(counterFile>=0){vtk.setCounter(counterFile);}
1120  vtk.write();
1121 #if MIMMO_ENABLE_MPI
1122  }
1123 #endif
1124 };
1125 
1130 void
1132 
1133  std::string dir = m_outputPlot;
1134  std::string nameCloud = m_name;
1135  std::string nameCloudD = m_name+"_moved";
1136 
1137  plotCloud(dir, nameCloud, getId(), true, false );
1138  plotCloud(dir, nameCloudD, getId(), true, true );
1139 }
1140 
1145 void
1147 
1148  m_effectiveSR.clear();
1149  int nodesCount = getTotalNodesCount();
1150  //First step check variable support radii.
1151  //if not empty, pass as it is to m_effectiveSR, resize to the total count of nodes and return.
1152  // if class is in MRBFSol::WHOLE/GREEDY m_supportRadii should already be empty
1153  // see control of setVariableSupportRadii
1154  if(!m_supportRadii.empty()){
1156  m_effectiveSR.resize(nodesCount, std::numeric_limits<double>::min());
1157  return;
1158  }
1159 
1160  // now you are working with singular supportRadius
1161  double candidateRadius = 0.0;
1162  //check if it's negative.
1163  if(m_supportRadiusValue < std::numeric_limits<double>::min()) {
1164  //get maximum weight/value displ and assign support radius a 3 times this value.
1165  int dataCount = getDataCount();
1166  dvector1D data(dataCount);
1167  for(int i=0; i<nodesCount; ++i){
1168  for(int j=0; j<dataCount; ++j){
1169  if(m_solver == MRBFSol::NONE) data[j] = m_weight[j][i];
1170  else data[j] = m_value[j][i];
1171  }
1172  candidateRadius = std::max(candidateRadius, norm2(data));
1173  }
1174  candidateRadius *=3.0;
1175  }else{
1176 
1177  candidateRadius = m_supportRadiusValue;
1178 
1179  // check if its local(based on AABB)
1180  if (!m_srIsReal){
1181  double bboxDiag;
1182  darray3E pmin, pmax;
1183  getGeometry()->getBoundingBox(pmin, pmax);
1184  bboxDiag= norm2(pmax - pmin);
1185  candidateRadius *= bboxDiag;
1186  }
1187  }
1188 
1189  //create homogeneous vector of support radii with this candidateRadius;
1190  m_effectiveSR.resize(nodesCount, candidateRadius);
1191 
1192  //If you are in WHOLE/GREEDY mode, push to the class base
1193  // the info on the candidate radius
1194  if(m_solver != MRBFSol::NONE){
1195  setSupportRadius(candidateRadius);
1196  }
1197 }
1198 
1208 std::vector<double>
1209 MRBF::evalRBF( const std::array<double,3> &point){
1210 
1211  int datasize = getDataCount();
1212  std::vector<double> values(datasize, 0.0);
1213  int i, j;
1214  double dist, basis;
1215 
1216  for( i=0; i<m_nodes; ++i ){
1217  if( m_activeNodes[i] ) {
1218 
1219  dist = norm2(point - m_node[i]) / m_effectiveSR[i];
1220  basis = evalBasis( dist );
1221 
1222  for( j=0; j<datasize; ++j) {
1223  values[j] += basis * m_weight[j][i];
1224  }
1225  }
1226  }
1227 
1228  return values;
1229 }
1230 
1236 void
1238  m_solver = solver;
1239  if (m_solver == MRBFSol::NONE) RBF::setMode(bitpit::RBFMode::PARAM);
1240  else RBF::setMode(bitpit::RBFMode::INTERP);
1241 };
1242 
1247 bool
1249 
1250  // If rbf displ is null and Scalar mode if off skip check on linked geometry
1251  if(m_rbfdispl != nullptr && !m_areScalarResults){
1252  // If displacementes have unlinked geometry skip
1253  if (!m_rbfdispl->getGeometry()){
1254  (*m_log)<<m_name + " : null RBF geometry linked by displacements DOF vectors. Skip object."<<std::endl;
1255  return false;
1256  }
1257  else if (m_rbfdispl->getGeometry() != m_rbfgeometry){
1258  (*m_log)<<m_name + " : RBF DOF vector displacements not linked to RBF geometry. Skip object."<<std::endl;
1259  return false;
1260  }
1261  }
1262 
1263  // If rbfScalarDispl is null and Scalar mode is on skip check on linked geometry
1264  if(m_rbfScalarDispl != nullptr && m_areScalarResults){
1265  // If displacementes have unlinked geometry skip
1266  if (!m_rbfScalarDispl->getGeometry()){
1267  (*m_log)<<m_name + " : null RBF geometry linked by displacements DOF scalars. Skip object."<<std::endl;
1268  return false;
1269  }
1270  else if (m_rbfScalarDispl->getGeometry() != m_rbfgeometry){
1271  (*m_log)<<m_name + " : RBF DOF scalar displacements not linked to RBF geometry. Skip object."<<std::endl;
1272  return false;
1273  }
1274  }
1275 
1276  // If rbf support radii is null skip check on linked geometry
1277  if (m_rbfSupportRadii){
1278  if (!m_rbfSupportRadii->getGeometry()){
1279  (*m_log)<<m_name + " : null RBF geometry linked by support radii vector. Skip object."<<std::endl;
1280  return false;
1281  }
1283  (*m_log)<<m_name + " : RBF support radii not linked to RBF geometry. Skip object."<<std::endl;
1284  return false;
1285  }
1286  }
1287 
1288  //clear the previous data into MRBF
1289  removeAllNodes();
1290  removeAllData();
1291 
1292  //fill data locally from m_rbfgeometry, m_rbfdispl/m_rbfScalarDispl and m_rbfSupportRadii
1293  std::map<long, std::array<double,3> > nodes, displs;
1294  std::map<long, double> radii;
1295  for(const bitpit::Vertex & vert : m_rbfgeometry->getVertices()){
1296  long id = vert.getId();
1297  nodes[id] = vert.getCoords();
1298 
1299  if(m_areScalarResults){
1300  if(m_rbfScalarDispl && m_rbfScalarDispl->exists(id)){
1301  displs[id].fill(0.0);
1302  displs[id][0] = m_rbfScalarDispl->at(id);
1303  }
1304  }else{
1305  if(m_rbfdispl && m_rbfdispl->exists(id)){
1306  displs[id] = m_rbfdispl->at(id);
1307  }
1308  }
1309  if (m_rbfSupportRadii && m_rbfSupportRadii->exists(id)){
1310  radii[id] = m_rbfSupportRadii->at(id);
1311  }
1312  }
1313 
1314 #if MIMMO_ENABLE_MPI
1315  //MPI stuffs - serialize nodes and displs data so that
1316  // every rank has exactly the same data chunks.
1317 
1318  //Send my own and receive mpvres from others.
1319 
1320  //prepare my own send buffer.
1321  mimmo::OBinaryStream myrankNodeDataBuffer, myrankDisplDataBuffer, myrankRadiiDataBuffer;
1322  myrankNodeDataBuffer << (std::size_t)nodes.size();
1323  for (auto& tuple: nodes){
1324  myrankNodeDataBuffer << tuple.first;
1325  myrankNodeDataBuffer << tuple.second;
1326  }
1327  myrankDisplDataBuffer << (std::size_t)displs.size();
1328  for (auto& tuple: displs){
1329  myrankDisplDataBuffer << tuple.first;
1330  myrankDisplDataBuffer << tuple.second;
1331  }
1332  myrankRadiiDataBuffer << (std::size_t)radii.size();
1333  for (auto& tuple: radii){
1334  myrankRadiiDataBuffer << tuple.first;
1335  myrankRadiiDataBuffer << tuple.second;
1336  }
1337 
1338  long myrankNodeDataBufferSize = myrankNodeDataBuffer.getSize();
1339  long myrankDisplDataBufferSize = myrankDisplDataBuffer.getSize();
1340  long myrankRadiiDataBufferSize = myrankRadiiDataBuffer.getSize();
1341 
1342  for (int sendRank=0; sendRank<m_nprocs; sendRank++){
1343 
1344  if (m_rank != sendRank){
1345 
1346  std::size_t nP;
1347  std::array<double,3> val;
1348  double radius;
1349  long int id;
1350 
1351  // receive node data from other ranks.
1352  long nodeBufferSize;
1353  MPI_Recv(&nodeBufferSize, 1, MPI_LONG, sendRank, 900, m_communicator, MPI_STATUS_IGNORE);
1354  mimmo::IBinaryStream nodeBuffer(nodeBufferSize);
1355  MPI_Recv(nodeBuffer.data(), nodeBuffer.getSize(), MPI_CHAR, sendRank, 910, m_communicator, MPI_STATUS_IGNORE);
1356 
1357  nodeBuffer >> nP;
1358  for (std::size_t i = 0; i < nP; ++i) {
1359  nodeBuffer >> id;
1360  nodeBuffer >> val;
1361  if(nodes.count(id) == 0) nodes.insert({{id, val}});
1362  }
1363 
1364  // receive displ data from other ranks.
1365  long displBufferSize;
1366  MPI_Recv(&displBufferSize, 1, MPI_LONG, sendRank, 920, m_communicator, MPI_STATUS_IGNORE);
1367  mimmo::IBinaryStream displBuffer(displBufferSize);
1368  MPI_Recv(displBuffer.data(), displBuffer.getSize(), MPI_CHAR, sendRank, 930, m_communicator, MPI_STATUS_IGNORE);
1369 
1370  displBuffer >> nP;
1371  for (std::size_t i = 0; i < nP; ++i) {
1372  displBuffer >> id;
1373  displBuffer >> val;
1374  if(displs.count(id) == 0) displs.insert({{id, val}});
1375  }
1376 
1377  // receive radii data from other ranks.
1378  long radiiBufferSize;
1379  MPI_Recv(&radiiBufferSize, 1, MPI_LONG, sendRank, 920, m_communicator, MPI_STATUS_IGNORE);
1380  mimmo::IBinaryStream radiiBuffer(radiiBufferSize);
1381  MPI_Recv(radiiBuffer.data(), radiiBuffer.getSize(), MPI_CHAR, sendRank, 930, m_communicator, MPI_STATUS_IGNORE);
1382 
1383  radiiBuffer >> nP;
1384  for (std::size_t i = 0; i < nP; ++i) {
1385  radiiBuffer >> id;
1386  radiiBuffer >> radius;
1387  if(radii.count(id) == 0) radii.insert({{id, radius}});
1388  }
1389 
1390  }else{
1391  //send to all other except me the def data.
1392  for (int recvRank=0; recvRank<m_nprocs; recvRank++){
1393  if (m_rank != recvRank){
1394  MPI_Send(&myrankNodeDataBufferSize, 1, MPI_LONG, recvRank, 900, m_communicator);
1395  MPI_Send(myrankNodeDataBuffer.data(), myrankNodeDataBuffer.getSize(), MPI_CHAR, recvRank, 910, m_communicator);
1396  MPI_Send(&myrankDisplDataBufferSize, 1, MPI_LONG, recvRank, 920, m_communicator);
1397  MPI_Send(myrankDisplDataBuffer.data(), myrankDisplDataBuffer.getSize(), MPI_CHAR, recvRank, 930, m_communicator);
1398  MPI_Send(&myrankRadiiDataBufferSize, 1, MPI_LONG, recvRank, 920, m_communicator);
1399  MPI_Send(myrankRadiiDataBuffer.data(), myrankRadiiDataBuffer.getSize(), MPI_CHAR, recvRank, 930, m_communicator);
1400  }
1401  }
1402  }
1403  }// end external sendrank loop
1404 
1405 #endif
1406 
1407  dvecarr3E nodeRawList(nodes.size());
1408  std::array<std::vector<double>,3> displList;
1409  displList.fill(dvector1D(nodes.size(), 0.));
1410 
1411  // Resize support radii to the effective serialized size
1412  // Empty if support radii not passed as pierced vector
1413  m_supportRadii.clear();
1414  m_supportRadii.resize(radii.size());
1415 
1416  int count(0);
1417  for(auto & tuple : nodes){
1418  long id = tuple.first;
1419  nodeRawList[count] = tuple.second;
1420  if(displs.count(id) > 0){
1421  for(int k=0; k<3; ++k){
1422  displList[k][count] = displs[id][k];
1423  }
1424  }
1425  if(radii.count(id) > 0){
1426  m_supportRadii[count] = radii[id];
1427  }
1428  ++count;
1429  }
1430 
1431  RBF::addNode(nodeRawList);
1432  int numberOfData = 1 + int(!m_areScalarResults)*2;
1433  for(int loc=0; loc<numberOfData; ++loc){
1434  addData(displList[loc]);
1435  }
1436 
1437  // Return valid initialization
1438  return true;
1439 }
1440 
1446 double
1447 heaviside10( double dist )
1448 {
1449  return 1./(1.+std::exp(-10.*(1.-dist)));
1450 }
1451 
1457 double
1458 heaviside50( double dist )
1459 {
1460  return 1./(1.+std::exp(-50.*(1.-dist)));
1461 }
1462 
1468 double
1469 heaviside100( double dist )
1470 {
1471  return 1./(1.+std::exp(-100.*(1.-dist)));
1472 }
1473 
1479 double
1480 heaviside1000( double dist )
1481 {
1482  return 1./(1.+std::exp(-1000.*(1.-dist)));
1483 }
1484 
1494 double
1495 dsigmoid( double dist )
1496 {
1497  return 4.*(std::exp(-10.*dist)/std::pow((1.+std::exp(-10.*dist)),int(2)));
1498 }
1499 
1500 }
dmpvecarr3E * getDisplacements()
Definition: MRBF.cpp:262
void plotCloud(std::string directory, std::string filename, int counterFile, bool binary, bool deformed)
Definition: MRBF.cpp:1069
bool isSupportRadiusReal()
Definition: MRBF.cpp:206
#define M_GDISPLS
void computeEffectiveSupportRadiusList()
Definition: MRBF.cpp:1146
dmpvector1D * getFilter()
Definition: MRBF.cpp:195
dvector1D m_supportRadii
Definition: MRBF.hpp:155
bool isVariableSupportRadiusSet()
Definition: MRBF.cpp:216
void setWeight(dvector2D value)
Definition: MRBF.cpp:1043
dmpvector1D * m_rbfSupportRadii
Definition: MRBF.hpp:169
#define M_DATAFIELD
#define M_DATAFIELD2
void execute()
Definition: MRBF.cpp:681
#define M_DISPLS
#define M_GEOM
void setNode(darray3E)
Definition: MRBF.cpp:329
MRBF(MRBFSol mode=MRBFSol::NONE)
Definition: MRBF.cpp:32
double getDiagonalFactor()
Definition: MRBF.cpp:236
std::vector< double > evalRBF(const std::array< double, 3 > &val)
Definition: MRBF.cpp:1209
ivector1D checkDuplicatedNodes(double tol=1.0E-12)
Definition: MRBF.cpp:373
void setDisplacements(dvecarr3E displ)
Definition: MRBF.cpp:514
std::vector< bool > bvector1D
void setTol(double tol)
Definition: MRBF.cpp:498
std::vector< darray3E > dvecarr3E
bool m_srIsReal
Definition: MRBF.hpp:154
void setSupportRadiusReal(double suppR_)
Definition: MRBF.cpp:436
MRBF & operator=(MRBF other)
Definition: MRBF.cpp:116
int getFunctionType()
Definition: MRBF.cpp:244
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
Definition: MRBF.cpp:865
dvector1D m_effectiveSR
Definition: MRBF.hpp:163
mimmo custom derivation of bitpit OBinaryStream (see relative doc)
dmpvecarr3E m_displ
Definition: MRBF.hpp:160
#define M_GEOM2
double m_supportRadiusValue
Definition: MRBF.hpp:153
bool completeMissingData(const mpv_t &defValue)
bool m_areScalarResults
Definition: MRBF.hpp:170
MRBFSol getMode()
Definition: MRBF.cpp:187
void warningXML(bitpit::Logger *log, std::string name)
void setMode(MRBFSol solver)
Definition: MRBF.cpp:1237
void setSupportRadiusLocal(double suppR_)
Definition: MRBF.cpp:419
bool m_isCompact
Definition: MRBF.hpp:164
BaseManipulation is the base class of any manipulation object of the library.
dvecarr3E * getNodes()
Definition: MRBF.cpp:177
MRBFSol
Solver enum for MRBF data fields interpolation/ direct parameterization.
Definition: MRBF.hpp:50
#define M_VECTORFIELD
void apply()
Definition: MRBF.cpp:820
MimmoSharedPointer< MimmoObject > getGeometry() const
double m_diagonalFactor
Definition: MRBF.hpp:156
MRBFSol m_solver
Definition: MRBF.hpp:150
virtual ~MRBF()
Definition: MRBF.cpp:90
dvector1D & getEffectivelyUsedSupportRadii()
Definition: MRBF.cpp:226
std::vector< int > ivector1D
void setVariableSupportRadii(dvector1D sradii)
Definition: MRBF.cpp:462
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
dmpvector1D m_filter
Definition: MRBF.hpp:151
bool initRBFwGeometry()
Definition: MRBF.cpp:1248
void clearFilter()
Definition: MRBF.cpp:668
std::vector< double > dvector1D
void setDiagonalFactor(double diagonalFactor)
Definition: MRBF.cpp:489
void buildPorts()
Definition: MRBF.cpp:154
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
void setSupportRadiusValue(double suppR_)
Definition: MRBF.cpp:447
MimmoSharedPointer< MimmoObject > m_geometry
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
void setFilter(dmpvector1D *)
Definition: MRBF.cpp:360
void setScalarDisplacements(dvector1D displ)
Definition: MRBF.cpp:562
void swap(MRBF &x) noexcept
Definition: MRBF.cpp:125
dmpvecarr3E * m_rbfdispl
Definition: MRBF.hpp:167
bool isCompact()
Definition: MRBF.cpp:301
double m_tol
Definition: MRBF.hpp:149
void _apply(MimmoPiercedVector< darray3E > &displacements)
bool areResultsInScalarMode()
Definition: MRBF.cpp:291
std::vector< dvector1D > dvector2D
void clear()
Definition: MRBF.cpp:657
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
Definition: MRBF.cpp:970
int m_functype
Definition: MRBF.hpp:159
bool removeDuplicatedNodes(ivector1D *list=nullptr)
Definition: MRBF.cpp:398
void setDataLocation(MPVLocation loc)
virtual void plotOptionalResults()
Definition: MRBF.cpp:1131
#define M_SCALARFIELD
mimmo custom derivation of bitpit IBinaryStream (see relative doc)
std::array< double, 3 > darray3E
void checkFilter()
Definition: MRBF.cpp:1015
int addNode(darray3E)
Definition: MRBF.cpp:311
dmpvector1D m_scalarDispl
Definition: MRBF.hpp:161
Radial Basis Function evaluation from clouds of control points.
Definition: MRBF.hpp:146
MRBFBasisFunction
Enum class defining types of mimmo RBF kernel functions that could be used also in MRBF class,...
Definition: MRBF.hpp:38
#define M_SCALARFIELD2
bool m_bfilter
Definition: MRBF.hpp:152
MimmoSharedPointer is a custom implementation of shared pointer.
dmpvector1D * m_rbfScalarDispl
Definition: MRBF.hpp:168
MimmoSharedPointer< MimmoObject > getGeometry()
void setCompactSupport(bool isCompact=true)
Definition: MRBF.cpp:650
dmpvector1D * getScalarDisplacements()
Definition: MRBF.cpp:276
void swap(BaseManipulation &x) noexcept
#define M_COORDS
void setFunction(const MRBFBasisFunction &funct, bool isCompact=false)
Definition: MRBF.cpp:594
#define M_FILTER
MimmoSharedPointer< MimmoObject > m_rbfgeometry
Definition: MRBF.hpp:166