gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelIO_INP.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 "GModel.h"
7 #include "OS.h"
8 #include "MPoint.h"
9 #include "MLine.h"
10 #include "MTriangle.h"
11 #include "MQuadrangle.h"
12 #include "MTetrahedron.h"
13 #include "MHexahedron.h"
14 #include "MPrism.h"
15 #include "MPyramid.h"
16 
17 template <class T>
18 static void writeElementsINP(FILE *fp, GEntity *ge, std::vector<T *> &elements,
19  bool saveAll)
20 {
21  if(elements.size() && (saveAll || ge->physicals.size())) {
22  const char *typ = elements[0]->getStringForINP();
23  if(typ) {
24  const char *str = (ge->dim() == 3) ? "Volume" :
25  (ge->dim() == 2) ? "Surface" :
26  (ge->dim() == 1) ? "Line" :
27  "Point"; // currently unused
28  fprintf(fp, "*ELEMENT, type=%s, ELSET=%s%d\n", typ, str, ge->tag());
29  for(std::size_t i = 0; i < elements.size(); i++)
30  elements[i]->writeINP(fp, elements[i]->getNum());
31  }
32  }
33 }
34 
35 static std::string physicalName(GModel *m, int dim, int num)
36 {
37  std::string name = m->getPhysicalName(dim, num);
38  if(name.empty()) {
39  char tmp[256];
40  sprintf(tmp, "%s%d",
41  (dim == 3) ? "PhysicalVolume" :
42  (dim == 2) ? "PhysicalSurface" :
43  (dim == 1) ? "PhysicalLine" :
44  "PhysicalPoint",
45  num);
46  name = tmp;
47  }
48  for(std::size_t i = 0; i < name.size(); i++)
49  if(name[i] == ' ') name[i] = '_';
50  return name;
51 }
52 
53 int GModel::writeINP(const std::string &name, bool saveAll,
54  int saveGroupsOfElements, int saveGroupsOfNodes,
55  double scalingFactor)
56 {
57  FILE *fp = Fopen(name.c_str(), "w");
58  if(!fp) {
59  Msg::Error("Unable to open file '%s'", name.c_str());
60  return 0;
61  }
62 
63  if(noPhysicalGroups()) saveAll = true;
64 
65  indexMeshVertices(saveAll, 0, false);
66  std::vector<GEntity *> entities;
67  getEntities(entities);
68 
69  fprintf(fp, "*Heading\n");
70  fprintf(fp, " %s\n", name.c_str());
71 
72  fprintf(fp, "*NODE\n");
73  for(std::size_t i = 0; i < entities.size(); i++)
74  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
75  entities[i]->mesh_vertices[j]->writeINP(fp, scalingFactor);
76 
77  fprintf(fp, "******* E L E M E N T S *************\n");
78  // a negative value of saveGroupsOfElements can be used to prevent saving
79  // elements of dimension dim, if the (dim+1)^th least significant digit of
80  // -saveGroupsOfElements is equal to 0. This is useful to be able to e.g. only
81  // have 3D elements in the output file, but node sets identified by physical
82  // surfaces or curves. Cf. #1664 and the comments below for the underlying
83  // rationale
84  if(saveGroupsOfElements >= 0 || ((-saveGroupsOfElements / 1) % 10)){
85  for(auto it = firstVertex(); it != lastVertex(); ++it) {
86  writeElementsINP(fp, *it, (*it)->points, saveAll);
87  }
88  }
89  if(saveGroupsOfElements >= 0 || ((-saveGroupsOfElements / 10) % 10)){
90  for(auto it = firstEdge(); it != lastEdge(); ++it) {
91  writeElementsINP(fp, *it, (*it)->lines, saveAll);
92  }
93  }
94  if(saveGroupsOfElements >= 0 || ((-saveGroupsOfElements / 100) % 10)){
95  for(auto it = firstFace(); it != lastFace(); ++it) {
96  writeElementsINP(fp, *it, (*it)->triangles, saveAll);
97  writeElementsINP(fp, *it, (*it)->quadrangles, saveAll);
98  }
99  }
100  if(saveGroupsOfElements >= 0 || ((-saveGroupsOfElements / 1000) % 10)){
101  for(auto it = firstRegion(); it != lastRegion(); ++it) {
102  writeElementsINP(fp, *it, (*it)->tetrahedra, saveAll);
103  writeElementsINP(fp, *it, (*it)->hexahedra, saveAll);
104  writeElementsINP(fp, *it, (*it)->prisms, saveAll);
105  writeElementsINP(fp, *it, (*it)->pyramids, saveAll);
106  }
107  }
108 
109  std::map<int, std::vector<GEntity *> > groups[4];
110  getPhysicalGroups(groups);
111 
112  if(saveGroupsOfElements) {
113  // save elements sets for each physical group (currently we don't save point
114  // elements: is there this concept in Abaqus?) if saveGroupsOfElements is
115  // positive; if saveGroupsOfElements is negative, only save groups of
116  // dimension dim if the (dim+1)^th least significant digit of
117  // -saveGroupsOfElements is 1 (for example: -100 will only save surfaces,
118  // while -1010 will save volumes and curves)
119  for(int dim = 1; dim <= 3; dim++) {
120  if(saveGroupsOfElements > 0 ||
121  (saveGroupsOfElements < 0 &&
122  ((-saveGroupsOfElements / (int)std::pow(10, dim)) % 10) == 1)) {
123  for(auto it = groups[dim].begin(); it != groups[dim].end(); it++) {
124  std::vector<GEntity *> &ent = it->second;
125  fprintf(fp, "*ELSET,ELSET=%s\n",
126  physicalName(this, dim, it->first).c_str());
127  int n = 0;
128  for(std::size_t i = 0; i < ent.size(); i++) {
129  for(std::size_t j = 0; j < ent[i]->getNumMeshElements(); j++) {
130  MElement *e = ent[i]->getMeshElement(j);
131  if(n && !(n % 10)) fprintf(fp, "\n");
132  fprintf(fp, "%lu, ", e->getNum());
133  n++;
134  }
135  }
136  fprintf(fp, "\n");
137  }
138  }
139  }
140  }
141 
142  if(saveGroupsOfNodes) {
143  for(int dim = 0; dim <= 3; dim++) {
144  // save a node set for each physical group (here we include node sets on
145  // physical points) if saveGroupsOfNodes is positive; if saveGroupsOfNodes
146  // is negative and the (dim+1)^th least significant digit of
147  // -saveGroupsOfNodes is equal to 1, save groups of dimension dim
148  if(saveGroupsOfNodes > 0 ||
149  (saveGroupsOfNodes < 0 &&
150  ((-saveGroupsOfNodes / (int)std::pow(10, dim)) % 10) == 1)) {
151  for(auto it = groups[dim].begin(); it != groups[dim].end(); it++) {
152  std::set<MVertex *, MVertexPtrLessThan> nodes;
153  std::vector<GEntity *> &ent = it->second;
154  for(std::size_t i = 0; i < ent.size(); i++) {
155  for(std::size_t j = 0; j < ent[i]->getNumMeshElements(); j++) {
156  MElement *e = ent[i]->getMeshElement(j);
157  for(std::size_t k = 0; k < e->getNumVertices(); k++)
158  nodes.insert(e->getVertex(k));
159  }
160  }
161  fprintf(fp, "*NSET,NSET=%s\n",
162  physicalName(this, dim, it->first).c_str());
163  int n = 0;
164  for(auto it2 = nodes.begin(); it2 != nodes.end(); it2++) {
165  if(n && !(n % 10)) fprintf(fp, "\n");
166  fprintf(fp, "%ld, ", (*it2)->getIndex());
167  n++;
168  }
169  fprintf(fp, "\n");
170  }
171  }
172 
173  // if saveGroupsOfNodes is negative and the (dim+1)^th least significant
174  // digit of -saveGroupsOfNodes is equal to 2, save node sets for each
175  // entity of dimension dim. This is dangerous (the nodes in the group
176  // could reference nodes whose coordinates are not saved in the file), but
177  // useful for some workflows (cf. #1664)
178  if(saveGroupsOfNodes < 0 &&
179  ((-saveGroupsOfNodes / (int)std::pow(10, dim)) % 10) == 2) {
180  std::vector<GEntity *> ent;
181  getEntities(ent, dim);
182  for(std::size_t i = 0; i < ent.size(); i++) {
183  std::set<MVertex *, MVertexPtrLessThan> nodes;
184  for(std::size_t j = 0; j < ent[i]->getNumMeshElements(); j++) {
185  MElement *e = ent[i]->getMeshElement(j);
186  for(std::size_t k = 0; k < e->getNumVertices(); k++)
187  nodes.insert(e->getVertex(k));
188  }
189  if(nodes.size()) {
190  fprintf(fp, "*NSET,NSET=%s%d\n",
191  (dim == 3) ? "Volume" : (dim == 2) ? "Surface" :
192  (dim == 1) ? "Line" : "Point", ent[i]->tag());
193  int n = 0;
194  for(auto it2 = nodes.begin(); it2 != nodes.end(); it2++) {
195  if(n && !(n % 10)) fprintf(fp, "\n");
196  fprintf(fp, "%ld, ", (*it2)->getIndex());
197  n++;
198  }
199  fprintf(fp, "\n");
200  }
201  }
202  }
203  }
204  }
205 
206  fclose(fp);
207  return 1;
208 }
MElement::getNum
virtual std::size_t getNum() const
Definition: MElement.h:68
MTriangle.h
GModel::firstEdge
eiter firstEdge()
Definition: GModel.h:356
OS.h
physicalName
static std::string physicalName(GModel *m, int dim, int num)
Definition: GModelIO_INP.cpp:35
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
GEntity::physicals
std::vector< int > physicals
Definition: GEntity.h:65
MPoint.h
GModel::firstVertex
viter firstVertex()
Definition: GModel.h:357
MLine.h
GEntity
Definition: GEntity.h:31
writeElementsINP
static void writeElementsINP(FILE *fp, GEntity *ge, std::vector< T * > &elements, bool saveAll)
Definition: GModelIO_INP.cpp:18
MElement::getNumVertices
virtual std::size_t getNumVertices() const =0
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
MElement::getVertex
virtual const MVertex * getVertex(int num) const =0
GModel::getPhysicalGroups
void getPhysicalGroups(std::map< int, std::vector< GEntity * > > groups[4]) const
Definition: GModel.cpp:837
GModel::lastFace
fiter lastFace()
Definition: GModel.h:359
GModel::getPhysicalName
std::string getPhysicalName(int dim, int num) const
Definition: GModel.cpp:961
MHexahedron.h
GModel::lastVertex
viter lastVertex()
Definition: GModel.h:361
GModel
Definition: GModel.h:44
MPyramid.h
GModel::firstFace
fiter firstFace()
Definition: GModel.h:355
MElement
Definition: MElement.h:30
GEntity::tag
int tag() const
Definition: GEntity.h:280
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
GModel::writeINP
int writeINP(const std::string &name, bool saveAll=false, int saveGroupsOfElements=0, int saveGroupsOfNodes=0, double scalingFactor=1.0)
Definition: GModelIO_INP.cpp:53
GModel::firstRegion
riter firstRegion()
Definition: GModel.h:354
GModel::lastRegion
riter lastRegion()
Definition: GModel.h:358
MTetrahedron.h
MQuadrangle.h
GModel::noPhysicalGroups
bool noPhysicalGroups()
Definition: GModel.cpp:828
MPrism.h
GModel::lastEdge
eiter lastEdge()
Definition: GModel.h:360
GModel.h
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
GModel::indexMeshVertices
std::size_t indexMeshVertices(bool all, int singlePartition=0, bool renumber=true)
Definition: GModel.cpp:2135