--- /dev/null
+
+
+/*----------------------------------------------------------*/
+/* */
+/* LIBMESH V 5.45 */
+/* */
+/*----------------------------------------------------------*/
+/* */
+/* Description: handle .meshb file format I/O */
+/* Author: Loic MARECHAL */
+/* Creation date: feb 16 2007 */
+/* Last modification: feb 08 2011 */
+/* */
+/*----------------------------------------------------------*/
+
+
+/*----------------------------------------------------------*/
+/* Includes */
+/*----------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+#include <ctype.h>
+#include "libmesh5.h"
+
+
+/*----------------------------------------------------------*/
+/* Defines */
+/*----------------------------------------------------------*/
+
+#define Asc 1
+#define Bin 2
+#define MshFil 4
+#define SolFil 8
+#define MaxMsh 100
+#define InfKwd 1
+#define RegKwd 2
+#define SolKwd 3
+#define WrdSiz 4
+#define BufSiz 10000
+
+
+/*----------------------------------------------------------*/
+/* Structures */
+/*----------------------------------------------------------*/
+
+typedef struct
+{
+ int typ, SolSiz, NmbWrd, NmbLin, NmbTyp, TypTab[ GmfMaxTyp ];
+ long pos;
+ char fmt[ GmfMaxTyp*9 ];
+}KwdSct;
+
+typedef struct
+{
+ int dim, ver, mod, typ, cod, pos;
+ long NexKwdPos;
+ KwdSct KwdTab[ GmfMaxKwd + 1 ];
+ FILE *hdl;
+ int *IntBuf;
+ float *FltBuf;
+ unsigned char *buf;
+ char FilNam[ GmfStrSiz ];
+ double DblBuf[1000/8];
+ unsigned char blk[ BufSiz + 1000 ];
+}GmfMshSct;
+
+
+/*----------------------------------------------------------*/
+/* Global variables */
+/*----------------------------------------------------------*/
+
+int GmfIniFlg=0;
+GmfMshSct *GmfMshTab[ MaxMsh + 1 ];
+char *GmfKwdFmt[ GmfMaxKwd + 1 ][4] =
+{ {"Reserved", "", "", ""},
+ {"MeshVersionFormatted", "", "", "i"},
+ {"Reserved", "", "", ""},
+ {"Dimension", "", "", "i"},
+ {"Vertices", "Vertex", "i", "dri"},
+ {"Edges", "Edge", "i", "iii"},
+ {"Triangles", "Triangle", "i", "iiii"},
+ {"Quadrilaterals", "Quadrilateral", "i", "iiiii"},
+ {"Tetrahedra", "Tetrahedron", "i", "iiiii"},
+ {"Prisms", "Prism", "i", "iiiiiii"},
+ {"Hexahedra", "Hexahedron", "i", "iiiiiiiii"},
+ {"IterationsAll", "IterationAll","","i"},
+ {"TimesAll", "TimeAll","","r"},
+ {"Corners", "Corner", "i", "i"},
+ {"Ridges", "Ridge", "i", "i"},
+ {"RequiredVertices", "RequiredVertex", "i", "i"},
+ {"RequiredEdges", "RequiredEdge", "i", "i"},
+ {"RequiredTriangles", "RequiredTriangle", "i", "i"},
+ {"RequiredQuadrilaterals", "RequiredQuadrilateral", "i", "i"},
+ {"TangentAtEdgeVertices", "TangentAtEdgeVertex", "i", "iii"},
+ {"NormalAtVertices", "NormalAtVertex", "i", "ii"},
+ {"NormalAtTriangleVertices", "NormalAtTriangleVertex", "i", "iii"},
+ {"NormalAtQuadrilateralVertices", "NormalAtQuadrilateralVertex", "i", "iiii"},
+ {"AngleOfCornerBound", "", "", "r"},
+ {"TrianglesP2", "TriangleP2", "i", "iiiiiii"},
+ {"EdgesP2", "EdgeP2", "i", "iiii"},
+ {"SolAtPyramids", "SolAtPyramid", "i", "sr"},
+ {"QuadrilateralsQ2", "QuadrilateralQ2", "i", "iiiiiiiiii"},
+ {"ISolAtPyramids", "ISolAtPyramid", "i", "iiiii"},
+ {"Reserved", "", "", ""},
+ {"TetrahedraP2", "TetrahedronP2", "i", "iiiiiiiiiii"},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"HexahedraQ2", "HexahedronQ2", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiii"},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Polyhedra", "Polyhedron", "i", "iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii"},
+ {"Polygons", "Polygon", "", "iiiiiiiii"},
+ {"Reserved", "", "", ""},
+ {"Pyramids", "Pyramid", "i", "iiiiii"},
+ {"BoundingBox", "", "", "drdr"},
+ {"Body","i", "drdrdrdr"},
+ {"PrivateTable", "PrivateTable", "i", "i"},
+ {"Reserved", "", "", ""},
+ {"End", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Reserved", "", "", ""},
+ {"Tangents", "Tangent", "i", "dr"},
+ {"Normals", "Normal", "i", "dr"},
+ {"TangentAtVertices", "TangentAtVertex", "i", "ii"},
+ {"SolAtVertices", "SolAtVertex", "i", "sr"},
+ {"SolAtEdges", "SolAtEdge", "i", "sr"},
+ {"SolAtTriangles", "SolAtTriangle", "i", "sr"},
+ {"SolAtQuadrilaterals", "SolAtQuadrilateral", "i", "sr"},
+ {"SolAtTetrahedra", "SolAtTetrahedron", "i", "sr"},
+ {"SolAtPrisms", "SolAtPrism", "i", "sr"},
+ {"SolAtHexahedra", "SolAtHexahedron", "i", "sr"},
+ {"DSolAtVertices", "DSolAtVertex", "i", "sr"},
+ {"ISolAtVertices", "ISolAtVertex", "i", "i"},
+ {"ISolAtEdges", "ISolAtEdge", "i", "ii"},
+ {"ISolAtTriangles", "ISolAtTriangle", "i", "iii"},
+ {"ISolAtQuadrilaterals", "ISolAtQuadrilateral", "i", "iiii"},
+ {"ISolAtTetrahedra", "ISolAtTetrahedron", "i", "iiii"},
+ {"ISolAtPrisms", "ISolAtPrism", "i", "iiiiii"},
+ {"ISolAtHexahedra", "ISolAtHexahedron", "i", "iiiiiiii"},
+ {"Iterations", "","","i"},
+ {"Time", "","","r"},
+ {"Reserved", "","",""}
+ };
+
+
+/*----------------------------------------------------------*/
+/* Prototypes of local procedures */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *, unsigned char *);
+static void ScaDblWrd(GmfMshSct *, unsigned char *);
+static void ScaBlk(GmfMshSct *, unsigned char *, int);
+static long GetPos(GmfMshSct *);
+static void RecWrd(GmfMshSct *, unsigned char *);
+static void RecDblWrd(GmfMshSct *, unsigned char *);
+static void RecBlk(GmfMshSct *, unsigned char *, int);
+static void SetPos(GmfMshSct *, long);
+static int ScaKwdTab(GmfMshSct *);
+static void ExpFmt(GmfMshSct *, int);
+static void ScaKwdHdr(GmfMshSct *, int);
+
+
+/*----------------------------------------------------------*/
+/* Open a mesh file in read or write mod */
+/*----------------------------------------------------------*/
+
+int GmfOpenMesh(const char *FilNam, int mod, ...)
+{
+ int i, KwdCod, res, *PtrVer, *PtrDim, MshIdx=0;
+ char str[ GmfStrSiz ];
+ va_list VarArg;
+ GmfMshSct *msh;
+
+ if(!GmfIniFlg)
+ {
+ for(i=0;i<=MaxMsh;i++)
+ GmfMshTab[i] = NULL;
+
+ GmfIniFlg = 1;
+ }
+
+ /*---------------------*/
+ /* MESH STRUCTURE INIT */
+ /*---------------------*/
+
+ for(i=1;i<=MaxMsh;i++)
+ if(!GmfMshTab[i])
+ {
+ MshIdx = i;
+ break;
+ }
+
+ if( !MshIdx || !(msh = calloc(1, sizeof(GmfMshSct))) )
+ return(0);
+
+ /* Copy the FilNam into the structure */
+
+ if(strlen(FilNam) + 7 >= GmfStrSiz)
+ return(0);
+
+ strcpy(msh->FilNam, FilNam);
+
+ /* Store the opening mod (read or write) and guess the filetype (binary or ascii) depending on the extension */
+
+ msh->mod = mod;
+ msh->buf = (void *)msh->DblBuf;
+ msh->FltBuf = (void *)msh->DblBuf;
+ msh->IntBuf = (void *)msh->DblBuf;
+
+ if(strstr(msh->FilNam, ".meshb"))
+ msh->typ |= (Bin | MshFil);
+ else if(strstr(msh->FilNam, ".mesh"))
+ msh->typ |= (Asc | MshFil);
+ else if(strstr(msh->FilNam, ".solb"))
+ msh->typ |= (Bin | SolFil);
+ else if(strstr(msh->FilNam, ".sol"))
+ msh->typ |= (Asc | SolFil);
+ else
+ return(0);
+
+ /* Open the file in the required mod and initialyse the mesh structure */
+
+ if(msh->mod == GmfRead)
+ {
+
+ /*-----------------------*/
+ /* OPEN FILE FOR READING */
+ /*-----------------------*/
+
+ va_start(VarArg, mod);
+ PtrVer = va_arg(VarArg, int *);
+ PtrDim = va_arg(VarArg, int *);
+ va_end(VarArg);
+
+ /* Create the name string and open the file */
+
+ if(!(msh->hdl = fopen(msh->FilNam, "rb")))
+ return(0);
+
+ /* Read the endian coding tag, the mesh version and the mesh dimension (mandatory kwd) */
+
+ if(msh->typ & Bin)
+ {
+ fread((unsigned char *)&msh->cod, WrdSiz, 1, msh->hdl);
+
+ if( (msh->cod != 1) && (msh->cod != 16777216) )
+ return(0);
+
+ ScaWrd(msh, (unsigned char *)&msh->ver);
+
+ if( (msh->ver < 1) || (msh->ver > 3) )
+ return(0);
+
+ if( (msh->ver == 3) && (sizeof(long) == 4) )
+ return(0);
+
+ ScaWrd(msh, (unsigned char *)&KwdCod);
+
+ if(KwdCod != GmfDimension)
+ return(0);
+
+ GetPos(msh);
+ ScaWrd(msh, (unsigned char *)&msh->dim);
+ }
+ else
+ {
+ do
+ {
+ res = fscanf(msh->hdl, "%s", str);
+ }while( (res != EOF) && strcmp(str, "MeshVersionFormatted") );
+
+ if(res == EOF)
+ return(0);
+
+ fscanf(msh->hdl, "%d", &msh->ver);
+
+ if( (msh->ver < 1) || (msh->ver > 3) )
+ return(0);
+
+ do
+ {
+ res = fscanf(msh->hdl, "%s", str);
+ }while( (res != EOF) && strcmp(str, "Dimension") );
+
+ if(res == EOF)
+ return(0);
+
+ fscanf(msh->hdl, "%d", &msh->dim);
+ }
+
+ if( (msh->dim != 2) && (msh->dim != 3) )
+ return(0);
+
+ (*PtrVer) = msh->ver;
+ (*PtrDim) = msh->dim;
+
+ /*------------*/
+ /* KW READING */
+ /*------------*/
+
+ /* Read the list of kw present in the file */
+
+ if(!ScaKwdTab(msh))
+ return(0);
+
+ GmfMshTab[ MshIdx ] = msh;
+
+ return(MshIdx);
+ }
+ else if(msh->mod == GmfWrite)
+ {
+
+ /*-----------------------*/
+ /* OPEN FILE FOR WRITING */
+ /*-----------------------*/
+
+ msh->cod = 1;
+
+ /* Check if the user provided a valid version number and dimension */
+
+ va_start(VarArg, mod);
+ msh->ver = va_arg(VarArg, int);
+ msh->dim = va_arg(VarArg, int);
+ va_end(VarArg);
+
+ if( (msh->ver < 1) || (msh->ver > 3) )
+ return(0);
+
+ if( (msh->ver == 3) && (sizeof(long) == 4) )
+ return(0);
+
+ if( (msh->dim != 2) && (msh->dim != 3) )
+ return(0);
+
+ /* Create the mesh file */
+
+ if(!(msh->hdl = fopen(msh->FilNam, "wb")))
+ return(0);
+
+ GmfMshTab[ MshIdx ] = msh;
+
+
+ /*------------*/
+ /* KW WRITING */
+ /*------------*/
+
+ /* Write the mesh version and dimension */
+
+ if(msh->typ & Asc)
+ {
+ fprintf(msh->hdl, "%s %d\n\n", GmfKwdFmt[ GmfVersionFormatted ][0], msh->ver);
+ fprintf(msh->hdl, "%s %d\n", GmfKwdFmt[ GmfDimension ][0], msh->dim);
+ }
+ else
+ {
+ RecWrd(msh, (unsigned char *)&msh->cod);
+ RecWrd(msh, (unsigned char *)&msh->ver);
+ GmfSetKwd(MshIdx, GmfDimension, 0);
+ RecWrd(msh, (unsigned char *)&msh->dim);
+ }
+
+ return(MshIdx);
+ }
+ else
+ return(0);
+}
+
+
+/*----------------------------------------------------------*/
+/* Close a meshfile in the right way */
+/*----------------------------------------------------------*/
+
+int GmfCloseMesh(int MshIdx)
+{
+ int res = 1;
+ GmfMshSct *msh;
+
+ if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+ return(0);
+
+ msh = GmfMshTab[ MshIdx ];
+ RecBlk(msh, msh->buf, 0);
+
+ /* In write down the "End" kw in write mode */
+
+ if(msh->mod == GmfWrite) {
+ if(msh->typ & Asc)
+ fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ GmfEnd ][0]);
+ else
+ GmfSetKwd(MshIdx, GmfEnd, 0);
+ }
+
+ /* Close the file and free the mesh structure */
+
+ if(fclose(msh->hdl))
+ res = 0;
+
+ free(msh);
+ GmfMshTab[ MshIdx ] = NULL;
+
+ return(res);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read the number of lines and set the position to this kwd*/
+/*----------------------------------------------------------*/
+
+int GmfStatKwd(int MshIdx, int KwdCod, ...)
+{
+ int i, *PtrNmbTyp, *PtrSolSiz, *TypTab;
+ GmfMshSct *msh;
+ KwdSct *kwd;
+ va_list VarArg;
+
+ if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+ return(0);
+
+ msh = GmfMshTab[ MshIdx ];
+
+ if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+ return(0);
+
+ kwd = &msh->KwdTab[ KwdCod ];
+
+ if(!kwd->NmbLin)
+ return(0);
+
+ /* Read further arguments if this kw is a sol */
+
+ if(kwd->typ == SolKwd)
+ {
+ va_start(VarArg, KwdCod);
+
+ PtrNmbTyp = va_arg(VarArg, int *);
+ *PtrNmbTyp = kwd->NmbTyp;
+
+ PtrSolSiz = va_arg(VarArg, int *);
+ *PtrSolSiz = kwd->SolSiz;
+
+ TypTab = va_arg(VarArg, int *);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ TypTab[i] = kwd->TypTab[i];
+
+ va_end(VarArg);
+ }
+
+ return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Set the current file position to a given kwd */
+/*----------------------------------------------------------*/
+
+int GmfGotoKwd(int MshIdx, int KwdCod)
+{
+ GmfMshSct *msh;
+ KwdSct *kwd;
+
+ if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+ return(0);
+
+ msh = GmfMshTab[ MshIdx ];
+
+ if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+ return(0);
+
+ kwd = &msh->KwdTab[ KwdCod ];
+
+ if(!kwd->NmbLin)
+ return(0);
+
+ return(fseek(msh->hdl, kwd->pos, SEEK_SET));
+}
+
+
+/*----------------------------------------------------------*/
+/* Write the kwd and set the number of lines */
+/*----------------------------------------------------------*/
+
+int GmfSetKwd(int MshIdx, int KwdCod, ...)
+{
+ int i, NmbLin=0, *TypTab;
+ long CurPos;
+ va_list VarArg;
+ GmfMshSct *msh;
+ KwdSct *kwd;
+
+ if( (MshIdx < 1) || (MshIdx > MaxMsh) )
+ return(0);
+
+ msh = GmfMshTab[ MshIdx ];
+ RecBlk(msh, msh->buf, 0);
+
+ if( (KwdCod < 1) || (KwdCod > GmfMaxKwd) )
+ return(0);
+
+ kwd = &msh->KwdTab[ KwdCod ];
+
+ /* Read further arguments if this kw has a header */
+
+ if(strlen(GmfKwdFmt[ KwdCod ][2]))
+ {
+ va_start(VarArg, KwdCod);
+ NmbLin = va_arg(VarArg, int);
+
+ if(!strcmp(GmfKwdFmt[ KwdCod ][3], "sr"))
+ {
+ kwd->NmbTyp = va_arg(VarArg, int);
+ TypTab = va_arg(VarArg, int *);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ kwd->TypTab[i] = TypTab[i];
+ }
+
+ va_end(VarArg);
+ }
+
+ /* Setup the kwd info */
+
+ ExpFmt(msh, KwdCod);
+
+ if(!kwd->typ)
+ return(0);
+ else if(kwd->typ == InfKwd)
+ kwd->NmbLin = 1;
+ else
+ kwd->NmbLin = NmbLin;
+
+ /* Store the next kwd position in binary file */
+
+ if( (msh->typ & Bin) && msh->NexKwdPos )
+ {
+ CurPos = ftell(msh->hdl);
+ fseek(msh->hdl, msh->NexKwdPos, SEEK_SET);
+ SetPos(msh, CurPos);
+ fseek(msh->hdl, CurPos, SEEK_SET);
+ }
+
+ /* Write the header */
+
+ if(msh->typ & Asc)
+ {
+ fprintf(msh->hdl, "\n%s\n", GmfKwdFmt[ KwdCod ][0]);
+
+ if(kwd->typ != InfKwd)
+ fprintf(msh->hdl, "%d\n", kwd->NmbLin);
+
+ /* In case of solution field, write the extended header */
+
+ if(kwd->typ == SolKwd)
+ {
+ fprintf(msh->hdl, "%d ", kwd->NmbTyp);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ fprintf(msh->hdl, "%d ", kwd->TypTab[i]);
+
+ fprintf(msh->hdl, "\n\n");
+ }
+ }
+ else
+ {
+ RecWrd(msh, (unsigned char *)&KwdCod);
+ msh->NexKwdPos = ftell(msh->hdl);
+ SetPos(msh, 0);
+
+ if(kwd->typ != InfKwd)
+ RecWrd(msh, (unsigned char *)&kwd->NmbLin);
+
+ /* In case of solution field, write the extended header at once */
+
+ if(kwd->typ == SolKwd)
+ {
+ RecWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ RecWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+ }
+ }
+ msh->pos = 0;
+ return(kwd->NmbLin);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a full line from the current kwd */
+/*----------------------------------------------------------*/
+
+void GmfGetLin(int MshIdx, int KwdCod, ...)
+{
+ int i, j;
+ float *FltSolTab;
+ double *DblSolTab;
+ va_list VarArg;
+ GmfMshSct *msh = GmfMshTab[ MshIdx ];
+ KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+ /* Start decoding the arguments */
+
+ va_start(VarArg, KwdCod);
+
+ if(kwd->typ != SolKwd)
+ {
+ if(msh->ver == 1)
+ {
+ if(msh->typ & Asc)
+ {
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ fscanf(msh->hdl, "%f", va_arg(VarArg, float *));
+ else
+ fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+ }
+ else
+ {
+ ScaBlk(msh, msh->buf, kwd->SolSiz);
+
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ *(va_arg(VarArg, float *)) = msh->FltBuf[i];
+ else
+ *(va_arg(VarArg, int *)) = msh->IntBuf[i];
+ }
+ }
+ else
+ {
+ if(msh->typ & Asc)
+ {
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ fscanf(msh->hdl, "%lf", va_arg(VarArg, double *));
+ else
+ fscanf(msh->hdl, "%d", va_arg(VarArg, int *));
+ }
+ else
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ ScaDblWrd(msh, (unsigned char *)va_arg(VarArg, double *));
+ else
+ ScaWrd(msh, (unsigned char *)va_arg(VarArg, int *));
+ }
+ }
+ else
+ {
+ if(msh->ver == 1)
+ {
+ FltSolTab = va_arg(VarArg, float *);
+
+ if(msh->typ & Asc)
+ for(j=0;j<kwd->SolSiz;j++)
+ fscanf(msh->hdl, "%f", &FltSolTab[j]);
+ else
+ ScaBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
+ }
+ else
+ {
+ DblSolTab = va_arg(VarArg, double *);
+
+ if(msh->typ & Asc)
+ for(j=0;j<kwd->SolSiz;j++)
+ fscanf(msh->hdl, "%lf", &DblSolTab[j]);
+ else
+ for(j=0;j<kwd->SolSiz;j++)
+ ScaDblWrd(msh, (unsigned char *)&DblSolTab[j]);
+ }
+ }
+
+ va_end(VarArg);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a full line from the current kwd */
+/*----------------------------------------------------------*/
+
+void GmfSetLin(int MshIdx, int KwdCod, ...)
+{
+ int i, j, pos, *IntBuf;
+ float *FltSolTab;
+ double *DblSolTab, *DblBuf;
+ va_list VarArg;
+ GmfMshSct *msh = GmfMshTab[ MshIdx ];
+ KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+ /* Start decoding the arguments */
+
+ va_start(VarArg, KwdCod);
+
+ if(kwd->typ != SolKwd)
+ {
+ if(msh->ver == 1)
+ {
+ if(msh->typ & Asc)
+ {
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ fprintf(msh->hdl, "%g ", (float)va_arg(VarArg, double));
+ else
+ fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+ }
+ else
+ {
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ msh->FltBuf[i] = va_arg(VarArg, double);
+ else
+ msh->IntBuf[i] = va_arg(VarArg, int);
+
+ RecBlk(msh, msh->buf, kwd->SolSiz);
+ }
+ }
+ else
+ {
+ if(msh->typ & Asc)
+ {
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ fprintf(msh->hdl, "%.15lg ", va_arg(VarArg, double));
+ else
+ fprintf(msh->hdl, "%d ", va_arg(VarArg, int));
+ }
+ else
+ {
+ pos = 0;
+
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'r')
+ {
+ DblBuf = (void *)&msh->buf[ pos ];
+ *DblBuf = va_arg(VarArg, double);
+ pos += 8;
+ }
+ else
+ {
+ IntBuf = (void *)&msh->buf[ pos ];
+ *IntBuf = va_arg(VarArg, int);
+ pos += 4;
+ }
+ RecBlk(msh, msh->buf, kwd->NmbWrd);
+ }
+ }
+ }
+ else
+ {
+ if(msh->ver == 1)
+ {
+ FltSolTab = va_arg(VarArg, float *);
+
+ if(msh->typ & Asc)
+ for(j=0;j<kwd->SolSiz;j++)
+ fprintf(msh->hdl, "%g ", FltSolTab[j]);
+ else
+ RecBlk(msh, (unsigned char *)FltSolTab, kwd->NmbWrd);
+ }
+ else
+ {
+ DblSolTab = va_arg(VarArg, double *);
+
+ if(msh->typ & Asc)
+ for(j=0;j<kwd->SolSiz;j++)
+ fprintf(msh->hdl, "%.15lg ", DblSolTab[j]);
+ else
+ RecBlk(msh, (unsigned char *)DblSolTab, kwd->NmbWrd);
+ }
+ }
+
+ va_end(VarArg);
+
+ if(msh->typ & Asc)
+ fprintf(msh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Private procedure for transmesh : copy a whole line */
+/*----------------------------------------------------------*/
+
+void GmfCpyLin(int InpIdx, int OutIdx, int KwdCod)
+{
+ double d;
+ float f;
+ int i, a;
+ GmfMshSct *InpMsh = GmfMshTab[ InpIdx ], *OutMsh = GmfMshTab[ OutIdx ];
+ KwdSct *kwd = &InpMsh->KwdTab[ KwdCod ];
+
+ for(i=0;i<kwd->SolSiz;i++)
+ {
+ if(kwd->fmt[i] == 'r')
+ {
+ if(InpMsh->ver == 1)
+ {
+ if(InpMsh->typ & Asc)
+ fscanf(InpMsh->hdl, "%f", &f);
+ else
+ ScaWrd(InpMsh, (unsigned char *)&f);
+
+ d = f;
+ }
+ else
+ {
+ if(InpMsh->typ & Asc)
+ fscanf(InpMsh->hdl, "%lf", &d);
+ else
+ ScaDblWrd(InpMsh, (unsigned char *)&d);
+
+ f = (float)d;
+ }
+
+ if(OutMsh->ver == 1)
+ if(OutMsh->typ & Asc)
+ fprintf(OutMsh->hdl, "%g ", f);
+ else
+ RecWrd(OutMsh, (unsigned char *)&f);
+ else
+ if(OutMsh->typ & Asc)
+ fprintf(OutMsh->hdl, "%.15g ", d);
+ else
+ RecDblWrd(OutMsh, (unsigned char *)&d);
+ }
+ else
+ {
+ if(InpMsh->typ & Asc)
+ fscanf(InpMsh->hdl, "%d", &a);
+ else
+ ScaWrd(InpMsh, (unsigned char *)&a);
+
+ if(OutMsh->typ & Asc)
+ fprintf(OutMsh->hdl, "%d ", a);
+ else
+ RecWrd(OutMsh, (unsigned char *)&a);
+ }
+ }
+
+ if(OutMsh->typ & Asc)
+ fprintf(OutMsh->hdl, "\n");
+}
+
+
+/*----------------------------------------------------------*/
+/* Find every kw present in a meshfile */
+/*----------------------------------------------------------*/
+
+static int ScaKwdTab(GmfMshSct *msh)
+{
+ int KwdCod;
+ long NexPos, CurPos, EndPos;
+ char str[ GmfStrSiz ];
+
+ if(msh->typ & Asc)
+ {
+ /* Scan each string in the file until the end */
+
+ while(fscanf(msh->hdl, "%s", str) != EOF)
+ {
+ /* Fast test in order to reject quickly the numeric values */
+
+ if(isalpha(str[0]))
+ {
+ /* Search which kwd code this string is associated with,
+ then get its header and save the curent position in file (just before the data) */
+
+ for(KwdCod=1; KwdCod<= GmfMaxKwd; KwdCod++)
+ if(!strcmp(str, GmfKwdFmt[ KwdCod ][0]))
+ {
+ ScaKwdHdr(msh, KwdCod);
+ break;
+ }
+ }
+ else if(str[0] == '#')
+ while(fgetc(msh->hdl) != '\n');
+ }
+ }
+ else
+ {
+ /* Get file size */
+
+ CurPos = ftell(msh->hdl);
+ fseek(msh->hdl, 0, SEEK_END);
+ EndPos = ftell(msh->hdl);
+ fseek(msh->hdl, CurPos, SEEK_SET);
+
+ /* Jump through kwd positions in the file */
+
+ do
+ {
+ /* Get the kwd code and the next kwd position */
+
+ ScaWrd(msh, (unsigned char *)&KwdCod);
+ NexPos = GetPos(msh);
+
+ if(NexPos > EndPos)
+ return(0);
+
+ /* Check if this kwd belongs to this mesh version */
+
+ if( (KwdCod >= 1) && (KwdCod <= GmfMaxKwd) )
+ ScaKwdHdr(msh, KwdCod);
+
+ /* Go to the next kwd */
+
+ if(NexPos)
+ fseek(msh->hdl, NexPos, SEEK_SET);
+ }while(NexPos && (KwdCod != GmfEnd));
+ }
+
+ return(1);
+}
+
+
+/*----------------------------------------------------------*/
+/* Read and setup the keyword's header */
+/*----------------------------------------------------------*/
+
+static void ScaKwdHdr(GmfMshSct *msh, int KwdCod)
+{
+ int i;
+ KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+ if(!strcmp("i", GmfKwdFmt[ KwdCod ][2]))
+ {
+ if(msh->typ & Asc)
+ fscanf(msh->hdl, "%d", &kwd->NmbLin);
+ else
+ ScaWrd(msh, (unsigned char *)&kwd->NmbLin);
+ }
+ else
+ kwd->NmbLin = 1;
+
+ if(!strcmp("sr", GmfKwdFmt[ KwdCod ][3]))
+ {
+ if(msh->typ & Asc)
+ {
+ fscanf(msh->hdl, "%d", &kwd->NmbTyp);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ fscanf(msh->hdl, "%d", &kwd->TypTab[i]);
+ }
+ else
+ {
+ ScaWrd(msh, (unsigned char *)&kwd->NmbTyp);
+
+ for(i=0;i<kwd->NmbTyp;i++)
+ ScaWrd(msh, (unsigned char *)&kwd->TypTab[i]);
+ }
+ }
+
+ ExpFmt(msh, KwdCod);
+ kwd->pos = ftell(msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Expand the compacted format and compute the line size */
+/*----------------------------------------------------------*/
+
+static void ExpFmt(GmfMshSct *msh, int KwdCod)
+{
+ int i, j, TmpSiz=0;
+ char chr, *InpFmt = GmfKwdFmt[ KwdCod ][3];
+ KwdSct *kwd = &msh->KwdTab[ KwdCod ];
+
+ /* Set the kwd's type */
+
+ if(!strlen(GmfKwdFmt[ KwdCod ][2]))
+ kwd->typ = InfKwd;
+ else if(!strcmp(InpFmt, "sr"))
+ kwd->typ = SolKwd;
+ else
+ kwd->typ = RegKwd;
+
+ /* Get the solution-field's size */
+
+ if(kwd->typ == SolKwd)
+ for(i=0;i<kwd->NmbTyp;i++)
+ switch(kwd->TypTab[i])
+ {
+ case GmfSca : TmpSiz += 1; break;
+ case GmfVec : TmpSiz += msh->dim; break;
+ case GmfSymMat : TmpSiz += (msh->dim * (msh->dim+1)) / 2; break;
+ case GmfMat : TmpSiz += msh->dim * msh->dim; break;
+ }
+
+ /* Scan each character from the format string */
+
+ i = kwd->SolSiz = kwd->NmbWrd = 0;
+
+ while(i < strlen(InpFmt))
+ {
+ chr = InpFmt[ i++ ];
+
+ if(chr == 'd')
+ {
+ chr = InpFmt[i++];
+
+ for(j=0;j<msh->dim;j++)
+ kwd->fmt[ kwd->SolSiz++ ] = chr;
+ }
+ else if(chr == 's')
+ {
+ chr = InpFmt[i++];
+
+ for(j=0;j<TmpSiz;j++)
+ kwd->fmt[ kwd->SolSiz++ ] = chr;
+ }
+ else
+ kwd->fmt[ kwd->SolSiz++ ] = chr;
+ }
+
+ for(i=0;i<kwd->SolSiz;i++)
+ if(kwd->fmt[i] == 'i')
+ kwd->NmbWrd++;
+ else if(msh->ver >= 2)
+ kwd->NmbWrd += 2;
+ else
+ kwd->NmbWrd++;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a four bytes word from a mesh file */
+/*----------------------------------------------------------*/
+
+static void ScaWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+ unsigned char swp;
+
+ fread(wrd, WrdSiz, 1, msh->hdl);
+
+ if(msh->cod == 1)
+ return;
+
+ swp = wrd[3];
+ wrd[3] = wrd[0];
+ wrd[0] = swp;
+
+ swp = wrd[2];
+ wrd[2] = wrd[1];
+ wrd[1] = swp;
+}
+
+
+/*----------------------------------------------------------*/
+/* Read an eight bytes word from a mesh file */
+/*----------------------------------------------------------*/
+
+static void ScaDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+ int i;
+ unsigned char swp;
+
+ fread(wrd, WrdSiz, 2, msh->hdl);
+
+ if(msh->cod == 1)
+ return;
+
+ for(i=0;i<4;i++)
+ {
+ swp = wrd[7-i];
+ wrd[7-i] = wrd[i];
+ wrd[i] = swp;
+ }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read ablock of four bytes word from a mesh file */
+/*----------------------------------------------------------*/
+
+static void ScaBlk(GmfMshSct *msh, unsigned char *blk, int siz)
+{
+ int i, j;
+ unsigned char swp, *wrd;
+
+ fread(blk, WrdSiz, siz, msh->hdl);
+
+ if(msh->cod == 1)
+ return;
+
+ for(i=0;i<siz;i++)
+ {
+ wrd = &blk[ i * 4 ];
+
+ for(j=0;j<2;j++)
+ {
+ swp = wrd[ 3-j ];
+ wrd[ 3-j ] = wrd[j];
+ wrd[j] = swp;
+ }
+ }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a 4 or 8 bytes position in mesh file */
+/*----------------------------------------------------------*/
+
+static long GetPos(GmfMshSct *msh)
+{
+ int IntVal;
+ long pos;
+
+ if(msh->ver >= 3)
+ ScaDblWrd(msh, (unsigned char*)&pos);
+ else
+ {
+ ScaWrd(msh, (unsigned char*)&IntVal);
+ pos = IntVal;
+ }
+
+ return(pos);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a four bytes word to a mesh file */
+/*----------------------------------------------------------*/
+
+static void RecWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+ fwrite(wrd, WrdSiz, 1, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write an eight bytes word to a mesh file */
+/*----------------------------------------------------------*/
+
+static void RecDblWrd(GmfMshSct *msh, unsigned char *wrd)
+{
+ fwrite(wrd, WrdSiz, 2, msh->hdl);
+}
+
+
+/*----------------------------------------------------------*/
+/* Write a block of four bytes word to a mesh file */
+/*----------------------------------------------------------*/
+
+static void RecBlk(GmfMshSct *msh, unsigned char *blk, int siz)
+{
+ /* Copy this line-block into the main mesh buffer */
+
+ if(siz)
+ {
+ memcpy(&msh->blk[ msh->pos ], blk, siz * WrdSiz);
+ msh->pos += siz * WrdSiz;
+ }
+
+ /* When the buffer is full or this procedure is called with a 0 size, flush the cache on disk */
+
+ if( (msh->pos > BufSiz) || (!siz && msh->pos) )
+ {
+ fwrite(msh->blk, 1, msh->pos, msh->hdl);
+ msh->pos = 0;
+ }
+}
+
+
+/*----------------------------------------------------------*/
+/* Read a 4 or 8 bytes position in mesh file */
+/*----------------------------------------------------------*/
+
+static void SetPos(GmfMshSct *msh, long pos)
+{
+ int IntVal;
+
+ if(msh->ver >= 3)
+ RecDblWrd(msh, (unsigned char*)&pos);
+ else
+ {
+ IntVal = pos;
+ RecWrd(msh, (unsigned char*)&IntVal);
+ }
+}