Problem solving transient brick with MUMPS

I want to solve a two dimensional unsteady Navier-Stokes equation about circular cylinder flow. Belowing is my code:

#define GMM_WARNING_LEVEL 1

#include "getfem/getfem_model_solvers.h"
#include "getfem/getfem_export.h"
#include "getfem/getfem_mesher.h"
#include "getfem/getfem_generic_assembly.h"
#include "getfem/getfem_import.h"
#include "getfem/getfem_derivatives.h"
#include "getfem/getfem_assembling.h"

#include "gmm/gmm.h"
#include "gmm/gmm_MUMPS_interface.h"
#include "mumps_seq/mpi.h"

#include <filesystem>
#include <complex.h>
#include <chrono>

using std::endl; using std::cout; using std::cerr;
using std::ends; using std::cin; using std::string;

using bgeot::size_type;
using bgeot::base_node;
using bgeot::base_small_vector;
using bgeot::scalar_type; /* = double */

typedef getfem::modeling_standard_sparse_matrix sparse_matrix;
typedef gmm::rsvector<scalar_type> sparse_vector_type;
typedef gmm::row_matrix<sparse_vector_type> sparse_matrix_type;
typedef std::vector<scalar_type> plain_vector;

typedef std::complex<double> complex;
typedef getfem::modeling_standard_complex_plain_vector complex_plain_vector;
typedef gmm::dense_matrix<std::complex<double>> complex_dense_matrix;
typedef getfem::modeling_standard_complex_sparse_matrix complex_sparse_matrix;

typedef gmm::mumps_interf<double>::MUMPS_STRUC_C MUMPS_STRUC;

/* Global parameters----------------------------------------- */
double Re = 50.;    /* Reynolds number */
double nu = 1./Re;  /* viscosity */
double dt = 0.05;   /* time interval */
int nt = 1640;      /* number of time iteration steps */
int ntSave = 20;    /* saving result */
double residual = 1e-8;

