Source code for trusspy.solvers.zerosearch
# -*- coding: utf-8 -*-
"""
title: TrussPy - Truss Solver for Python
author: Andreas Dutzler
year: 2023
"""
from numpy.linalg import norm
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import spsolve
[docs]def newton(f, dfdx, x, nfev=8, ftol=1e-8, xtol=1e-8, verbose=0, *args):
"""Find the roots of a function using the Newton-Rhapson algorithm.
Find the roots of the (non-linear) equations `f` given a starting
estimate x. The derivative `dfdx`of `f` w.r.t. `x` has to be provided by the
user. Iteration loop stops after maximum number of function
evaluations is reached (default: `nfev=8`). Default tolerance is
8 digits for vector norm of function residual and 8 digits for
vector norm of incremental dx. If both tolerances are reached then
the loop ends and the `success` flag becomes `True`. Return the roots of the
(non-linear) equations defined by ``f(x) = 0`` given a starting estimate.
Parameters
----------
f : ndarray
1D Vectorized function to minimize which depends on vector `x`
dfdx : ndarray
2D Derivative of function w.r.t. `x`
x : ndarray
1D Initial solution vector
nfev : int, optional
Maximum number of newton iterations (default is 8)
ftol : float, optional
Tolerance for residual of function: `norm(f)` (default is 1e-8)
xtol : float, optional
Tolerance for residual of `x`: `norm(x)` (default is 1e-8)
verbose : int, optional
Level of information during iterations (default is 0):
`verbose=0` ... no information,
`verbose=1` ... print `iteration number`, `norm(f)`, `norm(x)`
arg s: tuple, optional
pass arbitrary number of additional variables
to function and derivative
Returns
-------
x : ndarray
final solution
success : bool
'True' if valid solution found, 'False' if not converged
n : int
number of function iterations
f_norm : float
norm(f)
x_norm : float
norm(x)
Examples
--------
>>> import numpy as np
>>> def f(x, a):
... return np.array([a*x[0]**3-1])
>>> def dfdx(x, a):
... return np.array([a*3*x[0]**2])
>>> x0 = np.array([1.5])
>>> a = 2
>>> from trusspy.solvers import newton
>>> x,success,ntot,f_norm,x_norm = newton(f, dfdx, x0, 8, 1e-8, 1e-8, 0, a)
>>> x
array([0.79370053])
>>> success
True
>>> ntot
6
>>> f_norm <= 1e-8
True
>>> x_norm <= 1e-8
True
"""
success = False
# NEWTON-RHAPSON ITERATIONS
for n in range(nfev):
dx = spsolve(csr_matrix(dfdx(x, *args)), -f(x, *args))
# UPDATE SOLUTION
x = x + dx
# CHECK IF EQUILIBRUM FOUND
f_norm = norm(f(x, *args))
x_norm = norm(dx)
if verbose > 0:
print(
"| | {0:2d} | |{1:1.3e}| | | | | | |".format(
n + 1, f_norm
)
)
if f_norm < ftol and x_norm < xtol:
success = True
break
return x, success, n + 1, f_norm, x_norm