236 subroutine lss_solve(this, fcn, x, fvec, ib, err)
240 real(real64),
intent(inout),
dimension(:) :: x
241 real(real64),
intent(out),
dimension(:) :: fvec
243 class(errors),
intent(inout),
optional,
target :: err
246 real(real64),
parameter :: zero = 0.0d0
247 real(real64),
parameter :: p0001 = 1.0d-4
248 real(real64),
parameter :: p1 = 0.1d0
249 real(real64),
parameter :: qtr = 0.25d0
250 real(real64),
parameter :: half = 0.5d0
251 real(real64),
parameter :: p75 = 0.75d0
252 real(real64),
parameter :: one = 1.0d0
253 real(real64),
parameter :: hndrd = 1.0d2
256 logical :: xcnvrg, fcnvrg, gcnvrg
257 integer(int32) :: i, neqn, nvar, flag, neval, iter, j, l, maxeval, &
259 integer(int32),
allocatable,
dimension(:) :: jpvt
260 real(real64) :: ftol, xtol, gtol, fac, eps, fnorm, par, xnorm, delta, &
261 sm, temp, gnorm, pnorm, fnorm1, actred, temp1, temp2, prered, &
263 real(real64),
allocatable,
dimension(:,:) :: jac
264 real(real64),
allocatable,
dimension(:) :: diag, qtf, wa1, wa2, wa3, wa4, w
265 class(errors),
pointer :: errmgr
266 type(errors),
target :: deferr
267 character(len = 256) :: errmsg
273 neqn = fcn%get_equation_count()
274 nvar = fcn%get_variable_count()
279 ftol = this%get_fcn_tolerance()
280 xtol = this%get_var_tolerance()
281 gtol = this%get_gradient_tolerance()
282 maxeval = this%get_max_fcn_evals()
284 if (
present(ib))
then
287 ib%jacobian_count = njac
288 ib%converge_on_fcn = fcnvrg
289 ib%converge_on_chng = xcnvrg
290 ib%converge_on_zero_diff = gcnvrg
292 if (
present(err))
then
299 if (.not.fcn%is_fcn_defined())
then
301 call errmgr%report_error(
"lss_solve", &
302 "No function has been defined.", &
303 nl_invalid_operation_error)
306 if (nvar > neqn)
then
308 call errmgr%report_error(
"lss_solve",
"The solver cannot " // &
309 "solve the underdetermined problem. The number of " // &
310 "unknowns must not exceed the number of equations.", &
311 nl_invalid_input_error)
315 if (
size(x) /= nvar)
then
317 else if (
size(fvec) /= neqn)
then
322 write(errmsg, 100)
"Input number ", flag, &
323 " is not sized correctly."
324 call errmgr%report_error(
"lss_solve", trim(errmsg), &
330 allocate(jpvt(nvar), stat = flag)
331 if (flag == 0)
allocate(jac(neqn, nvar), stat = flag)
332 if (flag == 0)
allocate(diag(nvar), stat = flag)
333 if (flag == 0)
allocate(qtf(nvar), stat = flag)
334 if (flag == 0)
allocate(wa1(nvar), stat = flag)
335 if (flag == 0)
allocate(wa2(nvar), stat = flag)
336 if (flag == 0)
allocate(wa3(nvar), stat = flag)
337 if (flag == 0)
allocate(wa4(neqn), stat = flag)
339 call fcn%jacobian(x, jac, fv = fvec, olwork = lwork)
340 allocate(w(lwork), stat = flag)
344 call errmgr%report_error(
"qns_solve", &
345 "Insufficient memory available.", nl_out_of_memory_error)
350 call fcn%fcn(x, fvec)
360 call fcn%jacobian(x, jac, fvec, w)
364 call lmfactor(jac, .true., jpvt, wa1, wa2, wa3)
371 if (wa2(j) == zero) diag(j) = one
376 if (delta == zero) delta = fac
382 if (jac(j,j) /= zero)
then
385 sm = sm + jac(i,j) * wa4(i)
387 temp = -sm / jac(j,j)
388 wa4(j:neqn) = wa4(j:neqn) + jac(j:neqn,j) * temp
396 if (fnorm /= zero)
then
399 if (wa2(l) == zero) cycle
402 sm = sm + jac(i,j) * (qtf(i) / fnorm)
404 gnorm = max(gnorm, abs(sm / wa2(l)))
409 if (gnorm <= gtol)
then
416 diag(j) = max(diag(j), wa2(j))
422 call lmpar(jac, jpvt, diag, qtf, delta, par, wa1, wa2, wa3, wa4)
427 wa2(j) = x(j) + wa1(j)
428 wa3(j) = diag(j) * wa1(j)
433 if (iter == 1) delta = min(delta, pnorm)
436 call fcn%fcn(wa2, wa4)
442 if (p1 * fnorm1 < fnorm) actred = one - (fnorm1 / fnorm)**2
450 wa3(1:j) = wa3(1:j) + jac(1:j,j) * temp
452 temp1 = norm2(wa3) / fnorm
453 temp2 = (sqrt(par) * pnorm) / fnorm
454 prered = temp1**2 + temp2**2 / half
455 dirder = -(temp1**2 + temp2**2)
459 if (prered /= zero) ratio = actred / prered
462 if (ratio <= qtr)
then
463 if (actred >= zero) temp = half
464 if (actred < zero) temp = half * dirder / &
465 (dirder + half * actred)
466 if (p1 * fnorm1 >= fnorm .or. temp < p1) temp = p1
467 delta = temp * min(delta, pnorm / p1)
470 if (par /= zero .and. ratio < p75)
then
479 if (ratio >= p0001)
then
482 wa2(j) = diag(j) * x(j)
491 if (abs(actred) <= ftol .and. prered <= ftol .and. &
492 half * ratio <= one) fcnvrg = .true.
493 if (delta <= xtol * xnorm) xcnvrg = .true.
494 if (fcnvrg .or. xcnvrg)
exit
497 if (neval >= maxeval) flag = nl_convergence_error
498 if (abs(actred) <= eps .and. prered <= eps .and. &
499 half * ratio <= one) flag = nl_tolerance_too_small_error
500 if (delta <= eps * xnorm) flag = nl_tolerance_too_small_error
501 if (gnorm <= eps) flag = nl_tolerance_too_small_error
504 if (ratio >= p0001)
exit
508 if (fcnvrg .or. xcnvrg .or. gcnvrg .or. flag /= 0)
exit
511 if (this%get_print_status())
then
512 call print_status(iter, neval, njac, xnorm, fnorm)
517 if (
present(ib))
then
520 ib%jacobian_count = njac
521 ib%converge_on_fcn = fcnvrg
522 ib%converge_on_chng = xcnvrg
523 ib%converge_on_zero_diff = gcnvrg
528 write(errmsg, 101)
"The algorithm failed to " // &
529 "converge. Function evaluations performed: ", neval, &
530 "." // new_line(
'c') //
"Change in Variable: ", xnorm, &
531 new_line(
'c') //
"Residual: ", fnorm
532 call errmgr%report_error(
"lss_solve", trim(errmsg), &
538101
format(a, i0, a, e10.3, a, e10.3)
570 subroutine lmpar(r, ipvt, diag, qtb, delta, par, x, sdiag, wa1, wa2)
572 real(real64),
intent(inout),
dimension(:,:) :: r
573 integer(int32),
intent(in),
dimension(:) :: ipvt
574 real(real64),
intent(in),
dimension(:) :: diag, qtb
575 real(real64),
intent(in) :: delta
576 real(real64),
intent(inout) :: par
577 real(real64),
intent(out),
dimension(:) :: x, sdiag, wa1, wa2
580 real(real64),
parameter :: zero = 0.0d0
581 real(real64),
parameter :: p001 = 1.0d-3
582 real(real64),
parameter :: p1 = 0.1d0
585 integer :: iter, j, jm1, jp1, k, l, nsing, n
586 real(real64) :: dxnorm, dwarf, fp, gnorm, parc, parl, paru, sm, temp
597 if (r(j,j) == zero .and. nsing == n) nsing = j - 1
598 if (nsing < n) wa1(j) = zero
604 wa1(j) = wa1(j) / r(j,j)
608 wa1(1:jm1) = wa1(1:jm1) - r(1:jm1,j) * temp
623 dxnorm = norm2(wa2(1:n))
625 if (fp <= p1 * delta)
then
627 if (iter == 0) par = zero
638 wa1(j) = diag(l) * (wa2(l) / dxnorm)
645 sm = dot_product(r(1:jm1,j), wa1(1:jm1))
647 wa1(j) = (wa1(j) - sm) / r(j,j)
650 parl = ((fp / delta) / temp) / temp
655 sm = dot_product(r(1:j,j), qtb(1:j))
657 wa1(j) = sm / diag(l)
661 if (paru == zero) paru = dwarf / min(delta, p1)
667 if (par == zero) par = gnorm / dxnorm
674 if (par == zero) par = max(dwarf, p001 * paru)
677 call lmsolve(r(1:n,1:n), ipvt, wa1, qtb, x, sdiag, wa2)
686 if (abs(fp) <= p1 * delta &
687 .or. parl == zero .and. fp <= temp &
688 .and. temp < zero .or. iter == 10)
exit
693 wa1(j) = diag(l) * (wa2(l) / dxnorm)
696 wa1(j) = wa1(j) / sdiag(j)
700 wa1 = wa1 - r(1:n,j) * temp
703 parc = ((fp / delta) / temp) / temp
706 if (fp > zero) parl = max(parl, par)
707 if (fp < zero) paru = min(paru, par)
710 par = max(parl, par + parc)
712 if (iter == zero) par = zero
737 subroutine lmfactor(a, pivot, ipvt, rdiag, acnorm, wa)
739 real(real64),
intent(inout),
dimension(:,:) :: a
740 logical,
intent(in) :: pivot
741 integer(int32),
intent(out),
dimension(:) :: ipvt
742 real(real64),
intent(out),
dimension(:) :: rdiag, acnorm, wa
745 real(real64),
parameter :: zero = 0.0d0
746 real(real64),
parameter :: p05 = 5.0d-2
747 real(real64),
parameter :: one = 1.0d0
750 integer(int32) :: m, n, i, j, jp1, k, kmax, minmn
751 real(real64) :: ajnorm, epsmch, sm, temp
757 epsmch = epsilon(epsmch)
761 acnorm(j) = norm2(a(:,j))
764 if (pivot) ipvt(j) = j
773 if (rdiag(k) > rdiag(kmax)) kmax = k
781 rdiag(kmax) = rdiag(j)
791 ajnorm = norm2(a(j:m,j))
792 if (ajnorm /= zero)
then
793 if (a(j,j) < zero) ajnorm = -ajnorm
794 a(j:m,j) = a(j:m,j) / ajnorm
795 a(j,j) = a(j,j) + one
802 sm = dot_product(a(j:m,j), a(j:m,k))
804 a(j:m,k) = a(j:m,k) - temp * a(j:m,j)
805 if (.not.pivot .or. rdiag(k) == zero) cycle
806 temp = a(j,k) / rdiag(k)
807 rdiag(k) = rdiag(k) * sqrt(max(zero, one - temp**2))
808 if (p05 * (rdiag(k) / wa(k))**2 > epsmch) cycle
809 rdiag(k) = norm2(a(jp1:m,k))
840 subroutine lmsolve(r, ipvt, diag, qtb, x, sdiag, wa)
842 real(real64),
intent(inout),
dimension(:,:) :: r
843 integer(int32),
intent(in),
dimension(:) :: ipvt
844 real(real64),
intent(in),
dimension(:) :: diag, qtb
845 real(real64),
intent(out),
dimension(:) :: x, sdiag, wa
848 real(real64),
parameter :: zero = 0.0d0
849 real(real64),
parameter :: qtr = 0.25d0
850 real(real64),
parameter :: half = 0.5d0
853 integer(int32) :: n, i, j, jp1, k, kp1, l, nsing
854 real(real64) :: cs, ctan, qtbpj, sn, sm, tn, temp
871 if (diag(l) /= zero)
then
882 if (sdiag(k) == zero) cycle
883 if (abs(r(k,k)) < abs(sdiag(k)))
then
884 ctan = r(k,k) / sdiag(k)
885 sn = half / sqrt(qtr + qtr * ctan**2)
888 tn = sdiag(k) / r(k,k)
889 cs = half / sqrt(qtr + qtr * tn**2)
895 r(k,k) = cs * r(k,k) + sn * sdiag(k)
896 temp = cs * wa(k) + sn * qtbpj
897 qtbpj = -sn * wa(k) + cs * qtbpj
904 temp = cs * r(i,k) + sn * sdiag(i)
905 sdiag(i) = -sn * r(i,k) + cs * sdiag(i)
921 if (sdiag(j) == zero .and. nsing == n) nsing = j - 1
922 if (nsing < n) wa(j) = zero
929 if (nsing >= jp1)
then
930 sm = dot_product(r(jp1:nsing,j), wa(jp1:nsing))
932 wa(j) = (wa(j) - sm) / sdiag(j)