/* * Copyright (C) 2012 Addition, Lda. (addition at addition dot pt) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package org.addition.epanet.msx.Solvers; import org.addition.epanet.msx.Utilities; public class Newton { int Nmax; // max. number of equations int []Indx; // permutation vector of row indexes double []F; // function & adjustment vector double []W; // work vector double [][]J; // Jacobian matrix /** * opens the algebraic solver to handle a system of n equations. */ public void newton_open(int n) { Nmax = 0; Indx = null; F = null; W = null; Indx = new int[n+1]; F = new double[n+1]; W = new double[n+1]; J = Utilities.createMatrix(n+1, n+1); Nmax = n; } //============================================================================= // uses newton-raphson iterations to solve n nonlinear eqns. /*public int newton_solve(double x[], int n, int maxit, int numsig, JacobianFunction func) { int i, k; double errx, errmax, cscal, relconvg = Math.pow(10.0, -numsig); // --- check that system was sized adequetely if ( n > Nmax ) return -3; // --- use up to maxit iterations to find a solution for (k=1; k<=maxit; k++) { // --- evaluate the Jacobian matrix Utilities.jacobian(x, n, F, W, J, func); // --- factorize the Jacobian if ( Utilities.factorize(J, n, W, Indx) ==0 ) return -1; // --- solve for the updates to x (returned in F) for (i=1; i<=n; i++) F[i] = -F[i]; Utilities.solve(J, n, Indx, F); // --- update solution x & check for convergence errmax = 0.0; for (i=1; i<=n; i++) { cscal = x[i]; if (cscal < relconvg) cscal = relconvg; x[i] += F[i]; errx = Math.abs(F[i]/cscal); if (errx > errmax) errmax = errx; } if (errmax <= relconvg) return k; } // --- return error code if no convergence return -2; }*/ /** * uses newton-raphson iterations to solve n nonlinear eqns. */ public int newton_solve(double x[], int n, int maxit, int numsig, JacobianInterface jint, JacobianInterface.Operation op) { int i, k; double errx, errmax, cscal, relconvg = Math.pow(10.0, -numsig); // check that system was sized adequetely if ( n > Nmax ) return -3; // use up to maxit iterations to find a solution for (k=1; k<=maxit; k++) { // evaluate the Jacobian matrix Utilities.jacobian(x, n, F, W, J, jint,op); // factorize the Jacobian if ( Utilities.factorize(J, n, W, Indx) ==0 ) return -1; // solve for the updates to x (returned in F) for (i=1; i<=n; i++) F[i] = -F[i]; Utilities.solve(J, n, Indx, F); // update solution x & check for convergence errmax = 0.0; for (i=1; i<=n; i++) { cscal = x[i]; if (cscal < relconvg) cscal = relconvg; x[i] += F[i]; errx = Math.abs(F[i]/cscal); if (errx > errmax) errmax = errx; } if (errmax <= relconvg) return k; } // return error code if no convergence return -2; } }