diff --git a/.github/workflows/fast-check.yml b/.github/workflows/fast-check.yml deleted file mode 100644 index e835dfb4a..000000000 --- a/.github/workflows/fast-check.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Fast check without dependencies - -on: - push: - # run tests on PR events - pull_request: - types: [opened, synchronize] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - name: configure - run: mkdir build && cd build && cmake -DONLY_VERY_SHORT_TESTS=ON -DBUILD_TESTING=ON .. - - name: make - run: cd build && make - - name: test - run: cd build && ctest diff --git a/.github/workflows/long-tests.yml b/.github/workflows/long-tests.yml index 5ae5ae4eb..06b8907eb 100644 --- a/.github/workflows/long-tests.yml +++ b/.github/workflows/long-tests.yml @@ -26,3 +26,5 @@ jobs: cmake_build_type: RelWithAssert add_cmake_cfg_args: -D LONG_TESTS=ON branch_name: ${{github.event.inputs.branch}} + code_coverage: true + secrets: inherit diff --git a/.github/workflows/main-job.yml b/.github/workflows/main-job.yml index 0901c7997..1d6588c70 100644 --- a/.github/workflows/main-job.yml +++ b/.github/workflows/main-job.yml @@ -17,6 +17,12 @@ on: required: false type: string + code_coverage: + description: 'Code coverage' + required: false + default: true + type: boolean + # job jobs: ci: @@ -141,6 +147,24 @@ jobs: int: int64_t steps: + - name: Set cmake_build_type and export coverage flags + run: | + if ${{ matrix.os == 'ubuntu-20.04' && inputs.code_coverage == true }}; then + # if code coverage is enabled, linux build is runned in Debug mode + + if [[ ${{ inputs.cmake_build_type }} != Debug ]]; then + echo "WARNING: build type is forced to debug mode on ubuntu to allow coverage." + fi + + echo "BUILD_TYPE=Debug" >> "$GITHUB_ENV" + echo "C_FLG_PROF=-fprofile-arcs -ftest-coverage" >> "$GITHUB_ENV" + + else + echo "BUILD_TYPE=${{ inputs.cmake_build_type }}" >> "$GITHUB_ENV" + fi + + shell: bash + - name: Print options and set environment variables run: | echo "${{ github.event.inputs.name }}: @@ -149,7 +173,7 @@ jobs: Scotch: ${{ matrix.scotch }}, VTK: ${{ matrix.vtk }}, int: ${{ matrix.int }}, - Build: ${{ inputs.cmake_build_type }}" + Build: ${{ env.BUILD_TYPE }}" # gfortran compiler and scotch makefile depends on the os if [ "$RUNNER_OS" == "macOS" ]; then @@ -170,9 +194,14 @@ jobs: - name: Set environment variables for output comparison if: "! contains(github.event.head_commit.message, '[skip output comparison]')" run: | - echo "C_FLG=\"-DCMAKE_C_FLAGS=-DMMG_COMPARABLE_OUTPUT\"" >> "$GITHUB_ENV" + echo "C_FLG=-DMMG_COMPARABLE_OUTPUT" >> "$GITHUB_ENV" echo "MMG_ERROR_RULE=\"COMMAND_ERROR_IS_FATAL ANY\"" >> "$GITHUB_ENV" + - name: Assign CMAKE_C_FLAGS if needed + if: ${{ env.C_FLG || env.C_FLG_PROF }} + run: | + echo "CMAKE_C_FLG=-DCMAKE_C_FLAGS=\"${{ env.C_FLG }} ${{ env.C_FLG_PROF }}\"" >> "$GITHUB_ENV" + - name: Install VTK # Download vtk only if used if: matrix.vtk == 'on' @@ -195,7 +224,7 @@ jobs: cd src cp ${{ env.SCOTCH_MAKE }} Makefile.inc make scotch -j ${{ env.NJOBS }} - make install scotch -j ${{ env.NJOBS }} + make prefix=../../scotch-install install -j ${{ env.NJOBS }} - name: Install LibCommons # LinearElasticity don't build with MSVC @@ -220,14 +249,14 @@ jobs: make install # checkout the provided branch name if workflow is manually run - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: inputs.branch_name with: ref: ${{github.event.inputs.branch}} path: mmg # checkout the event branch for automatic workflows - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: inputs.branch_name == '' with: path: mmg @@ -235,14 +264,15 @@ jobs: - name: Test compilation with shared libs linkage run: | cmake -Smmg -Bbuild_shared \ - ${{ env.C_FLG }} \ + ${{ env.CMAKE_C_FLG }} \ ${{ env.FORT_FLG }} \ -DCI_CONTEXT=ON \ -DBUILD_TESTING=ON \ - -DCMAKE_BUILD_TYPE=${{ inputs.cmake_build_type }} \ + -DUSE_POINTMAP=${{ matrix.pointmap }} \ + -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DMMG_PATTERN=${{ matrix.pattern }} \ -DUSE_SCOTCH=${{ matrix.scotch }} \ - -DSCOTCH_DIR=scotch \ + -DSCOTCH_DIR=scotch-install \ -DUSE_VTK=${{ matrix.vtk }} \ -DMMG5_INT=${{ matrix.int }} \ -DBUILD_SHARED_LIBS=ON \ @@ -251,20 +281,21 @@ jobs: -DTEST_LIBMMG2D=ON \ -DTEST_LIBMMG3D=ON \ ${{ inputs.add_cmake_cfg_args }} - cmake --build build_shared --config ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + cmake --build build_shared --config ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} shell: bash - name: Test compilation without library linkage run: | cmake -Smmg -Bbuild_nolibs \ - ${{ env.C_FLG }} \ + ${{ env.CMAKE_C_FLG }} \ ${{ env.FORT_FLG }} \ -DCI_CONTEXT=ON \ -DBUILD_TESTING=ON \ - -DCMAKE_BUILD_TYPE=${{ inputs.cmake_build_type }} \ + -DUSE_POINTMAP=${{ matrix.pointmap }} \ + -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DMMG_PATTERN=${{ matrix.pattern }} \ -DUSE_SCOTCH=${{ matrix.scotch }} \ - -DSCOTCH_DIR=scotch \ + -DSCOTCH_DIR=scotch-install \ -DUSE_VTK=${{ matrix.vtk }} \ -DMMG5_INT=${{ matrix.int }} \ -DLIBMMG_STATIC=OFF \ @@ -272,21 +303,22 @@ jobs: -DLIBMMG2D_STATIC=OFF \ -DLIBMMG3D_STATIC=OFF \ ${{ inputs.add_cmake_cfg_args }} - cmake --build build_nolibs --config ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + cmake --build build_nolibs --config ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} shell: bash - name: Configure Mmg with static libs (default behaviour) run: | cmake -Smmg -Bbuild \ - ${{ env.C_FLG }} \ + ${{ env.CMAKE_C_FLG }} \ ${{ env.FORT_FLG }} \ -DCMAKE_INSTALL_PREFIX=mmg-install \ -DCI_CONTEXT=ON \ -DBUILD_TESTING=ON \ - -DCMAKE_BUILD_TYPE=${{ inputs.cmake_build_type }} \ + -DUSE_POINTMAP=${{ matrix.pointmap }} \ + -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} \ -DMMG_PATTERN=${{ matrix.pattern }} \ -DUSE_SCOTCH=${{ matrix.scotch }} \ - -DSCOTCH_DIR=scotch \ + -DSCOTCH_DIR=scotch-install \ -DUSE_VTK=${{ matrix.vtk }} \ -DMMG5_INT=${{ matrix.int }} \ -DTEST_LIBMMG=ON \ @@ -298,15 +330,15 @@ jobs: - name: Build Mmg run: | - cmake --build build --config ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + cmake --build build --config ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} - name: Install Mmg run: | - cmake --build build --target install --config ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + cmake --build build --target install --config ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} - name: Archive production artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: Mmg-bin + name: Mmg-bin-${{ matrix.os }}-${{ matrix.pattern }}-${{ matrix.pointmap }}-${{ matrix.scotch }}-${{ matrix.vtk }}-${{ matrix.int }} path: | build/bin @@ -315,25 +347,35 @@ jobs: if: matrix.vtk == 'off' && matrix.int == 'int32_t' run: | cd build - ctest --timeout 7200 -VV -C ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + ctest --timeout 7200 -VV -C ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} - name: Test Mmg with in64_t integers # Run long tests only on ubuntu with pattern off, scotch on, vtk on and int64_t integers if: matrix.os == 'ubuntu-20.04' && matrix.pattern == 'off' && matrix.scotch == 'on' && matrix.vtk == 'on' && matrix.int == 'int64_t' run: | cd build - ctest --timeout 7200 -VV -C ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} + ctest --timeout 7200 -VV -C ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} - name: Test non native I/Os of Mmg if: matrix.vtk == 'on' run: | cd build - ctest -R "msh|vtk" -VV -C ${{ inputs.cmake_build_type }} -j ${{ env.NJOBS }} - - # - name: Archive production artifacts for tests - # if: success() || failure() - # uses: actions/upload-artifact@v2 - # with: - # name: Mmg-tests - # path: | - # build/TEST_OUTPUTS + ctest -R "msh|vtk" -VV -C ${{ env.BUILD_TYPE }} -j ${{ env.NJOBS }} + + - name: Archive production artifacts for tests + if: success() || failure() + uses: actions/upload-artifact@v4 + with: + name: Mmg-tests-${{ matrix.os }}-${{ matrix.pattern }}-${{ matrix.pointmap }}-${{ matrix.scotch }}-${{ matrix.vtk }}-${{ matrix.int }} + path: | + build/TEST_OUTPUTS + + - name: Upload coverage to Codecov + if: matrix.os == 'ubuntu-20.04' && inputs.code_coverage == true + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + root_dir: . + verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 000000000..09d2488c6 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,3 @@ +fixes: + - "mmg/mmg::" + diff --git a/src/mmg3d/boulep_3d.c b/src/mmg3d/boulep_3d.c index 94eb81d9a..a2b37f5a5 100644 --- a/src/mmg3d/boulep_3d.c +++ b/src/mmg3d/boulep_3d.c @@ -748,8 +748,8 @@ int MMG5_boulesurfvolp(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, /** * \param mesh pointer to the mesh structure. - * \param start index of the starting tetra. - * \param ip index in \a start of the looked point. + * \param start index of the starting tetrahedron. + * \param ip index in \a start of the desired vertex. * \param iface index in \a start of the starting face. * \param listv pointer to the computed volumic ball. * \param ilistv pointer to the computed volumic ball size. @@ -757,32 +757,38 @@ int MMG5_boulesurfvolp(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, * \param ilists pointer to the computed surfacic ball size. * \param refmin return the reference of one of the two subdomains in presence * \param refplus return the reference of the other subdomain in presence - * \param isnm is the looked point \a ip non-manifold? - * \return -1 if fail, 1 otherwise. + * \param isnm is the vertex non-manifold? + * \return 1 if succesful, a negative value if the ball cannot be computed: + * -1 if a surface ball had too many elements, + * -2 if there are more than two references around, + * -3 if an edge cannot be found, and + * -4 if a volume ball had too many elements. + * Among these, -1, -3 and -4 can be taken as a sign that further remeshing + * is not possible, while -2 just mean the job could not be done. * * Compute the volumic ball of a SURFACE point \a p, as well as its surfacic - * ball, starting from tetra \a start, with point \a ip, and face \a if in tetra + * ball, starting from tetra \a start, with point \a ip, and face \a if in the * volumic ball. * \a listv[k] = 4*number of tet + index of point surfacic ball. * \a lists[k] = 4*number of tet + index of face. * - * \warning Don't work for a non-manifold point if \a start has an adjacent - * through \a iface (for example : a non-manifold subdomain). Thus, if \a ip is + * \warning Doesn't work for a non-manifold point if \a start has an adjacent + * through \a iface (for example: a non-manifold subdomain). Thus, if \a ip is * non-manifold, must be called only if \a start has no adjacent through iface. * */ -int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, - int64_t *listv,int *ilistv,MMG5_int *lists,int *ilists, - MMG5_int *refmin,MMG5_int *refplus,int isnm) +int MMG5_boulesurfvolpNom(MMG5_pMesh mesh, MMG5_int start, int ip, int iface, + int64_t *listv, int *ilistv, MMG5_int *lists, int *ilists, + MMG5_int *refmin, MMG5_int *refplus, int isnm) { - MMG5_pTetra pt,pt1; + MMG5_pTetra pt, pt1; MMG5_pxTetra pxt; - MMG5_int k,k1,nump,*adja,piv,na,nb,adj,cur,nvstart,fstart,aux,base; - int8_t iopp,ipiv,i,j,l,isface; + MMG5_int k, k1, nump, *adja, piv, na, nb, adj, cur, nvstart, fstart, aux, base; + int8_t iopp, ipiv, i, j, l, isface; static int8_t mmgErr0=0, mmgErr1=0, mmgErr2=0; - + if ( isnm ) assert(!mesh->adja[4*(start-1)+iface+1]); - + base = ++mesh->base; *ilists = 0; *ilistv = 0; @@ -814,16 +820,15 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, MMG3D_indPt(mesh,nump)); mmgErr0 = 1; } - return -1; } - + aux = nb; nb = piv; piv = aux; nvstart = k; adj = k; - + /* Now unfold shell of edge (na,nb) starting from k (included)*/ do { k = adj; @@ -835,7 +840,7 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, assert(i<4); listv[(*ilistv)] = 4*k+i; (*ilistv)++; - + /* Identify references of both subdomains in presence */ if ( *refmin == -1 ) *refmin = pt->ref; @@ -843,14 +848,14 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, if ( *refplus == -1 ) { if ( pt->ref != *refmin ) *refplus = pt->ref; } - else if ( pt->ref != *refmin && pt->ref != *refplus ) return -1; + else if ( pt->ref != *refmin && pt->ref != *refplus ) return -2; } pt->flag = base; } - + /* identification of edge number in tetra k */ - if ( !MMG3D_findEdge(mesh,pt,k,na,nb,0,&mmgErr2,&i) ) return -1; - + if ( !MMG3D_findEdge(mesh,pt,k,na,nb,0,&mmgErr2,&i) ) return -3; + /* set sense of travel */ if ( pt->v[ MMG5_ifar[i][0] ] == piv ) { iopp = MMG5_ifar[i][0]; @@ -878,14 +883,14 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, while ( adj && (adj != nvstart) && !isface ); } while ( 4*k+iopp != fstart ); - + /* Now, surfacic ball is complete ; finish travel of volumic ball */ cur = 0; // Check numerotation while ( cur < (*ilistv) ) { k = listv[cur]/4; i = listv[cur]%4; // index of point p in tetra k adja = &mesh->adja[4*(k-1)+1]; - + for (l=0; l<3; l++) { i = MMG5_inxt3[i]; k1 = adja[i]; @@ -894,11 +899,11 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, pt1 = &mesh->tetra[k1]; if ( pt1->flag == base ) continue; pt1->flag = base; - + for (j=0; j<4; j++) if ( pt1->v[j] == nump ) break; assert(j<4); - + /* overflow */ if ( *ilistv > MMG3D_LMAX-3 ) { if ( !mmgErr1 ) { @@ -909,11 +914,11 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, " or/and the maximum mesh.\n"); mmgErr1 = 1; } - return -1; + return -4; } listv[(*ilistv)] = 4*k1+j; (*ilistv)++; - + /* Identify references of both subdomains in presence */ if ( *refmin == -1 ) *refmin = pt1->ref; @@ -921,12 +926,12 @@ int MMG5_boulesurfvolpNom(MMG5_pMesh mesh,MMG5_int start,int ip,int iface, if ( *refplus == -1 ) { if ( pt1->ref != *refmin ) *refplus = pt1->ref; } - else if ( pt1->ref != *refmin && pt1->ref != *refplus ) return -1; + else if ( pt1->ref != *refmin && pt1->ref != *refplus ) return -2; } } cur++; } - + return 1; } diff --git a/src/mmg3d/mmg3d1.c b/src/mmg3d/mmg3d1.c index 9cb8aef26..566ac50d1 100644 --- a/src/mmg3d/mmg3d1.c +++ b/src/mmg3d/mmg3d1.c @@ -880,12 +880,12 @@ MMG5_int MMG5_movtet(MMG5_pMesh mesh,MMG5_pSol met, MMG3D_pPROctree PROctree, * \param mesh pointer to the mesh structure. * \param met pointer to the metric structure. * \param typchk type of checking permformed for edge length (hmin or LSHORT criterion). - * \return -1 if failed, number of collapsed points otherwise. + * \return a negative value in case of failure, number of collapsed points otherwise. * - * Attempt to collapse small edges. + * Attempt to collapse short edges. * */ -static int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { +static MMG5_int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { MMG5_pTetra pt,ptloc; MMG5_pxTetra pxt; MMG5_pPoint p0,p1; @@ -897,7 +897,7 @@ static int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { int l,kk,isloc,ifac1; int16_t tag,isnm,isnmint; int8_t i,j,ip,iq; - int ier; + int ier, bsret; // function return values/error codes nc = nnm = 0; @@ -963,15 +963,21 @@ static int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { } else { if ( mesh->adja[4*(k-1)+1+i] ) continue; - if (MMG5_boulesurfvolpNom(mesh,k,ip,i, - list,&ilist,lists,&ilists,&refmin,&refplus,p0->tag & MG_NOM) < 0 ) - return -1; + + bsret = MMG5_boulesurfvolpNom(mesh,k,ip,i, + list,&ilist,lists,&ilists,&refmin,&refplus,p0->tag & MG_NOM); + if(bsret==-1 || bsret==-3 || bsret==-4){ + return -3; // fatal + }else if(bsret==-2){ + continue; // ball computation failed: cannot handle this vertex + } + assert(bsret==1 && "unexpected return value from MMG5_boulesurfvolpNom"); } } else { if (MMG5_boulesurfvolp(mesh,k,ip,i, list,&ilist,lists,&ilists,p0->tag & MG_NOM) < 0 ) - return -1; + return -2; } } else { @@ -1094,15 +1100,20 @@ static int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { } else { if ( mesh->adja[4*(k-1)+1+i] ) continue; - if (MMG5_boulesurfvolpNom(mesh,k,ip,i, - list,&ilist,lists,&ilists,&refmin,&refplus,p0->tag & MG_NOM) < 0 ) - return -1; + bsret = MMG5_boulesurfvolpNom(mesh,k,ip,i, + list,&ilist,lists,&ilists,&refmin,&refplus,p0->tag & MG_NOM); + if(bsret==-1 || bsret==-3 || bsret==-4){ + return -3; // fatal + }else if(bsret==-2){ + continue; // ball computation failed: cannot handle this vertex + } + assert(bsret==1 && "unexpected return value from MMG5_boulesurfvolpNom"); } } else { if (MMG5_boulesurfvolp(mesh,k,ip,i, list,&ilist,lists,&ilists,p0->tag & MG_NOM) < 0 ) - return -1; + return -4; } } else { @@ -1134,13 +1145,13 @@ static int MMG5_coltet(MMG5_pMesh mesh,MMG5_pSol met,int8_t typchk) { if ( ilist > 0 ) { ier = MMG5_colver(mesh,met,list,ilist,iq,typchk); - if ( ier < 0 ) return -1; + if ( ier < 0 ) return -5; else if ( ier ) { MMG3D_delPt(mesh,ier); break; } } - else if (ilist < 0 ) return -1; + else if (ilist < 0 ) return -6; } if ( ier ) { p1->flag = base;