nonlin 1.5.2
A library that provides routines to compute the solutions to systems of nonlinear equations.
Loading...
Searching...
No Matches
nonlin_least_squares.f90
1! nonlin_least_squares.f90
2
8 use, intrinsic :: iso_fortran_env, only : int32, real64
10 use nonlin_core
11 use ferror, only : errors
12 implicit none
13 private
14 public :: least_squares_solver
15
16! ******************************************************************************
17! TYPES
18! ------------------------------------------------------------------------------
22 private
24 real(real64) :: m_factor = 100.0d0
25 contains
27 procedure, public :: get_step_scaling_factor => lss_get_factor
29 procedure, public :: set_step_scaling_factor => lss_set_factor
31 procedure, public :: solve => lss_solve
32 end type
33
34contains
35! ******************************************************************************
36! LEAST_SQUARES_SOLVER MEMBERS
37! ------------------------------------------------------------------------------
49 pure function lss_get_factor(this) result(x)
50 class(least_squares_solver), intent(in) :: this
51 real(real64) :: x
52 x = this%m_factor
53 end function
54
55! --------------------
68 subroutine lss_set_factor(this, x)
69 class(least_squares_solver), intent(inout) :: this
70 real(real64), intent(in) :: x
71 if (x < 0.1d0) then
72 this%m_factor = 0.1d0
73 else if (x > 1.0d2) then
74 this%m_factor = 1.0d2
75 else
76 this%m_factor = x
77 end if
78 end subroutine
79
80! ------------------------------------------------------------------------------
236 subroutine lss_solve(this, fcn, x, fvec, ib, err)
237 ! Arguments
238 class(least_squares_solver), intent(inout) :: this
239 class(vecfcn_helper), intent(in) :: fcn
240 real(real64), intent(inout), dimension(:) :: x
241 real(real64), intent(out), dimension(:) :: fvec
242 type(iteration_behavior), optional :: ib
243 class(errors), intent(inout), optional, target :: err
244
245 ! Parameters
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
254
255 ! Local Variables
256 logical :: xcnvrg, fcnvrg, gcnvrg
257 integer(int32) :: i, neqn, nvar, flag, neval, iter, j, l, maxeval, &
258 njac, lwork
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, &
262 dirder, ratio
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
268
269 ! Initialization
270 xcnvrg = .false.
271 fcnvrg = .false.
272 gcnvrg = .false.
273 neqn = fcn%get_equation_count()
274 nvar = fcn%get_variable_count()
275 neval = 0
276 iter = 0
277 njac = 0
278 fac = this%m_factor
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()
283 eps = epsilon(eps)
284 if (present(ib)) then
285 ib%iter_count = iter
286 ib%fcn_count = neval
287 ib%jacobian_count = njac
288 ib%converge_on_fcn = fcnvrg
289 ib%converge_on_chng = xcnvrg
290 ib%converge_on_zero_diff = gcnvrg
291 end if
292 if (present(err)) then
293 errmgr => err
294 else
295 errmgr => deferr
296 end if
297
298 ! Input Check
299 if (.not.fcn%is_fcn_defined()) then
300 ! ERROR: No function is defined
301 call errmgr%report_error("lss_solve", &
302 "No function has been defined.", &
303 nl_invalid_operation_error)
304 return
305 end if
306 if (nvar > neqn) then
307 ! ERROR: System is underdetermined
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)
312 return
313 end if
314 flag = 0
315 if (size(x) /= nvar) then
316 flag = 3
317 else if (size(fvec) /= neqn) then
318 flag = 4
319 end if
320 if (flag /= 0) then
321 ! One of the input arrays is not sized correctly
322 write(errmsg, 100) "Input number ", flag, &
323 " is not sized correctly."
324 call errmgr%report_error("lss_solve", trim(errmsg), &
325 nl_array_size_error)
326 return
327 end if
328
329 ! Local Memory Allocation
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)
338 if (flag == 0) then
339 call fcn%jacobian(x, jac, fv = fvec, olwork = lwork)
340 allocate(w(lwork), stat = flag)
341 end if
342 if (flag /= 0) then
343 ! ERROR: Out of memory
344 call errmgr%report_error("qns_solve", &
345 "Insufficient memory available.", nl_out_of_memory_error)
346 return
347 end if
348
349 ! Evaluate the function at the starting point, and calculate its norm
350 call fcn%fcn(x, fvec)
351 neval = 1
352 fnorm = norm2(fvec)
353
354 ! Process
355 par = zero
356 iter = 1
357 flag = 0
358 do
359 ! Evaluate the Jacobian
360 call fcn%jacobian(x, jac, fvec, w)
361 njac = njac + 1
362
363 ! Compute the QR factorization of the Jacobian
364 call lmfactor(jac, .true., jpvt, wa1, wa2, wa3)
365
366 ! On the first iteration, scale the problem according to the norms
367 ! of each of the columns of the initial Jacobian
368 if (iter == 1) then
369 do j = 1, nvar
370 diag(j) = wa2(j)
371 if (wa2(j) == zero) diag(j) = one
372 end do
373 wa3 = diag * x
374 xnorm = norm2(wa3)
375 delta = fac * xnorm
376 if (delta == zero) delta = fac
377 end if
378
379 ! Form Q**T * FVEC, and store the first N components in QTF
380 wa4 = fvec
381 do j = 1, nvar
382 if (jac(j,j) /= zero) then
383 sm = zero
384 do i = j, neqn
385 sm = sm + jac(i,j) * wa4(i)
386 end do
387 temp = -sm / jac(j,j)
388 wa4(j:neqn) = wa4(j:neqn) + jac(j:neqn,j) * temp
389 end if ! LINE 120
390 jac(j,j) = wa1(j)
391 qtf(j) = wa4(j)
392 end do
393
394 ! Compute the norm of the scaled gradient
395 gnorm = zero
396 if (fnorm /= zero) then
397 do j = 1, nvar
398 l = jpvt(j)
399 if (wa2(l) == zero) cycle
400 sm = zero
401 do i = 1, j
402 sm = sm + jac(i,j) * (qtf(i) / fnorm)
403 end do
404 gnorm = max(gnorm, abs(sm / wa2(l)))
405 end do
406 end if ! LINE 170
407
408 ! Test for convergence of the gradient norm
409 if (gnorm <= gtol) then
410 gcnvrg = .true.
411 exit
412 end if
413
414 ! Rescale if necessary
415 do j = 1, nvar
416 diag(j) = max(diag(j), wa2(j))
417 end do
418
419 ! Inner Loop
420 do
421 ! Determine the Levenberg-Marquardt parameter
422 call lmpar(jac, jpvt, diag, qtf, delta, par, wa1, wa2, wa3, wa4)
423
424 ! Store the direction P, and X + P. Calculate the norm of P
425 do j = 1, nvar
426 wa1(j) = -wa1(j)
427 wa2(j) = x(j) + wa1(j)
428 wa3(j) = diag(j) * wa1(j)
429 end do
430 pnorm = norm2(wa3)
431
432 ! On the first iteration, adjust the initial step bounds
433 if (iter == 1) delta = min(delta, pnorm)
434
435 ! Evaluate the function at X + P, and calculate its norm
436 call fcn%fcn(wa2, wa4)
437 neval = neval + 1
438 fnorm1 = norm2(wa4)
439
440 ! Compute the scaled actual reduction
441 actred = -one
442 if (p1 * fnorm1 < fnorm) actred = one - (fnorm1 / fnorm)**2
443
444 ! Compute the scaled predicted reduction and the scaled
445 ! directional derivative
446 do j = 1, nvar
447 wa3(j) = zero
448 l = jpvt(j)
449 temp = wa1(l)
450 wa3(1:j) = wa3(1:j) + jac(1:j,j) * temp
451 end do
452 temp1 = norm2(wa3) / fnorm
453 temp2 = (sqrt(par) * pnorm) / fnorm
454 prered = temp1**2 + temp2**2 / half
455 dirder = -(temp1**2 + temp2**2)
456
457 ! Compute the ratio of the actual to the predicted reduction
458 ratio = zero
459 if (prered /= zero) ratio = actred / prered
460
461 ! Update the step bounds
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)
468 par = par / temp
469 else
470 if (par /= zero .and. ratio < p75) then
471 ! NO ACTION REQUIRED
472 else
473 delta = pnorm / half
474 par = half * par
475 end if
476 end if ! LINE 240
477
478 ! Test for successful iteration
479 if (ratio >= p0001) then
480 do j = 1, nvar
481 x(j) = wa2(j)
482 wa2(j) = diag(j) * x(j)
483 end do
484 fvec = wa4
485 xnorm = norm2(wa2)
486 fnorm = fnorm1
487 iter = iter + 1
488 end if ! LINE 290
489
490 ! Tests for convergence
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
495
496 ! Tests for termination and stringent tolerances
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
502 if (flag /= 0) exit
503
504 if (ratio >= p0001) exit
505 end do ! End of the inner loop
506
507 ! Check for termination criteria
508 if (fcnvrg .or. xcnvrg .or. gcnvrg .or. flag /= 0) exit
509
510 ! Print the iteration status
511 if (this%get_print_status()) then
512 call print_status(iter, neval, njac, xnorm, fnorm)
513 end if
514 end do
515
516 ! Report out iteration statistics
517 if (present(ib)) then
518 ib%iter_count = iter
519 ib%fcn_count = neval
520 ib%jacobian_count = njac
521 ib%converge_on_fcn = fcnvrg
522 ib%converge_on_chng = xcnvrg
523 ib%converge_on_zero_diff = gcnvrg
524 end if
525
526 ! Check for convergence issues
527 if (flag /= 0) then
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), &
533 flag)
534 end if
535
536 ! Formatting
537100 format(a, i0, a)
538101 format(a, i0, a, e10.3, a, e10.3)
539 end subroutine
540
541! ------------------------------------------------------------------------------
570 subroutine lmpar(r, ipvt, diag, qtb, delta, par, x, sdiag, wa1, wa2)
571 ! Arguments
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
578
579 ! Parameters
580 real(real64), parameter :: zero = 0.0d0
581 real(real64), parameter :: p001 = 1.0d-3
582 real(real64), parameter :: p1 = 0.1d0
583
584 ! Local Variables
585 integer :: iter, j, jm1, jp1, k, l, nsing, n
586 real(real64) :: dxnorm, dwarf, fp, gnorm, parc, parl, paru, sm, temp
587
588 ! Initialization
589 n = size(r, 2) ! NOTE: R is M-by-N
590 dwarf = tiny(dwarf)
591 nsing = n
592
593 ! Compute and store in X, the Gauss-Newton direction. If the Jacobian
594 ! is rank deficient, obtain a least-squares solution.
595 do j = 1, n
596 wa1(j) = qtb(j)
597 if (r(j,j) == zero .and. nsing == n) nsing = j - 1
598 if (nsing < n) wa1(j) = zero
599 end do ! LINE 10
600
601 if (nsing >= 1) then
602 do k = 1, nsing
603 j = nsing - k + 1
604 wa1(j) = wa1(j) / r(j,j)
605 temp = wa1(j)
606 jm1 = j - 1
607 if (jm1 >= 1) then
608 wa1(1:jm1) = wa1(1:jm1) - r(1:jm1,j) * temp
609 end if
610 end do ! LINE 40
611 end if
612
613 ! LINE 50
614 do j = 1, n
615 l = ipvt(j)
616 x(l) = wa1(j)
617 end do
618
619 ! Initialize the iteration counter, evaluate the function at the origin,
620 ! and test for acceptance of the Gauss-Newton direction.
621 iter = 0
622 wa2(1:n) = diag * x
623 dxnorm = norm2(wa2(1:n))
624 fp = dxnorm - delta
625 if (fp <= p1 * delta) then
626 ! LINE 220
627 if (iter == 0) par = zero
628 return
629 end if
630
631 ! If the Jacobian is not rank deficient, the Newton step provides a
632 ! lower bound, PARL, for the zero of the function; else, set this bound
633 ! to zero
634 parl = zero
635 if (nsing == n) then
636 do j = 1, n
637 l = ipvt(j)
638 wa1(j) = diag(l) * (wa2(l) / dxnorm)
639 end do ! LINE 80
640
641 do j = 1, n
642 sm = zero
643 jm1 = j - 1
644 if (jm1 >= 1) then
645 sm = dot_product(r(1:jm1,j), wa1(1:jm1))
646 end if
647 wa1(j) = (wa1(j) - sm) / r(j,j)
648 end do ! LINE 110
649 temp = norm2(wa1)
650 parl = ((fp / delta) / temp) / temp
651 end if
652
653 ! Calculate an upper bound, PARU, for the zero of the function
654 do j = 1, n
655 sm = dot_product(r(1:j,j), qtb(1:j))
656 l = ipvt(j)
657 wa1(j) = sm / diag(l)
658 end do ! LINE 140
659 gnorm = norm2(wa1)
660 paru = gnorm / delta
661 if (paru == zero) paru = dwarf / min(delta, p1)
662
663 ! If the input PAR lies outside of the interval (PARL,PARU), set
664 ! PAR to the closer end point.
665 par = max(par, parl)
666 par = min(par, paru)
667 if (par == zero) par = gnorm / dxnorm
668
669 ! Iteration
670 do
671 iter = iter + 1
672
673 ! Evaluate the function at the current value of PAR
674 if (par == zero) par = max(dwarf, p001 * paru)
675 temp = sqrt(par)
676 wa1 = temp * diag
677 call lmsolve(r(1:n,1:n), ipvt, wa1, qtb, x, sdiag, wa2)
678 wa2 = diag * x
679 dxnorm = norm2(wa2)
680 temp = fp
681 fp = dxnorm - delta
682
683 ! If the function is small enough, accept the current value of PAR.
684 ! Also test for the exceptional cases where PARL is zero, or the
685 ! number of iterations has reached 10
686 if (abs(fp) <= p1 * delta &
687 .or. parl == zero .and. fp <= temp &
688 .and. temp < zero .or. iter == 10) exit
689
690 ! Compute the Newton correction
691 do j = 1, n
692 l = ipvt(j)
693 wa1(j) = diag(l) * (wa2(l) / dxnorm)
694 end do ! LINE 180
695 do j = 1, n
696 wa1(j) = wa1(j) / sdiag(j)
697 temp = wa1(j)
698 jp1 = j + 1
699 if (n < jp1) cycle
700 wa1 = wa1 - r(1:n,j) * temp
701 end do ! LINE 210
702 temp = norm2(wa1)
703 parc = ((fp / delta) / temp) / temp
704
705 ! Depending on the sign of the function update PARL or PARU
706 if (fp > zero) parl = max(parl, par)
707 if (fp < zero) paru = min(paru, par)
708
709 ! Compute an improved estimate for PAR
710 par = max(parl, par + parc)
711 end do ! LINE 220 (End of iteration)
712 if (iter == zero) par = zero
713 return
714 end subroutine
715
716! ------------------------------------------------------------------------------
737 subroutine lmfactor(a, pivot, ipvt, rdiag, acnorm, wa)
738 ! Arguments
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
743
744 ! Parameters
745 real(real64), parameter :: zero = 0.0d0
746 real(real64), parameter :: p05 = 5.0d-2
747 real(real64), parameter :: one = 1.0d0
748
749 ! Local Variables
750 integer(int32) :: m, n, i, j, jp1, k, kmax, minmn
751 real(real64) :: ajnorm, epsmch, sm, temp
752
753 ! Initialization
754 m = size(a, 1)
755 n = size(a, 2)
756 minmn = min(m, n)
757 epsmch = epsilon(epsmch)
758
759 ! Compute the initial column norms, and initialize several arrays
760 do j = 1, n
761 acnorm(j) = norm2(a(:,j))
762 rdiag(j) = acnorm(j)
763 wa(j) = rdiag(j)
764 if (pivot) ipvt(j) = j
765 end do ! LINE 10
766
767 ! Reduce A to R with Householder transformations
768 do j = 1, minmn
769 if (pivot) then
770 ! Bring the column of largest norm into the pivot position
771 kmax = j
772 do k = j, n
773 if (rdiag(k) > rdiag(kmax)) kmax = k
774 end do ! LINE 20
775 if (kmax /= j) then
776 do i = 1, m
777 temp = a(i,j)
778 a(i,j) = a(i,kmax)
779 a(i,kmax) = temp
780 end do ! LINE 30
781 rdiag(kmax) = rdiag(j)
782 wa(kmax) = wa(j)
783 k = ipvt(j)
784 ipvt(j) = ipvt(kmax)
785 ipvt(kmax) = k
786 end if
787 end if ! LINE 40
788
789 ! Compute the Householder transformation to reduce the J-th column
790 ! of A to a multiple of the J-th unit vector
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
796
797 ! Apply the transformation to the remaining columns and update
798 ! the norms
799 jp1 = j + 1
800 if (n >= jp1) then
801 do k = jp1, n
802 sm = dot_product(a(j:m,j), a(j:m,k))
803 temp = sm / a(j,j)
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))
810 wa(k) = rdiag(k)
811 end do ! LINE 90
812 end if
813 end if ! LINE 100
814 rdiag(j) = -ajnorm
815 end do ! LINE 110
816 end subroutine
817
818! ------------------------------------------------------------------------------
840 subroutine lmsolve(r, ipvt, diag, qtb, x, sdiag, wa)
841 ! Arguments
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
846
847 ! Parameters
848 real(real64), parameter :: zero = 0.0d0
849 real(real64), parameter :: qtr = 0.25d0
850 real(real64), parameter :: half = 0.5d0
851
852 ! Local Variables
853 integer(int32) :: n, i, j, jp1, k, kp1, l, nsing
854 real(real64) :: cs, ctan, qtbpj, sn, sm, tn, temp
855
856 ! Initialization
857 n = size(r, 1)
858
859 ! Copy R and Q**T*B to preserve inputs and initialize S
860 do j = 1, n
861 r(j:n,j) = r(j,j:n)
862 x(j) = r(j,j)
863 wa(j) = qtb(j)
864 end do ! LINE 20
865
866 ! Eliminate the diagonal matrix D using a Givens rotation
867 do j = 1, n
868 ! Prepare the row of D to be eliminated, locating the diagonal
869 ! element using P from the QR factorization
870 l = ipvt(j)
871 if (diag(l) /= zero) then
872 sdiag(j:n) = zero
873 sdiag(j) = diag(l)
874
875 ! The transformations to eliminate the row of D modify only a
876 ! single element of Q**T * B beyond the first N, which is
877 ! initially zero.
878 qtbpj = zero
879 do k = j, n
880 ! Determine a Givens rotation which eliminates the
881 ! appropriate element in the current row of D
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)
886 cs = sn * ctan
887 else
888 tn = sdiag(k) / r(k,k)
889 cs = half / sqrt(qtr + qtr * tn**2)
890 sn = cs * tn
891 end if
892
893 ! Compute the modified diagonal element of R and the
894 ! modified element of Q**T * B
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
898 wa(k) = temp
899
900 ! Accumulate the transformation in the row of S
901 kp1 = k + 1
902 if (n < kp1) cycle
903 do i = kp1, n
904 temp = cs * r(i,k) + sn * sdiag(i)
905 sdiag(i) = -sn * r(i,k) + cs * sdiag(i)
906 r(i,k) = temp
907 end do ! LINE 60
908 end do ! LINE 80
909 end if
910
911 ! Store the diagonal element of S and restore the corresponding
912 ! diagonal element of R
913 sdiag(j) = r(j,j)
914 r(j,j) = x(j)
915 end do ! LINE 100
916
917 ! Solve the triangular system. If the system is singular, then obtain a
918 ! least-squares solution
919 nsing = n
920 do j = 1, n
921 if (sdiag(j) == zero .and. nsing == n) nsing = j - 1
922 if (nsing < n) wa(j) = zero
923 end do ! LINE 110
924 if (nsing >= 1) then
925 do k = 1, nsing
926 j = nsing - k + 1
927 sm = zero
928 jp1 = j + 1
929 if (nsing >= jp1) then
930 sm = dot_product(r(jp1:nsing,j), wa(jp1:nsing))
931 end if
932 wa(j) = (wa(j) - sm) / sdiag(j)
933 end do ! LINE 140
934 end if
935
936 ! Permute the components of Z back to components of X
937 do j = 1, n
938 l = ipvt(j)
939 x(l) = wa(j)
940 end do ! LINE 160
941 end subroutine
942
943! ------------------------------------------------------------------------------
944end module
nonlin_constants
nonlin_core
nonlin_least_squares
A base class for various solvers of nonlinear systems of equations.
Defines a set of parameters that describe the behavior of the iteration process.
Defines a type capable of encapsulating a system of nonlinear equations of the form: F(X) = 0....
Defines a Levenberg-Marquardt based solver for unconstrained least-squares problems.