1 // Gmsh - Copyright (C) 1997-2021 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 "BGMBase.h"
7 
8 #include <iostream>
9 #include "OS.h"
10 #include "GPoint.h"
11 #include "GFace.h"
12 #include "GmshDefines.h"
13 #include "MElementOctree.h"
14 
export_scalar(const std::string & filename,const DoubleStorageType & _whatToPrint) const15 void BGMBase::export_scalar(const std::string &filename,
16                             const DoubleStorageType &_whatToPrint) const
17 {
18   FILE *f = Fopen(filename.c_str(), "w");
19   if(!f) {
20     Msg::Error("Could not open file '%s'", filename.c_str());
21     return;
22   }
23 
24   fprintf(f, "View \"Background Mesh\"{\n");
25 
26   const MElement *elem;
27   int nvertex;
28   int type;
29 
30   for(unsigned int i = 0; i < getNumMeshElements(); i++) {
31     elem = getElement(i);
32     nvertex = elem->getNumVertices();
33     type = elem->getType();
34     const char *s = 0;
35     switch(type) {
36     case TYPE_PNT: s = "SP"; break;
37     case TYPE_LIN: s = "SL"; break;
38     case TYPE_TRI: s = "ST"; break;
39     case TYPE_QUA: s = "SQ"; break;
40     case TYPE_TET: s = "SS"; break;
41     case TYPE_HEX: s = "SH"; break;
42     case TYPE_PRI: s = "SI"; break;
43     case TYPE_PYR: s = "SY"; break;
44     default: throw;
45     }
46 
47     fprintf(f, "%s(", s);
48     const MVertex *v;
49     std::vector<double> values(nvertex);
50     for(int iv = 0; iv < nvertex; iv++) {
51       v = elem->getVertex(iv);
52       values[iv] = get_nodal_value(v, _whatToPrint);
53       // GPoint p = gf->point(SPoint2(v->x(),v->y()));
54       GPoint p = get_GPoint_from_MVertex(v);
55       fprintf(f, "%g,%g,%g", p.x(), p.y(), p.z());
56       if(iv != nvertex - 1)
57         fprintf(f, ",");
58       else
59         fprintf(f, "){");
60     }
61     for(int iv = 0; iv < nvertex; iv++) {
62       fprintf(f, "%g", values[iv]);
63       if(iv != nvertex - 1)
64         fprintf(f, ",");
65       else
66         fprintf(f, "};\n");
67     }
68   }
69   fprintf(f, "};\n");
70   fclose(f);
71 }
72 
export_vector(const std::string & filename,const VectorStorageType & _whatToPrint) const73 void BGMBase::export_vector(const std::string &filename,
74                             const VectorStorageType &_whatToPrint) const
75 {
76   FILE *f = Fopen(filename.c_str(), "w");
77   if(!f) {
78     Msg::Error("Could not open file '%s'", filename.c_str());
79     return;
80   }
81 
82   fprintf(f, "View \"Background Mesh\"{\n");
83 
84   const MElement *elem;
85   int nvertex;
86   int type;
87 
88   for(unsigned int i = 0; i < getNumMeshElements(); i++) {
89     elem = getElement(i);
90     nvertex = elem->getNumVertices();
91     type = elem->getType();
92     const char *s = 0;
93     switch(type) {
94     case TYPE_PNT: s = "VP"; break;
95     case TYPE_LIN: s = "VL"; break;
96     case TYPE_TRI: s = "VT"; break;
97     case TYPE_QUA: s = "VQ"; break;
98     case TYPE_TET: s = "VS"; break;
99     case TYPE_HEX: s = "VH"; break;
100     case TYPE_PRI: s = "VI"; break;
101     case TYPE_PYR: s = "VY"; break;
102     default: throw;
103     }
104 
105     fprintf(f, "%s(", s);
106     const MVertex *v;
107     std::vector<double> values(nvertex * 3);
108     for(int iv = 0; iv < nvertex; iv++) {
109       v = elem->getVertex(iv);
110       std::vector<double> temp = get_nodal_value(v, _whatToPrint);
111       for(int j = 0; j < 3; j++) values[iv * 3 + j] = temp[j];
112       GPoint p = get_GPoint_from_MVertex(v);
113       fprintf(f, "%g,%g,%g", p.x(), p.y(), p.z());
114       if(iv != nvertex - 1)
115         fprintf(f, ",");
116       else
117         fprintf(f, "){");
118     }
119     for(int iv = 0; iv < nvertex; iv++) {
120       for(int j = 0; j < 3; j++) {
121         fprintf(f, "%g", values[iv * 3 + j]);
122         if(!((iv == nvertex - 1) && (j == 2)))
123           fprintf(f, ",");
124         else
125           fprintf(f, "};\n");
126       }
127     }
128   }
129   fprintf(f, "};\n");
130   fclose(f);
131 }
132 
export_tensor_as_vectors(const std::string & filename,const TensorStorageType & _whatToPrint) const133 void BGMBase::export_tensor_as_vectors(
134   const std::string &filename, const TensorStorageType &_whatToPrint) const
135 {
136   FILE *f = Fopen(filename.c_str(), "w");
137   if(!f) {
138     Msg::Error("Could not open file '%s'", filename.c_str());
139     return;
140   }
141 
142   fprintf(f, "View \"Background Mesh\"{\n");
143 
144   TensorStorageType::const_iterator it = _whatToPrint.begin();
145   const char *s = "VP";
146 
147   for(; it != _whatToPrint.end(); it++) { // for all vertices
148     GPoint p = get_GPoint_from_MVertex(it->first);
149     for(int i = 0; i < 3; i++) {
150       fprintf(f, "%s(%g,%g,%g){%g,%g,%g};\n", s, p.x(), p.y(), p.z(),
151               (it->second)(0, i), (it->second)(1, i), (it->second)(2, i));
152       fprintf(f, "%s(%g,%g,%g){%g,%g,%g};\n", s, p.x(), p.y(), p.z(),
153               -(it->second)(0, i), -(it->second)(1, i), -(it->second)(2, i));
154     }
155   }
156   fprintf(f, "};\n");
157   fclose(f);
158 }
159 
BGMBase(int dim,GEntity * _gf)160 BGMBase::BGMBase(int dim, GEntity *_gf)
161   : octree(NULL), gf(_gf), DIM(dim), order(1)
162 {
163 }
164 
~BGMBase()165 BGMBase::~BGMBase() {}
166 
inDomain(double u,double v,double w)167 bool BGMBase::inDomain(double u, double v, double w)
168 {
169   return (findElement(u, v, w) != NULL);
170 }
171 
findElement(double u,double v,double w,bool strict)172 const MElement *BGMBase::findElement(double u, double v, double w, bool strict)
173 {
174   return (getOctree()->find(u, v, w, DIM, strict));
175 }
176 
get_field_value(double u,double v,double w,const VectorStorageType & data)177 std::vector<double> BGMBase::get_field_value(double u, double v, double w,
178                                              const VectorStorageType &data)
179 {
180   // TODO C++11 remove const_cast and enforce const-correctness otherwise
181   MElement *e = const_cast<MElement *>(findElement(u, v, w));
182 
183   if(!e) return std::vector<double>(3, -1000.);
184 
185   std::vector<std::vector<double> > val = get_nodal_values(e, data);
186   std::vector<double> element_uvw = get_element_uvw_from_xyz(e, u, v, w);
187 
188   std::vector<double> res(3);
189 
190   for(int j = 0; j < 3; j++) {
191     std::vector<double> values(e->getNumVertices());
192 
193     for(std::size_t i = 0; i < e->getNumVertices(); i++) {
194       values[i] = val[i][j];
195     }
196     res[j] = e->interpolate(&values[0], element_uvw[0], element_uvw[1],
197                             element_uvw[2], 1, order);
198   }
199   return res;
200 }
201 
get_field_value(double u,double v,double w,const DoubleStorageType & data)202 double BGMBase::get_field_value(double u, double v, double w,
203                                 const DoubleStorageType &data)
204 {
205   // TODO C++11 Remove const_cast
206   MElement *e = const_cast<MElement *>(findElement(u, v, w));
207   if(!e) return -1000.;
208   std::vector<double> val = get_nodal_values(e, data);
209   std::vector<double> element_uvw = get_element_uvw_from_xyz(e, u, v, w);
210   std::vector<double> values(e->getNumVertices());
211   for(std::size_t i = 0; i < e->getNumVertices(); i++) values[i] = val[i];
212 
213   return e->interpolate(&values[0], element_uvw[0], element_uvw[1],
214                         element_uvw[2], 1, order);
215 }
216 
size(double u,double v,double w)217 double BGMBase::size(double u, double v, double w)
218 {
219   return get_field_value(u, v, w, sizeField);
220 }
221 
size(const MVertex * v)222 double BGMBase::size(const MVertex *v) { return get_nodal_value(v, sizeField); }
223 
224 std::vector<double>
get_nodal_value(const MVertex * v,const VectorStorageType & data) const225 BGMBase::get_nodal_value(const MVertex *v, const VectorStorageType &data) const
226 {
227   VectorStorageType::const_iterator itfind = data.find(v);
228   if(itfind == data.end()) {
229     Msg::Error("Unknown vertex %d in BGMBase::get_nodal_value", v->getNum());
230     return std::vector<double>(3, 0.);
231   }
232   return itfind->second;
233 }
234 
get_nodal_value(const MVertex * v,const DoubleStorageType & data) const235 double BGMBase::get_nodal_value(const MVertex *v,
236                                 const DoubleStorageType &data) const
237 {
238   DoubleStorageType::const_iterator itfind = data.find(v);
239   if(itfind == data.end()) {
240     Msg::Error("Unknown vertex %d in BGMBase::get_nodal_value", v->getNum());
241     return 0.;
242   }
243   return itfind->second;
244 }
245 
246 std::vector<std::vector<double> >
get_nodal_values(const MElement * e,const VectorStorageType & data) const247 BGMBase::get_nodal_values(const MElement *e,
248                           const VectorStorageType &data) const
249 {
250   std::vector<std::vector<double> > res(e->getNumVertices());
251 
252   for(std::size_t i = 0; i < e->getNumVertices(); i++) {
253     VectorStorageType::const_iterator itfind =
254       data.find(const_cast<MVertex *>(e->getVertex(i)));
255     for(int j = 0; j < 3; j++) res[i].push_back((itfind->second)[j]);
256   }
257   return res;
258 }
259 
260 std::vector<double>
get_nodal_values(const MElement * element,const DoubleStorageType & data) const261 BGMBase::get_nodal_values(const MElement *element,
262                           const DoubleStorageType &data) const
263 {
264   std::vector<double> res(element->getNumVertices(), 0.);
265 
266   for(std::size_t i = 0; i < element->getNumVertices(); i++)
267     // res[i] = (data.find(const_cast<MVertex*>(e->getVertex(i))))->second;
268     res[i] = data.find(element->getVertex(i))->second;
269   return res;
270 }
271 
get_element_uvw_from_xyz(const MElement * e,double x,double y,double z) const272 std::vector<double> BGMBase::get_element_uvw_from_xyz(const MElement *e,
273                                                       double x, double y,
274                                                       double z) const
275 {
276   std::vector<double> res(3);
277 
278   double xyz[3] = {x, y, z};
279   e->xyz2uvw(xyz, &res[0]);
280 
281   return res;
282 }
283 
get_vertices_of_maximum_dim(int dim)284 std::set<MVertex *> BGMBase::get_vertices_of_maximum_dim(int dim)
285 {
286   std::set<MVertex *> bnd_vertices;
287   for(unsigned int i = 0; i < gf->getNumMeshElements(); i++) {
288     MElement *element = gf->getMeshElement(i);
289     for(std::size_t j = 0; j < element->getNumVertices(); j++) {
290       MVertex *vertex = element->getVertex(j);
291       if(vertex->onWhat()->dim() <= dim) bnd_vertices.insert(vertex);
292     }
293   }
294   return bnd_vertices;
295 }
296 
getBackgroundGEntity()297 GEntity *BGMBase::getBackgroundGEntity() { return gf; }
298