Online course and simulator for engineering thermodynamics

Using the minPack solver for solving systems of non-linear equations

Introduction

In many cases, the equations describing the off-design behavior of an energy system are nonlinear, so that their resolution is a difficult problem, especially when the number of unknowns is high.

Presentation of minPack

Based on the method of Marquardt-Levendberg, minPack is a set of algorithms developed in Fortran and then translated in Java. This method combines the Gauss-Newton method and gradient descent. Its main interest is to be very robust and to only require as initialization an approximate solution.

Note that minPack is actually a set of algorithms for minimization which can be used to find the minimum of the standard L2 norm of the residues || F (X) || of a set of m nonlinear equations in n unknowns F( X).

When n is equal to m, minPack can be used to solve the system of equations F (X), or at least seek a vector X that is as close as possible to the solution.

MinPack can also be used to identify a set of n parameters to fit a nonlinear equation on a set of m data, or to optimize a function of several variables.

Implementation of minPack

All the classes required are included in the library extBib.zip downloadable below that must be declared in the classpath.

The Java implementation of minPack is done using an interface called optimization.Lmdif_fcn, which forces the calling class to have a function called fcn ().

This function fcn () receives as a main argument an array x [n] containing the variables and an array fvec [m] returning residues of the functions that we seek to set to zero. Their numbers may exceed that of the variables, but it must be the same if we seek the solution of a system of equations.

Guiding the algorithm is done by playing on two criteria of accuracy, one on the sum of the residues, and the other on the accuracy of the partial derivatives, estimated by finite differences.

Example

To illustrate the use of minPack, we built a test class called TestMinPack, which solves the system of equations corresponding to the intersection of a circle and a straight line. The code is as shown below.

Attention: in order to maintain the same indices as in Fortran, the Java implementation declares n+1 dimensional arrays, instead of a n, the index 0 not being used

int info[] = new int[2];

int m = 2;//système de deux équations / system of two equations

int n = 2;//à deux inconnues / with two unknowns

int iflag[] = new int[2];

double fvec[] = new double[m+1];//vecteur des résidus / vector of residuals

double x[] = new double[n+1];

double residu0;//norme L2 initiale / initial L2 norm

double residu1;//norme L2 finale / final L2 norm

System.out.print("\n\n\n\n\n problem dimensions: " + n + " " + m + "\n");

//initialisation des inconnues / initialization of unknowns

x[1] = 1;

x[2] = 0;

iflag[1] = 0;

testMinPack.fcn(m,n,x,fvec,iflag);//premier appel pour calcul norme L2 initiale / first call for calculating initial L2 norm

/ / Initial L2 norm

//norme L2 initiale

residu0 = optimization.Minpack_f77.enorm_f77(m,fvec);

testMinPack.nfev = 0;

testMinPack.njev = 0;

double epsi=0.0005;//précision globale demandée sur la convergence / overall accuracy required on the convergence

double epsfcn = 1.e-6;//précision calcul des différences finies / precision calculus of finite differences

//appel à minPack / Call minPack

optimization.Minpack_f77.lmdif2_f77(testMinPack, m, n, x, fvec, epsi, epsfcn, info);

//norme L2 finale / final L2 norm

residu1 = optimization.Minpack_f77.enorm_f77(m,fvec);

//affichage des résultats / Display of results

System.out.println("\n Initial L2 norm of the residuals: " + residu0 +

"\n Final L2 norm of the residuals: " + residu1 +

"\n Number of function evaluations: " + testMinPack.nfev +

"\n Number of Jacobian evaluations: " + testMinPack.njev +

"\n Info value: " + info[1] );

System.out.println();

System.out.println("precision: \t" + residu1);

for(int i=1;i<=n;i++){//affichage de la solution / display solution

System.out.println("x["+i+"] \t" + x[i]);

}

La fonction fcn est définie comme suit : function fcn is defined as follows

public void fcn(int m, int n, double x[], double fvec[], int iflag[]) {

if (iflag[1]==1) this.nfev++;

if (iflag[1]==2) this.njev++;

fvec[1] =x[1]*x[1]+x[2]*x[2]-1;

fvec[2] =3*x[1]+2*x[2]-1;

}

The results obtained are as follows, for initialization x[1] = 1, x[2] = 0 :

problem dimensions: 2 2

Initial L2 norm of the residuals: 2.0

Final L2 norm of the residuals: 2.39665398638067E-10

Number of function evaluations: 6

Number of Jacobian evaluations: 10

Info value: 2

precision: 2.39665398638067E-10

x[1] 0.7637079407212384

x[2] -0.6455619110818576

for initialization x [1] = 0, x [2] = 0, we obtain:

problem dimensions: 2 2

Initial L2 norm of the residuals: 1.4142135623730951

Final L2 norm of the residuals: 3.853333208070353E-10

Number of function evaluations: 9

Number of Jacobian evaluations: 12

Info value: 2

precision: 3.853333208070353E-10

x[1] -0.3021694793631984

x[2] 0.9532542190447976

This example illustrates on the one hand how minPack can be used, but also the importance of well-initialize the problem. In our case, the problem has two solutions, but the algorithm is satisfied with the first it finds, the one closest to the starting value.

TestMinPack class is given below.

copyright R. Gicquel v2024.2

Created with Scenari (new window)