IOCloudPoints.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 "IOCloudPoints.hpp"
26 
27 namespace mimmo {
28 
34  m_name = "mimmo.IOCloudPoints";
35  m_read = readMode;
36  m_template = false;
37  m_dir = ".";
38  m_filename = m_name+"_source.dat";
39 };
40 
45 IOCloudPoints::IOCloudPoints(const bitpit::Config::Section & rootXML){
46 
47  m_name = "mimmo.IOCloudPoints";
48  m_template = false;
49  m_dir = ".";
50  m_filename = m_name+"_source.dat";
51  m_read = true;
52 
53  std::string fallback_name = "ClassNONE";
54  std::string input = rootXML.get("ClassName", fallback_name);
55  input = bitpit::utils::string::trim(input);
56 
57  std::string fallback_name2 = "1";
58  std::string input2 = rootXML.get("IOmode", fallback_name2);
59  input2 = bitpit::utils::string::trim(input2);
60 
61  m_read = bool(std::atoi(input2.c_str()));
62 
63  if(input == "mimmo.IOCloudPoints"){
64  absorbSectionXML(rootXML);
65  }else{
67  };
68 }
69 
70 
71 IOCloudPoints::~IOCloudPoints(){};
72 
77  m_read = other.m_read;
78  m_dir = other.m_dir;
79  m_filename = other.m_filename;
80  m_template = other.m_template;
81 };
82 
86  swap(other);
87  return *this;
88 };
89 
95 {
96  std::swap(m_read , x.m_read);
97  std::swap(m_dir , x.m_dir);
98  std::swap(m_filename , x.m_filename);
99  std::swap(m_template , x.m_template);
100  std::swap(m_labels , x.m_labels);
101  std::swap(m_points , x.m_points);
102  m_scalarfield.swap(x.m_scalarfield);
103  m_vectorfield.swap(x.m_vectorfield);
105 }
106 
110 void
112  bool built = true;
113 
114  built = (built && createPortIn<dmpvector1D*, IOCloudPoints>(this, &mimmo::IOCloudPoints::setScalarField, M_SCALARFIELD));
115  built = (built && createPortIn<dmpvecarr3E*, IOCloudPoints>(this, &mimmo::IOCloudPoints::setVectorField, M_VECTORFIELD));
116  built = (built && createPortIn<MimmoSharedPointer<MimmoObject>, IOCloudPoints>(this, &mimmo::IOCloudPoints::setGeometry, M_GEOM));
117 
118  built = (built && createPortOut<MimmoSharedPointer<MimmoObject>, IOCloudPoints>(this, &mimmo::IOCloudPoints::getGeometry, M_GEOM));
119  built = (built && createPortOut<dmpvector1D*, IOCloudPoints>(this, &mimmo::IOCloudPoints::getScalarField, M_SCALARFIELD));
120  built = (built && createPortOut<dmpvecarr3E*, IOCloudPoints>(this, &mimmo::IOCloudPoints::getVectorField, M_VECTORFIELD));
121 
122  m_arePortsBuilt = built;
123 }
124 
131  return &m_scalarfield;
132 };
133 
140  return &m_vectorfield;
141 };
142 
147 bool
149  return m_template;
150 };
151 
156 void
157 IOCloudPoints::setReadDir(std::string dir){
158  if(!m_read) return;
159  m_dir = dir;
160 };
161 
166 void
167 IOCloudPoints::setReadFilename(std::string filename){
168  if(!m_read) return;
169  m_filename = filename;
170 };
171 
176 void
177 IOCloudPoints::setWriteDir(std::string dir){
178  if(m_read) return;
179  m_dir = dir;
180 };
181 
186 void
188  // Check if geometry is a point cloud
189  if (geometry->getType() != 3) return;
190  m_geometry = geometry;
191 };
192 
197 void
198 IOCloudPoints::setWriteFilename(std::string filename){
199  if(m_read) return;
200  m_filename = filename;
201 };
202 
208 void
210  if(m_read) return;
211  m_scalarfield = *scalarfield;
212 };
213 
219 void
221  if(m_read) return;
222  m_vectorfield = *vectorfield;
223 };
224 
225 
230 void
232  if(m_read) return;
233  m_template = flag;
234 };
235 
239 void
243  m_template = false;
244  m_filename = m_name+"_source.dat";
246 }
247 
252 void
254  if(m_read){
255  read();
256  }else{
257  write();
258  }
259 };
260 
266 void
267 IOCloudPoints::absorbSectionXML(const bitpit::Config::Section & slotXML, std::string name){
268 
269  BITPIT_UNUSED(name);
270 
271  std::string input;
272 
273  //checking IOmode
274 
275  if(slotXML.hasOption("IOmode")){
276  input = slotXML.get("IOmode");
277  bool value = true;
278  if(!input.empty()){
279  std::stringstream ss(bitpit::utils::string::trim(input));
280  ss>>value;
281  }
282  if (m_read != value){
283  (*m_log)<< "warning in class "<<m_name<<": cannot absorb xml parameters for class IOmode mismatching"<<std::endl;
284  throw std::runtime_error (m_name + " : xml absorbing failed ");
285  }
286  };
287 
288  BaseManipulation::absorbSectionXML(slotXML, name);
289 
290  if(m_read){
291  if(slotXML.hasOption("ReadDir")){
292  std::string input = slotXML.get("ReadDir");
293  input = bitpit::utils::string::trim(input);
294  setReadDir(input);
295  };
296 
297  if(slotXML.hasOption("ReadFilename")){
298  std::string input = slotXML.get("ReadFilename");
299  input = bitpit::utils::string::trim(input);
300  setReadFilename(input);
301  };
302  }else{
303  if(slotXML.hasOption("WriteDir")){
304  std::string input = slotXML.get("WriteDir");
305  input = bitpit::utils::string::trim(input);
306  setWriteDir(input);
307  };
308 
309  if(slotXML.hasOption("WriteFilename")){
310  std::string input = slotXML.get("WriteFilename");
311  input = bitpit::utils::string::trim(input);
312  setWriteFilename(input);
313  };
314  }
315 
316 
317  if(slotXML.hasOption("Template")){
318  std::string input = slotXML.get("Template");
319  input = bitpit::utils::string::trim(input);
320  bool temp = false;
321  if(!input.empty()){
322  std::stringstream ss(input);
323  ss>>temp;
324  }
325  setTemplate(temp);
326  };
327 
328 }
329 
335 void
336 IOCloudPoints::flushSectionXML(bitpit::Config::Section & slotXML, std::string name){
337 
338  BITPIT_UNUSED(name);
339 
340  BaseManipulation::flushSectionXML(slotXML, name);
341 
342  slotXML.set("IOmode", std::to_string(int(m_read)));
343 
344  if(m_read){
345  slotXML.set("ReadDir", m_dir);
346  slotXML.set("ReadFilename", m_filename);
347  }else{
348  slotXML.set("WriteDir", m_dir);
349  slotXML.set("WriteFilename", m_filename);
350  }
351 
352  slotXML.set("Template", std::to_string(int(m_template)));
353 };
354 
355 
359 void
361 
362  if (getGeometry() == nullptr) return;
363  //Assessing data;
366 
367  if (!f1.getGeometry()) f1.setGeometry(getGeometry());
368  if (!f2.getGeometry()) f2.setGeometry(getGeometry());
369  //force both data to have location on POINT, otherwise all these class is pointless
372  f1.completeMissingData(0.0);
373  f2.completeMissingData({{0.0,0.0,0.0}});
374 
375  if(f1.getName() == f2.getName()){
376  std::string temp = f1.getName();
377  f1.setName(temp+"_scalar");
378 
379  temp = f2.getName();
380  f2.setName(temp+"_vector");
381 
382  }
383  //Write
385 }
386 
390 void
391 IOCloudPoints::read(){
392 
393  m_points.clear();
394  m_labels.clear();
397 
398  // Instantiate a new MimmoObject of type point cloud
399  m_geometry.reset(new MimmoObject(3));
400 
401 #if MIMMO_ENABLE_MPI
402  // Leave the reading only to the master rank
403  if(getRank() == 0)
404 #endif
405  {
406 
407  std::unordered_map<long, int> mapP;
408  std::ifstream reading;
409  std::string source = m_dir+"/"+m_filename;
410  reading.open(source.c_str());
411  if(reading.is_open()){
412 
413  std::string keyword, line;
414  long label;
415  darray3E dtrial;
416  double temp;
417 
418  do{
419  line.clear();
420  keyword.clear();
421  std::getline(reading,line);
422  line = bitpit::utils::string::trim(line);
423  std::stringstream ss(line);
424  ss>>keyword;
425  keyword = bitpit::utils::string::trim(keyword);
426  if(keyword == "$POINT") {
427 
428  ss>>label;
429  m_labels.push_back(label);
430 
431  dtrial.fill(0.0);
432  ss>>dtrial[0]>>dtrial[1]>>dtrial[2];
433  m_points.push_back(dtrial);
434  }
435 
436  }while(!reading.eof());
437 
438  int counter = 0;
439  for(auto &lab :m_labels){
440  mapP[lab] = counter;
441  ++counter;
442  }
443 
444  m_scalarfield.reserve(m_points.size());
445  m_vectorfield.reserve(m_points.size());
446 
447  reading.clear();
448  reading.seekg(0, std::ios::beg);
449 
450  do{
451  line.clear();
452  keyword.clear();
453  std::getline(reading,line);
454  line = bitpit::utils::string::trim(line);
455  std::stringstream ss(line);
456  ss>>keyword;
457  keyword = bitpit::utils::string::trim(keyword);
458  if(keyword == "$SCALARF") {
459 
460  ss>>label>>temp;
461  m_scalarfield.insert(mapP[label],temp);
462  }
463  if(keyword == "$VECTORF") {
464 
465  dtrial.fill(0.0);
466  ss>>label>>dtrial[0]>>dtrial[1]>>dtrial[2];
467  m_vectorfield.insert(mapP[label],dtrial);
468  }
469 
470  }while(!reading.eof());
471 
472  }else{
473  (*m_log)<<"error of "<<m_name<<" : cannot open "<<m_filename<< " requested. Exiting... "<<std::endl;
474  throw std::runtime_error (m_name + " : cannot open " + m_filename + " requested. Exiting... ");
475  }
476 
477  reading.close();
478 
479  }
480 
481  // Fill geometry
482 
483  // Fill geometry with point cloud list
484  // Only rank 0 read points, so only rank 0 enters the loop and fills its partition
485  std::size_t ind = 0;
486  for (darray3E & coords : m_points){
487  long label = m_labels[ind];
488  getGeometry()->addVertex(coords, label);
489  getGeometry()->addConnectedCell(livector1D(1,label), bitpit::ElementType::VERTEX, label);
490  ind++;
491  }
492 
493  getGeometry()->update();
494 
495  // Clear points and label structure
496  dvecarr3E().swap(m_points);
497  livector1D().swap(m_labels);
498 
499  // Set the mimmo pierced vectors
502  m_scalarfield.setName("scalarfield");
505  m_vectorfield.setName("vectorfield");
506 
507 };
508 
512 void
513 IOCloudPoints::write(){
514 
515  //assessing data;
518  //force both data to have location on POINT, otherwise all these class is pointless
521 
523  if(!m_vectorfield.empty()) m_vectorfield.completeMissingData({{0.0,0.0,0.0}});
524 
525  std::string filename;
526  if(m_template){
527  filename = "TEMPLATE_"+m_filename;
528  }else{
529  filename = m_filename;
530  }
531 
532  std::ofstream writing;
533  std::string source = m_dir+"/"+m_filename;
534  std::string keyT1 = "{", keyT2 = "}";
535 
536 #if MIMMO_ENABLE_MPI
537  // Write on the file in a sequential way
538  for (int irank = 0; irank < getGeometry()->getProcessorCount(); irank++){
539  if(getRank() == irank){
540 
541  // If parallel and not the first process open file in appending mode
542  if (getRank() == 0)
543  writing.open(source.c_str());
544  else
545  writing.open(source.c_str(), std::ofstream::out | std::ofstream::app);
546 #else
547  writing.open(source.c_str());
548 #endif
549 
550  if(writing.is_open()){
551 
552  MimmoSharedPointer<MimmoObject> geometry = getGeometry();
553  darray3E coords;
554  for(const long & label : geometry->getVerticesIds()){
555  coords = geometry->getVertexCoords(label);
556  writing<<"$POINT"<<'\t'<<label<<'\t'<<coords[0]<<'\t'<<coords[1]<<'\t'<<coords[2]<<std::endl;
557  }
558  writing<<""<<std::endl;
559 
560  for(const long & label : geometry->getVerticesIds()){
561  if(m_template){
562  std::string str1 = keyT1+"s"+std::to_string(label)+keyT2;
563  writing<<"$SCALARF"<<'\t'<<label<<'\t'<<str1<<std::endl;
564  }else{
565  if(!m_scalarfield.exists(label)) continue;
566  double val = m_scalarfield[label];
567  writing<<"$SCALARF"<<'\t'<<label<<'\t'<<val<<std::endl;
568  }
569  }
570  writing<<""<<std::endl;
571 
572  for(const long & label : geometry->getVerticesIds()){
573  if(m_template){
574  std::string str1 = keyT1+"x"+std::to_string(label)+keyT2;
575  std::string str2 = keyT1+"y"+std::to_string(label)+keyT2;
576  std::string str3 = keyT1+"z"+std::to_string(label)+keyT2;
577 
578  writing<<"$VECTORF"<<'\t'<<label<<'\t'<<str1<<'\t'<<str2<<'\t'<<str3<<std::endl;
579  }else{
580  if(!m_vectorfield.exists(label)) continue;
581  std::array<double,3> val = m_vectorfield[label];
582  writing<<"$VECTORF"<<'\t'<<label<<'\t'<<val[0]<<'\t'<<val[1]<<'\t'<<val[2]<<std::endl;
583  }
584  }
585  writing<<""<<std::endl;
586  }else{
587  (*m_log)<<"error of "<<m_name<<" : cannot open "<<m_filename<< " requested. Exiting... "<<std::endl;
588  throw std::runtime_error (m_name + " : cannot open " + m_filename + " requested. Exiting... ");
589  }
590 
591  writing.close();
592 #if MIMMO_ENABLE_MPI
593  } // End if rank is the current one that has to write and wait all
594 
595  MPI_Barrier(getCommunicator());
596 
597  }// End loop on processors to write sequentially
598 #endif
599 
600 };
601 
602 
603 }
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
void setReadFilename(std::string filename)
void setReadDir(std::string dir)
void setTemplate(bool flag)
MimmoObject is the basic geometry container for mimmo library.
#define M_GEOM
dmpvector1D * getScalarField()
void setGeometry(MimmoSharedPointer< MimmoObject > geometry)
std::vector< darray3E > dvecarr3E
void setName(std::string name)
std::vector< long > livector1D
dmpvecarr3E * getVectorField()
bool completeMissingData(const mpv_t &defValue)
void warningXML(bitpit::Logger *log, std::string name)
IOCloudPoints & operator=(IOCloudPoints other)
BaseManipulation is the base class of any manipulation object of the library.
void setVectorField(dmpvecarr3E *vectorfield)
#define M_VECTORFIELD
MimmoSharedPointer< MimmoObject > getGeometry() const
void write(MimmoSharedPointer< MimmoObject > geometry)
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
void setWriteFilename(std::string filename)
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
void setScalarField(dmpvector1D *scalarfield)
MimmoSharedPointer< MimmoObject > m_geometry
void setGeometry(MimmoSharedPointer< MimmoObject > geo)
void setDataLocation(MPVLocation loc)
#define M_SCALARFIELD
std::array< double, 3 > darray3E
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
IOCloudPoints is the class to read from file a set of cloud 3D points w/ attached a scalar field of f...
MimmoSharedPointer is a custom implementation of shared pointer.
void setWriteDir(std::string dir)
MimmoSharedPointer< MimmoObject > getGeometry()
void swap(BaseManipulation &x) noexcept
void swap(IOCloudPoints &x) noexcept
IOCloudPoints(bool readMode=true)