Salome HOME
INT PAL 0052683: Parameter "Color group" in the "Create Group" dialog box is empty
[modules/smesh.git] / src / DriverGMF / libmesh5.c
1
2
3 /*----------------------------------------------------------*/
4 /*                                                                                                                      */
5 /*                                              LIBMESH V 5.46                                          */
6 /*                                                                                                                      */
7 /*----------------------------------------------------------*/
8 /*                                                                                                                      */
9 /*      Description:            handle .meshb file format I/O           */
10 /*      Author:                         Loic MARECHAL                                           */
11 /*      Creation date:          feb 16 2007                                                     */
12 /*      Last modification:      apr 03 2012                                                     */
13 /*                                                                                                                      */
14 /*----------------------------------------------------------*/
15
16
17 /*----------------------------------------------------------*/
18 /* Includes                                                                                                     */
19 /*----------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <float.h>
26 #include <math.h>
27 #include <ctype.h>
28 #include "libmesh5.h"
29
30
31 /*----------------------------------------------------------*/
32 /* Defines                                                                                                      */
33 /*----------------------------------------------------------*/
34
35 #define Asc 1
36 #define Bin 2
37 #define MshFil 4
38 #define SolFil 8
39 #define MaxMsh 100
40 #define InfKwd 1
41 #define RegKwd 2
42 #define SolKwd 3
43 #define WrdSiz 4
44 #define BufSiz 10000
45
46
47 /*----------------------------------------------------------*/
48 /* Structures                                                                                           */
49 /*----------------------------------------------------------*/
50
51 typedef struct
52 {
53         int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
54         long pos;
55         char fmt[ GmfMaxTyp*9 ];
56 }KwdSct;
57
58 typedef struct
59 {
60         int dim, ver, mod, typ, cod, pos;
61         long NexKwdPos, siz;
62         KwdSct KwdTab[ GmfMaxKwd + 1 ];
63         FILE *hdl;
64         int *IntBuf;
65         float *FltBuf;
66         unsigned char *buf;
67         char FilNam[ GmfStrSiz ];
68         double DblBuf[1000/8];
69         unsigned char blk[ BufSiz + 1000 ];
70 }GmfMshSct;
71
72
73 /*----------------------------------------------------------*/
74 /* Global variables                                                                                     */
75 /*----------------------------------------------------------*/
76
77 static int GmfIniFlg=0;
78 static GmfMshSct *GmfMshTab[ MaxMsh + 1 ];
79 static const char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] = 
80 {       {"Reserved", "", "", ""},
81         {"MeshVersionFormatted", "", "", "i"},
82         {"Reserved", "", "", ""},
83         {"Dimension", "", "", "i"},
84         {"Vertices", "Vertex", "i", "dri"},
85         {"Edges", "Edge", "i", "iii"},
86         {"Triangles", "Triangle", "i", "iiii"},
87         {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
88         {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
89         {"Prisms", "Prism", "i", "iiiiiii"},
90         {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
91         {"IterationsAll", "IterationAll","","i"},
92         {"TimesAll", "TimeAll","","r"},                                 
93         {"Corners", "Corner", "i", "i"},
94         {"Ridges", "Ridge", "i", "i"},
95         {"RequiredVertices", "RequiredVertex", "i", "i"},
96         {"RequiredEdges", "RequiredEdge", "i", "i"},
97         {"RequiredTriangles", "RequiredTriangle", "i", "i"},
98         {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
99         {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
100         {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
101         {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
102         {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
103         {"AngleOfCornerBound", "", "", "r"},
104         {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
105         {"EdgesP2", "EdgeP2", "i", "iiii"},
106         {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
107         {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
108         {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
109         {"SubDomainFromGeom", "SubDomainFromGeom", "i", "iiii"},
110         {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
111         {"Fault_NearTri", "Fault_NearTri", "i", "i"},
112         {"Fault_Inter", "Fault_Inter", "i", "i"},
113         {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
114         {"ExtraVerticesAtEdges", "ExtraVerticesAtEdge", "i", "in"},
115         {"ExtraVerticesAtTriangles", "ExtraVerticesAtTriangle", "i", "in"},
116         {"ExtraVerticesAtQuadrilaterals", "ExtraVerticesAtQuadrilateral", "i", "in"},
117         {"ExtraVerticesAtTetrahedra", "ExtraVerticesAtTetrahedron", "i", "in"},
118         {"ExtraVerticesAtPrisms", "ExtraVerticesAtPrism", "i", "in"},
119         {"ExtraVerticesAtHexahedra", "ExtraVerticesAtHexahedron", "i", "in"},
120         {"VerticesOnGeometricVertices", "VertexOnGeometricVertex", "i", "iir"},
121         {"VerticesOnGeometricEdges", "VertexOnGeometricEdge", "i", "iirr"},
122         {"VerticesOnGeometricTriangles", "VertexOnGeometricTriangle", "i", "iirrr"},
123         {"VerticesOnGeometricQuadrilaterals", "VertexOnGeometricQuadrilateral", "i", "iirrr"},
124         {"EdgesOnGeometricEdges", "EdgeOnGeometricEdge", "i", "iir"},
125         {"Fault_FreeEdge", "Fault_FreeEdge", "i", "i"},
126         {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
127         {"Polygons", "Polygon", "", "iiiiiiiii"},
128         {"Fault_Overlap", "Fault_Overlap", "i", "i"},
129         {"Pyramids", "Pyramid", "i", "iiiiii"},
130         {"BoundingBox", "", "", "drdr"},
131         {"Body","i", "drdrdrdr"},
132         {"PrivateTable", "PrivateTable", "i", "i"},
133         {"Fault_BadShape", "Fault_BadShape", "i", "i"},
134         {"End", "", "", ""},
135         {"TrianglesOnGeometricTriangles", "TriangleOnGeometricTriangle", "i", "iir"},
136         {"TrianglesOnGeometricQuadrilaterals", "TriangleOnGeometricQuadrilateral", "i", "iir"},
137         {"QuadrilateralsOnGeometricTriangles", "QuadrilateralOnGeometricTriangle", "i", "iir"},
138         {"QuadrilateralsOnGeometricQuadrilaterals", "QuadrilateralOnGeometricQuadrilateral", "i", "iir"},
139         {"Tangents", "Tangent", "i", "dr"},
140         {"Normals", "Normal", "i", "dr"},
141         {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
142         {"SolAtVertices", "SolAtVertex", "i", "sr"},
143         {"SolAtEdges", "SolAtEdge", "i", "sr"},
144         {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
145         {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
146         {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
147         {"SolAtPrisms", "SolAtPrism", "i", "sr"},
148         {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
149         {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
150         {"ISolAtVertices", "ISolAtVertex", "i", "i"},
151         {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
152         {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
153         {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
154         {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
155         {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
156         {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
157         {"Iterations", "","","i"},
158         {"Time", "","","r"},
159         {"Fault_SmallTri", "Fault_SmallTri","i","i"},
160         {"CoarseHexahedra", "CoarseHexahedron", "i", "i"}
161  };
162
163
164 /*----------------------------------------------------------*/
165 /* Prototypes of local procedures                                                       */
166 /*----------------------------------------------------------*/
167
168 static void ScaWrd(GmfMshSct *, unsigned char *);
169 static void ScaDblWrd(GmfMshSct *, unsigned char *);
170 static void ScaBlk(GmfMshSct *, unsigned char *, int);
171 static long GetPos(GmfMshSct *);
172 static void RecWrd(GmfMshSct *, unsigned char *);
173 static void RecDblWrd(GmfMshSct *, unsigned char *);
174 static void RecBlk(GmfMshSct *, unsigned char *, int);
175 static void SetPos(GmfMshSct *, long);
176 static int ScaKwdTab(GmfMshSct *);
177 static void ExpFmt(GmfMshSct *, int);
178 static void ScaKwdHdr(GmfMshSct *, int);
179
180
181 /*----------------------------------------------------------*/
182 /* Open a mesh file in read or write mod                                        */
183 /*----------------------------------------------------------*/
184
185 int GmfOpenMesh(const char *FilNam, int mod, ...)
186 {
187         int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
188         char str[ GmfStrSiz ];
189         va_list VarArg;
190         GmfMshSct *msh;
191         char *ptr;
192         int k;
193
194         if(!GmfIniFlg)
195         {
196                 for(i=0;i<=MaxMsh;i++)
197                         GmfMshTab[i] = NULL;
198
199                 GmfIniFlg = 1;
200         }
201
202         /*---------------------*/
203         /* MESH STRUCTURE INIT */
204         /*---------------------*/
205
206         for(i=1;i<=MaxMsh;i++)
207                 if(!GmfMshTab[i])
208                 {
209                         MshIdx = i;
210                         break;
211                 }
212
213         if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) )
214                 return(0);
215
216         /* Copy the FilNam into the structure */
217
218         if(strlen(FilNam) + 7 >= GmfStrSiz)
219         {
220                 free (msh);
221                 return(0);
222         }
223
224         strcpy(msh->FilNam, FilNam);
225
226         /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
227
228         msh->mod = mod;
229         msh->buf = (unsigned char *)msh->DblBuf;
230         msh->FltBuf = (float *)msh->DblBuf;
231         msh->IntBuf = (int *)msh->DblBuf;
232
233         k = strlen(msh->FilNam) - 6;
234         if(k < 0)
235                 k = 0;
236         ptr = msh->FilNam+k;
237         if(strstr(ptr, ".meshb"))
238                 msh->typ |= (Bin | MshFil);
239         else if(strstr(ptr, ".mesh"))
240                 msh->typ |= (Asc | MshFil);
241         else if(strstr(ptr, ".solb"))
242                 msh->typ |= (Bin | SolFil);
243         else if(strstr(ptr, ".sol"))
244                 msh->typ |= (Asc | SolFil);
245         else {
246                 free (msh);
247                 return(0);
248         }
249
250         /* Open the file in the required mod and initialyse the mesh structure */
251
252         if(msh->mod == GmfRead)
253         {
254
255                 /*-----------------------*/
256                 /* OPEN FILE FOR READING */
257                 /*-----------------------*/
258
259                 va_start(VarArg, mod);
260                 PtrVer = va_arg(VarArg, int *);
261                 PtrDim = va_arg(VarArg, int *);
262                 va_end(VarArg);
263
264                 /* Create the name string and open the file */
265
266                 if(!(msh->hdl = fopen(msh->FilNam, "rb")))
267                 {
268                         free (msh);
269                         return(0);
270                 }
271
272                 /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
273
274                 if(msh->typ & Bin)
275                 {
276                         fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
277
278                         if( (msh->cod != 1) && (msh->cod != 16777216) )
279                         {
280                                 free (msh);
281                                 return(0);
282                         }
283
284                         ScaWrd(msh, (unsigned char *)&msh->ver);
285
286                         if( (msh->ver < 1) || (msh->ver > 3) )
287                         {
288                                 free (msh);
289                                 return(0);
290                         }
291
292                         if( (msh->ver == 3) && (sizeof(long) == 4) )
293                         {
294                                 free (msh);
295                                 return(0);
296                         }
297
298                         ScaWrd(msh, (unsigned char *)&KwdCod);
299
300                         if(KwdCod != GmfDimension)
301                         {
302                                 free (msh);
303                                 return(0);
304                         }
305
306                         GetPos(msh);
307                         ScaWrd(msh, (unsigned char *)&msh->dim);
308                 }
309                 else
310                 {
311                         do
312                         {
313                                 res = fscanf(msh->hdl, "%s", str);
314                         }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
315
316                         if(res == EOF)
317                         {
318                                 free (msh);
319                                 return(0);
320                         }
321
322                         fscanf(msh->hdl, "%d", &msh->ver);
323
324                         if( (msh->ver < 1) || (msh->ver > 3) )
325                         {
326                                 free (msh);
327                                 return(0);
328                         }
329
330                         do
331                         {
332                                 res = fscanf(msh->hdl, "%s", str);
333                         }while( (res != EOF) && strcmp(str, "Dimension") );
334
335                         if(res == EOF)
336                         {
337                                 free (msh);
338                                 return(0);
339                         }
340
341                         fscanf(msh->hdl, "%d", &msh->dim);
342                 }
343
344                 if( (msh->dim != 2) && (msh->dim != 3) )
345                 {
346                         free (msh);
347                         return(0);
348                 }
349
350                 (*PtrVer) = msh->ver;
351                 (*PtrDim) = msh->dim;
352
353                 /*------------*/
354                 /* KW READING */
355                 /*------------*/
356
357                 /* Read the list of kw present in the file */
358
359                 if(!ScaKwdTab(msh))
360                 {
361                         free (msh);
362                         return(0);
363                 }
364
365                 GmfMshTab[ MshIdx ] = msh;
366
367                 return(MshIdx);
368         }
369         else if(msh->mod == GmfWrite)
370         {
371
372                 /*-----------------------*/
373                 /* OPEN FILE FOR WRITING */
374                 /*-----------------------*/
375
376                 msh->cod = 1;
377
378                 /* Check if the user provided a valid version number and dimension */
379
380                 va_start(VarArg, mod);
381                 msh->ver = va_arg(VarArg, int);
382                 msh->dim = va_arg(VarArg, int);
383                 va_end(VarArg);
384
385                 if( (msh->ver < 1) || (msh->ver > 3) )
386                 {
387                         free (msh);
388                         return(0);
389                 }
390
391                 if( (msh->ver == 3) && (sizeof(long) == 4) )
392                 {
393                         free (msh);
394                         return(0);
395                 }
396
397                 if( (msh->dim != 2) && (msh->dim != 3) )
398                 {
399                         free (msh);
400                         return(0);
401                 }
402
403                 /* Create the mesh file */
404
405                 if(!(msh->hdl = fopen(msh->FilNam, "wb")))
406                 {
407                         free (msh);
408                         return(0);
409                 }
410
411                 GmfMshTab[ MshIdx ] = msh;
412
413
414                 /*------------*/
415                 /* KW WRITING */
416                 /*------------*/
417
418                 /* Write the mesh version and dimension */
419
420                 if(msh->typ & Asc)
421                 {
422                         fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
423                         fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
424                 }
425                 else
426                 {
427                         RecWrd(msh, (unsigned char *)&msh->cod);
428                         RecWrd(msh, (unsigned char *)&msh->ver);
429                         GmfSetKwd(MshIdx, GmfDimension, 0);
430                         RecWrd(msh, (unsigned char *)&msh->dim);
431                 }
432
433                 return(MshIdx);
434         }
435         else
436         {
437                 free (msh);
438                 return(0);
439         }
440 }
441
442
443 /*----------------------------------------------------------*/
444 /* Close a meshfile in the right way                                            */
445 /*----------------------------------------------------------*/
446
447 int GmfCloseMesh(int MshIdx)
448 {
449         int res = 1;
450         GmfMshSct *msh;
451
452         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
453                 return(0);
454
455         msh = GmfMshTab[ MshIdx ];
456         RecBlk(msh, msh->buf, 0);
457
458         /* In write down the "End" kw in write mode */
459
460         if(msh->mod == GmfWrite){
461                 if(msh->typ & Asc)
462                         fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
463                 else
464                         GmfSetKwd(MshIdx, GmfEnd, 0);
465         }
466         /* Close the file and free the mesh structure */
467
468         if(fclose(msh->hdl))
469                 res = 0;
470
471         free(msh);
472         GmfMshTab[ MshIdx ] = NULL;
473
474         return(res);
475 }
476
477
478 /*----------------------------------------------------------*/
479 /* Read the number of lines and set the position to this kwd*/
480 /*----------------------------------------------------------*/
481
482 int GmfStatKwd(int MshIdx, int KwdCod, ...)
483 {
484         int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
485         GmfMshSct *msh;
486         KwdSct *kwd;
487         va_list VarArg;
488
489         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
490                 return(0);
491
492         msh = GmfMshTab[ MshIdx ];
493
494         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
495                 return(0);
496
497         kwd = &msh->KwdTab[ KwdCod ];
498
499         if(!kwd->NmbLin)
500                 return(0);
501
502         /* Read further arguments if this kw is a sol */
503
504         if(kwd->typ == SolKwd)
505         {
506                 va_start(VarArg, KwdCod);
507
508                 PtrNmbTyp = va_arg(VarArg, int *);
509                 *PtrNmbTyp = kwd->NmbTyp;
510
511                 PtrSolSiz = va_arg(VarArg, int *);
512                 *PtrSolSiz = kwd->SolSiz;
513
514                 TypTab = va_arg(VarArg, int *);
515
516                 for(i=0;i<kwd->NmbTyp;i++)
517                         TypTab[i] = kwd->TypTab[i];
518
519                 va_end(VarArg);
520         }
521
522         return(kwd->NmbLin);
523 }
524
525
526 /*----------------------------------------------------------*/
527 /* Set the current file position to a given kwd                         */
528 /*----------------------------------------------------------*/
529
530 int GmfGotoKwd(int MshIdx, int KwdCod)
531 {
532         GmfMshSct *msh;
533         KwdSct *kwd;
534
535         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
536                 return(0);
537
538         msh = GmfMshTab[ MshIdx ];
539
540         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
541                 return(0);
542
543         kwd = &msh->KwdTab[ KwdCod ];
544
545         if(!kwd->NmbLin)
546                 return(0);
547
548         return(fseek(msh->hdl, kwd->pos, SEEK_SET));
549 }
550
551
552 /*----------------------------------------------------------*/
553 /* Write the kwd and set the number of lines                            */
554 /*----------------------------------------------------------*/
555
556 int GmfSetKwd(int MshIdx, int KwdCod, ...)
557 {
558         int i, NmbLin=0, *TypTab;
559         long CurPos;
560         va_list VarArg;
561         GmfMshSct *msh;
562         KwdSct *kwd;
563
564         if( (MshIdx < 1) || (MshIdx > MaxMsh) )
565                 return(0);
566
567         msh = GmfMshTab[ MshIdx ];
568         RecBlk(msh, msh->buf, 0);
569
570         if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
571                 return(0);
572
573         kwd = &msh->KwdTab[ KwdCod ];
574
575         /* Read further arguments if this kw has a header */
576
577         if(strlen(GmfKwdFmt[ KwdCod ][2]))
578         {
579                 va_start(VarArg, KwdCod);
580                 NmbLin = va_arg(VarArg, int);
581
582                 if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
583                 {
584                         kwd->NmbTyp = va_arg(VarArg, int);
585                         TypTab = va_arg(VarArg, int *);
586
587                         for(i=0;i<kwd->NmbTyp;i++)
588                                 kwd->TypTab[i] = TypTab[i];
589                 }
590
591                 va_end(VarArg);
592         }
593
594         /* Setup the kwd info */
595
596         ExpFmt(msh, KwdCod);
597
598         if(!kwd->typ)
599                 return(0);
600         else if(kwd->typ == InfKwd)
601                 kwd->NmbLin = 1;
602         else
603                 kwd->NmbLin = NmbLin;
604
605         /* Store the next kwd position in binary file */
606
607         if( (msh->typ & Bin) && msh->NexKwdPos )
608         {
609                 CurPos = ftell(msh->hdl);
610                 fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
611                 SetPos(msh, CurPos);
612                 fseek(msh->hdl, CurPos, SEEK_SET);
613         }
614
615         /* Write the header */
616
617         if(msh->typ & Asc)
618         {
619                 fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
620
621                 if(kwd->typ != InfKwd)
622                         fprintf(msh->hdl, "%d\n", kwd->NmbLin);
623
624                 /* In case of solution field, write the extended header */
625
626                 if(kwd->typ == SolKwd)
627                 {
628                         fprintf(msh->hdl, "%d ", kwd->NmbTyp);
629
630                         for(i=0;i<kwd->NmbTyp;i++)
631                                 fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
632
633                         fprintf(msh->hdl, "\n\n");
634                 }
635         }
636         else
637         {
638                 RecWrd(msh, (unsigned char *)&KwdCod);
639                 msh->NexKwdPos = ftell(msh->hdl);
640                 SetPos(msh, 0);
641
642                 if(kwd->typ != InfKwd)
643                         RecWrd(msh, (unsigned char *)&kwd->NmbLin);
644
645                 /* In case of solution field, write the extended header at once */
646
647                 if(kwd->typ == SolKwd)
648                 {
649                         RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
650
651                         for(i=0;i<kwd->NmbTyp;i++)
652                                 RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
653                 }
654         }
655
656         /* Reset write buffer position */
657         msh->pos = 0;
658
659         /* Estimate the total file size and check whether it crosses the 2GB threshold */
660
661         msh->siz += kwd->NmbLin * kwd->NmbWrd * WrdSiz;
662
663         if(msh->siz > 2E9)
664                 return(0);
665         else
666                 return(kwd->NmbLin);
667 }
668
669
670 /*----------------------------------------------------------*/
671 /* Read a full line from the current kwd                                        */
672 /*----------------------------------------------------------*/
673
674 void GmfGetLin(int MshIdx, int KwdCod, ...)
675 {
676         int i, j;
677         float *FltSolTab;
678         double *DblSolTab;
679         va_list VarArg;
680         GmfMshSct *msh = GmfMshTab[ MshIdx ];
681         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
682
683         /* Start decoding the arguments */
684
685         va_start(VarArg, KwdCod);
686
687         if(kwd->typ != SolKwd)
688         {
689                 int k, nb_repeat = 0;
690
691                 if(msh->ver == 1)
692                 {
693                         if(msh->typ & Asc)
694                         {
695                                 for(i=0;i<kwd->SolSiz;i++)
696                                         if(kwd->fmt[i] == 'r')
697                                                 fscanf(msh->hdl, "%f", va_arg(VarArg, float *));
698                                         else if(kwd->fmt[i] == 'n') {
699                                                 fscanf(msh->hdl, "%d", &nb_repeat);
700                                                 *(va_arg(VarArg,  int *)) = nb_repeat;
701                                                 for(k=0;k<nb_repeat;k++)
702                                                         fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
703                                         }
704                                         else
705                                                 fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
706                         }
707                         else
708                         {
709                                 for(i=0;i<kwd->SolSiz;i++)
710                                         if(kwd->fmt[i] == 'r')
711                                                 ScaWrd(msh, (unsigned char *)va_arg(VarArg, float *));
712                                         else if(kwd->fmt[i] == 'n') {
713                                                 ScaWrd(msh, (unsigned char *)&nb_repeat);
714                                                 *(va_arg(VarArg,  int *)) = nb_repeat;
715                                                 for(k=0;k<nb_repeat;k++)
716                                                         ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
717                                         }
718                                         else
719                                                 ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
720                         }
721                 }
722                 else
723                 {
724                         if(msh->typ & Asc)
725                         {
726                                 for(i=0;i<kwd->SolSiz;i++)
727                                         if(kwd->fmt[i] == 'r')
728                                                 fscanf(msh->hdl, "%lf", va_arg(VarArg, double *));
729                                         else if(kwd->fmt[i] == 'n') {
730                                                 fscanf(msh->hdl, "%d", &nb_repeat);
731                                                 *(va_arg(VarArg,  int *)) = nb_repeat;
732                                                 for(k=0;k<nb_repeat;k++)
733                                                         fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
734                                         }
735                                         else
736                                                 fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
737                         }
738                         else
739                                 for(i=0;i<kwd->SolSiz;i++)
740                                         if(kwd->fmt[i] == 'r')
741                                                 ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
742                                         else if(kwd->fmt[i] == 'n') {
743                                                 ScaWrd(msh, (unsigned char *)&nb_repeat);
744                                                 *(va_arg(VarArg,  int *)) = nb_repeat;
745                                                 for(k=0;k<nb_repeat;k++)
746                                                         ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
747                                         }
748                                         else
749                                                 ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
750                 }
751         }
752         else
753         {
754                 if(msh->ver == 1)
755                 {
756                         FltSolTab = va_arg(VarArg, float *);
757
758                         if(msh->typ & Asc)
759                                 for(j=0;j<kwd->SolSiz;j++)
760                                         fscanf(msh->hdl, "%f", &FltSolTab[j]);
761                         else
762                                 ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
763                 }
764                 else
765                 {
766                         DblSolTab = va_arg(VarArg, double *);
767
768                         if(msh->typ & Asc)
769                                 for(j=0;j<kwd->SolSiz;j++)
770                                         fscanf(msh->hdl, "%lf", &DblSolTab[j]);
771                         else
772                                 for(j=0;j<kwd->SolSiz;j++)
773                                         ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
774                 }
775         }
776
777         va_end(VarArg);
778 }
779
780
781 /*----------------------------------------------------------*/
782 /* Write a full line from the current kwd                                       */
783 /*----------------------------------------------------------*/
784
785 void GmfSetLin(int MshIdx, int KwdCod, ...)
786 {
787         int i, j, pos, *IntBuf;
788         float *FltSolTab;
789         double *DblSolTab, *DblBuf;
790         va_list VarArg;
791         GmfMshSct *msh = GmfMshTab[ MshIdx ];
792         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
793
794         /* Start decoding the arguments */
795
796         va_start(VarArg, KwdCod);
797
798         if(kwd->typ != SolKwd)
799         {
800                 int k, nb_repeat = 0;
801
802                 if(msh->ver == 1)
803                 {
804                         if(msh->typ & Asc)
805                         {
806                                 for(i=0;i<kwd->SolSiz;i++)
807                                         if(kwd->fmt[i] == 'r')
808                                                 fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double));
809                                         else if(kwd->fmt[i] == 'n') {
810                                                 nb_repeat = va_arg(VarArg, int);
811                                                 fprintf(msh->hdl, "%d ", nb_repeat);
812                                                 for(k=0;k<nb_repeat;k++)
813                                                         fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
814                                         }
815                                         else
816                                                 fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
817                         }
818                         else
819                         {
820                                 int size_of_block = kwd->SolSiz;
821                                 for(i=0;i<kwd->SolSiz;i++)
822                                         if(kwd->fmt[i] == 'r')
823                                                 msh->FltBuf[i] = va_arg(VarArg, double);
824                                         else if(kwd->fmt[i] == 'n') {
825                                                 nb_repeat = va_arg(VarArg, int);
826                                                 msh->FltBuf[i] = nb_repeat;
827                                                 for(k=0;k<nb_repeat;k++) {
828                                                         msh->IntBuf[i+1+k] = va_arg(VarArg, int);
829                                                         size_of_block ++;
830                                                 }
831                                         }
832                                         else
833                                                 msh->IntBuf[i] = va_arg(VarArg, int);
834
835                                 RecBlk(msh, msh->buf, size_of_block);
836                         }
837                 }
838                 else
839                 {
840                         if(msh->typ & Asc)
841                         {
842                                 for(i=0;i<kwd->SolSiz;i++)
843                                         if(kwd->fmt[i] == 'r')
844                                                 fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double));
845                                         else if(kwd->fmt[i] == 'n') {
846                                                 nb_repeat = va_arg(VarArg, int);
847                                                 fprintf(msh->hdl, "%d ", nb_repeat);
848                                                 for(k=0;k<nb_repeat;k++)
849                                                         fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
850                                         }
851                                         else
852                                                 fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
853                         }
854                         else
855                         {
856                                 pos = 0;
857
858                                 for(i=0;i<kwd->SolSiz;i++)
859                                         if(kwd->fmt[i] == 'r')
860                                         {
861                                                 DblBuf = (double *)&msh->buf[ pos ];
862                                                 *DblBuf = va_arg(VarArg, double);
863                                                 pos += 8;
864                                         }
865                                         else if(kwd->fmt[i] == 'n')
866                                         {
867                                                 IntBuf = (int *)&msh->buf[ pos ];
868                                                 nb_repeat = va_arg(VarArg, int);
869                                                 *IntBuf = nb_repeat;
870                                                 pos += 4;
871                                                 for(k=0;k<nb_repeat;k++) {
872                                                         IntBuf = (int *)&msh->buf[ pos ];
873                                                         *IntBuf = va_arg(VarArg, int);
874                                                         pos += 4;
875                                                 }
876                                         }
877                                         else
878                                         {
879                                                 IntBuf = (int *)&msh->buf[ pos ];
880                                                 *IntBuf = va_arg(VarArg, int);
881                                                 pos += 4;
882                                         }
883                                 RecBlk(msh, msh->buf, pos/4);
884                         }
885                 }
886         }
887         else
888         {
889                 if(msh->ver == 1)
890                 {
891                         FltSolTab = va_arg(VarArg, float *);
892
893                         if(msh->typ & Asc)
894                                 for(j=0;j<kwd->SolSiz;j++)
895                                         fprintf(msh->hdl, "%g ", FltSolTab[j]);
896                         else
897                                 RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
898                 }
899                 else
900                 {
901                         DblSolTab = va_arg(VarArg, double *);
902
903                         if(msh->typ & Asc)
904                                 for(j=0;j<kwd->SolSiz;j++)
905                                         fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
906                         else
907                                 RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
908                 }
909         }
910
911         va_end(VarArg);
912
913         if(msh->typ & Asc)
914                 fprintf(msh->hdl, "\n");
915 }
916
917
918 /*----------------------------------------------------------*/
919 /* Private procedure for transmesh : copy a whole line          */
920 /*----------------------------------------------------------*/
921
922 void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
923 {
924         double d;
925         float f;
926         int i, a;
927         GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ];
928         KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
929
930         for(i=0;i<kwd->SolSiz;i++)
931         {
932                 if(kwd->fmt[i] == 'r')
933                 {
934                         if(InpMsh->ver == 1)
935                         {
936                                 if(InpMsh->typ & Asc)
937                                         fscanf(InpMsh->hdl, "%f", &f);
938                                 else
939                                         ScaWrd(InpMsh, (unsigned char *)&f);
940
941                                 d = f;
942                         }
943                         else
944                         {
945                                 if(InpMsh->typ & Asc)
946                                         fscanf(InpMsh->hdl, "%lf", &d);
947                                 else
948                                         ScaDblWrd(InpMsh, (unsigned char *)&d);
949
950                                 f = (float)d;
951                         }
952
953                         if(OutMsh->ver == 1)
954                                 if(OutMsh->typ & Asc)
955                                         fprintf(OutMsh->hdl, "%g ", f);
956                                 else
957                                         RecWrd(OutMsh, (unsigned char *)&f);
958                         else
959                                 if(OutMsh->typ & Asc)
960                                         fprintf(OutMsh->hdl, "%.15g ", d);
961                                 else
962                                         RecDblWrd(OutMsh, (unsigned char *)&d);
963                 }
964                 else if(kwd->fmt[i] == 'n')
965                 {
966                         int k, nb_repeat = 0;
967
968                         if(InpMsh->typ & Asc)
969                                 fscanf(InpMsh->hdl, "%d", &a);
970                         else
971                                 ScaWrd(InpMsh, (unsigned char *)&a);
972
973                         nb_repeat = a;
974
975                         if(OutMsh->typ & Asc)
976                                 fprintf(OutMsh->hdl, "%d ", a);
977                         else
978                                 RecWrd(OutMsh, (unsigned char *)&a);
979
980                         for(k=0;k<nb_repeat;k++) {
981                                 if(InpMsh->typ & Asc)
982                                         fscanf(InpMsh->hdl, "%d", &a);
983                                 else
984                                         ScaWrd(InpMsh, (unsigned char *)&a);
985
986                                 if(OutMsh->typ & Asc)
987                                         fprintf(OutMsh->hdl, "%d ", a);
988                                 else
989                                         RecWrd(OutMsh, (unsigned char *)&a);
990                         }
991                 }
992                 else
993                 {
994                         if(InpMsh->typ & Asc)
995                                 fscanf(InpMsh->hdl, "%d", &a);
996                         else
997                                 ScaWrd(InpMsh, (unsigned char *)&a);
998
999                         if(OutMsh->typ & Asc)
1000                                 fprintf(OutMsh->hdl, "%d ", a);
1001                         else
1002                                 RecWrd(OutMsh, (unsigned char *)&a);
1003                 }
1004         }
1005
1006         if(OutMsh->typ & Asc)
1007                 fprintf(OutMsh->hdl, "\n");
1008 }
1009
1010
1011 /*----------------------------------------------------------*/
1012 /* Find every kw present in a meshfile                                          */
1013 /*----------------------------------------------------------*/
1014
1015 static int ScaKwdTab(GmfMshSct *msh)
1016 {
1017         int KwdCod;
1018         long  NexPos, CurPos, EndPos;
1019         char str[ GmfStrSiz ];
1020
1021         if(msh->typ & Asc)
1022         {
1023                 /* Scan each string in the file until the end */
1024
1025                 while(fscanf(msh->hdl, "%s", str) != EOF)
1026                 {
1027                         /* Fast test in order to reject quickly the numeric values */
1028
1029                         if(isalpha(str[0]))
1030                         {
1031                                 /* Search which kwd code this string is associated with, 
1032                                         then get its header and save the curent position in file (just before the data) */
1033
1034                                 for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
1035                                         if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
1036                                         {
1037                                                 ScaKwdHdr(msh, KwdCod);
1038                                                 break;
1039                                         }
1040                         }
1041                         else if(str[0] == '#')
1042                                 while(fgetc(msh->hdl) != '\n');
1043                 }
1044         }
1045         else
1046         {
1047                 /* Get file size */
1048
1049                 CurPos = ftell(msh->hdl);
1050                 fseek(msh->hdl, 0, SEEK_END);
1051                 EndPos = ftell(msh->hdl);
1052                 fseek(msh->hdl, CurPos, SEEK_SET);
1053
1054                 /* Jump through kwd positions in the file */
1055
1056                 do
1057                 {
1058                         /* Get the kwd code and the next kwd position */
1059
1060                         ScaWrd(msh, (unsigned char *)&KwdCod);
1061                         NexPos = GetPos(msh);
1062
1063                         if(NexPos > EndPos)
1064                                 return(0);
1065
1066                         /* Check if this kwd belongs to this mesh version */
1067
1068                         if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
1069                                 ScaKwdHdr(msh, KwdCod);
1070
1071                         /* Go to the next kwd */
1072
1073                         if(NexPos)
1074                                 fseek(msh->hdl, NexPos, SEEK_SET);
1075                 }while(NexPos && (KwdCod != GmfEnd));
1076         }
1077
1078         return(1);
1079 }
1080
1081
1082 /*----------------------------------------------------------*/
1083 /* Read and setup the keyword's header                                          */
1084 /*----------------------------------------------------------*/
1085
1086 static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
1087 {
1088         int i;
1089         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1090
1091         if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
1092         {
1093                 if(msh->typ & Asc)
1094                         fscanf(msh->hdl, "%d", &kwd->NmbLin);
1095                 else
1096                         ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
1097         }
1098         else
1099                 kwd->NmbLin = 1;
1100
1101         if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
1102         {
1103                 if(msh->typ & Asc)
1104                 {
1105                         fscanf(msh->hdl, "%d", &kwd->NmbTyp);
1106
1107                         for(i=0;i<kwd->NmbTyp;i++)
1108                                 fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
1109                 }
1110                 else
1111                 {
1112                         ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
1113
1114                         for(i=0;i<kwd->NmbTyp;i++)
1115                                 ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
1116                 }
1117         }
1118
1119         ExpFmt(msh, KwdCod);
1120         kwd->pos = ftell(msh->hdl);
1121 }
1122
1123
1124 /*----------------------------------------------------------*/
1125 /* Expand the compacted format and compute the line size        */
1126 /*----------------------------------------------------------*/
1127
1128 static void ExpFmt(GmfMshSct *msh, int KwdCod)
1129 {
1130         int i, j, TmpSiz=0;
1131         char chr;
1132         const char *InpFmt = GmfKwdFmt[ KwdCod ][3];
1133         KwdSct *kwd = &msh->KwdTab[ KwdCod ];
1134
1135         /* Set the kwd's type */
1136
1137         if(!strlen(GmfKwdFmt[ KwdCod ][2]))
1138                 kwd->typ = InfKwd;
1139         else if(!strcmp(InpFmt, "sr"))
1140                 kwd->typ = SolKwd;
1141         else
1142                 kwd->typ = RegKwd;
1143
1144         /* Get the solution-field's size */
1145
1146         if(kwd->typ == SolKwd)
1147                 for(i=0;i<kwd->NmbTyp;i++)
1148                         switch(kwd->TypTab[i])
1149                         {
1150                                 case GmfSca    : TmpSiz += 1; break;
1151                                 case GmfVec    : TmpSiz += msh->dim; break;
1152                                 case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
1153                                 case GmfMat    : TmpSiz += msh->dim * msh->dim; break;
1154                         }
1155
1156         /* Scan each character from the format string */
1157
1158         i = kwd->SolSiz = kwd->NmbWrd = 0;
1159
1160         while(i < strlen(InpFmt))
1161         {
1162                 chr = InpFmt[ i++ ];
1163
1164                 if(chr == 'd')
1165                 {
1166                         chr = InpFmt[i++];
1167
1168                         for(j=0;j<msh->dim;j++)
1169                                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1170                 }
1171                 else if(chr == 's')
1172                 {
1173                         chr = InpFmt[i++];
1174
1175                         for(j=0;j<TmpSiz;j++)
1176                                 kwd->fmt[ kwd->SolSiz++ ] = chr;
1177                 }
1178                 else
1179                         kwd->fmt[ kwd->SolSiz++ ] = chr;
1180         }
1181
1182         for(i=0;i<kwd->SolSiz;i++)
1183                 if(kwd->fmt[i] == 'i')
1184                         kwd->NmbWrd++;
1185                 else if(msh->ver >= 2)
1186                         kwd->NmbWrd += 2;
1187                 else
1188                         kwd->NmbWrd++;
1189 }
1190
1191
1192 /*----------------------------------------------------------*/
1193 /* Read a four bytes word from a mesh file                                      */
1194 /*----------------------------------------------------------*/
1195
1196 static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
1197 {
1198         unsigned char swp;
1199
1200         fread(wrd, WrdSiz, 1, msh->hdl);
1201
1202         if(msh->cod == 1)
1203                 return;
1204
1205         swp = wrd[3];
1206         wrd[3] = wrd[0];
1207         wrd[0] = swp;
1208
1209         swp = wrd[2];
1210         wrd[2] = wrd[1];
1211         wrd[1] = swp;
1212 }
1213
1214
1215 /*----------------------------------------------------------*/
1216 /* Read an eight bytes word from a mesh file                            */
1217 /*----------------------------------------------------------*/
1218
1219 static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
1220 {
1221         int i;
1222         unsigned char swp;
1223
1224         fread(wrd, WrdSiz, 2, msh->hdl);
1225
1226         if(msh->cod == 1)
1227                 return;
1228
1229         for(i=0;i<4;i++)
1230         {
1231                 swp = wrd[7-i];
1232                 wrd[7-i] = wrd[i];
1233                 wrd[i] = swp;
1234         }
1235 }
1236
1237
1238 /*----------------------------------------------------------*/
1239 /* Read ablock of four bytes word from a mesh file                      */
1240 /*----------------------------------------------------------*/
1241
1242 static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1243 {
1244         int i, j;
1245         unsigned char swp, *wrd;
1246
1247         fread(blk, WrdSiz, siz, msh->hdl);
1248
1249         if(msh->cod == 1)
1250                 return;
1251
1252         for(i=0;i<siz;i++)
1253         {
1254                 wrd = &blk[ i * 4 ];
1255
1256                 for(j=0;j<2;j++)
1257                 {
1258                         swp = wrd[ 3-j ];
1259                         wrd[ 3-j ] = wrd[j];
1260                         wrd[j] = swp;
1261                 }
1262         }
1263 }
1264
1265
1266 /*----------------------------------------------------------*/
1267 /* Read a 4 or 8 bytes position in mesh file                            */
1268 /*----------------------------------------------------------*/
1269
1270 static long GetPos(GmfMshSct *msh)
1271 {
1272         int IntVal;
1273         long pos;
1274
1275         if(msh->ver >= 3)
1276                 ScaDblWrd(msh, (unsigned char*)&pos);
1277         else
1278         {
1279                 ScaWrd(msh, (unsigned char*)&IntVal);
1280                 pos = IntVal;
1281         }
1282
1283         return(pos);
1284 }
1285
1286
1287 /*----------------------------------------------------------*/
1288 /* Write a four bytes word to a mesh file                                       */
1289 /*----------------------------------------------------------*/
1290
1291 static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
1292 {
1293         fwrite(wrd, WrdSiz, 1, msh->hdl);
1294 }
1295
1296
1297 /*----------------------------------------------------------*/
1298 /* Write an eight bytes word to a mesh file                                     */
1299 /*----------------------------------------------------------*/
1300
1301 static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
1302 {
1303         fwrite(wrd, WrdSiz, 2, msh->hdl);
1304 }
1305
1306
1307 /*----------------------------------------------------------*/
1308 /* Write a block of four bytes word to a mesh file                      */
1309 /*----------------------------------------------------------*/
1310
1311 static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz)
1312 {
1313         /* Copy this line-block into the main mesh buffer */
1314
1315         if(siz)
1316         {
1317                 memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz);
1318                 msh->pos += siz * WrdSiz;
1319         }
1320
1321         /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */
1322
1323         if( (msh->pos > BufSiz) || (!siz && msh->pos) )
1324         {
1325                 fwrite(msh->blk, 1, msh->pos, msh->hdl);
1326                 msh->pos = 0;
1327         }
1328 }
1329
1330
1331 /*----------------------------------------------------------*/
1332 /* Write a 4 or 8 bytes position in a mesh file                         */
1333 /*----------------------------------------------------------*/
1334
1335 static void SetPos(GmfMshSct *msh, long pos)
1336 {
1337         int IntVal;
1338
1339         if(msh->ver >= 3)
1340                 RecDblWrd(msh, (unsigned char*)&pos);
1341         else
1342         {
1343                 IntVal = pos;
1344                 RecWrd(msh, (unsigned char*)&IntVal);
1345         }
1346 }