/* Main program---------------------------------------------- */
int main(int argc, char *argv[]){
    MPI_Init(&argc, &argv);
try{
    /* Initialise------------------------------- */
    getfem::mesh msh;
    getfem::import_mesh("./mesh/cylFlow.msh2", "gmsh", msh);
    int N = msh.dim();
    GMM_ASSERT1(N==2, "mesh dim != 2.");

    int MESH_INLET = 101;
    int MESH_OUTLET = 102;
    int MESH_TOP = 103;
    int MESH_BOTTOM = 104;
    int MESH_CYL_WALL = 105;

    getfem::mesh_fem mf_p(msh);
    getfem::mesh_fem mf_u(msh);
    getfem::mesh_fem mf_v(msh);
    getfem::mesh_im mim(msh);

    mf_p.set_qdim(1);
    mf_u.set_qdim(1);
    mf_v.set_qdim(1);

    getfem::pintegration_method ppi = getfem::int_method_descriptor("IM_TRIANGLE(3)");
    mim.set_integration_method(msh.convex_index(), ppi);

    getfem::pfem pf_p = getfem::fem_descriptor("FEM_PK(2,1)");
    getfem::pfem pf_u = getfem::fem_descriptor("FEM_PK(2,2)");
    getfem::pfem pf_v = getfem::fem_descriptor("FEM_PK(2,2)");

    mf_p.set_finite_element(msh.convex_index(), pf_p);
    mf_u.set_finite_element(msh.convex_index(), pf_u);
    mf_v.set_finite_element(msh.convex_index(), pf_v);

    string outPath = "./out/";
    if (!std::filesystem::exists(outPath)){
        std::filesystem::create_directory(outPath);
        cout << "Create output path: "+outPath << endl;
    }
    std::ofstream of1(outPath+"info.txt");

    cout << "\ngetfem mesh regions: " << msh.regions_index() << endl;
    of1 << "\ngetfem mesh regions: " << msh.regions_index() << endl;

    /* Build model---------------------------- */
    getfem::model model;
    model.add_fem_variable("p", mf_p);
    model.add_fem_variable("u", mf_u, 2);   /* niter=2 */
    model.add_fem_variable("v", mf_v, 2);   /* niter=2 */
    dal::bit_vector transientBricks;

    int nbdof_p = mf_p.nb_dof();
    int nbdof_u = mf_u.nb_dof();
    int nbdof_v = mf_v.nb_dof();
    int nbdof_total = nbdof_p + nbdof_u + nbdof_v;

    gmm::sub_interval I_p = model.interval_of_variable("p");
    gmm::sub_interval I_u = model.interval_of_variable("u");
    gmm::sub_interval I_v = model.interval_of_variable("v");

    cout << "\nnbdof: \n"
        << "nbdof_p: " << nbdof_p << endl
        << "nbdof_u: " << nbdof_u << endl
        << "nbdof_v: " << nbdof_v << endl
        << "\nsub interval: \n"
        << "I_p: " << I_p << endl
        << "I_u: " << I_u << endl
        << "I_v: " << I_v << endl;
    of1 << "\nnbdof: \n"
        << "nbdof_p: " << nbdof_p << endl
        << "nbdof_u: " << nbdof_u << endl
        << "nbdof_v: " << nbdof_v << endl
        << "\nsub interval: \n"
        << "I_p: " << I_p << endl
        << "I_u: " << I_u << endl
        << "I_v: " << I_v << endl;

    /* Nonlinear term: (u.nabla)u */
    int ibNonlinear = getfem::add_nonlinear_term(model, mim, "Test_u*[u,v].Grad_u + Test_v*[u,v].Grad_v");
    transientBricks.add(ibNonlinear);

    /* Laplacian term: -1/Re Delta u */
    model.add_initialized_scalar_data("nu", nu);
    int ibLaplacian = getfem::add_linear_term(model, mim, "nu*(Grad_u.Grad_Test_u + Grad_v.Grad_Test_v)");
    transientBricks.add(ibLaplacian);

    /* Pressure term: nabla p */
    int ibPressure = getfem::add_source_term(model, mim, "p*(Grad_Test_u(1)+Grad_Test_v(2))");
    transientBricks.add(ibPressure);

    /* Continuity condition */
    int ibContinuity = getfem::add_linear_term(model, mim, "Test_p*(Grad_u(1)+Grad_v(2))");
    transientBricks.add(ibContinuity);

    /* Boundary conditions----------------------- */
    /* Inlet: u=1, v=0 */
    model.add_initialized_scalar_data("Uin", 1.);
    getfem::add_Dirichlet_condition_with_simplification(model, "u", MESH_INLET, "Uin");
    getfem::add_Dirichlet_condition_with_simplification(model, "v", MESH_INLET);

    /* Outlet: p=0 */
    getfem::add_Dirichlet_condition_with_simplification(model, "p", MESH_OUTLET);

    /* Top and Bottom: v=0 */
    getfem::add_Dirichlet_condition_with_simplification(model, "v", MESH_TOP);
    getfem::add_Dirichlet_condition_with_simplification(model, "v", MESH_BOTTOM);

    /* Cylinder wall: u=0, v=0 */
    getfem::add_Dirichlet_condition_with_simplification(model, "u", MESH_CYL_WALL);
    getfem::add_Dirichlet_condition_with_simplification(model, "v", MESH_CYL_WALL);

    /* Transient part-------------------------------- */
    model.add_initialized_scalar_data("dt", dt);
    model.add_initialized_scalar_data("alpha", 0.5);
    getfem::add_basic_d_on_dt_brick(model, mim, "u", "dt", "alpha");
    getfem::add_basic_d_on_dt_brick(model, mim, "v", "dt", "alpha");
    getfem::add_midpoint_dispatcher(model, transientBricks);

    /* Output info */
    of1 << "=========================================================\n";
    model.listbricks(of1);
    of1 << "=========================================================\n";
    model.listvar(of1);

    /* Solve----------------------------------------------- */
    // MUMPS_STRUC id;
    gmm::mumps_interf<double>::MUMPS_STRUC_C id;
    id.job = -1;    /* MUMPS initialize */
    id.par = 1;
    id.sym = 0;     /* symmetric matrix=false */
    gmm::mumps_interf<double>::mumps_c(id);

    /* set MUMPS parameters, see https://petsc.org/release/manualpages/Mat/MATSOLVERMUMPS/ */
    id.icntl[0] = -1;
    id.icntl[1] = -1;
    id.icntl[2] = -1;
    id.icntl[3] = 0;
    id.icntl[13] = 200;     /* increase ICNTL(14) */
    id.job = 6;             /* Request all phases: analysis + factorization + solve */
    gmm::mumps_interf<double>::mumps_c(id);
    
    gmm::iteration iter(residual, 0, 5e4);
    model.first_iter();
    /* Initial conditions */
    plain_vector U0, V0;
    gmm::resize(U0, mf_u.nb_dof());
    gmm::resize(V0, mf_v.nb_dof());
    gmm::fill(U0, 1.);
    gmm::clear(V0);

    gmm::copy(U0, model.set_real_variable("u", 1));
    gmm::copy(V0, model.set_real_variable("v", 1));
    
    /* Time iteration */
    double sol_t = 0.;
    plain_vector X(nbdof_total);    /* solution of each time step */
    plain_vector rhs(nbdof_total);
    sparse_matrix TGM(nbdof_total, nbdof_total);

    for (int i=0; i<nt; ++i){
        sol_t += dt;
        cout << "t = " << sol_t << endl;
        iter.init();
        model.assembly(getfem::model::BUILD_ALL);
        getfem::standard_solve(model, iter);
        // gmm::copy(model.real_tangent_matrix(), TGM);
        // gmm::copy(model.real_rhs(), rhs);
        // gmm::MUMPS_solve(TGM, X, rhs);
        // gmm::copy(gmm::sub_vector(X, I_p), model.set_real_variable("p"));
        // gmm::copy(gmm::sub_vector(X, I_u), model.set_real_variable("u"));
        // gmm::copy(gmm::sub_vector(X, I_v), model.set_real_variable("v"));

        /* Export */
        if (i%ntSave==0){
            char s[100];
            sprintf(s, "step%05d", i);
            getfem::vtk_export plot(outPath+string(s)+".vtk", true);
            plot.exporting(msh);
            plot.write_point_data(mf_p, model.real_variable("p"), "p");
            plot.write_point_data(mf_u, model.real_variable("u"), "u");
            plot.write_point_data(mf_v, model.real_variable("v"), "v");
            cout << "\nExporting done." << endl;
        }

        model.next_iter();
    }

    cout.precision(16);
    cout << "L2 norm of u: " << getfem::asm_L2_norm(mim, mf_u, model.real_variable("u")) << endl
        << "Linfty norm of u: " << gmm::vect_norm1(model.real_variable("u")) << endl
        << "L2 norm of v: " << getfem::asm_L2_norm(mim, mf_v, model.real_variable("v")) << endl
        << "Linfty norm of v: " << gmm::vect_norm1(model.real_variable("v")) << endl
        << "L2 norm of p: " << getfem::asm_L2_norm(mim, mf_p, model.real_variable("p")) << endl
        << "Linfty norm of p: " << gmm::vect_norm1(model.real_variable("p")) << endl;
}
GMM_STANDARD_CATCH_ERROR;
MPI_Finalize();
return 0;
}

