Create3DCurve.cpp
1 /*----------------------------------------------------------------------------*\
2  *
3  * mimmo
4  *
5  * Optimad Engineering S.r.l. ("COMPANY") CONFIDENTIAL
6  * Copyright (c) 2015-2021 Optimad Engineering S.r.l., All Rights Reserved.
7  *
8  * --------------------------------------------------------------------------
9  *
10  * NOTICE: All information contained herein is, and remains the property
11  * of COMPANY. The intellectual and technical concepts contained herein are
12  * proprietary to COMPANY and may be covered by Italian and Foreign Patents,
13  * patents in process, and are protected by trade secret or copyright law.
14  * Dissemination of this information or reproduction of this material is
15  * strictly forbidden unless prior written permission is obtained from
16  * COMPANY. Access to the source code contained herein is hereby forbidden
17  * to anyone except current COMPANY employees, managers or contractors who
18  * have executed Confidentiality and Non-disclosure agreements explicitly
19  * covering such access.
20  *
21  * The copyright notice above does not evidence any actual or intended
22  * publication or disclosure of this source code, which includes information
23  * that is confidential and/or proprietary, and is a trade secret, of
24  * COMPANY. ANY REPRODUCTION, MODIFICATION, DISTRIBUTION, PUBLIC PERFORMANCE,
25  * OR PUBLIC DISPLAY OF OR THROUGH USE OF THIS SOURCE CODE WITHOUT THE
26  * EXPRESS WRITTEN CONSENT OF COMPANY IS STRICTLY PROHIBITED, AND IN
27  * VIOLATION OF APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR
28  * POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT CONVEY
29  * OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS CONTENTS, OR
30  * TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY DESCRIBE, IN WHOLE OR
31  * IN PART.
32  *
33 \*----------------------------------------------------------------------------*/
34 
35 #include "Create3DCurve.hpp"
36 #include <queue>
37 
38 namespace mimmo{
39 
44  m_name = "mimmo.Create3DCurve";
45  m_closed = false;
46  m_nCells = 0;
47 };
48 
53 Create3DCurve::Create3DCurve(const bitpit::Config::Section & rootXML){
54 
55  m_name = "mimmo.Create3DCurve";
56  m_closed = false;
57  m_nCells = 0;
58 
59  std::string fallback_name = "ClassNONE";
60  std::string input = rootXML.get("ClassName", fallback_name);
61  input = bitpit::utils::string::trim(input);
62  if(input == "mimmo.Create3DCurve"){
63  absorbSectionXML(rootXML);
64  }else{
66  };
67 }
68 
73 
79  m_closed = other.m_closed;
80  m_nCells = other.m_nCells;
81  m_rawpoints = other.m_rawpoints;
82  m_rawvector = other.m_rawvector;
83  m_rawscalar = other.m_rawscalar;
84 };
85 
91  swap(other);
92  return *this;
93 };
94 
100 {
101  std::swap(m_nCells, x.m_nCells);
102  std::swap(m_closed , x.m_closed);
103  m_rawpoints.swap(x.m_rawpoints);
104  m_rawscalar.swap(x.m_rawscalar);
105  m_rawvector.swap(x.m_rawvector);
106  m_scalarfield.swap(x.m_scalarfield);
107  m_vectorfield.swap(x.m_vectorfield);
108 
110 }
111 
115 void
117  bool built = true;
118 
119  built = (built && createPortIn<dvecarr3E, Create3DCurve>(this, &mimmo::Create3DCurve::setRawPoints, M_COORDS, true,1));
120  built = (built && createPortIn<dvecarr3E, Create3DCurve>(this, &mimmo::Create3DCurve::setRawVectorField, M_DISPLS));
121  built = (built && createPortIn<dvector1D, Create3DCurve>(this, &mimmo::Create3DCurve::setRawScalarField, M_DATAFIELD));
122 
123  built = (built && createPortIn<dmpvecarr3E*, Create3DCurve>(this, &mimmo::Create3DCurve::setRawPoints, M_VECTORFIELD, true,1));
124  built = (built && createPortIn<dmpvecarr3E*, Create3DCurve>(this, &mimmo::Create3DCurve::setRawVectorField, M_VECTORFIELD2));
125  built = (built && createPortIn<dmpvector1D*, Create3DCurve>(this, &mimmo::Create3DCurve::setRawScalarField, M_SCALARFIELD));
126 
127  built = (built && createPortOut<MimmoSharedPointer<MimmoObject>, Create3DCurve>(this, &mimmo::Create3DCurve::getGeometry, M_GEOM));
128  built = (built && createPortOut<dmpvector1D*, Create3DCurve>(this, &mimmo::Create3DCurve::getScalarField, M_SCALARFIELD));
129  built = (built && createPortOut<dmpvecarr3E*, Create3DCurve>(this, &mimmo::Create3DCurve::getVectorField, M_VECTORFIELD));
130 
131  m_arePortsBuilt = built;
132 }
133 
140  return &m_scalarfield;
141 };
142 
149  return &m_vectorfield;
150 };
151 
152 
157 void
159  if(rawPoints) m_rawpoints = *rawPoints;
160 };
161 
166 void
168  m_rawpoints.clear();
169  m_rawpoints.reserve(rawPoints.size());
170  long count(0);
171  for(std::array<double,3> &val : rawPoints){
172  m_rawpoints.insert(count, val);
173  ++count;
174  }
175 };
176 
181 void
183  if(rawVectorField) m_rawvector = *rawVectorField;
184 };
185 
190 void
192  m_rawvector.clear();
193  m_rawvector.reserve(rawVectorField.size());
194  long count(0);
195  for(std::array<double,3> &val : rawVectorField){
196  m_rawvector.insert(count, val);
197  ++count;
198  }
199 };
200 
205 void
207  if(rawScalarField) m_rawscalar = *rawScalarField;
208 };
209 
214 void
216  m_rawscalar.clear();
217  m_rawscalar.reserve(rawScalarField.size());
218  long count(0);
219  for(double &val : rawScalarField){
220  m_rawscalar.insert(count, val);
221  ++count;
222  }
223 };
224 
228 void
232  m_rawscalar.clear();
233  m_rawvector.clear();
234  m_rawpoints.clear();
235  m_nCells = 0;
236  m_closed = false;
238 }
239 
240 
244 bool
246  return m_closed;
247 }
248 
253 void
255  m_closed = flag;
256 }
257 
265 void
267  m_nCells = ncells;
268 }
269 
270 
276 void Create3DCurve::absorbSectionXML(const bitpit::Config::Section & slotXML, std::string name){
277 
278  BITPIT_UNUSED(name);
279 
280  std::string input;
281 
282  BaseManipulation::absorbSectionXML(slotXML, name);
283 
284  if(slotXML.hasOption("ClosedLoop")){
285  input = slotXML.get("ClosedLoop");
286  bool flag = false;
287  if(!input.empty()){
288  std::stringstream ss(bitpit::utils::string::trim(input));
289  ss >> flag;
290  }
291  setClosedLoop(flag);
292  };
293 
294  if(slotXML.hasOption("nCells")){
295  input = slotXML.get("nCells");
296  int value = 0;
297  if(!input.empty()){
298  std::stringstream ss(bitpit::utils::string::trim(input));
299  ss >> value;
300  }
301  setNCells(value);
302  };
303 
304 };
305 
311 void Create3DCurve::flushSectionXML(bitpit::Config::Section & slotXML, std::string name){
312 
313  BITPIT_UNUSED(name);
314 
315  BaseManipulation::flushSectionXML(slotXML, name);
316 
317  slotXML.set("ClosedLoop", std::to_string(int(m_closed)));
318  slotXML.set("nCells", std::to_string(int(m_nCells)));
319 };
320 
324 void
326 
327  if (getGeometry() == nullptr) return;
329 }
330 
331 
335 void
337 
338  int np = int(m_rawpoints.size());
339 
340 #if MIMMO_ENABLE_MPI
341  // Rawpoints can be shared among all procs or retained by 0 only.
342  // The condition is that rank 0 must have the input points, because
343  // the geometry is filled only by master processor 0. The only useful
344  // points are those owned by rank 0.
345  // Check if rank 0 owns some points (not communicated to the other processors).
346  MPI_Bcast(&np, 1, MPI_INT, 0, m_communicator);
347 #endif
348 
349  if(np == 0){
350  (*m_log)<< "Warning in "<<m_name<<" : no raw points to work on"<<std::endl;
351  }
352 
353  m_nCells = std::max(m_nCells, (np - 1 + int(m_closed)));
354 
355  //create a brand new 3DCurve container
356  {
358  m_geometry = dum;
359  }
360 
361  // prepare connectivity of curve and handling refinement if needed
362  // then fill the curve container
363  dmpvecarr3E points, vector;
364  dmpvector1D scalar;
365  std::unordered_map<long, std::array<long,2> > connectivity;
366 #if MIMMO_ENABLE_MPI
367  //leave the job to the master rank
368  if(getRank() == 0)
369 #endif
370  {
371  points = m_rawpoints;
372  scalar.reserve(points.size());
373  vector.reserve(points.size());
374  for(auto it= points.begin(); it!= points.end(); ++it){
375 
376  auto itscalar = scalar.insert(it.getId(), 0.0);
377  if(m_rawscalar.exists(it.getId())){
378  *itscalar = m_rawscalar[it.getId()];
379  }
380  auto itvector = vector.insert(it.getId(), {{0., 0.,0.}});
381  if(m_rawvector.exists(it.getId())){
382  *itvector = m_rawvector[it.getId()];
383  }
384 
385  }
386 
387  int furtherCells = fillPreliminaryStructure(points, connectivity);
388  refineObject(points, scalar, vector, connectivity, furtherCells);
389 
390  m_geometry->getPatch()->reserveVertices(points.size());
391  m_geometry->getPatch()->reserveCells(connectivity.size());
392 
393  long id;
394  for(auto it= points.begin(); it != points.end(); ++it){
395  id = it.getId();
396  m_geometry->addVertex(*it, id);
397  }
398 
399  for(auto & tuple : connectivity){
400  m_geometry->addConnectedCell(livector1D(tuple.second.begin(),tuple.second.end()), bitpit::ElementType::LINE, 0, tuple.first, 0);
401  }
402 
403  }
404 
405  //initialize and fill the final fields
406  m_scalarfield.initialize(m_geometry,MPVLocation::POINT, 0.);
407  m_scalarfield.setName("3DCurveScalar");
408 
409  m_vectorfield.initialize(m_geometry,MPVLocation::POINT, {{0.,0.,0.}});
410  m_vectorfield.setName("3DCurveVector");
411 
412  for(auto it=scalar.begin(); it!=scalar.end(); ++it){
413  if(m_scalarfield.exists(it.getId())) m_scalarfield[it.getId()] = *it;
414  }
415  for(auto it=vector.begin(); it!=vector.end(); ++it){
416  if(m_vectorfield.exists(it.getId())) m_vectorfield[it.getId()] = *it;
417  }
418 
419  m_geometry->update();
420 };
421 
422 
429 int
430 Create3DCurve::fillPreliminaryStructure(dmpvecarr3E & points, std::unordered_map<long, std::array<long,2> > &connectivity){
431  int nVerts = (int) points.size();
432  int nCells = nVerts -1 + (int) m_closed;
433  int res = std::max(0, (m_nCells - nCells));
434 
435  auto itP = points.begin();
436  int countCell(0);
437  while (countCell < (nCells -(int)m_closed)){
438  connectivity[countCell][0] = itP.getId();
439  ++itP;
440  connectivity[countCell][1] = itP.getId();
441  ++countCell;
442  }
443 
444  if(m_closed){
445  itP = points.begin();
446  auto itE = points.end();
447  --itE;
448  connectivity[nCells-1][0] = itE.getId();
449  connectivity[nCells-1][1] = itP.getId();
450  }
451 
452  return (res);
453 }
454 
466 void
467 Create3DCurve::refineObject(dmpvecarr3E & points, dmpvector1D & scalarf, dmpvecarr3E & vectorf, std::unordered_map<long, std::array<long,2> > &connectivity, int fCells){
468  if ( fCells == 0) return;
469 
470  greatDist mycomp;
471  double dist;
472 
473  long idV(0);
474  {
475  livector1D ids = points.getIds();
476  if(!ids.empty()) idV = *(std::max_element(ids.begin(), ids.end()));
477  };
478  long idC(0);
479  std::vector<std::pair<double, long>> values;
480  values.reserve(int(connectivity.size()) + fCells);
481  for (auto &conn : connectivity){
482  dist = norm2(points[conn.second[1]] - points[conn.second[0]]);
483  values.push_back(std::make_pair(dist, conn.first));
484  idC = std::max(idC, conn.first);
485  }
486 
487  //prep your priority queue
488  std::priority_queue<std::pair<double,long>, std::vector<std::pair<double,long>>, greatDist > pQue(mycomp, values);
489 
490  int counterCell = 0;
491  darray3E point;
492  while (counterCell < fCells){
493 
494  //extract the longest segment
495  auto pp = pQue.top();
496  pQue.pop();
497 
498  idV++;
499  idC++;
500  //divide it by two and create a new point
501  point = 0.5*(points[connectivity[pp.second][1]] + points[connectivity[pp.second][0]]);
502  points.insert(idV, point);
503  //update scalar and vector
504  scalarf.insert(idV, 0.5*(scalarf[connectivity[pp.second][1]] + scalarf[connectivity[pp.second][0]]));
505  vectorf.insert(idV, 0.5*(vectorf[connectivity[pp.second][1]] + vectorf[connectivity[pp.second][0]]));
506 
507  //update connectivity
508  connectivity[idC]= {{ idV, connectivity[pp.second][1] }};
509  connectivity[pp.second][1] = idV;
510 
511  //update the priority queue
512  pQue.push(std::make_pair(0.5*pp.first, pp.second));
513  pQue.push(std::make_pair(0.5*pp.first, idC));
514 
515  //adding a new cell to the count;
516  ++counterCell;
517  }
518 };
519 
520 
521 }
dmpvector1D * getScalarField()
void swap(Create3DCurve &x) noexcept
#define M_DATAFIELD
MimmoObject is the basic geometry container for mimmo library.
#define M_DISPLS
#define M_GEOM
void setClosedLoop(bool flag)
std::vector< darray3E > dvecarr3E
std::vector< long > livector1D
Create a 3DCurve from a point cloud.
void warningXML(bitpit::Logger *log, std::string name)
BaseManipulation is the base class of any manipulation object of the library.
#define M_VECTORFIELD
void setRawVectorField(dvecarr3E rawVectorField)
void write(MimmoSharedPointer< MimmoObject > geometry)
void setNCells(int nCells)
virtual void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
void setRawPoints(dvecarr3E rawPoints)
std::vector< double > dvector1D
virtual void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
void setRawScalarField(dvector1D rawScalarField)
MimmoSharedPointer< MimmoObject > m_geometry
mimmo::MimmoPiercedVector< double > dmpvector1D
void flushSectionXML(bitpit::Config::Section &slotXML, std::string name="")
#define M_SCALARFIELD
std::array< double, 3 > darray3E
#define M_VECTORFIELD2
Create3DCurve & operator=(Create3DCurve other)
MimmoSharedPointer is a custom implementation of shared pointer.
MimmoSharedPointer< MimmoObject > getGeometry()
dmpvecarr3E * getVectorField()
void swap(BaseManipulation &x) noexcept
#define M_COORDS
void absorbSectionXML(const bitpit::Config::Section &slotXML, std::string name="")
mimmo::MimmoPiercedVector< darray3E > dmpvecarr3E