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,
'RootSolverRelTolerance', 1e-10_real64, rs%rel_tolerance)
128 call parse_variable(namespace,
'RootSolverAbsTolerance', 1e-10_real64, rs%abs_tolerance)
136 real(real64),
intent(out) :: root(:)
137 logical,
intent(out) :: success
138 real(real64),
optional,
intent(in) :: startval(:)
143 real(real64),
intent(in) :: z(:)
144 real(real64),
intent(out) ::
f(:), jf(:, :)
154 select case (rs%solver_type)
158 write(
message(1),
'(a,i4,a)')
"Error in droot_solver_run: '", rs%solver_type,
"' is not a valid root solver"
168 subroutine droot_newton(rs, func, root, startval, success)
170 real(real64),
intent(out) :: root(:)
171 real(real64),
optional,
intent(in) :: startval(:)
172 logical,
intent(out) :: success
174 subroutine func(z, f, jf)
177 real(real64),
intent(in) :: z(:)
178 real(real64),
intent(out) ::
f(:), jf(:, :)
183 real(real64) :: err, prev_err
184 real(real64),
allocatable ::
f(:), jf(:, :), delta(:, :), rhs(:, :), root_trial(:)
186 real(real64) :: mm, prev_m, alpha, err_trial
190 safe_allocate(
f(1:rs%dim))
191 safe_allocate(root_trial(1:rs%dim))
192 safe_allocate(jf(1:rs%dim, 1:rs%dim))
193 safe_allocate(delta(1:rs%dim, 1))
194 safe_allocate(rhs(1:rs%dim, 1))
196 if (
present(startval))
then
202 call func(root,
f, jf)
209 do while(err > rs%abs_tolerance)
210 rhs(1:rs%dim, 1) = -mm *
f(1:rs%dim)
217 root_trial = root + alpha * delta(:,1)
218 call func(root_trial,
f, jf)
221 if (err_trial < err)
exit
222 alpha = 0.5_real64 * alpha
223 if (alpha < 1e-12_real64)
then
228 if (.not. success)
exit
235 if (iter > rs%maxiter)
then
257 if (abs(mm - prev_m) > 0.5_real64) mm =
m_one
259 if ( mm > 10._real64 .or. mm < 1.0_real64) mm =
m_one
265 safe_deallocate_a(jf)
266 safe_deallocate_a(delta)
267 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)