Fetch specific errors in MMG

Hello there. First of all, thank you for this very useful library.
I’m using it for meshing 2d elements and I stumbled into a problem. Sometimes I’m passing data to MMG2D which are non-consistent, I mean numerically wrong.
Those are some very limited side cases, which happens when my meshes are very tiny, i.e. very little verts and edges lengths. The tool I use before calling MMG seem to have a bug, and generates those inconsistent results which are then fed to MMG.
Thus I get:

Error: MMG5_boundingBox: unable to scale mesh: Check that your mesh contains non-zero points and valid elements.
Assertion failed: ((dataPtr == 0) || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))), function MapBase, file /Users/Developer/eigen/Eigen/src/Core/MapBase.h, line 176.

which is in turn generated by the bbox code check in mmg/src/common/scalem.c,
int MMG5_boundingBox(MMG5_pMesh mesh), about line 70

  mesh->info.delta = 0.0;
  for (i=0; i<mesh->dim; i++) {
    dd = mesh->info.max[i] - mesh->info.min[i];
    if ( dd > mesh->info.delta )  mesh->info.delta = dd;
  }
  if ( mesh->info.delta < MMG5_EPSD ) {
    fprintf(stderr,"\n  ## Error: %s: unable to scale mesh:"
            " Check that your mesh contains non-zero points and "
            "valid elements.\n",__func__);
    return 0;
  }

called by MMG2D_mmg2dmesh in my code.
Of course I could trap the numerical errors by some isFinite check in Eigen, but I’d like to know if there’s a way to fetch this specific error in some way. Apparently the meshing call only returns MMG5_STRONGFAILURE, MMG5_LOWFAILURE…
Basically my question is if it’s possible to fetch a specific error in MMG.
Thank you in advance

Hello,

Thank you for using Mmg!

I think that it should be possible to play with stream redirection to redirect error messages in file and then parse this file to find a given error message. See for example the following links:

Do not hesitate to post a minimal code of your solution if it works, it can interest other users!

Best Regards,

Algiane

yes, actually is possible to fetch the stderrr. I have used

which gets things easier. Here it is:

main.cpp

#include <subprocess.hpp>

#include <filesystem>

#include <iostream>

auto subprocrun = [&](
                      std::vector<std::string> &params,
                      int &rc,
                      std::string &out,
                      std::string &err) -> bool
{
    using namespace std;
    using subprocess::CompletedProcess;
    using subprocess::PipeOption;
    using subprocess::RunBuilder;

    CompletedProcess process = {};

    // capture output with exceptions
    try
    {
        process = subprocess::run(
            {params}, RunBuilder().cerr(PipeOption::pipe).cout(PipeOption::pipe));
    }
    // command not found
    catch (const std::exception &e)
    {
        cout << "Cannot Run!" << endl;
        return false;
    }

    return true;
};

auto findstr = [](std::string item, std::string search) -> int
{
    std::size_t found = item.find(search);
    if (found == std::string::npos)
        return -1;

    return found;
};

int main(int argc, char *argv[])
{
    using namespace std;

    std::vector<std::string> params = {};
    std::string out, err = {};
    int rc = {};

    std::string mmg_exe = "your_path_to_mmg.exe";
    std::string mmg_data = "your_path_to_mmg_data_file";
    std::string mmg_param1 = "your_mmg_option1";
    std::string mmg_param2 = "your_mmg_option2";

    params.push_back({mmg_exe});
    params.push_back({mmg_data});
    params.push_back({mmg_param1});
    params.push_back({mmg_param2});
    // and so on

    if (!subprocrun(params, rc, out, err))
    {
        cout << "Cannot Run!" << endl;
        return EXIT_FAILURE;
    }

    // show output
    cout << "MMG called with reply:\n"
         << out << endl;

    // check result
    if (rc != 0)
    {
        cout << "MMG Error!" << endl;

        // check stderr
        if (err.size())
        {
            // check specific MMG error
            if (err.size())
            {
                //
                // YOUR MMG STRING ERROR TO CHECK
                //
                std::string MMG_STDERR = "unable to scale mesh";

                if (findstr(err, MMG_STDERR) > 0)
                {
                    cout << "MMG Error: " << MMG_STDERR << endl;
                    // DO YOUR LOGIC
                    return EXIT_FAILURE;
                }
            }
        }
    }

    return EXIT_SUCCESS;
};

Anyway, I’d like to fetch the error using a direct call… but this is not possible short of directly rewriting MMG error management in the library itself…
Thank you

Hi,

Great, thanks for the feedback.

Indeed, it is complicated to change the handling of errors of the library directly because it impacts existing interfacing.

Sorry for that,

Have a nice day,