gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelAutoExtrude.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 <vector>
7 #include "GmshMessage.h"
8 #include "GModel.h"
9 #include "Context.h"
10 #include "ExtrudeParams.h"
11 
12 static bool sameDir(const SVector3 &v1, const SVector3 &v2)
13 {
14  const double tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
15  if(std::abs(v1.x() - v2.x()) < tol &&
16  std::abs(v1.y() - v2.y()) < tol &&
17  std::abs(v1.z() - v2.z()) < tol) return true;
18  return false;
19 }
20 
21 static bool sortDirCount(const std::pair<SVector3, int> &a,
22  const std::pair<SVector3, int> &b)
23 {
24  return (a.second > b.second);
25 }
26 
27 class extrudeInfo {
28 private:
32  void _fillExtrudeParams(ExtrudeParams *ep, int sourceTag,
33  const std::vector<int> &numElements,
34  const std::vector<double> &heights,
35  const bool recombine)
36  {
38  0, 0, 0, 0, 0, 0, 0);
39  ep->geo.Source = sourceTag;
40  if(numElements.size()) {
41  ep->mesh.ExtrudeMesh = true;
42  ep->mesh.NbElmLayer = numElements;
43  ep->mesh.hLayer = heights;
44  if(ep->mesh.hLayer.empty()) {
45  ep->mesh.NbLayer = numElements.size();
46  for(int i = 0; i < ep->mesh.NbLayer; i++) {
47  ep->mesh.hLayer.push_back((i + 1.) / ep->mesh.NbLayer);
48  }
49  }
50  else {
51  ep->mesh.NbLayer = heights.size();
52  }
53  ep->mesh.Recombine = recombine;
54  }
55  }
57  {
58  if(ep1->geo.Mode != ep2->geo.Mode) return false;
59  if(ep1->geo.Type != ep2->geo.Type) return false;
60  if(ep1->geo.Source != ep2->geo.Source) return false;
61  for(int i = 0; i < 3; i++) {
62  if(ep1->geo.trans[i] != ep2->geo.trans[i]) return false;
63  }
64  if(ep1->mesh.ExtrudeMesh && ep2->mesh.ExtrudeMesh) {
65  if(ep1->mesh.NbElmLayer != ep2->mesh.NbElmLayer) return false;
66  if(ep1->mesh.hLayer != ep2->mesh.hLayer) return false;
67  if(ep1->mesh.NbLayer != ep2->mesh.NbLayer) return false;
68  }
69  return true;
70  }
71 
72 public:
74  : _region(r), _sourceFace(s), _targetFace(t), _direction(d)
75  {}
77  void print()
78  {
79  Msg::Info("Volume %d reverse-engineered as extruded from surface %d "
80  "to surface %d along (%g, %g, %g)", _region->tag(),
82  _direction.y(), _direction.z());
83  }
84 
85  bool fillExtrudeParams(const std::vector<int> &numElements,
86  const std::vector<double> &heights,
87  const bool recombine,
88  bool checkOnly)
89  {
90  auto se = _sourceFace->edges();
91  std::set<GEdge *, GEntityPtrLessThan> sourceEdges(se.begin(), se.end());
92  auto te = _targetFace->edges();
93  std::set<GEdge *, GEntityPtrLessThan> targetEdges(te.begin(), te.end());
94 
95  // volume
96  {
98  _fillExtrudeParams(ep, _sourceFace->tag(), numElements, heights, recombine);
101  Msg::Warning("Incompatible extrusion parameters on volume %d",
102  _region->tag());
103  delete ep;
104  return false;
105  }
106  }
107  if(checkOnly)
108  delete ep;
109  else
111  }
112 
113  // top surface
114  {
116  _fillExtrudeParams(ep, _sourceFace->tag(), numElements, heights, recombine);
119  Msg::Warning("Incompatible extrusion parameters on surface %d",
120  _targetFace->tag());
121  delete ep;
122  return false;
123  }
124  }
125  if(checkOnly)
126  delete ep;
127  else
129  }
130 
131  // lateral surfaces and top curves
132  std::vector<GFace *> regionFaces = _region->faces();
133  for(auto e : _sourceFace->edges()) {
134  auto f = e->faces();
135  std::set<GFace *, GEntityPtrLessThan> edgeFaces(f.begin(), f.end());
136  for(auto f : regionFaces) {
137  if(f == _sourceFace || f == _targetFace) continue;
138  if(edgeFaces.find(f) != edgeFaces.end()) {
139  // lateral surface
141  _fillExtrudeParams(ep, e->tag(), numElements, heights, recombine);
142  if(f->meshAttributes.extrude) {
143  if(!_isCompatible(f->meshAttributes.extrude, ep)) {
144  Msg::Warning("Incompatible extrusion parameters on surface %d",
145  f->tag());
146  delete ep;
147  return false;
148  }
149  }
150  if(checkOnly)
151  delete ep;
152  else
153  f->meshAttributes.extrude = ep;
154  // top curve
155  for(auto fe : f->edges()) {
156  if(targetEdges.find(fe) != targetEdges.end()) {
158  _fillExtrudeParams(ep, e->tag(), numElements, heights, recombine);
159  if(fe->meshAttributes.extrude) {
160  if(!_isCompatible(fe->meshAttributes.extrude, ep)) {
161  Msg::Warning("Incompatible extrusion parameters on curve %d",
162  fe->tag());
163  delete ep;
164  return false;
165  }
166  }
167  if(checkOnly)
168  delete ep;
169  else
170  fe->meshAttributes.extrude = ep;
171  }
172  }
173  }
174  }
175  }
176 
177  // lateral curves
178  std::vector<GEdge *> regionEdges = _region->edges();
179  for(auto v : _sourceFace->vertices()) {
180  auto ve = v->edges();
181  std::set<GEdge*, GEntityPtrLessThan> vertexEdges(ve.begin(), ve.end());
182  for(auto e : regionEdges) {
183  if(sourceEdges.find(e) != sourceEdges.end()) continue;
184  if(targetEdges.find(e) != targetEdges.end()) continue;
185  if(vertexEdges.find(e) != vertexEdges.end()) {
187  _fillExtrudeParams(ep, v->tag(), numElements, heights, recombine);
188  if(e->meshAttributes.extrude) {
189  if(!_isCompatible(e->meshAttributes.extrude, ep)) {
190  Msg::Warning("Incompatible extrusion parameters on curve %d",
191  e->tag());
192  delete ep;
193  return false;
194  }
195  }
196  if(checkOnly)
197  delete ep;
198  else
199  e->meshAttributes.extrude = ep;
200  }
201  }
202  }
203 
204  return true;
205  }
206 };
207 
208 void getCandidateExtrudeInfo(GRegion *gr, std::vector<extrudeInfo> &info,
209  std::vector<std::pair<SVector3, int>> &count)
210 {
211  std::vector<GFace*> f = gr->faces();
212  for(auto f1 : f) {
213  auto f1v = f1->vertices();
214  auto f1e = f1->edges();
215  std::set<GVertex *, GEntityPtrLessThan> v1(f1v.begin(), f1v.end());
216  std::set<GEdge *, GEntityPtrLessThan> e1(f1e.begin(), f1e.end());
217  for(auto f2 : f) {
218  // for each pair of surfaces
219  if(f1 == f2) continue;
220 
221  Msg::Debug("Testing surface pair %d - %d:", f1->tag(), f2->tag());
222  auto f2v = f2->vertices();
223  auto f2e = f2->edges();
224  std::set<GVertex *, GEntityPtrLessThan> v2(f2v.begin(), f2v.end());
225  std::set<GEdge *, GEntityPtrLessThan> e2(f2e.begin(), f2e.end());
226  // abort if different topology
227  if((v1.size() != v2.size()) || (e1.size() != e2.size())) {
228  Msg::Debug(" - incompatible surfaces %d (#points=%lu, #curves=%lu) - "
229  "%d (#points=%lu, #curves=%lu)",
230  f1->tag(), v1.size(), e1.size(),
231  f2->tag(), v2.size(), e2.size());
232  continue;
233  }
234 
235  SVector3 t0(0., 0., 0.);
236  bool translated = true;
237 
238  std::set<GEdge*> perp;
239  for(auto e : gr->edges()) {
240  // skip curves that are on the boundary of the 2 surfaces
241  if(e1.find(e) != e1.end() || e2.find(e) != e2.end()) {
242  continue;
243  }
244  if((v1.find(e->getBeginVertex()) != v1.end() ||
245  v1.find(e->getEndVertex()) != v1.end()) &&
246  (v2.find(e->getBeginVertex()) != v2.end() ||
247  v2.find(e->getEndVertex()) != v2.end())) {
248  perp.insert(e);
249  }
250  }
251 
252  if(perp.size() != v1.size()) {
253  Msg::Debug(" - number of extruded curves differs from number of "
254  "source/target surface points (%lu != %lu)",
255  perp.size(), v1.size());
256  continue;
257  }
258 
259  if(perp.size() + e1.size() + e2.size() != gr->edges().size()) {
260  Msg::Debug(" - extra curves not connected to source/target surfaces");
261  continue;
262  }
263 
264  for(auto e : perp) {
265  // straight lines with the same translation vector?
266  if(e->geomType() == GEntity::Line) {
267  GVertex *vs = e->getBeginVertex(), *vt = e->getEndVertex();
268  if(vs && vt) {
269  SVector3 t;
270  if(v1.find(vs) != v1.end() && v2.find(vt) != v2.end()) {
271  t = SVector3(vs->xyz(), vt->xyz());
272  }
273  else if(v1.find(vt) != v1.end() && v2.find(vs) != v2.end()) {
274  t = SVector3(vt->xyz(), vs->xyz());
275  }
276  else {
277  // should not happen
278  translated = false;
279  break;
280  }
281  if(t0.norm() == 0.) t0 = t;
282  if(!sameDir(t0, t)) {
283  Msg::Debug(" - straight line t=(%g, %g, %g) != t0=(%g, %g, %g)",
284  t.x(), t.y(), t.z(), t0.x(), t0.y(), t0.z());
285  translated = false;
286  break;
287  }
288  }
289  }
290  else {
291  // TODO: could check here if all curves are circles to detect
292  // extrusions by rotation
293  translated = false;
294  break;
295  }
296  }
297  if(translated && t0.norm() != 0.) {
298  for(auto v : v1) {
299  // common point is impossible, abort
300  if(v2.find(v) != v2.end()) continue;
301  }
302  // we have a candidate pair for extrusion by translation
303  Msg::Debug("Volume %d possible extrusion candidate from surface %d to "
304  "surface %d along (%g, %g, %g)", gr->tag(), f1->tag(), f2->tag(),
305  t0.x(), t0.y(), t0.z());
306  info.push_back(extrudeInfo(gr, f1, f2, t0));
307  // ... increase the popularity of the potential extrusion direction
308  bool found = false;
309  for(std::size_t i = 0; i < count.size(); i++) {
310  if(sameDir(count[i].first, t0)) {
311  count[i].second++;
312  found = true;
313  break;
314  }
315  }
316  if(!found) count.push_back(std::make_pair(t0, 1));
317  }
318  }
319  }
320 }
321 
322 bool GModel::addAutomaticExtrusionConstraints(const std::vector<int> &numElements,
323  const std::vector<double> &heights,
324  const bool recombine,
325  const std::vector<int> &regionTags)
326 {
327  std::vector<GRegion *> regs;
328  if(regionTags.empty()) {
329  regs.insert(regs.end(), regions.begin(), regions.end());
330  }
331  else {
332  for(auto t : regionTags) {
333  GRegion *r = getRegionByTag(t);
334  if(r) regs.push_back(r);
335  else Msg::Error("Unknown volume %d for automatic extrusion constraints");
336  }
337  }
338 
339  // get pairs of surfaces that could be candidates for extrusion by translation
340  std::vector<extrudeInfo> candidates;
341  std::vector<std::pair<SVector3, int>> dirCount;
342  for(auto r : regs) getCandidateExtrudeInfo(r, candidates, dirCount);
343 
344  if(candidates.empty()) {
345  Msg::Info("No candidates found for automatic extrusion constraints");
346  return false;
347  }
348 
349  // sort the extrusion directions by popularity
350  std::sort(dirCount.begin(), dirCount.end(), sortDirCount);
351 
352  // keep candidates corresponding to the most popular extrusion direction
353  std::vector<extrudeInfo> matches;
354  for(auto c : candidates) {
355  if(sameDir(c.getDirection(), dirCount.front().first)) matches.push_back(c);
356  }
357 
358  // compute extrude information
359  for(auto m : matches) {
360  if(m.fillExtrudeParams(numElements, heights, recombine, true)) {
361  m.fillExtrudeParams(numElements, heights, recombine, false);
362  m.print();
363  }
364  }
365 
366  return true;
367 }
ExtrudeParams::trans
double trans[3]
Definition: ExtrudeParams.h:52
contextGeometryOptions::tolerance
double tolerance
Definition: Context.h:99
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
extrudeInfo::getDirection
SVector3 getDirection()
Definition: GModelAutoExtrude.cpp:76
extrudeInfo::fillExtrudeParams
bool fillExtrudeParams(const std::vector< int > &numElements, const std::vector< double > &heights, const bool recombine, bool checkOnly)
Definition: GModelAutoExtrude.cpp:85
extrudeInfo::print
void print()
Definition: GModelAutoExtrude.cpp:77
GFace
Definition: GFace.h:33
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GModel::addAutomaticExtrusionConstraints
bool addAutomaticExtrusionConstraints(const std::vector< int > &numElements, const std::vector< double > &heights, const bool recombine, const std::vector< int > &regionTag)
Definition: GModelAutoExtrude.cpp:322
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
GFace::extrude
ExtrudeParams * extrude
Definition: GFace.h:357
sortDirCount
static bool sortDirCount(const std::pair< SVector3, int > &a, const std::pair< SVector3, int > &b)
Definition: GModelAutoExtrude.cpp:21
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
COPIED_ENTITY
#define COPIED_ENTITY
Definition: ExtrudeParams.h:18
GFace::meshAttributes
struct GFace::@18 meshAttributes
SVector3
Definition: SVector3.h:16
GmshMessage.h
ExtrudeParams::geo
struct ExtrudeParams::@15 geo
extrudeInfo::_targetFace
GFace * _targetFace
Definition: GModelAutoExtrude.cpp:30
getCandidateExtrudeInfo
void getCandidateExtrudeInfo(GRegion *gr, std::vector< extrudeInfo > &info, std::vector< std::pair< SVector3, int >> &count)
Definition: GModelAutoExtrude.cpp:208
GFace::vertices
virtual std::vector< GVertex * > vertices() const
Definition: GFace.cpp:390
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
GRegion::extrude
ExtrudeParams * extrude
Definition: GRegion.h:148
extrudeInfo::_direction
SVector3 _direction
Definition: GModelAutoExtrude.cpp:31
ExtrudeParams::mesh
struct ExtrudeParams::@14 mesh
extrudeInfo::_isCompatible
bool _isCompatible(ExtrudeParams *ep1, ExtrudeParams *ep2)
Definition: GModelAutoExtrude.cpp:56
EXTRUDED_ENTITY
#define EXTRUDED_ENTITY
Definition: ExtrudeParams.h:17
GVertex
Definition: GVertex.h:23
CTX::lc
double lc
Definition: Context.h:234
ExtrudeParams::fill
void fill(int type, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double angle)
Definition: ExtrudeParams.cpp:34
ExtrudeParams::NbLayer
int NbLayer
Definition: ExtrudeParams.h:39
GEntity::Line
@ Line
Definition: GEntity.h:92
ExtrudeParams.h
SVector3::norm
double norm() const
Definition: SVector3.h:33
ExtrudeParams::Recombine
bool Recombine
Definition: ExtrudeParams.h:37
GRegion::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GRegion.cpp:459
ExtrudeParams::Mode
int Mode
Definition: ExtrudeParams.h:49
extrudeInfo
Definition: GModelAutoExtrude.cpp:27
ExtrudeParams::NbElmLayer
std::vector< int > NbElmLayer
Definition: ExtrudeParams.h:40
GEntity::tag
int tag() const
Definition: GEntity.h:280
extrudeInfo::_fillExtrudeParams
void _fillExtrudeParams(ExtrudeParams *ep, int sourceTag, const std::vector< int > &numElements, const std::vector< double > &heights, const bool recombine)
Definition: GModelAutoExtrude.cpp:32
sameDir
static bool sameDir(const SVector3 &v1, const SVector3 &v2)
Definition: GModelAutoExtrude.cpp:12
SVector3::x
double x(void) const
Definition: SVector3.h:30
CTX::geom
contextGeometryOptions geom
Definition: Context.h:311
GRegion
Definition: GRegion.h:28
ExtrudeParams::ExtrudeMesh
bool ExtrudeMesh
Definition: ExtrudeParams.h:36
ExtrudeParams::Source
int Source
Definition: ExtrudeParams.h:51
extrudeInfo::_region
GRegion * _region
Definition: GModelAutoExtrude.cpp:29
Context.h
SVector3::y
double y(void) const
Definition: SVector3.h:31
GVertex::xyz
virtual SPoint3 xyz() const
Definition: GVertex.h:43
GRegion::meshAttributes
struct GRegion::@20 meshAttributes
SVector3::z
double z(void) const
Definition: SVector3.h:32
GModel::regions
std::set< GRegion *, GEntityPtrLessThan > regions
Definition: GModel.h:143
ExtrudeParams::Type
int Type
Definition: ExtrudeParams.h:50
GModel.h
GModel::getRegionByTag
GRegion * getRegionByTag(int n) const
Definition: GModel.cpp:316
TRANSLATE
#define TRANSLATE
Definition: ExtrudeParams.h:21
ExtrudeParams
Definition: ExtrudeParams.h:26
ExtrudeParams::hLayer
std::vector< double > hLayer
Definition: ExtrudeParams.h:41
extrudeInfo::_sourceFace
GFace * _sourceFace
Definition: GModelAutoExtrude.cpp:30
extrudeInfo::extrudeInfo
extrudeInfo(GRegion *r, GFace *s, GFace *t, SVector3 d)
Definition: GModelAutoExtrude.cpp:73