gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
Distance.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdlib.h>
7 #include "GmshGlobal.h"
8 #include "GmshConfig.h"
9 #include "GModel.h"
10 #include "OS.h"
11 #include "Distance.h"
12 #include "Context.h"
13 #include "Numeric.h"
14 
15 #if defined(HAVE_SOLVER)
16 #include "dofManager.h"
17 #include "linearSystemCSR.h"
18 #include "linearSystemFull.h"
19 #include "linearSystemPETSc.h"
20 #include "distanceTerm.h"
21 #endif
22 
23 template <class scalar> class simpleFunction;
24 
26  {GMSH_FULLRC, "PhysicalPoint", nullptr, 0.},
27  {GMSH_FULLRC, "PhysicalLine", nullptr, 0.},
28  {GMSH_FULLRC, "PhysicalSurface", nullptr, 0.},
29  {GMSH_FULLRC, "DistanceType", nullptr, 0},
30  {GMSH_FULLRC, "MinScale", nullptr, 0},
31  {GMSH_FULLRC, "MaxScale", nullptr, 0}};
32 
33 extern "C" {
35 }
36 
38 {
39  _maxDim = 0;
40  _data = nullptr;
41 }
42 
43 std::string GMSH_DistancePlugin::getHelp() const
44 {
45  return "Plugin(Distance) computes distances to entities in a mesh.\n\n"
46  "If `PhysicalPoint', `PhysicalLine' and `PhysicalSurface' are 0, the "
47  "distance is computed to all the boundaries. Otherwise the distance "
48  "is computed to the given physical group.\n\n"
49  "If `DistanceType' is 0, the plugin computes the geometrical "
50  "Euclidean "
51  "distance using the naive O(N^2) algorithm. If `DistanceType' > 0, "
52  "the plugin computes an approximate distance by solving a PDE with "
53  "a diffusion constant equal to `DistanceType' time the maximum size "
54  "of the bounding box of the mesh as in [Legrand et al. 2006].\n\n"
55  "Positive `MinScale' and `MaxScale' scale the distance function.\n\n"
56  "Plugin(Distance) creates one new list-based view.";
57 }
58 
60 {
61  return sizeof(DistanceOptions_Number) / sizeof(StringXNumber);
62 }
63 
65 {
66  return &DistanceOptions_Number[iopt];
67 }
68 
69 void GMSH_DistancePlugin::printView(std::vector<GEntity *> &entities,
70  std::map<MVertex *, double> &distanceMap)
71 {
72  double minScale = (double)DistanceOptions_Number[4].def;
73  double maxScale = (double)DistanceOptions_Number[5].def;
74 
75  double minDist = 1.e22;
76  double maxDist = 0.0;
77  for(auto itv = distanceMap.begin(); itv != distanceMap.end(); ++itv) {
78  double dist = itv->second;
79  if(dist > maxDist) maxDist = dist;
80  if(dist < minDist) minDist = dist;
81  itv->second = dist;
82  }
83 
84  for(std::size_t ii = 0; ii < entities.size(); ii++) {
85  if(entities[ii]->dim() == _maxDim) {
86  for(std::size_t i = 0; i < entities[ii]->getNumMeshElements(); i++) {
87  MElement *e = entities[ii]->getMeshElement(i);
88  std::size_t numNodes = e->getNumPrimaryVertices();
89  if(e->getNumChildren())
90  numNodes = e->getNumChildren() * e->getChild(0)->getNumVertices();
91  std::vector<double> x(numNodes), y(numNodes), z(numNodes);
92  std::vector<double> *out =
93  _data->incrementList(1, e->getType(), numNodes);
94  std::vector<MVertex *> nods;
95 
96  if(!e->getNumChildren())
97  for(std::size_t i = 0; i < numNodes; i++)
98  nods.push_back(e->getVertex(i));
99  else
100  for(int i = 0; i < e->getNumChildren(); i++)
101  for(std::size_t j = 0; j < e->getChild(i)->getNumVertices(); j++)
102  nods.push_back(e->getChild(i)->getVertex(j));
103 
104  for(std::size_t nod = 0; nod < numNodes; nod++)
105  out->push_back((nods[nod])->x());
106  for(std::size_t nod = 0; nod < numNodes; nod++)
107  out->push_back((nods[nod])->y());
108  for(std::size_t nod = 0; nod < numNodes; nod++)
109  out->push_back((nods[nod])->z());
110 
111  std::vector<double> dist;
112  for(std::size_t j = 0; j < numNodes; j++) {
113  MVertex *v = nods[j];
114  auto it = distanceMap.find(v);
115  dist.push_back(it->second);
116  }
117 
118  for(std::size_t i = 0; i < dist.size(); i++) {
119  if(minScale > 0 && maxScale > 0 && maxDist != minDist)
120  dist[i] = minScale + ((dist[i] - minDist) / (maxDist - minDist)) *
121  (maxScale - minScale);
122  else if(minScale > 0)
123  dist[i] = minScale + dist[i];
124  out->push_back(dist[i]);
125  }
126  }
127  }
128  }
129 }
130 
132 {
133  int id_point = (int)DistanceOptions_Number[0].def;
134  int id_line = (int)DistanceOptions_Number[1].def;
135  int id_face = (int)DistanceOptions_Number[2].def;
136  double type = (double)DistanceOptions_Number[3].def;
137 
138  GModel *m = GModel::current();
139  int totNumNodes = m->getNumMeshVertices();
140  if(!totNumNodes) {
141  Msg::Error("Plugin(Distance) needs a mesh");
142  return v;
143  }
144 
145  PView *view = new PView();
146  _data = getDataList(view);
147 
148  _maxDim = m->getMeshDim();
149 
150  std::vector<GEntity *> entities;
151  m->getEntities(entities);
152 
153  std::vector<SPoint3> pts(totNumNodes);
154  std::vector<double> distances(totNumNodes, 1.e22);
155  std::vector<MVertex *> pt2Vertex(totNumNodes);
156  std::map<MVertex *, double> distanceMap;
157 
158  std::size_t k = 0;
159  for(std::size_t i = 0; i < entities.size(); i++) {
160  GEntity *ge = entities[i];
161  for(std::size_t j = 0; j < ge->mesh_vertices.size(); j++) {
162  MVertex *v = ge->mesh_vertices[j];
163  pts[k] = SPoint3(v->x(), v->y(), v->z());
164  pt2Vertex[k] = v;
165  distanceMap.insert(std::make_pair(v, 0.0));
166  k++;
167  }
168  }
169 
170  if(type <= 0.0) { // Compute geometrical distance to mesh boundaries
171  bool existEntity = false;
172  for(std::size_t i = 0; i < entities.size(); i++) {
173  GEntity *g2 = entities[i];
174  int gDim = g2->dim();
175  bool computeForEntity = false;
176  if(!id_point && !id_line && !id_face && gDim == _maxDim - 1) {
177  computeForEntity = true;
178  }
179  else {
180  std::vector<int> phys = g2->getPhysicalEntities();
181  for(std::size_t k = 0; k < phys.size(); k++) {
182  if((phys[k] == id_point && gDim == 0) ||
183  (phys[k] == id_line && gDim == 1) ||
184  (phys[k] == id_face && gDim == 2)) {
185  computeForEntity = true;
186  break;
187  }
188  }
189  }
190  if(computeForEntity) {
191  existEntity = true;
192  for(std::size_t k = 0; k < g2->getNumMeshElements(); k++) {
193  std::vector<double> iDistances;
194  std::vector<SPoint3> iClosePts;
195  std::vector<double> iDistancesE;
196  MElement *e = g2->getMeshElement(k);
197  MVertex *v1 = e->getVertex(0);
198  MVertex *v2 = e->getVertex(1);
199  SPoint3 p1(v1->x(), v1->y(), v1->z());
200  SPoint3 p2(v2->x(), v2->y(), v2->z());
201  if(e->getType() == TYPE_LIN) {
202  signedDistancesPointsLine(iDistances, iClosePts, pts, p1, p2);
203  }
204  else if(e->getType() == TYPE_TRI) {
205  MVertex *v3 = e->getVertex(2);
206  SPoint3 p3(v3->x(), v3->y(), v3->z());
207  signedDistancesPointsTriangle(iDistances, iClosePts, pts, p1, p2,
208  p3);
209  }
210  for(std::size_t kk = 0; kk < pts.size(); kk++) {
211  if(std::abs(iDistances[kk]) < distances[kk]) {
212  distances[kk] = std::abs(iDistances[kk]);
213  MVertex *v = pt2Vertex[kk];
214  distanceMap[v] = distances[kk];
215  }
216  }
217  }
218  }
219  }
220  if(!existEntity) {
221  if(id_point) Msg::Warning("Physical Point %d does not exist", id_point);
222  if(id_line) Msg::Warning("Physical Curve %d does not exist", id_line);
223  if(id_face) Msg::Warning("Physical Surface %d does not exist", id_face);
224  }
225  else {
226  printView(entities, distanceMap);
227  }
228  }
229  else { // Compute PDE for distance function
230 #if defined(HAVE_SOLVER)
231 #if defined(HAVE_PETSC)
233 #elif defined(HAVE_GMM)
235 #else
237 #endif
238  dofManager<double> *dofView = new dofManager<double>(lsys);
239 
240  bool existEntity = false;
241  SBoundingBox3d bbox;
242  for(std::size_t i = 0; i < entities.size(); i++) {
243  GEntity *ge = entities[i];
244  int gDim = ge->dim();
245  bool fixForEntity = false;
246  if(!id_point && !id_line && !id_face && gDim == _maxDim - 1) {
247  fixForEntity = true;
248  }
249  else {
250  std::vector<int> phys = ge->getPhysicalEntities();
251  for(std::size_t k = 0; k < phys.size(); k++) {
252  if((phys[k] == id_point && gDim == 0) ||
253  (phys[k] == id_line && gDim == 1) ||
254  (phys[k] == id_face && gDim == 2)) {
255  fixForEntity = true;
256  break;
257  }
258  }
259  }
260  if(fixForEntity) {
261  existEntity = true;
262  for(std::size_t i = 0; i < ge->getNumMeshElements(); ++i) {
263  MElement *t = ge->getMeshElement(i);
264  for(std::size_t k = 0; k < t->getNumVertices(); k++) {
265  MVertex *v = t->getVertex(k);
266  dofView->fixVertex(v, 0, 1, 0.);
267  bbox += SPoint3(v->x(), v->y(), v->z());
268  }
269  }
270  }
271  }
272  if(!existEntity) {
273  if(id_point) Msg::Warning("Physical Point %d does not exist", id_point);
274  if(id_line) Msg::Warning("Physical Curve %d does not exist", id_line);
275  if(id_face) Msg::Warning("Physical Surface %d does not exist", id_face);
276  }
277  else {
278  std::vector<MElement *> allElems;
279  for(std::size_t ii = 0; ii < entities.size(); ii++) {
280  if(entities[ii]->dim() == _maxDim) {
281  GEntity *ge = entities[ii];
282  for(std::size_t i = 0; i < ge->getNumMeshElements(); ++i) {
283  MElement *t = ge->getMeshElement(i);
284  allElems.push_back(t);
285  for(std::size_t k = 0; k < t->getNumVertices(); k++)
286  dofView->numberVertex(t->getVertex(k), 0, 1);
287  }
288  }
289  }
290  double L = norm(SVector3(bbox.max(), bbox.min()));
291  double mu = type * L;
292  simpleFunction<double> DIFF(mu * mu), ONE(1.0);
293  distanceTerm distance(GModel::current(), 1, &DIFF, &ONE);
294  for(auto it = allElems.begin(); it != allElems.end(); it++) {
295  SElement se((*it));
296  distance.addToMatrix(*dofView, &se);
297  }
298  groupOfElements gr(allElems);
299  distance.addToRightHandSide(*dofView, gr);
300  lsys->systemSolve();
301  for(auto itv = distanceMap.begin(); itv != distanceMap.end(); ++itv) {
302  MVertex *v = itv->first;
303  double value;
304  dofView->getDofValue(v, 0, 1, value);
305  value = std::min(0.9999, value);
306  double dist = -mu * log(1. - value);
307  itv->second = dist;
308  }
309  printView(entities, distanceMap);
310  }
311  delete lsys;
312  delete dofView;
313 #endif
314  }
315 
316  _data->setName("distance");
317  _data->Time.push_back(0);
318  _data->setFileName("distance.pos");
319  _data->finalize();
320  return view;
321 }
linearSystemFull
Definition: linearSystemFull.h:17
PView
Definition: PView.h:27
distance
double distance(MVertex *v1, MVertex *v2)
Definition: MVertex.h:245
GModel::getNumMeshVertices
std::size_t getNumMeshVertices(int dim=-1) const
Definition: GModel.cpp:1529
linearSystemPETSc
Definition: linearSystemPETSc.h:150
TYPE_LIN
#define TYPE_LIN
Definition: GmshDefines.h:65
GMSH_Plugin
Definition: Plugin.h:26
GMSH_RegisterDistancePlugin
GMSH_Plugin * GMSH_RegisterDistancePlugin()
Definition: Distance.cpp:34
OS.h
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
PViewDataList::incrementList
std::vector< double > * incrementList(int numComp, int type, int numNodes=0)
Definition: PViewDataList.cpp:1243
linearSystemPETSc.h
SPoint3
Definition: SPoint3.h:14
StringXNumber
Definition: Options.h:918
signedDistancesPointsLine
void signedDistancesPointsLine(std::vector< double > &distances, std::vector< SPoint3 > &closePts, const std::vector< SPoint3 > &pts, const SPoint3 &p1, const SPoint3 &p2)
Definition: Numeric.cpp:923
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
SVector3
Definition: SVector3.h:16
TYPE_TRI
#define TYPE_TRI
Definition: GmshDefines.h:66
linearSystemCSR.h
DistanceOptions_Number
StringXNumber DistanceOptions_Number[]
Definition: Distance.cpp:25
groupOfElements
Definition: groupOfElements.h:24
GModel::getMeshDim
int getMeshDim() const
Definition: GModel.cpp:998
GMSH_DistancePlugin
Definition: Distance.h:17
GEntity
Definition: GEntity.h:31
PViewData::setFileName
virtual void setFileName(const std::string &val)
Definition: PViewData.h:75
signedDistancesPointsTriangle
void signedDistancesPointsTriangle(std::vector< double > &distances, std::vector< SPoint3 > &closePts, const std::vector< SPoint3 > &pts, const SPoint3 &p1, const SPoint3 &p2, const SPoint3 &p3)
Definition: Numeric.cpp:822
MElement::getNumVertices
virtual std::size_t getNumVertices() const =0
MElement::getVertex
virtual const MVertex * getVertex(int num) const =0
dofManager::numberVertex
void numberVertex(MVertex *v, int iComp, int iField)
Definition: dofManager.h:231
simpleFunction
Definition: GModel.h:30
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
MElement::getType
virtual int getType() const =0
MElement::getNumChildren
virtual int getNumChildren() const
Definition: MElement.h:234
GEntity::getNumMeshElements
virtual std::size_t getNumMeshElements() const
Definition: GEntity.h:348
GMSH_DistancePlugin::execute
PView * execute(PView *)
Definition: Distance.cpp:131
GMSH_FULLRC
#define GMSH_FULLRC
Definition: Options.h:20
linearSystemFull::systemSolve
virtual int systemSolve()
Definition: linearSystemFull.h:77
norm
void norm(const double *vec, double *norm)
Definition: gmshLevelset.cpp:202
Numeric.h
GModel
Definition: GModel.h:44
GMSH_DistancePlugin::getOption
StringXNumber * getOption(int iopt)
Definition: Distance.cpp:64
SElement
Definition: SElement.h:18
GMSH_DistancePlugin::printView
void printView(std::vector< GEntity * > &entities, std::map< MVertex *, double > &distance_map)
Definition: Distance.cpp:69
PViewDataList::finalize
bool finalize(bool computeMinMax=true, const std::string &interpolationScheme="")
Definition: PViewDataList.cpp:81
PViewData::setName
virtual void setName(const std::string &val)
Definition: PViewData.h:71
dofManager< double >
distanceTerm
Definition: distanceTerm.h:11
MElement
Definition: MElement.h:30
dofManager.h
linearSystemFull.h
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
linearSystemCSRGmm
Definition: linearSystemCSR.h:176
GmshGlobal.h
dofManager::getDofValue
virtual void getDofValue(std::vector< Dof > &keys, std::vector< dataVec > &Vals)
Definition: dofManager.h:235
distanceTerm.h
GMSH_DistancePlugin::getNbOptions
int getNbOptions() const
Definition: Distance.cpp:59
GMSH_DistancePlugin::_maxDim
int _maxDim
Definition: Distance.h:19
Context.h
GEntity::getMeshElement
virtual MElement * getMeshElement(std::size_t index) const
Definition: GEntity.h:363
MElement::getChild
virtual MElement * getChild(int i) const
Definition: MElement.h:235
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MElement::getNumPrimaryVertices
std::size_t getNumPrimaryVertices() const
Definition: MElement.h:160
GMSH_DistancePlugin::GMSH_DistancePlugin
GMSH_DistancePlugin()
Definition: Distance.cpp:37
PViewDataList::Time
std::vector< double > Time
Definition: PViewDataList.h:25
GEntity::getPhysicalEntities
virtual std::vector< int > getPhysicalEntities()
Definition: GEntity.h:288
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
ElementType::getNumVertices
int getNumVertices(int type)
Definition: ElementType.cpp:456
Distance.h
GMSH_DistancePlugin::_data
PViewDataList * _data
Definition: Distance.h:20
GMSH_DistancePlugin::getHelp
std::string getHelp() const
Definition: Distance.cpp:43
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
dofManager::fixVertex
void fixVertex(MVertex const *v, int iComp, int iField, const dataVec &value)
Definition: dofManager.h:170
SBoundingBox3d
Definition: SBoundingBox3d.h:21
GModel::current
static GModel * current(int index=-1)
Definition: GModel.cpp:136
MVertex::x
double x() const
Definition: MVertex.h:60
GMSH_PostPlugin::getDataList
virtual PViewDataList * getDataList(PView *view, bool showError=true)
Definition: Plugin.cpp:107