gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
CGNSRead.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 // Contributor(s):
7 // Thomas Toulorge
8 
9 #include <cstring>
10 #include "GmshMessage.h"
11 #include "GModel.h"
12 #include "MVertex.h"
13 #include "MElement.h"
14 #include "BergotBasis.h"
15 #include "BasisFactory.h"
16 #include "ElementType.h"
17 #include "GEntity.h"
18 #include "CGNSCommon.h"
19 #include "CGNSConventions.h"
20 #include "CGNSZone.h"
21 #include "CGNSZoneStruct.h"
22 #include "CGNSZoneUnstruct.h"
23 #include "CGNSRead.h"
24 
25 #if defined(HAVE_LIBCGNS)
26 
27 namespace {
28 
29 #ifdef HAVE_LIBCGNS_CPEX0045
30 
31  int readElementInterpolation(int fileIndex, int baseIndex, int familyIndex,
32  int interpIndex, ZoneEltNodeTransfo &nodeTransfo)
33  {
34  int cgnsErr;
35 
36  // read element interpolation tranformation info
37  char interpName[CGNS_MAX_STR_LEN];
38  CGNS_ENUMT(ElementType_t) cgnsType;
39  cgnsErr = cg_element_interpolation_read(fileIndex, baseIndex, familyIndex,
40  interpIndex, interpName, &cgnsType);
41  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
42 
43  // get number of user interpolation points
44  int nbPt;
45  cgnsErr = cg_element_lagrange_interpolation_size(cgnsType, &nbPt);
46  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
47 
48  // read user interpolation points (parametric coordinates)
49  std::vector<double> u(nbPt), v(nbPt), w(nbPt);
50  cgnsErr = cg_element_interpolation_points_read(
51  fileIndex, baseIndex, familyIndex, interpIndex, u.data(), v.data(),
52  w.data());
53  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
54 
55  // get Gmsh interpolation points
56  const int mshType = cgns2MshEltType(cgnsType);
57  const nodalBasis *basis = BasisFactory::getNodalBasis(mshType);
58  const fullMatrix<double> &mshPts = basis->getReferenceNodes();
59  if(nbPt != mshPts.size1()) {
60  Msg::Error("Internal error: number of interpolation points is different "
61  "between CGNS and Gmsh for Gmsh element %i (parent type %i)",
62  mshType, ElementType::getParentType(mshType));
63  return 0;
64  }
65  std::vector<double> uMsh(nbPt), vMsh(nbPt), wMsh(nbPt);
66  msh2CgnsReferenceElement(mshType, mshPts, uMsh, vMsh, wMsh);
67 
68  // copy user and Gmsh interpolation nodes to matrices for comparison
69  fullMatrix<double> uvw(nbPt, 3), uvwMsh(nbPt, 3);
70  for(int i = 0; i < nbPt; i++) {
71  uvw(i, 0) = u[i];
72  uvw(i, 1) = v[i];
73  uvw(i, 2) = w[i];
74  uvwMsh(i, 0) = uMsh[i];
75  uvwMsh(i, 1) = vMsh[i];
76  uvwMsh(i, 2) = wMsh[i];
77  }
78 
79  // compute node correspondence between user and Gmsh interpolation nodes
80  std::vector<int> transfo(nbPt);
81  if(!computeReordering(uvw, uvwMsh, transfo)) {
82  Msg::Error("Interpolation points '%s' cannot be converted to Gmsh for "
83  "element %i (parent type %i)",
84  mshType, ElementType::getParentType(mshType));
85  return 0;
86  }
87  nodeTransfo[mshType] = transfo;
88 
89  return 1;
90  }
91 
92 #endif
93 
94 } // namespace
95 
96 std::size_t nameIndex(const std::string &name,
97  std::vector<std::string> &allNames)
98 {
99  for(std::size_t i = 0; i < allNames.size(); i++) {
100  if(allNames[i] == name) return i;
101  }
102 
103  allNames.push_back(name);
104  return allNames.size() - 1;
105 }
106 
107 int readScale(int fileIndex, int baseIndex, double &scale)
108 {
109  int cgnsErr;
110 
111  scale = 1.;
112 
113  CGNS_ENUMT(MassUnits_t) mass;
114  CGNS_ENUMT(LengthUnits_t) length;
115  CGNS_ENUMT(TimeUnits_t) time;
116  CGNS_ENUMT(TemperatureUnits_t) temperature;
117  CGNS_ENUMT(AngleUnits_t) angle;
118  cgnsErr = cg_goto(fileIndex, baseIndex, "end");
119  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
120  cgnsErr = cg_units_read(&mass, &length, &time, &temperature, &angle);
121  if(cgnsErr == CG_NODE_NOT_FOUND) {
122  Msg::Info("Length unit in CGNS file not defined, therefore not rescaling");
123  return 1.;
124  }
125  else if(cgnsErr != CG_OK)
126  return cgnsError(__FILE__, __LINE__, fileIndex);
127 
128  switch(length) {
129  case CGNS_ENUMT(Centimeter):
130  Msg::Info("Length unit in CGNS file is cm, rescaling");
131  scale = 0.01;
132  break;
133  case CGNS_ENUMT(Millimeter):
134  Msg::Info("Length unit in CGNS file is mm, rescaling");
135  scale = 0.001;
136  break;
137  case CGNS_ENUMT(Foot):
138  Msg::Info("Length unit in CGNS file is feet, rescaling");
139  scale = 0.3048;
140  break;
141  case CGNS_ENUMT(Inch):
142  Msg::Info("Length unit in CGNS file is inch, rescaling");
143  scale = 0.0254;
144  break;
145  case CGNS_ENUMT(Meter):
146  Msg::Info("Length unit in CGNS file is meter, not rescaling");
147  break;
148  case CG_Null:
149  case CG_UserDefined:
150  default:
151  Msg::Info("Length unit in CGNS file not defined, therefore not rescaling");
152  break;
153  }
154 
155  return 1;
156 }
157 
158 int readEltNodeTransfo(int fileIndex, int baseIndex,
159  Family2EltNodeTransfo &allEltNodeTransfo)
160 {
161 #ifdef HAVE_LIBCGNS_CPEX0045
162  int cgnsErr;
163 
164  // read number of families
165  int nbFam;
166  cgnsErr = cg_nfamilies(fileIndex, baseIndex, &nbFam);
167  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
168 
169  // loop over families
170  for(int iFam = 1; iFam <= nbFam; iFam++) {
171  // read number of element interpolation transformations
172  int nbInterp;
173  cgnsErr =
174  cg_nelement_interpolation_read(fileIndex, baseIndex, iFam, &nbInterp);
175  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
176  if(nbInterp == 0) continue;
177 
178  // read family name
179  char famName[CGNS_MAX_STR_LEN];
180  int nbFamBC, nbGeoRef;
181  cgnsErr =
182  cg_family_read(fileIndex, baseIndex, iFam, famName, &nbFamBC, &nbGeoRef);
183  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
184 
185  // read element interpolation transformations
186  ZoneEltNodeTransfo &nodeTransfo = allEltNodeTransfo[std::string(famName)];
187  nodeTransfo.resize(NofValidElementTypes);
188  for(int iInterp = 1; iInterp <= nbInterp; iInterp++) {
189  int err = readElementInterpolation(fileIndex, baseIndex, iFam, iInterp,
190  nodeTransfo);
191  if(err == 0) return 0;
192  }
193  }
194 
195  return 1;
196 #else
197  return 1;
198 #endif
199 }
200 
201 int createZones(int fileIndex, int baseIndex, int meshDim,
202  const Family2EltNodeTransfo &allEltNodeTransfo,
203  std::vector<CGNSZone *> &allZones,
204  std::map<std::string, int> &name2Zone, bool &postpro)
205 {
206  const int nbZone = allZones.size() - 1;
207  int cgnsErr;
208 
209  // loop over zones
210  postpro = false;
211  cgsize_t startNode = 0;
212  for(int iZone = 1; iZone <= nbZone; iZone++) {
213  // read zone type
214  CGNS_ENUMT(ZoneType_t) zoneType;
215  cgnsErr = cg_zone_type(fileIndex, baseIndex, iZone, &zoneType);
216  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
217 
218  // create zone
219  int err = 1;
220  if(zoneType == CGNS_ENUMV(Structured)) {
221  if(meshDim == 2) {
222  allZones[iZone] =
223  new CGNSZoneStruct<2>(fileIndex, baseIndex, iZone, meshDim, startNode,
224  allEltNodeTransfo, err);
225  }
226  if(meshDim == 3) {
227  allZones[iZone] =
228  new CGNSZoneStruct<3>(fileIndex, baseIndex, iZone, meshDim, startNode,
229  allEltNodeTransfo, err);
230  }
231  }
232  else if(zoneType == CGNS_ENUMV(Unstructured)) {
233  allZones[iZone] =
234  new CGNSZoneUnstruct(fileIndex, baseIndex, iZone, meshDim, startNode,
235  allEltNodeTransfo, err);
236  }
237  if(err == 0) return 0;
238 
239  // check if there are flow solutions
240  int nbZoneSol;
241  cgnsErr = cg_nsols(fileIndex, baseIndex, iZone, &nbZoneSol);
242  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
243  postpro |= (nbZoneSol > 0);
244 
245  // helper variables
246  startNode += allZones[iZone]->nbNode();
247  name2Zone[allZones[iZone]->name()] = iZone;
248  }
249 
250  // read interface and periodicity info
251  for(int iZone = 1; iZone <= nbZone; iZone++) {
252  allZones[iZone]->readConnectivities(name2Zone, allZones);
253  }
254 
255  return 1;
256 }
257 
258 void setPeriodicityInEntities(const std::vector<CGNSZone *> &allZones)
259 {
260  // data structure keeping track of connections between entities to avoid
261  // two-way connections
262  typedef std::map<GEntity *, GEntity *> EntConnect;
263  typedef std::map<GEntity *, const std::vector<double> *> EntTransfo;
264  EntConnect entCon;
265  EntTransfo entTfo;
266 
267  // loop over zones
268  for(std::size_t iZone = 1; iZone < allZones.size(); iZone++) {
269  CGNSZone *zone = allZones[iZone];
270  // loop over periodic connections
271  for(int iPer = 0; iPer < zone->nbPerConnect(); iPer++) {
272  // loop over slave and master vertices
273  const std::vector<MVertex *> &slaveVert = zone->slaveVert(iPer);
274  const std::vector<MVertex *> &masterVert = zone->masterVert(iPer);
275  for(std::size_t iV = 0; iV < slaveVert.size(); iV++) {
276  // get slave and master entities
277  MVertex *sVert = slaveVert[iV], *mVert = masterVert[iV];
278  GEntity *sEnt = sVert->onWhat(), *mEnt = mVert->onWhat();
279 
280  // skip if entities of different dimensions (can happen if a zone has
281  // nodes on a boundary without elements on this boundary)
282  if(sEnt->dim() != mEnt->dim()) continue;
283 
284  // skip if another connnection with the same slave entity already
285  // exists, or if the inverse connection already exists
286  if(entCon.find(sEnt) != entCon.end()) continue;
287  auto itInv = entCon.find(mEnt);
288  if((itInv != entCon.end()) && (itInv->second == sEnt)) continue;
289 
290  // store connection and transformation and update corresponding vertices
291  entCon[sEnt] = mEnt;
292  entTfo[sEnt] = &(zone->perTransfo(iPer));
293  sEnt->correspondingVertices[sVert] = mVert;
294  }
295  }
296  }
297 
298  // set mesh master and transformation between entities
299  for(auto it = entCon.begin(); it != entCon.end(); ++it) {
300  GEntity *sEnt = it->first, *mEnt = it->second;
301  sEnt->setMeshMaster(mEnt, *(entTfo[sEnt]));
302  }
303 }
304 
305 int readPhysicals(int fileIndex, int baseIndex,
306  std::vector<std::string> &allPhysName,
307  std::multimap<std::string, int> &geomName2Phys)
308 {
309  int cgnsErr;
310 
311  // read number of families
312  int nbFam;
313  cgnsErr = cg_nfamilies(fileIndex, baseIndex, &nbFam);
314  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
315 
316  // loop over families
317  for(int iFam = 1; iFam <= nbFam; iFam++) {
318  // read family name (interpreted as name of geometrical entity)
319  char rawFamName[CGNS_MAX_STR_LEN];
320  int nbFamBC, nbGeoRef;
321  cgnsErr = cg_family_read(fileIndex, baseIndex, iFam, rawFamName, &nbFamBC,
322  &nbGeoRef);
323  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
324  const std::string geomName(rawFamName);
325 
326  // read number of sub-family names (interpreted as physical names)
327  int nbFamName;
328  cgnsErr = cg_nfamily_names(fileIndex, baseIndex, iFam, &nbFamName);
329  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
330  if(nbFamName == 0) continue;
331 
332  // read sub-family names (interpreted as physical names)
333  for(int iFamName = 1; iFamName <= nbFamName; iFamName++) {
334  // read names
335  char rawNodeName[CGNS_MAX_STR_LEN];
336  cgnsErr = cg_family_name_read(fileIndex, baseIndex, iFam, iFamName,
337  rawNodeName, rawFamName);
338  if(cgnsErr != CG_OK) return cgnsError(__FILE__, __LINE__, fileIndex);
339 
340  // set physical name as sub-family name or, if empty, to node name
341  std::string physName;
342  if(std::strcmp(rawFamName, "") == 0)
343  physName = std::string(rawNodeName);
344  else
345  physName = std::string(rawFamName);
346 
347  // store physical name and tag
348  int physTag = nameIndex(physName, allPhysName);
349  geomName2Phys.insert(std::make_pair(geomName, physTag));
350  }
351  }
352 
353  return 1;
354 }
355 
356 void setGeomAndPhysicalEntities(GModel *model, int meshDim,
357  std::vector<std::string> &allGeomName,
358  std::vector<std::string> &allPhysName,
359  std::multimap<std::string, int> &geomName2Phys)
360 {
361  // loop over dimensions
362  for(int d = 0; d <= meshDim; d++) {
363  // get entities fo dimension d
364  std::vector<GEntity *> ent;
365  model->getEntities(ent, d);
366 
367  // loop over entities
368  for(std::size_t iEnt = 0; iEnt < ent.size(); iEnt++) {
369  // get entity tag and name
370  int geomTag = ent[iEnt]->tag();
371  if(geomTag >= (int)allGeomName.size()) continue;
372  const std::string &geomName = allGeomName[geomTag];
373 
374  // set name of geometrical entity
375  model->setElementaryName(d, geomTag, geomName);
376 
377  // associate physical tags to geometrical entity and store physical names
378  auto range = geomName2Phys.equal_range(geomName);
379  for(auto it = range.first; it != range.second; ++it) {
380  const int physTag = it->second;
381  std::vector<int> &entPhys = ent[iEnt]->physicals;
382  if(std::find(entPhys.begin(), entPhys.end(), physTag) ==
383  entPhys.end()) {
384  entPhys.push_back(physTag);
385  }
386  model->setPhysicalName(allPhysName[physTag], d, physTag);
387  }
388  }
389  }
390 }
391 
392 #endif // HAVE_LIBCGNS
CGNSZoneStruct.h
CGNSRead.h
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
angle
double angle(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:157
GEntity.h
MVertex
Definition: MVertex.h:24
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
BergotBasis.h
CGNSZone.h
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
GmshMessage.h
nodalBasis::getReferenceNodes
void getReferenceNodes(fullMatrix< double > &nodes) const
Definition: nodalBasis.h:23
GEntity
Definition: GEntity.h:31
CGNSZoneUnstruct.h
fullMatrix< double >
BasisFactory::getNodalBasis
static const nodalBasis * getNodalBasis(int tag)
Definition: BasisFactory.cpp:23
GModel::setElementaryName
void setElementaryName(int dim, int tag, const std::string &name)
Definition: GModel.h:500
Msg
Definition: GmshMessage.h:31
MVertex.h
GModel
Definition: GModel.h:44
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
CGNSConventions.h
CGNSCommon.h
length
double length(Quaternion &q)
Definition: Camera.cpp:346
nodalBasis
Definition: nodalBasis.h:12
fullMatrix::size1
int size1() const
Definition: fullMatrix.h:274
MElement.h
GEntity::setMeshMaster
void setMeshMaster(GEntity *)
Definition: GEntity.cpp:128
GModel::setPhysicalName
int setPhysicalName(const std::string &name, int dim, int num=0)
Definition: GModel.cpp:937
GModel.h
ElementType.h
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
GEntity::correspondingVertices
std::map< MVertex *, MVertex * > correspondingVertices
Definition: GEntity.h:406
ElementType::getParentType
int getParentType(int type)
Definition: ElementType.cpp:10
BasisFactory.h
scale
static void scale(std::vector< double > &x, double s)
Definition: ConjugateGradients.cpp:21