coin-or / qpOASES

Open-source C++ implementation of the recently proposed online active set strategy
GNU Lesser General Public License v2.1
384 stars 129 forks source link

SQProblemSchur: MA57AD returns iflag = -15 with ierror = -1 #121

Closed hallfjonas closed 3 years ago

hallfjonas commented 3 years ago

Hello all,

I am currently trying to use the SQProblemSchur Method in a sequential approach (I am calling directly from C++).

When calling the init function I get the following error:

MA57AD returns iflag = -15 with ierror = -1

Has anybody encountered this or knows what these iflags and ierrors mean. I could not find anything on google yet. I'm on an Ubuntu 18.04 system with an installation set up according to this forked repo. I use the MA57 solver provided through MATLAB R2021A.

Please let me know if I should provide more details...

apotschka commented 3 years ago

I guess this originates from the following code starting at line 777 in SparseSolver.cpp:

        fint_t max_nnz = numNonzeros > dim ? numNonzeros : dim;
        fint_t lkeep_ma57 = 5*dim + numNonzeros + max_nnz + 42;
        fint_t *keep_ma57 = new fint_t[lkeep_ma57];
        fint_t *iwork_ma57 = new fint_t[5*dim];

        /* Set initial pivot sequence. */
        for (fint_t i = 0; i < lkeep_ma57; i++) keep_ma57[i] = i+1;

        fint_t info_ma57[40];
        double rinfo_ma57[20];

        MA57AD(&dim, &numNonzeros, irn_ma57, jcn_ma57, &lkeep_ma57, keep_ma57,
                        iwork_ma57, icntl_ma57, info_ma57, rinfo_ma57);

        /* Receive some information from MA57AD */
        fint_t iflag = info_ma57[0];   /* Information flag */
        fint_t ierror = info_ma57[1];  /* Error flag */
        if (iflag != 0)
        {
                MyPrintf("MA57AD returns iflag = %d with ierror = %d\n", iflag, ierror);

From the MA57 docs, p.12: -15 LKEEP less than 5*N+NE+MAX(N,NE)+42 on a call to MA57A/AD or MA57B/BD. INFO(2) holds value of LKEEP.

From the code above, lkeep_ma57 cannot become -1, but that's what Matlab's MA57 says.

This hints at a problem with incompatible integer sizes. I don't remember exactly, but I think Matlab's MA57 uses 32bit integers. For a start, try to compile without -D__USE_LONG_FINTS__ and let us know if the error persists.

hallfjonas commented 3 years ago

Thank you for your quick reply and indeed pointing me towards the right direction.

Up until now I compiled qpOASES without long integers and long fortran integers. Including the compile flag

-D__USE_LONG_FINTS__

solved my problem. I now understand why it might important to use long fortran integers. Just out of curiosity: Is there also a reason why it might be important to use long integers in general?

By the way: Using the mix of long fint_t and int int_t creates the following error:

SparseSolver.cpp:809:36: error: cannot convert ‘qpOASES::int_t* {aka int*}’ to ‘qpOASES::fint_t* {aka long int*}’ in assignment
       ifact_ma57 = new int_t[lifact_ma57];

For now I will just stick to long int_t

Thank you again for the quick help, and also for supplying info and documentation material on the return flags of MA57!

apotschka commented 3 years ago

It should be new fint_t[lifact_ma57]. Actually, I had this in a local version on my machine. Commit is now here.

If you need really large arrays, you need long integers to access them.

hallfjonas commented 3 years ago

If I'm not mistaken the code might also require the functions

inline fint_t getMin(fint_t x, fint_t y);
inline fint_t getMax(fint_t x, fint_t y);

At least getMax is called in SparseSolver line 777.

Extra Remark: I just noticed that this could become a problem if fint_t and int_t are of the same type... maybe they should be defined for long and int separately?

hallfjonas commented 3 years ago

As I see now this was also taken care of in 268b2f2659604df27c82aa6e32aeddb8c1d5cc7f