// simeq_newton3.swift solve nonlinear system of equations // method: newton iteration using Jacobian // use list for higher order terms // // Given problem A X = Y where X may have terms x1, x2, x3, x4, // and higher order such as: x1*x2, x1*x1*x3, x4*x4*x4, ... // A sparse matrix may be used, coefficients given // Y is vector of reals given // independent unknowns are x1, x2, x3, x4 // // for testing, generate A using pseudo random numbers // choose x1=1.1 x2=1.2 x3=1.4 x4 =1.5, compute products // compute terms of Y using Y = A X // // Solve by initial guess at values of x1, x2, x3, x4 computing products // X_next = X_initial - J_initial^-1 * (A * X_initial - Y) // in general X_next = X - (J_prev^-1 * (A * X - Y))*b // where 0 < b < 1, often 0.5, for stability // // solved when abs sum each row A * X_next -Y < epsilon // // It may stall, stop if abs(X_next-X) [Double] { // X var eps = 1.0e-6 // possible default var b = 0.5 // stability convergence factor max 1.0 var resid = 0.0 // residual from last iteration var presid = 0.0 // residual from prior to last iteration var maxiter = 10 // maximum number of iterations var Ja = [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) var X = [Double](repeating:0.0,count:n+nlin) var X_resid = [Double](repeating:0.0,count:n+nlin) var X_tmp2 = [Double](repeating:0.0,count:n+nlin) var X_next = [Double](repeating:0.0,count:n+nlin) if monitor>0 { print("simeq_newton3 running n=\(n), nlin=\(nlin)") } // end if eps = ueps maxiter = uiter b = ub // setup nonlinear terms for i in n..=0 { X[i] *= X[var2[i]] // -1 flag should not be used } // end if if var3[i]>=0 { X[i] *= X[var3[i]] } // end if } // end i for i in 0..2 { for i in 0..0 { print("simeq_newton3 itr \(itr), prev=\(presid) residual=\(resid)") } // end if if resid=0 { /* X^2 xa */ Ja[i][j] += A[i][k]*2.0*X[var2[k]]*X[var3[k]] /* 2X xa */ } // end else if else if var1[k]==j && var2[k]==j && var3[k]<0 { /* X^2 */ Ja[i][j] += A[i][k]*2.0*X[var2[k]] /* 2X */ } // end else if else if var2[k]==j && var3[k]==j && var1[k]>=0 { /* xa X^2 */ Ja[i][j] += A[i][k]*2.0*X[var3[k]]*X[var1[k]] /* 2X xa */ } // end else if else if var2[k]==j && var3[k]==j && var1[k]<0 { /* X^2 */ Ja[i][j] += A[i][k]*2.0*X[var3[k]] /* 2X */ } // end else if else if var3[k]==j && var1[k]==j && var2[k]>=0 { /* xa X^2 */ Ja[i][j] += A[i][k]*2.0*X[var1[k]]*X[var2[k]] /* 2X xa */ } // end else if else if var3[k]==j && var1[k]==j && var2[k]<0 { /* X^2 */ Ja[i][j] += A[i][k]*2.0*X[var1[k]] /* 2X */ } // end else if else if var1[k]==j { if var2[k]>=0 && var3[k]>=0 { Ja[i][j] += A[i][k]*X[var2[k]]*X[var3[k]] } // end if else if var2[k]>=0 { Ja[i][j] += A[i][k]*X[var2[k]] } // end else if else if var3[k]>=0 { Ja[i][j] += A[i][k]*X[var3[k]] } // end else if } // end if var1 else if var2[k]==j { if var1[k]>=0 && var3[k]>=0 { Ja[i][j] += A[i][k]*X[var1[k]]*X[var3[k]] } // end if else if var1[k]>=0 { Ja[i][j] += A[i][k]*X[var1[k]] } // end else if else if var3[k]>=0 { Ja[i][j] += A[i][k]*X[var3[k]] } // end else if } // end if var2 else if var3[k]==j { if var2[k]>=0 && var1[k]>=0 { Ja[i][j] += A[i][k]*X[var2[k]]*X[var1[k]] } // end if else if var2[k]>=0 { Ja[i][j] += A[i][k]*X[var2[k]] } // else if else if var1[k]>=0 { Ja[i][j] += A[i][k]*X[var1[k]] } // end else if } // end if var3 } // end k } // end j } // end i if monitor>4 { print("Ja computed ") for i in 0..5 { print("Ja inverted ") for i in 0..3 { for i in 0..=0 { X_next[i] *= X_next[var2[i]] } // end if if var3[i]>=0 { X_next[i] *= X_next[var3[i]] } // end if } // end i if monitor>2 { for i in 0..2 { print(" ") } // end if } // end iteration if monitor>0 { print("simeq_newton3.swift finished") } // end if return X } // end simeq_newton3 // end simeq_newton3.swift // matinv.swift should have import func matinv(_ a: [[Double]]) -> [[Double]] { let n = a.count var inv = [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) for i in 0.. abs_pivot { I_pivot = i J_pivot = j pivot = inv[row[i]][col[j]] } } } if abs(pivot) < 1.0E-10 { print("Matrix is singular !") return [[Double]](repeating:[Double](repeating:0.0,count:n),count:n) } hold = row[k] row[k] = row[I_pivot] row[I_pivot] = hold hold = col[k] col[k] = col[J_pivot] col[J_pivot] = hold // reduce about pivot inv[row[k]][col[k]] = 1.0 / pivot for j in 0..