ReconstructVector.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 "ReconstructFields.hpp"
26 #include <unordered_set>
27 
28 namespace mimmo{
29 
34  m_name = "mimmo.ReconstructVector";
35  m_overlapCriterium = OverlapMethod::SUM;
36  m_loc = loc;
38 }
39 
44 ReconstructVector::ReconstructVector(const bitpit::Config::Section & rootXML){
45 
46  m_name = "mimmo.ReconstructVector";
47  m_overlapCriterium = OverlapMethod::MAX;
48 
49  std::string fallback_name = "ClassNONE";
50  std::string input = rootXML.get("ClassName", fallback_name);
51  std::string fallback_loc = "-1";
52  std::string input_loc = rootXML.get("DataLocation", fallback_loc);
53 
54  input = bitpit::utils::string::trim(input);
55  input_loc = bitpit::utils::string::trim(input_loc);
56 
57  int loc = std::stoi(input_loc);
58  if(loc > 0 && loc < 3){
59  m_loc =static_cast<MPVLocation>(loc);
60  }else{
61  m_loc = MPVLocation::POINT;
62  }
63 
64  if(input == "mimmo.ReconstructVector"){
65  absorbSectionXML(rootXML);
66  }else{
68  };
69 }
70 
75 
80  m_loc = other.m_loc;
81  m_overlapCriterium = other.m_overlapCriterium;
82  m_subpatch = other.m_subpatch;
83  m_result = other.m_result;
84  m_subresults = other.m_subresults;
85 }
86 
92 {
93  std::swap(m_loc, x.m_loc);
94  std::swap(m_overlapCriterium,x.m_overlapCriterium);
95  std::swap(m_subpatch, x.m_subpatch);
96  std::swap(m_subresults, x.m_subresults);
97  //std::swap(m_result, x.m_result);
98  m_result.swap(x.m_result);
100 };
101 
108  return m_overlapCriterium;
109 }
110 
115 int
117  return static_cast<int>(m_overlapCriterium);
118 }
119 
124 int
126  return m_subpatch.size();
127 }
128 
133 dmpvecarr3E *
135  return &m_result;
136 };
137 
142 std::vector<dmpvecarr3E*>
144 
145  std::vector<dmpvecarr3E *> res;
146  res.reserve(m_subresults.size());
147  for(dmpvecarr3E & ffref : m_subresults){
148  res.push_back(&ffref);
149  }
150  return(res);
151 };
152 
158 void
160  setOverlapCriterium(static_cast<int>(funct));
161 };
162 
168 void
170  if(funct<1 ||funct>4) return;
171  m_overlapCriterium = static_cast<OverlapMethod>(funct);
172 };
173 
178 void
180  if(!field) return;
181  if(field->getGeometry()== nullptr && field->getDataLocation() != m_loc) return;
182  if(field->getGeometry()->getType()==3 && m_loc==MPVLocation::CELL){
183  (*m_log)<<"warning in "<<m_name<<" : trying to add field referred to a Point Cloud, while Class has Data Location referred to CELLS. Do Nothing."<<std::endl;
184  return;
185  }
186  m_subpatch.push_back(*field);
187 };
188 
193 void
195  //in m_subpatch remove progressively all pierced vector elements in last position
196  //which links towards a geometry of type patch.
197  while(m_subpatch.back().getGeometry() == patch){
198  m_subpatch.pop_back();
199  }
200 
201  //start searching from the begin on element linking patch
202  std::vector<dmpvecarr3E>::iterator it = m_subpatch.begin();
203 
204  while(it != m_subpatch.end()){
205  if (it->getGeometry() == patch){
206  *it = m_subpatch.back();
207  m_subpatch.pop_back();
208  //be always sure the last element is clean and does not link
209  // the patch
210  while(m_subpatch.back().getGeometry() == patch){
211  m_subpatch.pop_back();
212  }
213  }
214  ++it; //forward the iterator.
215  }
216 };
217 
221 void
223  m_subpatch.clear();
224  m_result.clear();
225  m_subresults.clear();
226 };
227 
231 void
234  removeAllData();
235  m_overlapCriterium = OverlapMethod::SUM;
236 }
237 
241 void
243 
244  m_result.setName("field");
245  write(m_result.getGeometry(), m_result);
246 
247 };
248 
253 void
255 
256  std::string originalname = m_name;
257  m_name = originalname + "SubPatch"+std::to_string(i);
258  m_subresults[i].setName("field");
259  write(m_subresults[i].getGeometry(), m_subresults[i]);
260  m_name = originalname;
261 
262 };
263 
268 void
270 
271  if(getGeometry() == nullptr){
272  (*m_log)<<m_name + " : nullptr pointer to linked geometry found"<<std::endl;
273  throw std::runtime_error("Error in "+m_name + " : nullptr pointer to linked geometry found");
274  }
275 
276  //Overlap fields
277  m_result.clear();
278  m_result.setGeometry(getGeometry());
279  m_result.setDataLocation(m_loc);
280 
281  m_subresults.clear();
282 
283  std::unordered_set<long> idsTarget;
284  {
285  livector1D ids = idsGeoDataLocation(getGeometry());
286  idsTarget.insert(ids.begin(), ids.end());
287  }
288 
289  bitpit::PiercedVector<int> counter;
290  for (int i=0; i<getNData(); i++){
291  dmpvecarr3E* pv = &m_subpatch[i];
292  livector1D ids = idsGeoDataLocation(pv->getGeometry());
293  for (auto ID: ids){
294  if(idsTarget.count(ID)==0) continue;
295 
296  if (!m_result.exists(ID)){
297  m_result.insert(ID, (*pv)[ID]);
298  counter.insert(ID, 1);
299  }
300  else{
301  overlapFields(ID, (*pv)[ID]);
302  counter[ID]++;
303  }
304  }
305  }
306 
307  if (m_overlapCriterium == OverlapMethod::AVERAGE){
308  long int ID;
309  auto itend = m_result.end();
310  for (auto it=m_result.begin(); it!=itend; ++it){
311  ID = it.getId();
312  for (int j=0; j<3; j++)
313  (*it)[j] = (*it)[j] / double(counter[ID]);
314  }
315  }
316 
317  //Update field on whole geometry
318  darray3E zero = {{0.0,0.0,0.0}};
319 
320  if(!m_result.completeMissingData(zero)){
321  (*m_log)<<"Warning in "<<m_name<<". It seems a reconstruct field with values uncoherent with target geometry is generated."<<std::endl;
322  }
323 
324  //Create subresults
325  m_subresults.resize(getNData());
326  for (int i=0; i<getNData(); i++){
327  dmpvecarr3E* pv = &m_subpatch[i];
328  m_subresults[i].setGeometry(pv->getGeometry());
329  m_subresults[i].setDataLocation(m_loc);
330  livector1D ids = idsGeoDataLocation(pv->getGeometry());
331  for (auto ID : ids){
332  if(idsTarget.count(ID)>0){
333  m_subresults[i].insert(ID, m_result[ID]);
334  }
335  }
336  }
337 }
338 
342 void
344  plotData();
345  for (int i=0; i<getNData(); i++){
346  plotSubData(i);
347  }
348 }
349 
356 //DEVELOPERS REMIND if more overlap methods are added refer to this method to implement them
357 void
358 ReconstructVector::overlapFields(long int ID, darray3E & locField){
359 
360  switch(m_overlapCriterium){
361  case OverlapMethod::MAX :
362 
363  {
364  double actual = norm2(m_result[ID]);
365  double dummy = norm2(locField);
366 
367  if (actual < dummy)
368  m_result[ID] = locField;
369  }
370  break;
371 
372  case OverlapMethod::MIN :
373  {
374  double actual = norm2(m_result[ID]);
375  double dummy = norm2(locField);
376 
377  if (actual > dummy)
378  m_result[ID] = locField;
379  }
380  break;
381 
383 
384  m_result[ID] += locField;
385  break;
386 
387  case OverlapMethod::SUM :
388 
389  m_result[ID] += locField;
390  break;
391 
392  default : //never been reached
393  break;
394  }
395 
396 };
397 
401 void
403 
404  bool built = true;
405 
406  //input
407  built = (built && createPortIn<mimmo::MimmoSharedPointer<MimmoObject>, ReconstructVector>(&m_geometry, M_GEOM, true));
408  built = (built && createPortIn<dmpvecarr3E*, ReconstructVector>(this, &mimmo::ReconstructVector::addData, M_VECTORFIELD, true));
409 
410  //output
411  built = (built && createPortOut<dmpvecarr3E*, ReconstructVector>(this, &ReconstructVector::getResultField, M_VECTORFIELD));
412  built = (built && createPortOut<mimmo::MimmoSharedPointer<MimmoObject>, ReconstructVector>(&m_geometry, M_GEOM));
413  built = (built && createPortOut<std::vector<dmpvecarr3E*>, ReconstructVector>(this, &mimmo::ReconstructVector::getResultFields, M_VECVECTORFIELDS));
414  m_arePortsBuilt = built;
415 };
416 
422 void ReconstructVector::absorbSectionXML(const bitpit::Config::Section & slotXML, std::string name){
423 
424  BITPIT_UNUSED(name);
425 
426  if(slotXML.hasOption("DataLocation")){
427  std::string input = slotXML.get("DataLocation");
428  input = bitpit::utils::string::trim(input);
429  int temp = -1;
430  if(!input.empty()){
431  std::stringstream ss(input);
432  ss>>temp;
433  }
434  if(int(m_loc) != temp){
435  (*m_log)<<"Error absorbing DataLocation in "<<m_name<<". Class and read locations mismatch"<<std::endl;
436  if (temp == 0) (*m_log)<<"XML DataLocation in "<<m_name<<" is set to 0-UNDEFINED"<<std::endl;
437  if (temp == 3) (*m_log)<<"XML DataLocation in "<<m_name<<" is set to 3-INTERFACE, not supported for now."<<std::endl;
438  throw std::runtime_error (m_name + " : xml absorbing failed.");
439  }
440  }
441 
442  //start absorbing
443  BaseManipulation::absorbSectionXML(slotXML, name);
444 
445  if(slotXML.hasOption("OverlapCriterium")){
446  std::string input = slotXML.get("OverlapCriterium");
447  input = bitpit::utils::string::trim(input);
448  int value = 4;
449  if(!input.empty()){
450  std::stringstream ss(input);
451  ss >> value;
452  value = std::min(std::max(1, value),4);
453  }
454  setOverlapCriterium(value);
455  }
456 };
457 
463 void ReconstructVector::flushSectionXML(bitpit::Config::Section & slotXML, std::string name){
464 
465  BITPIT_UNUSED(name);
466 
467  BaseManipulation::flushSectionXML(slotXML, name);
468 
469  slotXML.set("DataLocation", std::to_string(int(m_loc)));
470  int value = static_cast<int>(m_overlapCriterium);
471  slotXML.set("OverlapCriterium", std::to_string(value));
472 };
473 
480 livector1D ReconstructVector::idsGeoDataLocation(mimmo::MimmoSharedPointer<MimmoObject> geo){
481 
482  if (m_loc == MPVLocation::POINT) return geo->getVertices().getIds();
483  if (m_loc == MPVLocation::CELL) return geo->getCells().getIds();
484  return livector1D(0);
485 }
486 
487 
488 }
OverlapMethod
class for setting overlapping criterium for two different fields
#define M_GEOM
#define M_VECVECTORFIELDS
MPVLocation
Define data location for the MimmoPiercedVector field.
std::vector< dmpvecarr3E * > getResultFields()
void setOverlapCriteriumENUM(OverlapMethod)
void setName(std::string name)
std::vector< long > livector1D
bool completeMissingData(const mpv_t &defValue)
void warningXML(bitpit::Logger *log, std::string name)
void swap(ReconstructVector &) noexcept
ReconstructVector(MPVLocation loc=MPVLocation::POINT)
BaseManipulation is the base class of any manipulation object of the library.
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
#define M_VECTORFIELD
MimmoSharedPointer< MimmoObject > getGeometry() const
void write(MimmoSharedPointer< MimmoObject > geometry)
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
void removeData(mimmo::MimmoSharedPointer< MimmoObject >)
Reconstruct a vector field from daughter mesh to mother mesh.
MimmoSharedPointer< MimmoObject > m_geometry
OverlapMethod getOverlapCriteriumENUM()
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
void setDataLocation(MPVLocation loc)
std::array< double, 3 > darray3E
void addData(dmpvecarr3E *)
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
MimmoSharedPointer is a custom implementation of shared pointer.
MimmoSharedPointer< MimmoObject > getGeometry()
void swap(BaseManipulation &x) noexcept