sandbox/ecipriano/src/fsolve.h

    Non-Linear System of Equations Solver

    This module defines a function fsolve() which, in analogy with the MATLAB function, provides a high-level interface for the solution of non-linear systems of equations.

    KINSol Interface

    if the SUNDIALS library is used, the function fsolve() rely on the KINSol solver.

    #ifdef USE_SUNDIALS
    
    #include <kinsol/kinsol.h>
    #include <nvector/nvector_serial.h>
    #include <sunmatrix/sunmatrix_dense.h>
    #include <sunlinsol/sunlinsol_dense.h>
    #include <sundials/sundials_types.h>
    
    #define KIN_FTOL   1.e-6 // function tolerance 
    #define KIN_STOL   1.e-6 // step tolerance
    
    #pragma autolink -L$SUNDIALS_LIBRARY_PATH/build/src/kinsol -lsundials_kinsol
    
    typedef struct {
      int neq;
      Point point;
    } *UserData;
    
    struct Fsolve {
      KINSysFn func;
      Array * arrUnk;
      Point point;
    };
    
    //void fsolve (struct Fsolve p)
    void fsolve (KINSysFn func, Array * arrUnk, Point point)
    {
      //KINSysFn func = p.func;
      //Array * arrUnk = p.arrUnk;
      //Point point = p.point;
      int neq = arrUnk->len/sizeof(double);
    
      UserData data;
      N_Vector u, s;
      SUNMatrix J;
      SUNLinearSolver LS;
    
      u    = NULL;
      s    = NULL;
      J    = NULL;
      LS   = NULL;
      data = NULL;
    
      data = (UserData)malloc(sizeof *data);
      data->neq = neq;
      data->point = point;
    
      u = N_VNew_Serial (neq);
      s = N_VNew_Serial (neq);
    
      {
        realtype * udata = N_VGetArrayPointer (u);
        double * unk = (double *)arrUnk->p;
    
        for (unsigned int jj=0; jj<neq; jj++)
          udata[jj] = unk[jj];
      }
    
      N_VConst (1.0, s);
    
      void * kmem;
      kmem = KINCreate();
      KINSetUserData (kmem, data);
      KINSetFuncNormTol (kmem, KIN_FTOL);
      KINSetScaledStepTol (kmem, KIN_STOL);
      KINInit (kmem, func, u);
      J = SUNDenseMatrix (neq, neq);
      LS = SUNLinSol_Dense (u, J);
      KINSetLinearSolver (kmem, LS, J);
      KINSetMaxSetupCalls(kmem, 1);
      KINSetPrintLevel (kmem, 0);
    
      //TODO following two lines give problems
      //{
      //  char name[80];
      //  sprintf (name, "KINSolErr");
      //  const FILE * fKinErr = fopen (name, "a");
      //  KINSetErrFile (kmem, fKinErr);
      //}

    Solve non-linear system of equations.

      KINSol (kmem, u, KIN_NONE, s, s);
      //KINSol (kmem, u, KIN_LINESEARCH, s, s);

    Recover Nls solution.

      {
        realtype * udata = N_VGetArrayPointer (u);
        double * unk = (double *)arrUnk->p;
        for (unsigned jj=0; jj<neq; jj++) {
          unk[jj] = udata[jj];
        }
      }

    Free memory.

      N_VDestroy (u);
      N_VDestroy (s);
      KINFree (&kmem);
      SUNLinSolFree (LS);
      SUNMatDestroy (J);
      free (data);
    }
    
    #endif