1
2
3 /*----------------------------------------------------------*/
4 /* */
5 /* LIBMESH V 3.0 */
6 /* */
7 /*----------------------------------------------------------*/
8 /* */
9 /* Description: handle .meshb file format I/O */
10 /* Author: Loic MARECHAL */
11 /* Creation date: aug 2 2003 */
12 /* Last modification: jan 25 2006 */
13 /* */
14 /*----------------------------------------------------------*/
15
16
17 /*----------------------------------------------------------*/
18 /* Includes */
19 /*----------------------------------------------------------*/
20
21 #include <string.h>
22 #include <float.h>
23 #include <math.h>
24 #include <ctype.h>
25 #include "libmesh3.h"
26
27
28 /*----------------------------------------------------------*/
29 /* Global variables */
30 /*----------------------------------------------------------*/
31
32 char *LM_kw_table[ LM_NBKW + 1 ][3] =
33 { {"Reserved", "", ""},
34 {"MeshVersionFormatted", "", "i"},
35 {"Reserved", "", ""},
36 {"Dimension", "", "i"},
37 {"Vertices", "i", "dri"},
38 {"Edges", "i", "iii"},
39 {"Triangles", "i", "iiii"},
40 {"Quadrilaterals", "i", "iiiii"},
41 {"Tetrahedra", "i", "iiiii"},
42 {"Pentahedra", "i", "iiiiiii"},
43 {"Hexahedra", "i", "iiiiiiiii"},
44 {"SubDomainFromGeom", "i", "iiii"},
45 {"SubDomainFromMesh", "i", "iiii"},
46 {"Corners", "i", "i"},
47 {"Ridges", "i", "i"},
48 {"RequiredVertices", "i", "i"},
49 {"RequiredEdges", "i", "i"},
50 {"RequiredTriangles", "i", "i"},
51 {"RequiredQuadrilaterals", "i", "i"},
52 {"TangentAtEdgeVertices", "i", "iii"},
53 {"NormalAtVertices", "i", "ii"},
54 {"NormalAtTriangleVertices", "i", "iii"},
55 {"NormalAtQuadrilateralVertices", "i", "iiii"},
56 {"AngleOfCornerBound", "", "r"},
57 {"Geometry", "", "c"},
58 {"VertexOnGeometricVertex", "i", "ii"},
59 {"VertexOnGeometricEdge", "i", "iir"},
60 {"VertexOnGeometricTriangle", "i", "iirr"},
61 {"VertexOnGeometricQuadrilateral", "i", "iirr"},
62 {"EdgeOnGeometricEdge", "i", "ii"},
63 {"TriangleOnGeometricTriangle", "i", "ii"},
64 {"TriangleOnGeometricQuadrilateral", "i", "ii"},
65 {"QuadrilateralOnGeometricTriangle", "i", "ii"},
66 {"QuadrilateralOnGeometricQuadrilateral", "i", "ii"},
67 {"MeshSupportOfVertices", "", "c"},
68 {"VertexOnSupportVertex", "i", "ii"},
69 {"VertexOnSupportEdge", "i", "iir"},
70 {"VertexOnSupportTriangle", "i", "iirr"},
71 {"VertexOnSupportQuadrilateral", "i", "iirr"},
72 {"VertexOnSupportTetrahedron", "i", "iirrr"},
73 {"VertexOnSupportPentahedron", "i", "iirrr"},
74 {"VertexOnSupportHexahedron", "i", "iirrr"},
75 {"CrackedEdges", "i", "ii"},
76 {"CrackedTriangles", "i", "ii"},
77 {"CrackedQuadrilaterals", "i", "ii"},
78 {"EquivalentEdges", "i", "ii"},
79 {"EquivalentTriangles", "i", "ii"},
80 {"EquivalentQuadrilaterals", "i", "ii"},
81 {"PhysicsReference", "i", "ic"},
82 {"IncludeFile", "", "c"},
83 {"BoundingBox", "", "drdr"},
84 {"Identifier", "", "c"},
85 {"IdentityOfGeometry", "", "c"},
86 {"IdentityOfMeshSupport", "", "c"},
87 {"End", "", ""},
88 {"Reserved", "", ""},
89 {"Reserved", "", ""},
90 {"Reserved", "", ""},
91 {"Reserved", "", ""},
92 {"Tangents", "i", "dr"},
93 {"Normals", "i", "dr"},
94 {"TangentAtVertices", "i", "ii"},
95 {"SolAtVertices", "i", "sr"},
96 {"SolAtEdges", "i", "sr"},
97 {"SolAtTriangles", "i", "sr"},
98 {"SolAtQuadrilaterals", "i", "sr"},
99 {"SolAtTetrahedra", "i", "sr"},
100 {"SolAtPentahedra", "i", "sr"},
101 {"SolAtHexahedra", "i", "sr"},
102 {"DSolAtVertices", "i", "sr"},
103 {"ISolAtVertices", "i", "i"},
104 {"ISolAtEdges", "i", "ii"},
105 {"ISolAtTriangles", "i", "iii"},
106 {"ISolAtQuadrilaterals", "i", "iiii"},
107 {"ISolAtTetrahedra", "i", "iiii"},
108 {"ISolAtPentahedra", "i", "iiiiii"},
109 {"ISolAtHexahedra", "i", "iiiiiiii"},
110 {"Iterations","","i"},
111 {"Time","","r"},
112 {"VertexHack","","drdr"}
113 };
114
115
116 /*----------------------------------------------------------*/
117 /* Prototypes of local procedures */
118 /*----------------------------------------------------------*/
119
120 static void write_kw(LM_mesh_struct *, int);
121 static int read_int(LM_mesh_struct *);
122 static void write_int(LM_mesh_struct *, int);
123 static void file2kw_tab(LM_mesh_struct *);
124 static void kw_tab2file(LM_mesh_struct *);
125 static int expand_format(LM_mesh_struct *, int, char *);
126 static void swap_bytes(void *, void *, int);
127 static void read_sol_headers(LM_mesh_struct *);
128
129
130 /*----------------------------------------------------------*/
131 /* Open a mesh file in read or write mode */
132 /*----------------------------------------------------------*/
133
LM_open_mesh(char * filename,int mode,LM_mesh_struct * mesh,...)134 int LM_open_mesh(char *filename, int mode, LM_mesh_struct *mesh, ...)
135 {
136 int i;
137 va_list pa;
138
139
140 /*---------------------*/
141 /* MESH STRUCTURE INIT */
142 /*---------------------*/
143
144 /* Init the kw table */
145
146 for(i=0;i<=LM_NBKW;i++)
147 {
148 mesh->kw_counters[i] = 0;
149 mesh->kw_pos[i][0] = 0;
150 mesh->kw_pos[i][1] = 0;
151 mesh->kw_pos[i][2] = 0;
152 mesh->sol_headers[i] = NULL;
153 }
154
155 /* Allocate a string large enough to contain the full filename and path plus the ".meshb" extension. */
156
157 mesh->filename = (char *)calloc((strlen(filename) + 7), sizeof(char));
158 strcpy(mesh->filename, filename);
159
160 /* Store the opening mode (read or write) and guess the filetype (binary or ascii) depending on the extension */
161
162 mesh->mode = mode;
163 mesh->current_kw = mesh->type = 0;
164 mesh->endian = 1;
165
166 if(strstr(mesh->filename, ".meshb"))
167 mesh->type |= (LM_BINARY | LM_MESH);
168 else if(strstr(mesh->filename, ".mesh"))
169 mesh->type |= (LM_ASCII | LM_MESH);
170 else if(strstr(mesh->filename, ".solb"))
171 mesh->type |= (LM_BINARY | LM_SOL);
172 else if(strstr(mesh->filename, ".sol"))
173 mesh->type |= (LM_ASCII | LM_SOL);
174 else
175 return(0);
176
177 /* Open the file in the required mode and initialyse the mesh structure */
178
179 if(mesh->mode == LM_READ)
180 {
181
182 /*-----------------------*/
183 /* OPEN FILE FOR READING */
184 /*-----------------------*/
185
186 /* Create the name string and open the file */
187
188 if(!(mesh->handle = fopen(mesh->filename, "rb")))
189 return(0);
190
191 /* Read the endian tag and the mesh version in binary */
192
193 if(mesh->type & LM_BINARY)
194 {
195 mesh->endian = read_int(mesh);
196
197 if( (mesh->endian != 1) && (mesh->endian != 16777216) )
198 return(0);
199
200 mesh->version = read_int(mesh);
201 }
202
203
204 /*------------*/
205 /* KW READING */
206 /*------------*/
207
208 /* Read the list of kw present in the file */
209
210 file2kw_tab(mesh);
211
212 /* Check the mesh dimension */
213
214 if(!mesh->kw_counters[ LM_Dimension ])
215 return(0);
216
217 LM_read_field(mesh, LM_Dimension, 1, &mesh->dimension);
218
219 if( (mesh->dimension != 2) && (mesh->dimension != 3) )
220 return(0);
221
222 /* Read the meshversion in ascii case */
223
224 if(mesh->type & LM_ASCII)
225 LM_read_field(mesh, LM_MeshVersionFormatted, 1, &mesh->version);
226
227 /* And read the extended sol headers */
228
229 read_sol_headers(mesh);
230 }
231 else if(mesh->mode == LM_WRITE)
232 {
233
234 /*-----------------------*/
235 /* OPEN FILE FOR WRITING */
236 /*-----------------------*/
237
238 /* Check if the user provided a valid dimension */
239
240 va_start(pa, mesh);
241 mesh->dimension = va_arg(pa, int);
242 va_end(pa);
243
244 if( (mesh->dimension != 2) && (mesh->dimension != 3) )
245 return(0);
246
247 /* If no extension has been provided, create a binary file */
248
249 if(!(mesh->handle = fopen(mesh->filename, "wb")))
250 return(0);
251
252
253 /*------------*/
254 /* KW WRITING */
255 /*------------*/
256
257 /* Initialyse the required fields. The kw will be stored afterward. */
258
259 mesh->version = LM_MESH_VERSION;
260 mesh->endian = 1;
261
262 /* Write the mesh version */
263
264 if(mesh->type & LM_ASCII)
265 LM_write_field(mesh, LM_MeshVersionFormatted, 1, &mesh->version);
266 else
267 {
268 write_int(mesh, mesh->endian);
269 write_int(mesh, mesh->version);
270 }
271
272 /* Write the mesh dimension */
273
274 LM_write_field(mesh, LM_Dimension, 1, &mesh->dimension);
275 }
276 else
277 return(0);
278
279 return(1);
280 }
281
282
283 /*----------------------------------------------------------*/
284 /* Close a meshfile in the right way */
285 /*----------------------------------------------------------*/
286
LM_close_mesh(LM_mesh_struct * mesh)287 int LM_close_mesh(LM_mesh_struct *mesh)
288 {
289 if(mesh->mode == LM_WRITE)
290 {
291 /* Test if the user wrote the "End" kw */
292
293 if(!mesh->kw_counters[ LM_End ])
294 LM_write_field(mesh, LM_End, 0, NULL);
295
296 /* Write down the number lines written in each field to the file */
297
298 kw_tab2file(mesh);
299 }
300
301 if(fclose(mesh->handle))
302 return(0);
303 else
304 return(1);
305 }
306
307
308 /*----------------------------------------------------------*/
309 /* Bufferized read of a whole orpart of a field */
310 /*----------------------------------------------------------*/
311
LM_read_field(LM_mesh_struct * mesh,int kw_code,int nbl,void * buffer)312 int LM_read_field(LM_mesh_struct *mesh, int kw_code, int nbl, void *buffer)
313 {
314 int i, j, swaped, size, *int_buffer = (int *)buffer, string_size;
315 float *flt_buffer = (float *)buffer;
316 char format[256], letter, str_buf[256];
317
318 /* Check if the kw code is valid */
319
320 if( (kw_code < 1) || (kw_code > LM_NBKW) )
321 return(0);
322
323 /* Check if this kw has a format */
324
325 if(!strlen(LM_kw_table[ kw_code ][2]))
326 return(0);
327
328 /* If this kw is only a header, the number of lines to be read is set to one */
329
330 if(!strlen(LM_kw_table[ kw_code ][1]))
331 nbl = 1;
332
333 /* Check if the user is not asking more lines than the remaining lines in the file */
334
335 if(nbl > mesh->kw_counters[ kw_code ] - mesh->kw_pos[ kw_code ][2])
336 nbl = mesh->kw_counters[ kw_code ] - mesh->kw_pos[ kw_code ][2];
337
338 if(!nbl)
339 return(0);
340
341 /* Set the curent position in file to the begining of this kw's data */
342
343 fseek(mesh->handle, mesh->kw_pos[ kw_code ][1], SEEK_SET);
344
345 /* Transform the internal format into a "c" format string for the scanf and compute the size of
346 field's line in order to compute the right adresses in the buffer */
347
348 size = expand_format(mesh, kw_code, format);
349
350 if(mesh->type & LM_ASCII)
351 {
352 for(i=0;i<nbl;i++)
353 for(j=0;j<size;j++)
354 if(format[j] == 'i')
355 fscanf(mesh->handle, "%d", &int_buffer[ i * size + j ]);
356 else if(format[j] == 'r')
357 fscanf(mesh->handle, "%g", &flt_buffer[ i * size + j ]);
358 else if(format[j] == 'c')
359 {
360 string_size = 0;
361
362 do
363 {
364 fscanf(mesh->handle, "%c", &letter);
365 }while(letter != '"');
366
367 do
368 {
369 fscanf(mesh->handle, "%c", &letter);
370 str_buf[ string_size++ ] = letter;
371 }while( (letter != '"') && (string_size <= 256) );
372
373 str_buf[ string_size-1 ] = 0;
374
375 memset(&flt_buffer[ i * size + j ], 0, 256);
376 strcpy((char *)&flt_buffer[ i * size + j ], str_buf);
377 }
378 }
379 else
380 {
381 fread(buffer, nbl * size * 4, 1, mesh->handle);
382
383 /* Swap the bytes in the whole buffer in case of different endian */
384
385 if(mesh->endian != 1)
386 for(i=0;i<nbl*size;i++)
387 {
388 swap_bytes((void *)&int_buffer[i], (void *)&swaped, 4);
389 int_buffer[i] = swaped;
390 }
391 }
392
393 /* Then store the curent position and the total number of read lines in case we didn't read the whole data */
394
395 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
396 mesh->kw_pos[ kw_code ][2] += nbl;
397
398 return(nbl);
399 }
400
401
402 /*----------------------------------------------------------*/
403 /* Bufferized write of a whole field or part of it */
404 /*----------------------------------------------------------*/
405
LM_write_field(LM_mesh_struct * mesh,int kw_code,int nbl,void * buffer,...)406 int LM_write_field(LM_mesh_struct *mesh, int kw_code, int nbl, void *buffer, ...)
407 {
408 int i, j, size, *int_buffer = (int *)buffer, nbsol;
409 float *flt_buffer = (float *)buffer;
410 char format[256];
411 va_list pa;
412
413 /* Check if the kw code is valid */
414
415 if( (kw_code < 1) || (kw_code > LM_NBKW) )
416 return(0);
417
418 /* Read further arguments if this kw is solution field and the extra header was not provided by the user */
419
420 if(!mesh->sol_headers[ kw_code ] && !strcmp(LM_kw_table[ kw_code ][2], "sr"))
421 {
422 va_start(pa, buffer);
423
424 nbsol = va_arg(pa, int);
425
426 if(!(mesh->sol_headers[ kw_code ] = malloc((nbsol+2) * sizeof(int))))
427 return(0);
428
429 mesh->sol_headers[ kw_code ][0] = nbsol;
430 mesh->sol_headers[ kw_code ][1] = 0;
431
432 for(i=1;i<=nbsol;i++)
433 {
434 mesh->sol_headers[ kw_code ][i+1] = va_arg(pa, int);
435
436 switch(mesh->sol_headers[ kw_code ][i+1])
437 {
438 case 1 : mesh->sol_headers[ kw_code ][1] += 1; break;
439 case 2 : mesh->sol_headers[ kw_code ][1] += mesh->dimension; break;
440 case 3 : mesh->sol_headers[ kw_code ][1] += (mesh->dimension * (mesh->dimension+1)) / 2; break;
441 case 4 : mesh->sol_headers[ kw_code ][1] += mesh->dimension * mesh->dimension; break;
442 }
443 }
444
445 va_end(pa);
446 }
447
448 /* If this kw is only a header, the number of lines to be read is set to one */
449
450 if(!strlen(LM_kw_table[ kw_code ][1]))
451 nbl = 1;
452
453 if(!mesh->kw_counters[ kw_code ])
454 write_kw(mesh, kw_code);
455
456 mesh->kw_counters[ kw_code ] += nbl;
457
458 /* Check if this kw has a format */
459
460 if(!strlen(LM_kw_table[ kw_code ][2]))
461 return(0);
462
463 size = expand_format(mesh, kw_code, format);
464
465 if(mesh->type & LM_ASCII)
466 {
467 for(i=0;i<nbl;i++)
468 {
469 for(j=0;j<size;j++)
470 if(format[j] == 'i')
471 fprintf(mesh->handle, "%d ", int_buffer[ i * size + j ]);
472 else if(format[j] == 'r')
473 fprintf(mesh->handle, "%g ", flt_buffer[ i * size + j ]);
474 else if(format[j] == 'c')
475 {
476 fputc('"', mesh->handle);
477 fprintf(mesh->handle, "%s", (char *)&flt_buffer[ i * size + j ]);
478 fputc('"', mesh->handle);
479 }
480
481 fprintf(mesh->handle, "\n");
482 }
483 }
484 else
485 fwrite(buffer, nbl * size * 4, 1, mesh->handle);
486
487 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
488
489 return(1);
490 }
491
492
493 /*----------------------------------------------------------*/
494 /* Single line read */
495 /*----------------------------------------------------------*/
496
LM_read_line(LM_mesh_struct * mesh,int kw_code,...)497 int LM_read_line(LM_mesh_struct *mesh, int kw_code, ...)
498 {
499 float buffer[10], *ptr_flt;
500 int i, size;
501 char format[256];
502 va_list pa;
503
504 /* Check wether this kw is not a simple header */
505
506 if(!strlen(LM_kw_table[ kw_code ][2]))
507 return(0);
508
509 /* Get a one line buffer */
510
511 LM_read_field(mesh, kw_code, 1, buffer);
512
513 /* Start decoding the arguments */
514
515 va_start(pa, kw_code);
516 size = expand_format(mesh, kw_code, format);
517
518 for(i=0;i<size;i++)
519 {
520 ptr_flt = va_arg(pa, float *);
521 *ptr_flt = buffer[i];
522 }
523
524 va_end(pa);
525
526 /* return the number of arguments filled */
527
528 return(size);
529 }
530
531
532 /*----------------------------------------------------------*/
533 /* Single line write */
534 /*----------------------------------------------------------*/
535
LM_write_line(LM_mesh_struct * mesh,int kw_code,...)536 int LM_write_line(LM_mesh_struct *mesh, int kw_code, ...)
537 {
538 float buffer[10], *ptr_flt;
539 int i, size;
540 char format[256];
541 va_list pa;
542
543 /* Check wether this kw is not a simple header */
544
545 if(!strlen(LM_kw_table[ kw_code ][2]))
546 return(0);
547
548 /* Start decoding the arguments */
549
550 va_start(pa, kw_code);
551 size = expand_format(mesh, kw_code, format);
552
553 for(i=0;i<size;i++)
554 {
555 ptr_flt = va_arg(pa, float *);
556 buffer[i] = *ptr_flt;
557 }
558
559 va_end(pa);
560
561 /* Write a one line buffer */
562
563 LM_write_field(mesh, kw_code, 1, buffer);
564
565 /* return the number of arguments filled */
566
567 return(size);
568 }
569
570
571 /*----------------------------------------------------------*/
572 /* Find every kw present in a meshfile */
573 /*----------------------------------------------------------*/
574
file2kw_tab(LM_mesh_struct * mesh)575 static void file2kw_tab(LM_mesh_struct *mesh)
576 {
577 int kw_code, next_pos;
578 char str[256];
579
580 if(mesh->type & LM_ASCII)
581 {
582 /* Scan each string of the file until the end */
583
584 while(fscanf(mesh->handle, "%s", str) != EOF)
585 {
586 /* Fast test in order to reject quickly the numeric values */
587
588 if(isalpha(str[0]))
589 {
590 /* Search which kw code this string is associated with */
591
592 for(kw_code=1; kw_code<= LM_NBKW; kw_code++)
593 if(!strcmp(str, LM_kw_table[ kw_code ][0]))
594 {
595 /* The base position (0) in the file is set right after the kw */
596
597 mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
598
599 /* If this kw has a header, read the number of lines */
600
601 if(!strcmp(LM_kw_table[ kw_code ][1], "i"))
602 mesh->kw_counters[ kw_code ] = read_int(mesh);
603 else
604 mesh->kw_counters[ kw_code ] = 1;
605
606 /* The curent position (1) in the file is set right before the data */
607
608 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
609 break;
610 }
611 }
612 else if(str[0] == '#')
613 while(fgetc(mesh->handle) != '\n');
614 }
615 }
616 else
617 {
618 /* Jump through kw positions in the file */
619
620 do
621 {
622 kw_code = read_int(mesh);
623
624 /* Check if this kw belongs to this mesh version */
625
626 if( (kw_code >= 1) && (kw_code <= LM_NBKW) )
627 {
628 /* The base position (0) in the file is set right after the kw */
629
630 mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
631
632 /* Read the next kw position */
633
634 next_pos = read_int(mesh);
635
636 /* If this kw has a header, read the number of lines */
637
638 if(!strcmp(LM_kw_table[ kw_code ][1], "i"))
639 mesh->kw_counters[ kw_code ] = read_int(mesh);
640 else
641 mesh->kw_counters[ kw_code ] = 1;
642
643 /* The curent position (1) in the file is set right before the data */
644
645 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
646 }
647 else
648 {
649 /* Otherwise, read the next kw position in order to skip these unknown kw */
650
651 next_pos = read_int(mesh);
652 }
653
654 /* Go to the next kw */
655
656 if(next_pos)
657 fseek(mesh->handle, next_pos, SEEK_SET);
658 }while(next_pos);
659 }
660 }
661
662
663 /*----------------------------------------------------------*/
664 /* Update the number of lines written for each kw */
665 /*----------------------------------------------------------*/
666
kw_tab2file(LM_mesh_struct * mesh)667 static void kw_tab2file(LM_mesh_struct *mesh)
668 {
669 int i;
670
671 for(i=1;i<=LM_NBKW;i++)
672 if( mesh->kw_counters[i] && strlen(LM_kw_table[i][2]) )
673 write_kw(mesh, i);
674 }
675
676
677 /*----------------------------------------------------------*/
678 /* Write the string associated with the kw code */
679 /*----------------------------------------------------------*/
680
write_kw(LM_mesh_struct * mesh,int kw_code)681 static void write_kw(LM_mesh_struct *mesh, int kw_code)
682 {
683 int i;
684
685 if(mesh->type & LM_ASCII)
686 {
687 /* Test if it is the first time this kw is written */
688
689 if(!mesh->kw_counters[ kw_code ])
690 {
691 /* If so, write the string and reserve some place afterward in order to store the
692 number of lines */
693
694 fprintf(mesh->handle, "\n%s\n", LM_kw_table[ kw_code ][0]);
695
696 mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
697
698 if(!strcmp("i", LM_kw_table[ kw_code ][1]))
699 fprintf(mesh->handle, " \n");
700
701 /* In case of solution field, write the extended header at once */
702
703 if(mesh->sol_headers[ kw_code ])
704 {
705 fprintf(mesh->handle, "%d ", mesh->sol_headers[ kw_code ][0]);
706
707 for(i=1;i<=mesh->sol_headers[ kw_code ][0];i++)
708 fprintf(mesh->handle, "%d ", mesh->sol_headers[ kw_code ][i+1]);
709
710 fprintf(mesh->handle, "\n\n");
711 }
712
713 /* Store the positions right after the kw in order to write the number of lines at closing time.
714 Store the position right before the data for the write_field process. */
715
716 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
717 }
718 else
719 {
720 /* If this kw has already be written in the file and has a header, go to pos(0) and write
721 down the final value */
722
723 if(strcmp("i", LM_kw_table[ kw_code ][1]))
724 return;
725
726 fseek(mesh->handle, mesh->kw_pos[ kw_code][0], SEEK_SET);
727 fprintf(mesh->handle, "%d\n", mesh->kw_counters[ kw_code ]);
728 }
729 }
730 else
731 {
732 /* Test if it is the first time this kw is written */
733
734 if(!mesh->kw_counters[ kw_code ])
735 {
736 /* If so, write the code, store the position afterward, reserve an int for the next kw position
737 and write the number of lines */
738
739 write_int(mesh, kw_code);
740 mesh->kw_pos[ kw_code ][0] = ftell(mesh->handle);
741 write_int(mesh, 0);
742
743 /* Set the next kw pos in the previously written kw */
744
745 if(mesh->current_kw)
746 {
747 fseek(mesh->handle, mesh->kw_pos[ mesh->current_kw ][0], SEEK_SET);
748 write_int(mesh, mesh->kw_pos[ kw_code ][0] - 4);
749 fseek(mesh->handle, mesh->kw_pos[ kw_code ][0] + 4, SEEK_SET);
750 }
751
752 mesh->current_kw = kw_code;
753
754 if(!strcmp("i", LM_kw_table[ kw_code ][1]))
755 write_int(mesh, 0);
756
757 /* In case of solution field, write the extended header at once */
758
759 if(mesh->sol_headers[ kw_code ])
760 {
761 write_int(mesh, mesh->sol_headers[ kw_code ][0]);
762
763 for(i=1;i<=mesh->sol_headers[ kw_code ][0];i++)
764 write_int(mesh, mesh->sol_headers[ kw_code ][i+1]);
765 }
766
767 mesh->kw_pos[ kw_code ][1] = ftell(mesh->handle);
768 }
769 else
770 {
771 /* Write the number of lines written at closing time */
772
773 if(strcmp("i", LM_kw_table[ kw_code ][1]))
774 return;
775
776 fseek(mesh->handle, mesh->kw_pos[ kw_code ][0] + 4, SEEK_SET);
777 write_int(mesh, mesh->kw_counters[ kw_code ]);
778 }
779 }
780 }
781
782
783 /*----------------------------------------------------------*/
784 /* Read an integer in a mesh file */
785 /*----------------------------------------------------------*/
786
read_int(LM_mesh_struct * mesh)787 static int read_int(LM_mesh_struct *mesh)
788 {
789 int swaped, integer = 0;
790
791 if(mesh->type & LM_ASCII)
792 fscanf(mesh->handle, "%d", &integer);
793 else
794 {
795 /* Read a 4 bytes block in the file */
796
797 fread(&integer, 4, 1, mesh->handle);
798
799 if(mesh->endian != 1)
800 {
801 swap_bytes((void *)&integer, (void *)&swaped, 4);
802 integer = swaped;
803 }
804 }
805
806 return(integer);
807 }
808
809
810 /*----------------------------------------------------------*/
811 /* Write an integer in a mesh file */
812 /*----------------------------------------------------------*/
813
write_int(LM_mesh_struct * mesh,int integer)814 static void write_int(LM_mesh_struct *mesh, int integer)
815 {
816 if(mesh->type & LM_ASCII)
817 fprintf(mesh->handle, "%d ", integer);
818 else
819 fwrite(&integer, 4, 1, mesh->handle);
820 }
821
822
823 /*----------------------------------------------------------*/
824 /* Convert little endian <-> big endian */
825 /*----------------------------------------------------------*/
826
swap_bytes(void * c1,void * c2,int nbytes)827 static void swap_bytes(void *c1, void *c2, int nbytes)
828 {
829 int k;
830 char *c11, *c22;
831
832 c11 = (char*)c1;
833 c22 = (char*)c2;
834
835 for (k=0; k<nbytes; k++)
836 c22[k] = c11[ nbytes-k-1 ];
837 }
838
839
840 /*----------------------------------------------------------*/
841 /* Expand the compacted format and compute the line size */
842 /*----------------------------------------------------------*/
843
expand_format(LM_mesh_struct * mesh,int kw_code,char * out_format)844 static int expand_format(LM_mesh_struct *mesh, int kw_code, char *out_format)
845 {
846 int i, j, duplicate_next = 0, size = 0;
847 char *in_format = LM_kw_table[ kw_code ][2];
848
849 out_format[0] = '\0';
850
851 /* Scan each character of the format string */
852
853 for(i=0;i<strlen(in_format);i++)
854 {
855 if( (in_format[i] == 'i') || (in_format[i] == 'r') )
856 {
857 if(!duplicate_next)
858 duplicate_next = 1;
859
860 for(j=1;j<=duplicate_next;j++)
861 {
862 strncat(out_format, &in_format[i], 1);
863 size++;
864 }
865
866 duplicate_next = 0;
867 }
868 else if(in_format[i] == 'c')
869 {
870 strncat(out_format, &in_format[i], 1);
871 size += 64;
872 }
873 else if(in_format[i] == 'd')
874 {
875 /* 'd' means duplicate the next character mesh->dimension times */
876
877 duplicate_next = mesh->dimension;
878 }
879 else if(in_format[i] == 's')
880 {
881 /* 's' means duplicate the next character mesh->solsize times */
882
883 duplicate_next = mesh->sol_headers[ kw_code ][1];
884 }
885 }
886
887 /* Return the sum of item to be read */
888
889 return(size);
890 }
891
892
893 /*----------------------------------------------------------*/
894 /* Read the extended sol headers */
895 /*----------------------------------------------------------*/
896
read_sol_headers(LM_mesh_struct * mesh)897 static void read_sol_headers(LM_mesh_struct *mesh)
898 {
899 int i, j, nbsol, solsize;
900
901 for(i=1;i<=LM_NBKW;i++)
902 {
903 /* If the kw is a special Sol field, read the extended header */
904
905 if(!mesh->kw_counters[i] || strcmp(LM_kw_table[i][2], "sr"))
906 continue;
907
908 /* Set the curent position in file to the begining of this kw's data */
909
910 fseek(mesh->handle, mesh->kw_pos[i][1], SEEK_SET);
911
912 nbsol = read_int(mesh);
913
914 if(mesh->sol_headers[i] = malloc((nbsol+2) * sizeof(int)))
915 {
916 mesh->sol_headers[i][0] = nbsol;
917 solsize = 0;
918
919 for(j=1;j<=nbsol;j++)
920 {
921 mesh->sol_headers[i][j+1] = read_int(mesh);
922
923 switch(mesh->sol_headers[i][j+1])
924 {
925 case LM_SCALAR : solsize += 1; break;
926 case LM_VECTOR : solsize += mesh->dimension; break;
927 case LM_SYM_MATRIX : solsize += (mesh->dimension * (mesh->dimension+1)) / 2; break;
928 case LM_MATRIX : solsize += mesh->dimension * mesh->dimension; break;
929 }
930
931 mesh->sol_headers[i][1] = solsize;
932 }
933
934 mesh->kw_pos[i][1] = ftell(mesh->handle);
935 }
936 }
937 }
938