nonlin 1.5.2
A library that provides routines to compute the solutions to systems of nonlinear equations.
Loading...
Searching...
No Matches
nonlin_solve.f90
1! nonlin_solve.f90
2
9 use, intrinsic :: iso_fortran_env, only : int32, real64
11 use nonlin_core
12 use nonlin_linesearch, only : line_search, limit_search_vector
13 use ferror
14 use linalg, only : qr_factor, form_qr, qr_rank1_update, lu_factor, &
15 rank1_update, mtx_mult, recip_mult_array, solve_triangular_system, &
16 solve_lu
17 implicit none
18 private
19 public :: line_search_solver
20 public :: quasi_newton_solver
21 public :: newton_solver
22 public :: brent_solver
23 public :: newton_1var_solver
24 public :: test_convergence
25
26! ******************************************************************************
27! NONLIN_SOLVE_LINE_SEARCH.F90
28! ------------------------------------------------------------------------------
31 type, abstract, extends(equation_solver) :: line_search_solver
32 private
34 class(line_search), allocatable :: m_linesearch
37 logical :: m_uselinesearch = .true.
38 contains
48 procedure, public :: get_line_search => lss_get_line_search
58 procedure, public :: set_line_search => lss_set_line_search
68 procedure, public :: set_default_line_search => lss_set_default
78 procedure, public :: is_line_search_defined => &
79 lss_is_line_search_defined
89 procedure, public :: get_use_line_search => lss_get_use_search
99 procedure, public :: set_use_line_search => lss_set_use_search
100 end type
101
102! ------------------------------------------------------------------------------
103 interface
104 module subroutine lss_get_line_search(this, ls)
105 class(line_search_solver), intent(in) :: this
106 class(line_search), intent(out), allocatable :: ls
107 end subroutine
108
109 module subroutine lss_set_line_search(this, ls)
110 class(line_search_solver), intent(inout) :: this
111 class(line_search), intent(in) :: ls
112 end subroutine
113
114 module subroutine lss_set_default(this)
115 class(line_search_solver), intent(inout) :: this
116 type(line_search) :: ls
117 end subroutine
118
119 pure module function lss_is_line_search_defined(this) result(x)
120 class(line_search_solver), intent(in) :: this
121 logical :: x
122 end function
123
124 pure module function lss_get_use_search(this) result(x)
125 class(line_search_solver), intent(in) :: this
126 logical :: x
127 end function
128
129 module subroutine lss_set_use_search(this, x)
130 class(line_search_solver), intent(inout) :: this
131 logical, intent(in) :: x
132 end subroutine
133 end interface
134
135! ******************************************************************************
136! NONLIN_SOLVE_QUASI_NEWTON.F90
137! ------------------------------------------------------------------------------
139 type, extends(line_search_solver) :: quasi_newton_solver
140 private
142 integer(int32) :: m_jdelta = 5
143 contains
237 procedure, public :: solve => qns_solve
248 procedure, public :: get_jacobian_interval => qns_get_jac_interval
259 procedure, public :: set_jacobian_interval => qns_set_jac_interval
260 end type
261
262! ------------------------------------------------------------------------------
263 interface
264 module subroutine qns_solve(this, fcn, x, fvec, ib, err)
265 class(quasi_newton_solver), intent(inout) :: this
266 class(vecfcn_helper), intent(in) :: fcn
267 real(real64), intent(inout), dimension(:) :: x
268 real(real64), intent(out), dimension(:) :: fvec
269 type(iteration_behavior), optional :: ib
270 class(errors), intent(inout), optional, target :: err
271 end subroutine
272
273 pure module function qns_get_jac_interval(this) result(n)
274 class(quasi_newton_solver), intent(in) :: this
275 integer(int32) :: n
276 end function
277
278 module subroutine qns_set_jac_interval(this, n)
279 class(quasi_newton_solver), intent(inout) :: this
280 integer(int32), intent(in) :: n
281 end subroutine
282 end interface
283
284! ******************************************************************************
285! ------------------------------------------------------------------------------
287 type, extends(line_search_solver) :: newton_solver
288 contains
378 procedure, public :: solve => ns_solve
379 end type
380
381! ------------------------------------------------------------------------------
382 interface
383 module subroutine ns_solve(this, fcn, x, fvec, ib, err)
384 class(newton_solver), intent(inout) :: this
385 class(vecfcn_helper), intent(in) :: fcn
386 real(real64), intent(inout), dimension(:) :: x
387 real(real64), intent(out), dimension(:) :: fvec
388 type(iteration_behavior), optional :: ib
389 class(errors), intent(inout), optional, target :: err
390 end subroutine
391 end interface
392
393! ******************************************************************************
394! NONLIN_SOLVE_BRENT.F90
395! ------------------------------------------------------------------------------
398 type, extends(equation_solver_1var) :: brent_solver
399 contains
479 procedure, public :: solve => brent_solve
480 end type
481
482! ------------------------------------------------------------------------------
483 interface
484 module subroutine brent_solve(this, fcn, x, lim, f, ib, err)
485 class(brent_solver), intent(inout) :: this
486 class(fcn1var_helper), intent(in) :: fcn
487 real(real64), intent(inout) :: x
488 type(value_pair), intent(in) :: lim
489 real(real64), intent(out), optional :: f
490 type(iteration_behavior), optional :: ib
491 class(errors), intent(inout), optional, target :: err
492 end subroutine
493 end interface
494
495! ******************************************************************************
496! NONLIN_SOLVE_NEWTON1VAR.F90
497! ------------------------------------------------------------------------------
502 type, extends(equation_solver_1var) :: newton_1var_solver
503 contains
591 procedure, public :: solve => newt1var_solve
592 end type
593! ------------------------------------------------------------------------------
594 interface
595 module subroutine newt1var_solve(this, fcn, x, lim, f, ib, err)
596 class(newton_1var_solver), intent(inout) :: this
597 class(fcn1var_helper), intent(in) :: fcn
598 real(real64), intent(inout) :: x
599 type(value_pair), intent(in) :: lim
600 real(real64), intent(out), optional :: f
601 type(iteration_behavior), optional :: ib
602 class(errors), intent(inout), optional, target :: err
603 end subroutine
604 end interface
605
606contains
607! ******************************************************************************
608! GENERAL ROUTINES
609! ------------------------------------------------------------------------------
629 subroutine test_convergence(x, xo, f, g, lg, xtol, ftol, gtol, c, cx, cf, &
630 cg, xnorm, fnorm)
631 ! Arguments
632 real(real64), intent(in), dimension(:) :: x, xo, f, g
633 real(real64), intent(in) :: xtol, ftol, gtol
634 logical, intent(in) :: lg
635 logical, intent(out) :: c, cx, cf, cg
636 real(real64), intent(out) :: xnorm, fnorm
637
638 ! Parameters
639 real(real64), parameter :: zero = 0.0d0
640 real(real64), parameter :: one = 1.0d0
641 real(real64), parameter :: half = 0.5d0
642
643 ! Local Variables
644 integer(int32) :: i, nvar, neqn
645 real(real64) :: test, dxmax, fc, den
646
647 ! Initialization
648 nvar = size(x)
649 neqn = size(f)
650 cx = .false.
651 cf = .false.
652 cg = .false.
653 c = .false.
654 fc = half * dot_product(f, f)
655 fnorm = zero
656 xnorm = zero
657
658 ! Test for convergence on residual
659 do i = 1, neqn
660 fnorm = max(abs(f(i)), fnorm)
661 end do
662 if (fnorm < ftol) then
663 cf = .true.
664 c = .true.
665 return
666 end if
667
668 ! Test the change in solution
669 do i = 1, nvar
670 test = abs(x(i) - xo(i)) / max(abs(x(i)), one)
671 xnorm = max(test, xnorm)
672 end do
673 if (xnorm < xtol) then
674 cx = .true.
675 c = .true.
676 return
677 end if
678
679 ! Test for zero gradient slope - do not set convergence flag
680 if (lg) then
681 test = zero
682 den = max(fc, half * nvar)
683 do i = 1, nvar
684 dxmax = abs(g(i)) * max(abs(x(i)), one) / den
685 test = max(test, dxmax)
686 end do
687 if (test < gtol) then
688 cg = .true.
689 end if
690 end if
691 end subroutine
692
693! ------------------------------------------------------------------------------
694end module
nonlin_constants
nonlin_core
nonlin_linesearch
nonlin_solve
A base class for various solvers of equations of one variable.
A base class for various solvers of nonlinear systems of equations.
Defines a type capable of encapsulating an equation of one variable of the form: f(x) = 0.
Defines a set of parameters that describe the behavior of the iteration process.
Defines a pair of numeric values.
Defines a type capable of encapsulating a system of nonlinear equations of the form: F(X) = 0....
Defines a type capable of performing an inexact, backtracking line search to find a point as far alon...
Defines a solver based upon Brent's method for solving an equation of one variable without using deri...
A class describing nonlinear solvers that use a line search algorithm to improve convergence behavior...
Defines a solver based upon Newtons's method for solving an equation of one variable....
Defines a Newton solver.
Defines a quasi-Newton type solver based upon Broyden's method.