After compiling the code, I ran the program, but got an error message:

============================================
|    A GMM error has been detected !!!     |
============================================
Error in ./gmm/gmm_MUMPS_interface.h, line 153 : 
Solve with MUMPS failed: error -9, increase ICNTL(14)

The debug call stack generated by lldb is:

__cxa_throw (@__cxa_throw:3)
___lldb_unnamed_symbol4801 (@___lldb_unnamed_symbol4801:79)
___lldb_unnamed_symbol11886 (@___lldb_unnamed_symbol11886:235)
___lldb_unnamed_symbol8322 (@___lldb_unnamed_symbol8322:14)
getfem::standard_solve(getfem::model&, gmm::iteration&, std::shared_ptr<getfem::abstract_linear_solver<gmm::col_matrix<gmm::rsvector<double>>, std::vector<double, std::allocator<double>>>>, getfem::abstract_newton_line_search&) (@getfem::standard_solve(getfem::model&, gmm::iteration&, std::shared_ptr<getfem::abstract_linear_solver<gmm::col_matrix<gmm::rsvector<double>>, std::vector<double, std::allocator<double>>>>, getfem::abstract_newton_line_search&):454)
getfem::standard_solve(getfem::model&, gmm::iteration&) (@getfem::standard_solve(getfem::model&, gmm::iteration&):54)
main (\mnt\d\codes\CFD\getfem\test\myProject\cylinderFlow\Re50\unsteadyNavierStokes\mycode.cc:213)
___lldb_unnamed_symbol3278 (@___lldb_unnamed_symbol3278:29)
__libc_start_main (@__libc_start_main:44)
_start (@_start:15)

It seems that I need to modify the MUMPS solver parameters utilized by getfem::standard_solve. I tried to set some parameters of gmm::mumps_interf<double>::MUMPS_STRUC_C id;, but it didn’t work.

I used to solve a steady NS equation by using getfem and didn’t encounter this kind of error. Could anyone please tell me the reason and how to revise my codes?

Thanks a lot!

if you have increased ICNTL(14) inside the file “gmm_MUMPS_interface.h” and is still giving the same error, then your tangent matrix might not be sparse enough. Can it be that the system tangent matrix contains some garbage? Or that you have basis function with big overlaps?

I would suggest to solve a minimal problem where you can print and inspect the tangent matrix.

Thanks for yourreply! I will try it and give a response. :slight_smile: