A basic multidimensional nonlinear equation solver, using a Newton-Raphson type direct method.
dgesv
or dgels
) to solve the linear system.Todo
add an istat
output to func and grad, for user stopping
or to take a smaller stop (if istat>0 take a smaller step, if istat<0 abort)
Note
The default real kind (wp
) can be
changed using optional preprocessor flags.
This library was built with real kind:
real(kind=real64)
[8 bytes]
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
integer, | public, | parameter | :: | nlesolver_rk | = | real64 |
real kind used by this module [8 bytes] |
integer, | private, | parameter | :: | wp | = | nlesolver_rk |
local copy of |
real(kind=wp), | private, | parameter | :: | zero | = | 0.0_wp | |
real(kind=wp), | private, | parameter | :: | one | = | 1.0_wp | |
real(kind=wp), | private, | parameter | :: | two | = | 2.0_wp | |
real(kind=wp), | private, | parameter | :: | eps | = | epsilon(one) |
machine |
real(kind=wp), | private, | parameter | :: | big | = | huge(one) | |
integer, | public, | parameter | :: | NLESOLVER_SPARSITY_DENSE | = | 1 |
assume dense (use dense solver). |
integer, | public, | parameter | :: | NLESOLVER_SPARSITY_LSQR | = | 2 |
assume sparse (use LSQR sparse solver). |
integer, | public, | parameter | :: | NLESOLVER_SPARSITY_LUSOL | = | 3 |
assume sparse (use LUSOL sparse solver). |
integer, | public, | parameter | :: | NLESOLVER_SPARSITY_LSMR | = | 4 |
assume sparse (use LSMR sparse solver). |
integer, | public, | parameter | :: | NLESOLVER_SPARSITY_CUSTOM_SPARSE | = | 5 |
assume sparse (use a user provided sparse solver). |
for a custom user-provided linear solver (sparse version)
solve Ax = b
for x
, given A
and b
.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
integer, | intent(in) | :: | n_cols |
|
||
integer, | intent(in) | :: | n_rows |
|
||
integer, | intent(in) | :: | n_nonzero |
number of nonzero elements of A. |
||
integer, | intent(in), | dimension(n_nonzero) | :: | irow |
sparsity pattern (size is |
|
integer, | intent(in), | dimension(n_nonzero) | :: | icol |
sparsity pattern (size is |
|
real(kind=wp), | intent(in), | dimension(n_nonzero) | :: | a |
matrix elements (size is |
|
real(kind=wp), | intent(in), | dimension(n_rows) | :: | b |
right hand side (size is |
|
real(kind=wp), | intent(out), | dimension(n_cols) | :: | x |
solution (size is |
|
integer, | intent(out) | :: | istat |
status code (=0 for success) |
compute the function
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(:) | :: | x | ||
real(kind=wp), | intent(out), | dimension(:) | :: | f |
compute the gradient of the function (Jacobian). Dense version.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(:) | :: | x | ||
real(kind=wp), | intent(out), | dimension(:,:) | :: | g |
compute the gradient of the function (Jacobian). Sparse version.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(:) | :: | x | ||
real(kind=wp), | intent(out), | dimension(:) | :: | g |
sparse jacobian. length is |
export an iteration:
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(:) | :: | x | ||
real(kind=wp), | intent(in), | dimension(:) | :: | f | ||
integer, | intent(in) | :: | iter |
iteration number |
enable a user-triggered stop of the iterations:
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
logical, | intent(out) | :: | user_stop |
line search method. Note that not all inputs/outputs are used by all methods.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(me%n) | :: | xold |
previous value of |
|
real(kind=wp), | intent(in), | dimension(me%n) | :: | p |
search direction |
|
real(kind=wp), | intent(out), | dimension(me%n) | :: | x |
new |
|
real(kind=wp), | intent(inout) | :: | f |
|
||
real(kind=wp), | intent(inout), | dimension(me%m) | :: | fvec |
|
|
real(kind=wp), | intent(in), | optional, | dimension(:,:) | :: | fjac |
jacobian matrix [dense] |
real(kind=wp), | intent(in), | optional, | dimension(:) | :: | fjac_sparse |
jacobian matrix [sparse] |
Nonlinear equations solver class.
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
integer, | private | :: | n | = | 0 |
number of opt vars |
|
integer, | private | :: | m | = | 0 |
number of constraints |
|
integer, | private | :: | max_iter | = | 100 |
maximum number of iterations |
|
real(kind=wp), | private | :: | tol | = | 1.0e-6_wp |
convergence tolerance for function values |
|
real(kind=wp), | private | :: | alpha | = | 1.0_wp |
step length (when specified constant) |
|
real(kind=wp), | private | :: | alpha_min | = | 0.1_wp |
minimum step length (when allowed to vary) |
|
real(kind=wp), | private | :: | alpha_max | = | 1.0_wp |
maximum step length (when allowed to vary) |
|
real(kind=wp), | private | :: | tolx | = | 1.0e-8_wp |
convergence tolerance for |
|
real(kind=wp), | private | :: | c | = | 0.5_wp |
backtracking linesearch parameter (0,1) |
|
real(kind=wp), | private | :: | tau | = | 0.5_wp |
backtracking linesearch parameter (0,1) |
|
real(kind=wp), | private | :: | fmin_tol | = | 1.0e-5_wp |
tolerance for "exact" linesearch |
|
integer, | private | :: | n_intervals | = | 2 |
number of intervals for fixed point linesearch |
|
logical, | private | :: | use_broyden | = | .false. |
if true, a Broyden update is used
rather than computing the Jacobian
at every step. The |
|
integer, | private | :: | broyden_update_n | = | 4 |
if this value is |
|
integer, | private | :: | n_uphill_max | = | 5 |
maximum number of consecutive steps
to allow where the value of |
|
logical, | private | :: | verbose | = | .false. |
verbose output printing |
|
integer, | private | :: | iunit | = | output_unit |
output unit for printing (assumed to be open). |
|
character(len=:), | private, | allocatable | :: | message |
latest status message |
||
integer, | private | :: | istat | = | -999 |
latest status message |
|
procedure(func_func), | private, | pointer | :: | func | => | null() |
user-supplied routine to compute the function |
procedure(export_func), | private, | pointer | :: | export_iteration | => | null() |
user-supplied routine to export iterations |
procedure(wait_func), | private, | pointer | :: | user_input_check | => | null() |
user-supplied routine to enable user to stop iterations |
procedure(linesearch_func), | private, | pointer | :: | linesearch | => | null() |
line search method (determined by |
integer, | private | :: | sparsity_mode | = | NLESOLVER_SPARSITY_DENSE |
sparsity mode: |
|
integer, | private | :: | n_nonzeros | = | -1 |
number of nonzero Jacobian elements (used for |
|
integer, | private, | dimension(:), allocatable | :: | irow |
sparsity pattern nonzero elements row indices. |
||
integer, | private, | dimension(:), allocatable | :: | icol |
sparsity pattern nonzero elements column indices |
||
real(kind=wp), | private | :: | atol | = | zero |
relative error in definition of |
|
real(kind=wp), | private | :: | btol | = | zero |
relative error in definition of |
|
real(kind=wp), | private | :: | conlim | = | zero |
An upper limit on |
|
integer, | private | :: | itnlim | = | 100 |
max iterations |
|
integer, | private | :: | nout | = | 0 |
output unit for printing |
|
real(kind=wp), | private | :: | damp | = | zero |
damp parameter for LSQR |
|
integer, | private | :: | localSize | = | 0 |
0 This many n-vectors "v" (the most recent ones) are saved for reorthogonalizing the next v. |
|
integer, | private | :: | lusol_method | = | 0 |
|
|
procedure(grad_func), | private, | pointer | :: | grad | => | null() |
user-supplied routine to compute the gradient of the function (dense version) |
procedure(grad_func_sparse), | private, | pointer | :: | grad_sparse | => | null() |
user-supplied routine to compute the gradient of the function (sparse version) |
procedure(sparse_solver_func), | private, | pointer | :: | custom_solver_sparse | => | null() |
user-supplied sparse linear solver routine (used for |
procedure, public :: initialize => initialize_nlesolver_variables | |
procedure, public :: solve => nlesolver_solver | |
procedure, public :: destroy => destroy_nlesolver_variables | |
procedure, public :: status => get_status | |
procedure, private :: set_status |
Set status flag and message.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
integer, | intent(in) | :: | istat |
status code |
||
character(len=*), | intent(in) | :: | string |
status message |
||
integer, | intent(in), | optional | :: | i |
an integer value to append |
|
real(kind=wp), | intent(in), | optional | :: | r |
a real value to append |
Return the status code and message from the nlesolver_type class.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
integer, | intent(out), | optional | :: | istat |
Integer status code. |
|
character(len=:), | intent(out), | optional, | allocatable | :: | message |
Text status message |
Constructor for the class.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
integer, | intent(in) | :: | n |
number of optimization variables |
||
integer, | intent(in) | :: | m |
number of constraints |
||
integer, | intent(in) | :: | max_iter |
maximum number of iterations |
||
real(kind=wp), | intent(in) | :: | tol |
function convergence tolerance |
||
real(kind=wp), | intent(in), | optional | :: | alpha |
constant step length for |
|
real(kind=wp), | intent(in), | optional | :: | alpha_min |
minimum step length (0,1] |
|
real(kind=wp), | intent(in), | optional | :: | alpha_max |
maximum step length (0,1] |
|
real(kind=wp), | intent(in), | optional | :: | tolx |
convergence tolerance for changes in |
|
real(kind=wp), | intent(in), | optional | :: | fmin_tol |
convergence tolerance for fmin (used when |
|
real(kind=wp), | intent(in), | optional | :: | backtrack_c |
backtracking linesearch parameter (0,1) |
|
real(kind=wp), | intent(in), | optional | :: | backtrack_tau |
backtracking linesearch parameter (0,1) |
|
logical, | intent(in), | optional | :: | use_broyden |
use a Broyden update (default is False) |
|
integer, | intent(in), | optional | :: | broyden_update_n |
For Broyden mode, update the full Jacobian at most every this many iterations (must be >1) If <=1 then Jacobian is only computed on the first iteration. |
|
integer, | intent(in), | optional | :: | step_mode |
step mode: |
|
procedure(func_func) | :: | func |
computes the function vector |
|||
procedure(grad_func), | optional | :: | grad |
computes the jacobian [required for dense mode: |
||
procedure(grad_func_sparse), | optional | :: | grad_sparse |
computes the jacobian [required for sparse mode: |
||
procedure(export_func), | optional | :: | export_iteration |
function to export each iteration |
||
procedure(wait_func), | optional | :: | user_input_check |
check for user input (to stop solver if necessary) |
||
logical, | intent(in), | optional | :: | verbose |
for verbose status printing |
|
integer, | intent(in), | optional | :: | iunit |
unit for verbose printing (assumed to be open).
by default this is |
|
integer, | intent(in), | optional | :: | n_uphill_max |
maximum number of consecutive steps
to allow where the value of |
|
integer, | intent(in), | optional | :: | n_intervals |
number of intervals for fixed point linesearch |
|
integer, | intent(in), | optional | :: | sparsity_mode |
sparsity mode: |
|
integer, | intent(in), | optional, | dimension(:) | :: | irow |
sparsity pattern nonzero elements row indices.
must be specified with |
integer, | intent(in), | optional, | dimension(:) | :: | icol |
sparsity pattern nonzero elements column indices
must be specified with |
real(kind=wp), | intent(in), | optional | :: | atol |
|
|
real(kind=wp), | intent(in), | optional | :: | btol |
|
|
real(kind=wp), | intent(in), | optional | :: | conlim |
|
|
real(kind=wp), | intent(in), | optional | :: | damp |
|
|
integer, | intent(in), | optional | :: | itnlim |
|
|
integer, | intent(in), | optional | :: | nout |
|
|
integer, | intent(in), | optional | :: | lusol_method |
|
|
integer, | intent(in), | optional | :: | localSize |
|
|
procedure(sparse_solver_func), | optional | :: | custom_solver_sparse |
for |
Main solver.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(inout), | dimension(:) | :: | x |
Solve the linear system: , using a dense, direct method.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
integer, | intent(in) | :: | m |
number of rows in |
||
integer, | intent(in) | :: | n |
number of columns in |
||
real(kind=wp), | intent(in), | dimension(m,n) | :: | a |
|
|
real(kind=wp), | intent(in), | dimension(m) | :: | b |
RHS of the linear system |
|
real(kind=wp), | intent(out), | dimension(n) | :: | x |
the solution of the linear system. |
|
integer, | intent(out) | :: | info |
output status flag ( |
Take a simple step in the search direction of p * alpha
.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(me%n) | :: | xold |
previous value of |
|
real(kind=wp), | intent(in), | dimension(me%n) | :: | p |
search direction |
|
real(kind=wp), | intent(out), | dimension(me%n) | :: | x |
new |
|
real(kind=wp), | intent(inout) | :: | f |
magnitude of |
||
real(kind=wp), | intent(inout), | dimension(me%m) | :: | fvec |
function vector |
|
real(kind=wp), | intent(in), | optional, | dimension(:,:) | :: | fjac |
jacobian matrix [dense] |
real(kind=wp), | intent(in), | optional, | dimension(:) | :: | fjac_sparse |
jacobian matrix [sparse] |
Backtracking line search.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(me%n) | :: | xold |
previous value of |
|
real(kind=wp), | intent(in), | dimension(me%n) | :: | p |
search direction |
|
real(kind=wp), | intent(out), | dimension(me%n) | :: | x |
new |
|
real(kind=wp), | intent(inout) | :: | f |
magnitude of |
||
real(kind=wp), | intent(inout), | dimension(me%m) | :: | fvec |
function vector |
|
real(kind=wp), | intent(in), | optional, | dimension(:,:) | :: | fjac |
jacobian matrix [dense] |
real(kind=wp), | intent(in), | optional, | dimension(:) | :: | fjac_sparse |
jacobian matrix [sparse] |
An exact linesearch that uses a derivative-free minimizer to
find the minimum value of f(x)
between
x = xold + p * alpha_min
and
x = xold + p * alpha_max
.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(me%n) | :: | xold |
previous value of |
|
real(kind=wp), | intent(in), | dimension(me%n) | :: | p |
search direction |
|
real(kind=wp), | intent(out), | dimension(me%n) | :: | x |
new |
|
real(kind=wp), | intent(inout) | :: | f |
magnitude of |
||
real(kind=wp), | intent(inout), | dimension(me%m) | :: | fvec |
function vector |
|
real(kind=wp), | intent(in), | optional, | dimension(:,:) | :: | fjac |
jacobian matrix [dense] |
real(kind=wp), | intent(in), | optional, | dimension(:) | :: | fjac_sparse |
jacobian matrix [sparse] |
A simple search that just evaluates the function at a specified number of points and picks the one with the minimum function value.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(nlesolver_type), | intent(inout) | :: | me | |||
real(kind=wp), | intent(in), | dimension(me%n) | :: | xold |
previous value of |
|
real(kind=wp), | intent(in), | dimension(me%n) | :: | p |
search direction |
|
real(kind=wp), | intent(out), | dimension(me%n) | :: | x |
new |
|
real(kind=wp), | intent(inout) | :: | f |
magnitude of |
||
real(kind=wp), | intent(inout), | dimension(me%m) | :: | fvec |
function vector |
|
real(kind=wp), | intent(in), | optional, | dimension(:,:) | :: | fjac |
jacobian matrix [dense] |
real(kind=wp), | intent(in), | optional, | dimension(:) | :: | fjac_sparse |
jacobian matrix [sparse] |