24 use,
intrinsic :: iso_fortran_env
41 integer,
public,
parameter :: &
46 integer :: solver_type
50 real(real64) :: abs_tolerance
51 real(real64) :: rel_tolerance
57 subroutine root_solver_init(rs, namespace, dimensionality, solver_type, maxiter, &
58 rel_tolerance, abs_tolerance)
59 type(root_solver_t),
intent(out) :: rs
60 type(namespace_t),
intent(in) :: namespace
61 integer,
intent(in) :: dimensionality
62 integer,
optional,
intent(in) :: solver_type, maxiter
63 real(real64),
optional,
intent(in) :: rel_tolerance, abs_tolerance
68 rs%dim = dimensionality
73 if (
present(solver_type)) rs%solver_type = solver_type
74 if (
present(maxiter)) rs%maxiter = maxiter
75 if (
present(rel_tolerance)) rs%rel_tolerance = rel_tolerance
76 if (
present(abs_tolerance)) rs%abs_tolerance = abs_tolerance
83 type(root_solver_t),
intent(inout) :: rs
84 type(namespace_t),
intent(in) :: namespace
97 call parse_variable(namespace,
'RootSolver', root_newton, rs%solver_type)
110 call parse_variable(namespace,
'RootSolverMaxIter', 500, rs%maxiter)
119 call parse_variable(namespace,
'RootSolverAbsTolerance', 1e-10_real64, rs%abs_tolerance)
126 type(root_solver_t),
intent(in) :: rs
127 real(real64),
intent(out) :: root(:)
128 logical,
intent(out) :: success
129 real(real64),
optional,
intent(in) :: startval(:)
131 subroutine func(z, f, jf)
134 real(real64),
intent(in) :: z(:)
135 real(real64),
intent(out) :: f(:), jf(:, :)
145 select case (rs%solver_type)
149 write(
message(1),
'(a,i4,a)')
"Error in droot_solver_run: '", rs%solver_type,
"' is not a valid root solver"
159 subroutine droot_newton(rs, func, root, startval, success)
161 real(real64),
intent(out) :: root(:)
162 real(real64),
optional,
intent(in) :: startval(:)
163 logical,
intent(out) :: success
165 subroutine func(z, f, jf)
168 real(real64),
intent(in) :: z(:)
169 real(real64),
intent(out) ::
f(:), jf(:, :)
174 real(real64) :: err, prev_err
175 real(real64),
allocatable ::
f(:), jf(:, :), delta(:, :), rhs(:, :), root_trial(:)
177 real(real64) :: mm, prev_m, alpha, err_trial
181 safe_allocate(
f(1:rs%dim))
182 safe_allocate(root_trial(1:rs%dim))
183 safe_allocate(jf(1:rs%dim, 1:rs%dim))
184 safe_allocate(delta(1:rs%dim, 1))
185 safe_allocate(rhs(1:rs%dim, 1))
187 if (
present(startval))
then
193 call func(root,
f, jf)
201 do while(err > rs%abs_tolerance)
202 rhs(1:rs%dim, 1) = -mm *
f(1:rs%dim)
209 root_trial = root + alpha * delta(:,1)
210 call func(root_trial,
f, jf)
213 if (err_trial < err)
exit
214 alpha = 0.5_real64 * alpha
215 if (alpha < 1e-12_real64)
then
220 if (.not. success)
exit
227 if (iter > rs%maxiter)
then
249 if (abs(mm - prev_m) > 0.5_real64) mm =
m_one
251 if ( mm > 10._real64 .or. mm < 1.0_real64) mm =
m_one
257 safe_deallocate_a(jf)
258 safe_deallocate_a(delta)
259 safe_deallocate_a(rhs)
double floor(double __x) __attribute__((__nothrow__
real(real64) function func(r1, rn, n, a)
real(real64), parameter, public m_zero
real(real64), parameter, public m_one
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine droot_newton(rs, func, root, startval, success)
Newton-Raphson scheme can only be used in the real case.
subroutine, public root_solver_init(rs, namespace, dimensionality, solver_type, maxiter, rel_tolerance, abs_tolerance)
subroutine, public droot_solver_run(rs, func, root, success, startval)
subroutine, public root_solver_read(rs, namespace)
static double f(double w, void *p)