diff --git a/CMakeLists.txt b/CMakeLists.txt index ff2d1d5..2ce3d4b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ cmake_minimum_required (VERSION 3.7.2) set (libMeshb_VERSION_MAJOR 7) -set (libMeshb_VERSION_MINOR 54) +set (libMeshb_VERSION_MINOR 80) project(libMeshb VERSION ${libMeshb_VERSION_MAJOR}.${libMeshb_VERSION_MINOR} LANGUAGES C) option(WITH_GMF_AIO "Use Unix low-level and asynchronous I/O for higher speed" OFF) diff --git a/Documentation/fortran_api.md b/Documentation/fortran_api.md index 63cfbec..44d6a3e 100644 --- a/Documentation/fortran_api.md +++ b/Documentation/fortran_api.md @@ -40,68 +40,66 @@ From Fortran you need to provide all arguments even if they are not needed. Calls C GmfSetHONodesOrdering() with the same arguments. -## VERTICES +### gmfgetlinef77(lib, kwd, IntTab, RealTab, Ref) -Vertices data is split in two fields: a pointer to consecutive REAL8 to store coordinates and a pointer on an INT4 that stores the reference. +Reads a full line of a giver keyword's data. +Right now, the default data kinds are integer*4 and real*8. +Integer fields are stored in IntTab(), floating point values are stored in DblTab() and if the keyword includes a reference (GmfVertices and all elements), it is stored in Ref. -### gmfgetvertex(lib, coordinates, ref) +Note that even though some keywords don't need all the parameters, you need to provide them all to the function call, use dummy parameters if needed. -Reads a single vertex. -Calls C GmfGetLin() with keyword GmfVertices, a pointer on a vector of 2 or 3 consecutive REAL8 and a pointer on an integer ref. +### gmfsetlinef77(lib, kwd, IntTab, RealTab, Ref) -### gmfsetvertex(lib, coordinates, ref) +Writes a full line of a giver keyword's data. +Right now, the default data kinds are integer*4 and real*8. -Writes a single vertex. -Calls C GmfSetLin() with keyword GmfVertices, a pointer on a vector of 2 or 3 consecutive REAL8 and the value of the integer ref. +Integer fields are stored in IntTab(), floating point values are stored in DblTab() and if the keyword includes a reference (GmfVertices and all elements), it is stored in Ref. -### gmfgetvertices(lib, start-index, end-index, map-type, map, start-coordinates, end-coordinate, start-ref, end-ref) +Note that even though some keywords don't need all the parameters, you need to provide them all to the function call, use dummy parameters if needed. -Reads a block of vertices. -Calls C GmfGetBlock with GmfVertices and pointers to the first vertex coordinates, last vertex coordinates, first vertex reference and last vertex reference. -### gmfsetvertices(lib, start-index, end-index, map-type, map, start-coordinates, end-coordinate, start-ref, end-ref) +### gmfget blockf77(lib, kwd, BegIdx, EndIdx, MapTyp, MapTab, BegInt, EndInt, BegReal, EndReal, BegRef, EndRef) -Writes a block of vertices. -Calls C GmfSetBlock with GmfVertices and pointers to the first vertex coordinates, last vertex coordinates, first vertex reference and last vertex reference. +Reads multiple data lines in a row. +You need to provide tables big enough to store all the data in one huge memory area. -## ELEMENTS +BegIdx and EndIdx are the first and last line number to be read (1 .. NbElements reads the whole mesh). -Elements data is split in two fields: a pointer to consecutive INT4 to store nodes indices and a pointer on an INT4 that stores the reference. +BegInt points to the first entity integer's data. -### gmfgetelement(lib, element-kind, nodes, ref) +EndInt points to the last entity integer's data. -Reads a single element. -Calls C GmfGetLin() with the provided element keyword, a pointer on a vector of several consecutive INT4 to store nodes indices and a pointer on an integer ref. +BegReal points to the first entity REAL*8's data. -### gmfsetelement(lib, element-kind, nodes, ref) +EndReal points to the last entity REAL*8's data. -Writes a single element. -Calls C GmfSetLin() with the provided element keyword, a pointer on a vector of several consecutive INT4 to store nodes indices and a pointer on an integer ref. +BegRef points to the first entity's reference -### gmfgetelements(lib, element-kind, start-index, end-index, map-type, map, start-nodes, end-nodes, start-ref, end-ref) +EndRef points to the last entity's reference -Reads a block of elements. -Calls C GmfGetBlock() with the provided element keyword, a pointer on the first element's nodes, a pointer on the last element's nodes, a pointer on the first element's reference and a pointer on the last element's reference. +Like with gmgetlinef77(), some arguments may be useless depending on the keyword but you need to provide some dummy argument instead. -### gmfsetelements(lib, element-kind, start-index, end-index, map-type, map, start-nodes, end-nodes, start-ref, end-ref) -Writes a block of elements. -Calls C GmfSetBlock() with the provided element keyword, a pointer on the first element's nodes, a pointer on the last element's nodes, a pointer on the first element's reference and a pointer on the last element's reference. +### gmfset blockf77(lib, kwd, BegIdx, EndIdx, MapTyp, MapTab, BegInt, EndInt, BegReal, EndReal, BegRef, EndRef) +Writes multiple data lines in a row. -## SOLUTIONS +You need to provide tables big enough to store all the data in one huge memory area. -Solution fields are stored in REAL8 into a .sol or .solb file. -All fields must be stored in a consecutive table. +BegIdx and EndIdx are the first and last line number to be read (1 .. NbElements reads the whole mesh). -### gmfgetsolution(lib, solution-keyword, solutions) +BegInt points to the first entity integer's data. -Reads one line of solution fields concatenated into a single REAL8 table. -Calls C GmfGetLin() with the provided solution keyword and a pointer on a vector of sufficent consecutive REAL8 to store a whole line of solution fields. +EndInt points to the last entity integer's data. -### gmfsetsolution(lib, solution-keyword, solutions) +BegReal points to the first entity REAL*8's data. -Writes one line of solution fields concatenated into a single REAL8 table. -Calls C GmfSetLin() with the provided solution keyword and a pointer on a vector of sufficient consecutive REAL8 to store a whole line of solution fields. +EndReal points to the last entity REAL*8's data. + +BegRef points to the first entity's reference + +EndRef points to the last entity's reference + +Like with gmsetlinef77(), some arguments may be useless depending on the keyword but you need to provide some dummy argument instead. diff --git a/README.md b/README.md index ac82c1a..273cdc1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -## libMeshb version 7.79 +## libMeshb version 7.80 A library to handle the *.meshb file format. ## Overview diff --git a/sources/libmeshb7.c b/sources/libmeshb7.c index 6a98e2f..cc4d075 100644 --- a/sources/libmeshb7.c +++ b/sources/libmeshb7.c @@ -2,14 +2,14 @@ /*----------------------------------------------------------------------------*/ /* */ -/* LIBMESHB V7.79 */ +/* LIBMESHB V7.80 */ /* */ /*----------------------------------------------------------------------------*/ /* */ /* Description: handles .meshb file format I/O */ /* Author: Loic MARECHAL */ /* Creation date: dec 09 1999 */ -/* Last modification: feb 23 2024 */ +/* Last modification: feb 27 2024 */ /* */ /*----------------------------------------------------------------------------*/ @@ -469,236 +469,15 @@ const char *GmfKwdFmt[ GmfMaxKwd + 1 ][3] = int GmfMaxRefTab[ GmfMaxKwd + 1 ]; #endif -static char NmbEleNod[ GmfMaxKwd + 1 ] = +static char F77RefFlg[ GmfMaxKwd + 1 ] = { - 0, - 0, - 0, - 0, - 1, - 2, - 3, - 4, - 4, - 6, - 8, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 6, - 3, - 0, - 9, - 0, - 0, - 10, - 0, - 0, - 27, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 32, - 8, - 0, - 5, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 18, - 14, - 14, - 25, - 9, - 13, - 4, - 5, - 0, - 0, - 20, - 35, - 64, - 125, - 30, - 55, - 40, - 75, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,0,0,0, + 0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0 }; @@ -1274,8 +1053,10 @@ int GmfGetLin(int64_t MshIdx, int KwdCod, ...) GmfMshSct *msh = (GmfMshSct *)MshIdx; KwdSct *kwd; + // Special trick: if the kwd is negative the call come from Fortran if(KwdCod < 0) { + // Set Fortran mode ON KwdCod = -KwdCod; kwd = &msh->KwdTab[ KwdCod ]; typ = F77Kwd; @@ -1416,7 +1197,7 @@ int GmfGetLin(int64_t MshIdx, int KwdCod, ...) IntVal = (int)LngVal; } - if(!NmbEleNod[ KwdCod ] || (i < kwd->SolSiz - 1)) + if(!F77RefFlg[ KwdCod ] || (i < kwd->SolSiz - 1)) IntTab[i] = IntVal; else *RefPtr = IntVal; @@ -1466,8 +1247,10 @@ int GmfSetLin(int64_t MshIdx, int KwdCod, ...) GmfMshSct *msh = (GmfMshSct *)MshIdx; KwdSct *kwd; + // Special trick: if the kwd is negative the call come from Fortran if(KwdCod < 0) { + // Set Fortran mode ON KwdCod = -KwdCod; kwd = &msh->KwdTab[ KwdCod ]; typ = F77Kwd; @@ -1615,13 +1398,13 @@ int GmfSetLin(int64_t MshIdx, int KwdCod, ...) else if(kwd->fmt[i] == 'i') { if(msh->ver <= 3) - if(!NmbEleNod[ KwdCod ] || (i < kwd->SolSiz - 1)) + if(!F77RefFlg[ KwdCod ] || (i < kwd->SolSiz - 1)) fprintf(msh->hdl, "%d ", IntTab[i]); else fprintf(msh->hdl, "%d ", *RefPtr); else { - if(!NmbEleNod[ KwdCod ] || (i < kwd->SolSiz - 1)) + if(!F77RefFlg[ KwdCod ] || (i < kwd->SolSiz - 1)) fprintf(msh->hdl, INT64_T_FMT " ", (int64_t)IntTab[i]); else fprintf(msh->hdl, INT64_T_FMT " ", (int64_t)*RefPtr); @@ -1656,7 +1439,7 @@ int GmfSetLin(int64_t MshIdx, int KwdCod, ...) { IntBuf = (void *)&msh->buf[ pos ]; - if(!NmbEleNod[ KwdCod ] || (i < kwd->SolSiz - 1)) + if(!F77RefFlg[ KwdCod ] || (i < kwd->SolSiz - 1)) *IntBuf = IntTab[i]; else *IntBuf = *RefPtr; @@ -1667,7 +1450,7 @@ int GmfSetLin(int64_t MshIdx, int KwdCod, ...) { LngBuf = (void *)&msh->buf[ pos ]; - if(!NmbEleNod[ KwdCod ] || (i < kwd->SolSiz - 1)) + if(!F77RefFlg[ KwdCod ] || (i < kwd->SolSiz - 1)) *LngBuf = (int64_t)IntTab[i]; else *LngBuf = (int64_t)*RefPtr; @@ -3451,11 +3234,13 @@ int APIF77(gmfsethonodesorderingf77)( int64_t *MshIdx, int *KwdCod, int APIF77(gmfgetlinef77)(int64_t *MshIdx, int *kwd, int *i, double *d, int *r) { + // Special trick: use a negative value kwd to set Fortran mode on return(GmfGetLin(*MshIdx, -*kwd, i, d, r)); } int APIF77(gmfsetlinef77)(int64_t *MshIdx, int *kwd, int *i, double *d, int *r) { + // Special trick: use a negative value kwd to set Fortran mode on return(GmfSetLin(*MshIdx, -*kwd, i, d, r)); } @@ -3471,6 +3256,8 @@ int APIF77(gmfgetblockf77)(int64_t *MshIdx, int *KwdCod, GmfMshSct *msh = (GmfMshSct *)*MshIdx; KwdSct *kwd = &msh->KwdTab[ *KwdCod ]; + // Fortran call to getblock uses the GmfArgTab mode where pointers are passed + // through tables: types[], vec sizes[], begin pointers[] and end pointers[] for(i=0;iSolSiz;i++) { if(kwd->fmt[i] == 'i') @@ -3478,7 +3265,7 @@ int APIF77(gmfgetblockf77)(int64_t *MshIdx, int *KwdCod, TypTab[i] = GmfInt; SizTab[i] = 1; - if( (NmbEleNod[ *KwdCod ]) && (i == kwd->SolSiz-1) ) + if( (F77RefFlg[ *KwdCod ]) && (i == kwd->SolSiz-1) ) { BegTab[i] = (char *)BegRef; EndTab[i] = (char *)EndRef; @@ -3513,6 +3300,8 @@ int APIF77(gmfsetblockf77)(int64_t *MshIdx, int *KwdCod, GmfMshSct *msh = (GmfMshSct *)*MshIdx; KwdSct *kwd = &msh->KwdTab[ *KwdCod ]; + // Fortran call to setblock uses the GmfArgTab mode where pointers are passed + // through tables: types[], vec sizes[], begin pointers[] and end pointers[] for(i=0;iSolSiz;i++) { if(kwd->fmt[i] == 'i') @@ -3520,7 +3309,7 @@ int APIF77(gmfsetblockf77)(int64_t *MshIdx, int *KwdCod, TypTab[i] = GmfInt; SizTab[i] = 1; - if( (NmbEleNod[ *KwdCod ]) && (i == kwd->SolSiz-1) ) + if( (F77RefFlg[ *KwdCod ]) && (i == kwd->SolSiz-1) ) { BegTab[i] = (char *)BegRef; EndTab[i] = (char *)EndRef; diff --git a/sources/libmeshb7.h b/sources/libmeshb7.h index 82982a0..5237375 100644 --- a/sources/libmeshb7.h +++ b/sources/libmeshb7.h @@ -2,14 +2,14 @@ /*----------------------------------------------------------------------------*/ /* */ -/* LIBMESHB V7.79 */ +/* LIBMESHB V7.80 */ /* */ /*----------------------------------------------------------------------------*/ /* */ /* Description: handle .meshb file format I/O */ /* Author: Loic MARECHAL */ /* Creation date: dec 09 1999 */ -/* Last modification: feb 08 2024 */ +/* Last modification: feb 27 2024 */ /* */ /*----------------------------------------------------------------------------*/ diff --git a/sources/libmeshb7.ins b/sources/libmeshb7.ins index bf9da1f..2e80863 100644 --- a/sources/libmeshb7.ins +++ b/sources/libmeshb7.ins @@ -2,14 +2,14 @@ c---------------------------------------------------------- c -c LIBMESH V 7.79 +c LIBMESH V 7.80 c c---------------------------------------------------------- c c Description: handles .meshb file format I/O c Author: Loic MARECHAL c Creation date: dec 08 2015 -c Last modification: feb 22 2024 +c Last modification: feb 27 2024 c c---------------------------------------------------------- diff --git a/todolist.md b/todolist.md index 0a418b1..5b76c73 100644 --- a/todolist.md +++ b/todolist.md @@ -13,21 +13,11 @@ - Setup a keyword to store Pk elements. - Give along a routine to convert to and from well-known high-order numberings. -### Handle arbitrary degree polygons and polyhedra -- Add a helper that cuts a polyhedron through a plane and generates the intersection's triangulated mesh in an STL-like format. - ### Solution fields comments - Add a procedure that would search for a string among comments. - Input: keyword name, physical property, free comment, wildcards. - Output: list of solutions keywords and particular field number. -### Convert HO examples to Fortran -- test_libmeshb_HO.c -- test_libmeshb_p2_sol.c - -### Add F77 API to GmfSetHONodesOrdering -An easy one. - ### Add IHOSol* + DHOSol* for each element kinds, For example: @@ -65,3 +55,7 @@ For example: - Added a set of keywords for each kind of element that stores the number of vertices and their barycentric coordinates. - Added a section about the AIO mode (Asynchronous Input Output). - Added a helper that evaluates the quality of a mesh numbering in terms of efficient cache reuse and inner concurrency. +- Added F77 API to GmfSetHONodesOrdering +- Completely rewrote the whole Fortran API because GFortran dropped support for C variable argumeents procedure. +- H.O. tests converted to Fortran by Christophe Peyret +- Added a helper that cuts a polyhedron through a plane and generates the intersection's triangulated mesh in an STL-like format. diff --git a/whatsnew.md b/whatsnew.md index 3d6fe19..dad7d3b 100644 --- a/whatsnew.md +++ b/whatsnew.md @@ -1,6 +1,6 @@ -## Release 7.79 +## Release 7.80 1. Complete rewrite of the Fortran API: - - No more variable arguments procedures are used in Fortran as such feature is no more supported by gfortran - - Addhoc procedures to handle a few keywords are provided - - Users are encouraged to add their own ! + - No more variable arguments procedures are used in Fortran as such feature is no more supported by gfortran. + - Line-based read and write go through three tables: one that stores all INTEGER4 values, one for REAL8 and an INTEGER4 scalar to store the reference. + - Block based access use the same data structures but each table is duplicated: one to store pointers to the first entities and the other one to store pointers to the last entities. This way, the procedure is able to compute the byte stride and store the mesh file data directly to or from the user's data structures. \ No newline at end of file