gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GModelIO_BDF.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 <string.h>
8 #include "GModel.h"
9 #include "OS.h"
10 #include "MLine.h"
11 #include "MTriangle.h"
12 #include "MQuadrangle.h"
13 #include "MTetrahedron.h"
14 #include "MHexahedron.h"
15 #include "MPrism.h"
16 #include "MPyramid.h"
17 
18 static int getFormatBDF(char *buffer, int &keySize)
19 {
20  for(std::size_t i = 0; i < strlen(buffer); i++) {
21  if(buffer[i] == ',') { // free fields
22  if(buffer[keySize] == '*') { // will contine on next line
23  keySize = i;
24  return -1;
25  }
26  else {
27  keySize = i;
28  return 0;
29  }
30  }
31  }
32  if(buffer[keySize] == '*') {
33  keySize++;
34  return 2;
35  } // long fields
36  return 1; // small fields;
37 }
38 
39 static double atofBDF(char *str)
40 {
41  int len = strlen(str);
42  // classic numbers with E or D exponent notation
43  for(int i = 0; i < len; i++) {
44  if(str[i] == 'E' || str[i] == 'e') { return atof(str); }
45  else if(str[i] == 'D' || str[i] == 'd') {
46  str[i] = 'E';
47  return atof(str);
48  }
49  }
50  // special Nastran floating point format (e.g. "-7.-1" instead of
51  // "-7.E-01" or "2.3+2" instead of "2.3E+02")
52  char tmp[32];
53  int j = 0, leading_minus = 1;
54  for(int i = 0; i < len; i++) {
55  if(leading_minus && str[i] != ' ' && str[i] != '-') leading_minus = 0;
56  if(!leading_minus && str[i] == '-') tmp[j++] = 'E';
57  if(str[i] == '+') tmp[j++] = 'E';
58  tmp[j++] = str[i];
59  }
60  tmp[j] = '\0';
61  return atof(tmp);
62 }
63 
64 static void copyChar(char *out, const char *in, int num)
65 {
66  for(int i = 0; i < num; i++) out[i] = in[i];
67 }
68 
69 static int readVertexBDF(FILE *fp, char *buffer, int keySize, int *num,
70  double *x, double *y, double *z)
71 {
72  char tmp[5][32];
73  int format = getFormatBDF(buffer, keySize);
74  int j = keySize;
75  switch(format) {
76  case 0: // free field
77  case -1: // free field with continuation
78  for(int i = 0; i < 5; i++) {
79  tmp[i][31] = '\0';
80  copyChar(tmp[i], &buffer[j + 1], 31);
81  for(int k = 0; k < 31; k++) {
82  if(tmp[i][k] == ',') tmp[i][k] = '\0';
83  }
84  j++;
85  while(j < (int)strlen(buffer) && buffer[j] != ',') j++;
86  }
87  if(format == -1) { // continued on next line
88  char buffer2[256];
89  if(!fgets(buffer2, sizeof(buffer2), fp)) return 0;
90  j = 0;
91  while(j < (int)strlen(buffer2) && buffer2[j] != ',') j++;
92  copyChar(tmp[4], &buffer2[j + 1], 31);
93  }
94  break;
95  case 1: // small field
96  for(int i = 0; i < 5; i++) tmp[i][8] = '\0';
97  copyChar(tmp[0], &buffer[8], 8);
98  copyChar(tmp[2], &buffer[24], 8);
99  copyChar(tmp[3], &buffer[32], 8);
100  copyChar(tmp[4], &buffer[40], 8);
101  break;
102  case 2: // long field
103  for(int i = 0; i < 5; i++) tmp[i][16] = '\0';
104  copyChar(tmp[0], &buffer[8], 16);
105  copyChar(tmp[2], &buffer[40], 16);
106  copyChar(tmp[3], &buffer[56], 16);
107  char buffer2[256];
108  for(std::size_t i = 0; i < sizeof(buffer2); i++) buffer2[i] = '\0';
109  if(!fgets(buffer2, sizeof(buffer2), fp)) return 0;
110  copyChar(tmp[4], &buffer2[8], 16);
111  break;
112  default: return 0;
113  }
114 
115  *num = atoi(tmp[0]);
116  *x = atofBDF(tmp[2]);
117  *y = atofBDF(tmp[3]);
118  *z = atofBDF(tmp[4]);
119  return 1;
120 }
121 
122 static bool emptyFieldBDF(char *field, int length)
123 {
124  for(int i = 0; i < length; i++)
125  if(field[i] != '\0' && field[i] != ' ' && field[i] != '\n' &&
126  field[i] != '\r')
127  return false;
128  return true;
129 }
130 
131 static void readLineBDF(char *buffer, int format, std::vector<char *> &fields)
132 {
133  int cmax = (format == 2) ? 16 : 8; // max char per (center) field
134  int nmax = (format == 2) ? 4 : 8; // max num of (center) fields per line
135 
136  if(format <= 0) { // free fields
137  for(std::size_t i = 0; i < strlen(buffer); i++) {
138  if(buffer[i] == ',') fields.push_back(&buffer[i + 1]);
139  }
140  }
141  else { // small or long fields
142  for(int i = 0; i < nmax + 1; i++) {
143  if(!emptyFieldBDF(&buffer[8 + cmax * i], cmax))
144  fields.push_back(&buffer[8 + cmax * i]);
145  }
146  }
147 }
148 
149 static int readElementBDF(FILE *fp, char *buffer, int keySize, int numVertices,
150  int &num, int &region,
151  std::vector<MVertex *> &vertices,
152  std::map<int, MVertex *> &vertexMap)
153 {
154  char buffer2[256], buffer3[256];
155  std::vector<char *> fields;
156  int format = getFormatBDF(buffer, keySize);
157 
158  for(std::size_t i = 0; i < sizeof(buffer2); i++)
159  buffer2[i] = buffer3[i] = '\0';
160 
161  readLineBDF(buffer, format, fields);
162 
163  if(((int)fields.size() - 2 < abs(numVertices)) ||
164  (numVertices < 0 && (fields.size() == 8 || fields.size() == 9))) {
165  if(fields.size() == 9) fields.pop_back(); // drop continuation string
166  fpos_t pos;
167  fgetpos(fp, &pos);
168  if(!fgets(buffer2, sizeof(buffer2), fp)) return 0;
169  if(buffer2[0] == 'C' || buffer2[0] == 'E' || buffer2[0] == '$') {
170  // next line is a new element or end of data - we're done; this can happen
171  // for CPENTA with 6 nodes, since we allow empty continuation fields
172  fsetpos(fp, &pos);
173  }
174  else {
175  readLineBDF(buffer2, format, fields);
176  }
177  }
178 
179  if(((int)fields.size() - 2 < abs(numVertices)) ||
180  (numVertices < 0 && (fields.size() == 15 || fields.size() == 17))) {
181  if(fields.size() == 17) fields.pop_back(); // drop continuation string
182  if(!fgets(buffer3, sizeof(buffer3), fp)) return 0;
183  readLineBDF(buffer3, format, fields);
184  }
185 
186  // negative 'numVertices' gives the minimum required number of vertices
187  if((int)fields.size() - 2 < abs(numVertices)) {
188  Msg::Error("Wrong number of nodes %d for element", fields.size() - 2);
189  return 0;
190  }
191 
192  int n[30], cmax = (format == 2) ? 16 : 8; // max char per (center) field
193  char tmp[32];
194  tmp[cmax] = '\0';
195  copyChar(tmp, fields[0], cmax);
196  num = atoi(tmp);
197  copyChar(tmp, fields[1], cmax);
198  region = atoi(tmp);
199  for(std::size_t i = 2; i < fields.size(); i++) {
200  copyChar(tmp, fields[i], cmax);
201  n[i - 2] = atoi(tmp);
202  }
203 
204  // ignore the extra fields when we know how many vertices we need
205  int numCheck = (numVertices > 0) ? numVertices : fields.size() - 2;
206 
207  for(int i = 0; i < numCheck; i++) {
208  auto it = vertexMap.find(n[i]);
209  if(it == vertexMap.end()) {
210  Msg::Error("Wrong node index %d", n[i]);
211  return 0;
212  }
213  vertices.push_back(it->second);
214  }
215  return 1;
216 }
217 
218 int GModel::readBDF(const std::string &name)
219 {
220  FILE *fp = Fopen(name.c_str(), "r");
221  if(!fp) {
222  Msg::Error("Unable to open file '%s'", name.c_str());
223  return 0;
224  }
225 
226  char buffer[256];
227  std::map<int, MVertex *> vertexMap;
228  std::map<int, std::vector<MElement *> > elements[7];
229 
230  // nodes can be defined after elements, so parse the file twice
231 
232  while(!feof(fp)) {
233  for(std::size_t i = 0; i < sizeof(buffer); i++) buffer[i] = '\0';
234  if(!fgets(buffer, sizeof(buffer), fp)) break;
235  if(buffer[0] != '$') { // skip comments
236  if(!strncmp(buffer, "GRID", 4)) {
237  int num;
238  double x, y, z;
239  if(!readVertexBDF(fp, buffer, 4, &num, &x, &y, &z)) break;
240  vertexMap[num] = new MVertex(x, y, z, nullptr, num);
241  }
242  }
243  }
244  Msg::Info("%d nodes", vertexMap.size());
245 
246  rewind(fp);
247  while(!feof(fp)) {
248  for(std::size_t i = 0; i < sizeof(buffer); i++) buffer[i] = '\0';
249  if(!fgets(buffer, sizeof(buffer), fp)) break;
250  if(buffer[0] != '$') { // skip comments
251  int num, region;
252  std::vector<MVertex *> vertices;
253  if(!strncmp(buffer, "CBAR", 4)) {
254  if(readElementBDF(fp, buffer, 4, 2, num, region, vertices, vertexMap))
255  elements[0][region].push_back(new MLine(vertices, num));
256  }
257  else if(!strncmp(buffer, "CROD", 4)) {
258  if(readElementBDF(fp, buffer, 4, 2, num, region, vertices, vertexMap))
259  elements[0][region].push_back(new MLine(vertices, num));
260  }
261  else if(!strncmp(buffer, "CBEAM", 5)) {
262  if(readElementBDF(fp, buffer, 5, 2, num, region, vertices, vertexMap))
263  elements[0][region].push_back(new MLine(vertices, num));
264  }
265  else if(!strncmp(buffer, "CTRIA3", 6)) {
266  if(readElementBDF(fp, buffer, 6, 3, num, region, vertices, vertexMap))
267  elements[1][region].push_back(new MTriangle(vertices, num));
268  }
269  else if(!strncmp(buffer, "CTRIA6", 6)) {
270  if(readElementBDF(fp, buffer, 6, 6, num, region, vertices, vertexMap))
271  elements[1][region].push_back(new MTriangle6(vertices, num));
272  }
273  else if(!strncmp(buffer, "CQUAD4", 6)) {
274  if(readElementBDF(fp, buffer, 6, 4, num, region, vertices, vertexMap))
275  elements[2][region].push_back(new MQuadrangle(vertices, num));
276  }
277  else if(!strncmp(buffer, "CQUAD8", 6)) {
278  if(readElementBDF(fp, buffer, 6, 8, num, region, vertices, vertexMap))
279  elements[2][region].push_back(new MQuadrangle8(vertices, num));
280  }
281  else if(!strncmp(buffer, "CQUAD", 5)) {
282  if(readElementBDF(fp, buffer, 5, -4, num, region, vertices,
283  vertexMap)) {
284  if(vertices.size() == 9)
285  elements[2][region].push_back(new MQuadrangle9(vertices, num));
286  else if(vertices.size() == 8)
287  elements[2][region].push_back(new MQuadrangle8(vertices, num));
288  else
289  elements[2][region].push_back(new MQuadrangle(vertices, num));
290  }
291  }
292  else if(!strncmp(buffer, "CTETRA", 6)) {
293  if(readElementBDF(fp, buffer, 6, -4, num, region, vertices,
294  vertexMap)) {
295  if(vertices.size() == 10)
296  elements[3][region].push_back(new MTetrahedron10(
297  vertices[0], vertices[1], vertices[2], vertices[3], vertices[4],
298  vertices[5], vertices[6], vertices[7], vertices[9], vertices[8],
299  num));
300  else
301  elements[3][region].push_back(new MTetrahedron(vertices, num));
302  }
303  }
304  else if(!strncmp(buffer, "CHEXA", 5)) {
305  if(readElementBDF(fp, buffer, 5, -8, num, region, vertices,
306  vertexMap)) {
307  if(vertices.size() == 20)
308  elements[4][region].push_back(new MHexahedron20(
309  vertices[0], vertices[1], vertices[2], vertices[3], vertices[4],
310  vertices[5], vertices[6], vertices[7], vertices[8], vertices[11],
311  vertices[12], vertices[9], vertices[13], vertices[10],
312  vertices[14], vertices[15], vertices[16], vertices[19],
313  vertices[17], vertices[18], num));
314  else
315  elements[4][region].push_back(new MHexahedron(vertices, num));
316  }
317  }
318  else if(!strncmp(buffer, "CPENTA", 6)) {
319  if(readElementBDF(fp, buffer, 6, -6, num, region, vertices,
320  vertexMap)) {
321  if(vertices.size() == 15)
322  elements[5][region].push_back(
323  new MPrism15(vertices[0], vertices[1], vertices[2], vertices[3],
324  vertices[4], vertices[5], vertices[6], vertices[8],
325  vertices[9], vertices[7], vertices[10], vertices[11],
326  vertices[12], vertices[14], vertices[13], num));
327  else
328  elements[5][region].push_back(new MPrism(vertices, num));
329  }
330  }
331  else if(!strncmp(buffer, "CPYRAM", 6)) {
332  if(readElementBDF(fp, buffer, 6, 5, num, region, vertices, vertexMap))
333  elements[6][region].push_back(new MPyramid(vertices, num));
334  }
335  }
336  }
337 
338  for(int i = 0; i < (int)(sizeof(elements) / sizeof(elements[0])); i++)
339  _storeElementsInEntities(elements[i]);
341  _storeVerticesInEntities(vertexMap);
342 
343  fclose(fp);
344  return 1;
345 }
346 
347 int GModel::writeBDF(const std::string &name, int format, int elementTagType,
348  bool saveAll, double scalingFactor)
349 {
350  FILE *fp = Fopen(name.c_str(), "w");
351  if(!fp) {
352  Msg::Error("Unable to open file '%s'", name.c_str());
353  return 0;
354  }
355 
356  if(noPhysicalGroups()) saveAll = true;
357 
358  indexMeshVertices(saveAll, 0, false);
359 
360  fprintf(fp, "$ Created by Gmsh\n");
361 
362  std::vector<GEntity *> entities;
363  getEntities(entities);
364 
365  // nodes
366  for(std::size_t i = 0; i < entities.size(); i++)
367  for(std::size_t j = 0; j < entities[i]->mesh_vertices.size(); j++)
368  entities[i]->mesh_vertices[j]->writeBDF(fp, format, scalingFactor);
369 
370  // elements
371  for(std::size_t i = 0; i < entities.size(); i++)
372  for(std::size_t j = 0; j < entities[i]->getNumMeshElements(); j++) {
373  int numPhys = entities[i]->physicals.size();
374  if(saveAll || numPhys)
375  entities[i]->getMeshElement(j)->writeBDF(
376  fp, format, elementTagType, entities[i]->tag(),
377  numPhys ? entities[i]->physicals[0] : 0);
378  }
379 
380  fprintf(fp, "ENDDATA\n");
381 
382  fclose(fp);
383  return 1;
384 }
MTriangle.h
readVertexBDF
static int readVertexBDF(FILE *fp, char *buffer, int keySize, int *num, double *x, double *y, double *z)
Definition: GModelIO_BDF.cpp:69
MPrism15
Definition: MPrism.h:263
MTetrahedron
Definition: MTetrahedron.h:34
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
OS.h
MVertex
Definition: MVertex.h:24
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
GModel::_storeElementsInEntities
void _storeElementsInEntities(std::map< int, std::vector< MElement * > > &map)
Definition: GModel.cpp:2273
MTetrahedron10
Definition: MTetrahedron.h:233
atofBDF
static double atofBDF(char *str)
Definition: GModelIO_BDF.cpp:39
MPyramid
Definition: MPyramid.h:32
copyChar
static void copyChar(char *out, const char *in, int num)
Definition: GModelIO_BDF.cpp:64
MPrism
Definition: MPrism.h:34
MLine.h
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
MLine
Definition: MLine.h:21
MHexahedron.h
MQuadrangle8
Definition: MQuadrangle.h:203
GModel::vertices
std::set< GVertex *, GEntityPtrLessThan > vertices
Definition: GModel.h:146
MPyramid.h
MHexahedron
Definition: MHexahedron.h:28
GModel::getEntities
void getEntities(std::vector< GEntity * > &entities, int dim=-1) const
Definition: GModel.cpp:651
GModel::readBDF
int readBDF(const std::string &name)
Definition: GModelIO_BDF.cpp:218
MTriangle
Definition: MTriangle.h:26
length
double length(Quaternion &q)
Definition: Camera.cpp:346
MTetrahedron.h
MTriangle6
Definition: MTriangle.h:191
MHexahedron20
Definition: MHexahedron.h:251
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MQuadrangle.h
GModel::noPhysicalGroups
bool noPhysicalGroups()
Definition: GModel.cpp:828
MPrism.h
MQuadrangle9
Definition: MQuadrangle.h:325
GModel.h
GModel::_storeVerticesInEntities
void _storeVerticesInEntities(std::map< int, MVertex * > &vertices)
Definition: GModel.cpp:2496
emptyFieldBDF
static bool emptyFieldBDF(char *field, int length)
Definition: GModelIO_BDF.cpp:122
GModel::writeBDF
int writeBDF(const std::string &name, int format=0, int elementTagType=1, bool saveAll=false, double scalingFactor=1.0)
Definition: GModelIO_BDF.cpp:347
GModel::_associateEntityWithMeshVertices
void _associateEntityWithMeshVertices()
Definition: GModel.cpp:2470
MQuadrangle
Definition: MQuadrangle.h:26
getFormatBDF
static int getFormatBDF(char *buffer, int &keySize)
Definition: GModelIO_BDF.cpp:18
readLineBDF
static void readLineBDF(char *buffer, int format, std::vector< char * > &fields)
Definition: GModelIO_BDF.cpp:131
GModel::indexMeshVertices
std::size_t indexMeshVertices(bool all, int singlePartition=0, bool renumber=true)
Definition: GModel.cpp:2135
readElementBDF
static int readElementBDF(FILE *fp, char *buffer, int keySize, int numVertices, int &num, int &region, std::vector< MVertex * > &vertices, std::map< int, MVertex * > &vertexMap)
Definition: GModelIO_BDF.cpp:149