ReconstructScalar.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 namespace mimmo{
28 
34  m_name = "mimmo.ReconstructScalar";
35  m_overlapCriterium = OverlapMethod::MAX;
36  m_loc = loc;
38 }
39 
44 ReconstructScalar::ReconstructScalar(const bitpit::Config::Section & rootXML){
45 
46  m_name = "mimmo.ReconstructScalar";
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.ReconstructScalar"){
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 
102 
109  return m_overlapCriterium;
110 }
111 
117  return static_cast<int>(m_overlapCriterium);
118 }
119 
124 int
126  return m_subpatch.size();
127 }
128 
133 dmpvector1D *
135  return &m_result;
136 };
137 
142 std::vector<dmpvector1D *>
144 
145  std::vector<dmpvector1D *> res;
146  res.reserve(m_subresults.size());
147  for(dmpvector1D & 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 
174 
179 void
181  if(!field) return;
182  if(field->getGeometry()== nullptr && field->getDataLocation() != m_loc) return;
183  if(field->getGeometry()->getType()==3 && m_loc==MPVLocation::CELL){
184  (*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;
185  return;
186  }
187  m_subpatch.push_back(*field);
188 
189 };
190 
195 void
197  //in m_subpatch remove progressively all pierced vector elements in last position
198  //which links towards a geometry of type patch.
199  while(m_subpatch.back().getGeometry() == patch){
200  m_subpatch.pop_back();
201  }
202 
203  //start searching from the begin on element linking patch
204  std::vector<dmpvector1D>::iterator it = m_subpatch.begin();
205 
206  while(it != m_subpatch.end()){
207  if (it->getGeometry() == patch){
208  *it = m_subpatch.back();
209  m_subpatch.pop_back();
210  //be always sure the last element is clean and does not link
211  // the patch
212  while(m_subpatch.back().getGeometry() == patch){
213  m_subpatch.pop_back();
214  }
215  }
216  ++it; //forward the iterator.
217  }
218 };
219 
223 void
225  m_subpatch.clear();
226  m_result.clear();
227  m_subresults.clear();
228 };
229 
233 void
236  removeAllData();
237  m_overlapCriterium = OverlapMethod::MAX;
238 }
239 
243 void
245 
246  m_result.setName("field");
247  write(m_result.getGeometry(), m_result);
248 
249 };
250 
255 void
257 
258  std::string originalname = m_name;
259  m_name = originalname + "SubPatch"+std::to_string(i);
260  m_subresults[i].setName("field");
261  write(m_subresults[i].getGeometry(), m_subresults[i]);
262  m_name = originalname;
263 
264 };
265 
270 void
272 
273  if(getGeometry() == nullptr){
274  (*m_log)<<m_name + " : nullptr pointer to linked geometry found"<<std::endl;
275  throw std::runtime_error("Error in "+m_name + " : nullptr pointer to linked geometry found");
276  }
277 
278  //Overlap fields
279  m_result.clear();
280  m_result.setGeometry(getGeometry());
281  m_result.setDataLocation(m_loc);
282 
283  m_subresults.clear();
284 
285  std::unordered_set<long> idsTarget;
286  {
287  livector1D ids = idsGeoDataLocation(getGeometry());
288  idsTarget.insert(ids.begin(), ids.end());
289  }
290 
291  bitpit::PiercedVector<int> counter;
292  for (int i=0; i<getNData(); i++){
293  dmpvector1D* pv = &m_subpatch[i];
294  livector1D ids = idsGeoDataLocation(pv->getGeometry());
295  for (auto ID: ids){
296  if(idsTarget.count(ID)==0) continue;
297 
298  if (!m_result.exists(ID)){
299  m_result.insert(ID, (*pv)[ID]);
300  counter.insert(ID, 1);
301  }
302  else{
303  overlapFields(ID, (*pv)[ID]);
304  counter[ID]++;
305  }
306  }
307  }
308 
309  if (m_overlapCriterium == OverlapMethod::AVERAGE){
310  long int ID;
311  auto itend = m_result.end();
312  for (auto it=m_result.begin(); it!=itend; ++it){
313  ID = it.getId();
314  (*it) = (*it) / double(counter[ID]);
315  }
316  }
317 
318  //Update field on whole geometry
319  if(!m_result.completeMissingData(0.0) ){
320  (*m_log)<<"Warning in "<<m_name<<". It seems a reconstruct field with values uncoherent with target geometry is generated."<<std::endl;
321  }
322 
323  //Create subresults
324  m_subresults.resize(getNData());
325  for (int i=0; i<getNData(); i++){
326  dmpvector1D* pv = &m_subpatch[i];
327  m_subresults[i].setGeometry(pv->getGeometry());
328  m_subresults[i].setDataLocation(m_loc);
329  livector1D ids = idsGeoDataLocation(pv->getGeometry());
330  for (auto ID : ids){
331  if(idsTarget.count(ID)>0){
332  m_subresults[i].insert(ID, m_result[ID]);
333  }
334  }
335  }
336 }
337 
342  plotData();
343  for (int i=0; i<getNData(); i++){
344  plotSubData(i);
345  }
346 }
347 
355 //DEVELOPERS REMIND if more overlap methods are added refer to this method to implement them
356 void
357 ReconstructScalar::overlapFields(long int ID, double & locField){
358 
359  switch(m_overlapCriterium){
360  case OverlapMethod::MAX :
361  {
362  double actual = m_result[ID];
363  double dummy = locField;
364 
365  if (actual < dummy)
366  m_result[ID] = locField;
367  }
368  break;
369  case OverlapMethod::MIN :
370  {
371  double actual = m_result[ID];
372  double dummy = locField;
373 
374  if (actual > dummy)
375  m_result[ID] = locField;
376  }
377  break;
379  m_result[ID] += locField;
380  break;
381  case OverlapMethod::SUM :
382  m_result[ID] += locField;
383  break;
384  default : //never been reached
385  break;
386  }
387 
388 };
389 
393 void
395 
396  bool built = true;
397 
398  //input
399  built = (built && createPortIn<mimmo::MimmoSharedPointer<MimmoObject>, ReconstructScalar>(&m_geometry, M_GEOM, true));
400  built = (built && createPortIn<dmpvector1D*, ReconstructScalar>(this, &mimmo::ReconstructScalar::addData, M_SCALARFIELD, true));
401 
402  //output
403  built = (built && createPortOut<dmpvector1D*, ReconstructScalar>(this, &ReconstructScalar::getResultField, M_SCALARFIELD));
404  built = (built && createPortOut<mimmo::MimmoSharedPointer<MimmoObject>, ReconstructScalar>(&m_geometry, M_GEOM));
405  built = (built && createPortOut<std::vector<dmpvector1D*>, ReconstructScalar>(this, &mimmo::ReconstructScalar::getResultFields, M_VECSCALARFIELDS));
406  m_arePortsBuilt = built;
407 };
408 
414 void
415 ReconstructScalar::absorbSectionXML(const bitpit::Config::Section & slotXML, std::string name){
416 
417  BITPIT_UNUSED(name);
418 
419  if(slotXML.hasOption("DataLocation")){
420  std::string input = slotXML.get("DataLocation");
421  input = bitpit::utils::string::trim(input);
422  int temp = -1;
423  if(!input.empty()){
424  std::stringstream ss(input);
425  ss>>temp;
426  }
427  if(int(m_loc) != temp){
428  (*m_log)<<"Error absorbing DataLocation in "<<m_name<<". Class and read locations mismatch"<<std::endl;
429  if (temp == 0) (*m_log)<<"XML DataLocation in "<<m_name<<" is set to 0-UNDEFINED"<<std::endl;
430  if (temp == 3) (*m_log)<<"XML DataLocation in "<<m_name<<" is set to 3-INTERFACE, not supported for now."<<std::endl;
431  throw std::runtime_error (m_name + " : xml absorbing failed.");
432  }
433  }
434  //start absorbing
435  BaseManipulation::absorbSectionXML(slotXML, name);
436 
437  if(slotXML.hasOption("OverlapCriterium")){
438  std::string input = slotXML.get("OverlapCriterium");
439  input = bitpit::utils::string::trim(input);
440  int value = 1;
441  if(!input.empty()){
442  std::stringstream ss(input);
443  ss >> value;
444  value = std::min(std::max(1, value),4);
445  }
446  setOverlapCriterium(value);
447  }
448 };
449 
455 void
456 ReconstructScalar::flushSectionXML(bitpit::Config::Section & slotXML, std::string name){
457 
458  BITPIT_UNUSED(name);
459  BaseManipulation::flushSectionXML(slotXML, name);
460 
461  slotXML.set("DataLocation", std::to_string(int(m_loc)));
462  int value = static_cast<int>(m_overlapCriterium);
463  slotXML.set("OverlapCriterium", std::to_string(value));
464 
465 };
466 
473 livector1D ReconstructScalar::idsGeoDataLocation(mimmo::MimmoSharedPointer<MimmoObject> geo){
474 
475  if (m_loc == MPVLocation::POINT) return geo->getVertices().getIds();
476  if (m_loc == MPVLocation::CELL) return geo->getCells().getIds();
477  return livector1D(0);
478 }
479 
480 }
Reconstruct a scalar field from daughter meshes to mother mesh.
OverlapMethod
class for setting overlapping criterium for two different fields
#define M_GEOM
MPVLocation
Define data location for the MimmoPiercedVector field.
OverlapMethod getOverlapCriteriumENUM()
void setName(std::string name)
std::vector< long > livector1D
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
bool completeMissingData(const mpv_t &defValue)
void warningXML(bitpit::Logger *log, std::string name)
BaseManipulation is the base class of any manipulation object of the library.
MimmoSharedPointer< MimmoObject > getGeometry() const
void write(MimmoSharedPointer< MimmoObject > geometry)
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
ReconstructScalar(MPVLocation loc=MPVLocation::POINT)
std::vector< dmpvector1D * > getResultFields()
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
MimmoSharedPointer< MimmoObject > m_geometry
void removeData(mimmo::MimmoSharedPointer< MimmoObject >)
void swap(ReconstructScalar &) noexcept
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
void setDataLocation(MPVLocation loc)
#define M_SCALARFIELD
#define M_VECSCALARFIELDS
void addData(dmpvector1D *)
MimmoSharedPointer is a custom implementation of shared pointer.
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
MimmoSharedPointer< MimmoObject > getGeometry()
void swap(BaseManipulation &x) noexcept
void setOverlapCriteriumENUM(OverlapMethod)