V3FIT
lmdif1.f90
1  SUBROUTINE lmdif1(fcn, m, n, x, fvec, tol, epsfcn, nfev_end, &
2  diag, mode, info, lwa, max_processors, num_lm_params)
3 !! ADDED EPSFCN TO ARG LIST: BY SPH (2/97)
4 !! ADDED NFEV_end == MAXFEV TO ARG LIST (6/31/99)
5 !! ADDED MAX_PROCESSORS, NUM_LM_PARAMS TO ARG LIST (11/23/99)
6 !! (NEED MAX_PROCESSORS, NUM_LM_PARAMS FOR MULTI-PROCESSOR APPLICATIONS)
7 
8  USE fdjac_mod, ONLY: maxj_processors=>max_processors, &
9  numj_lm_params=>num_lm_params
10  USE stel_kinds
11  IMPLICIT NONE
12 !-----------------------------------------------
13 ! D u m m y A r g u m e n t s
14 !-----------------------------------------------
15  INTEGER, INTENT(in) :: m, n, lwa, nfev_end, mode
16  INTEGER, INTENT(out) :: info
17  REAL(rprec), INTENT(in) :: tol, epsfcn
18  REAL(rprec), DIMENSION(n), INTENT(inout) :: x, diag
19  REAL(rprec), DIMENSION(m), INTENT(out) :: fvec
20  INTEGER, INTENT(in) :: max_processors, num_lm_params
21 !-----------------------------------------------
22 ! L o c a l P a r a m e t e r s
23 !-----------------------------------------------
24  REAL(rprec), PARAMETER :: zero=0, factor=10
25 !-----------------------------------------------
26 ! L o c a l V a r i a b l e s
27 !-----------------------------------------------
28  INTEGER, DIMENSION(:), ALLOCATABLE :: iwa
29  INTEGER :: maxfev, mp5n, nfev, nprint
30  REAL(rprec), DIMENSION(:), ALLOCATABLE :: wa
31  REAL(rprec) :: ftol, gtol, xtol
32 !-----------------------------------------------
33 ! E x t e r n a l F u n c t i o n s
34 !-----------------------------------------------
35  EXTERNAL fcn
36 !-----------------------------------------------
37  INTERFACE
38  SUBROUTINE lmdif(fcn, m, n, x, fvec, ftol, xtol, gtol, maxfev, &
39  epsfcn, diag, mode, factor, nprint, info, nfev, fjac, &
40  ldfjac, ipvt, qtf, wa1, wa2, wa3, wa4)
41  USE stel_kinds
42  INTEGER :: m, n, maxfev, mode, nprint, info, nfev, ldfjac
43  REAL(rprec), INTENT(in) :: ftol, xtol, gtol, epsfcn, factor
44  REAL(rprec), DIMENSION(n) :: x, wa1, wa2, wa3
45  REAL(rprec), DIMENSION(m) :: fvec, wa4
46  INTEGER, DIMENSION(n), TARGET :: ipvt
47  REAL(rprec), DIMENSION(n), TARGET :: diag, qtf
48  REAL(rprec), DIMENSION(ldfjac,n), TARGET :: fjac
49  EXTERNAL fcn
50  END SUBROUTINE lmdif
51  END INTERFACE
52 
53 !
54 ! SUBROUTINE lmdif1
55 !
56 ! the purpose of lmdif1 is to minimize the sum of the squares of
57 ! m nonlinear functions in n variables by a modification of the
58 ! levenberg-marquardt algorithm. this is done by using the more
59 ! general least-squares solver lmdif. the user must provide a
60 ! SUBROUTINE which calculates the functions. the jacobian is
61 ! THEN calculated by a forward-difference approximation.
62 !
63 ! the SUBROUTINE statement is
64 !
65 ! SUBROUTINE lmdif1(fcn,m,n,x,fvec,tol,info,lwa)
66 !
67 ! WHERE
68 !
69 ! fcn is the name of the user-supplied SUBROUTINE which
70 ! calculates the functions. fcn must be declared
71 ! in an external statement in the user calling
72 ! program, and should be written as follows.
73 !
74 ! SUBROUTINE fcn(m, n, x, fvec, iflag, ncnt)
75 ! INTEGER m,n,iflag
76 ! REAL(rprec) x(n),fvec(m)
77 ! ----------
78 ! calculate the functions at x and
79 ! RETURN this vector in fvec.
80 ! ----------
81 ! RETURN
82 ! END
83 !
84 ! the value of iflag should not be changed by fcn unless
85 ! the user wants to terminate execution of lmdif1.
86 ! in this CASE set iflag to a negative INTEGER. On a multi-processor
87 ! machine, iflag will be initialized to the particular processor id.
88 !
89 !
90 ! m is a positive INTEGER input variable set to the number
91 ! of functions.
92 !
93 ! n is a positive INTEGER input variable set to the number
94 ! of variables. n must not exceed m.
95 !
96 ! x is an array of length n. on input x must contain
97 ! an initial estimate of the solution vector. on output x
98 ! contains the final estimate of the solution vector.
99 !
100 ! fvec is an output array of length m which CONTAINS
101 ! the functions evaluated at the output x.
102 !
103 ! ncnt is a positive INTEGER input variable set to the current
104 ! iteration count (added by SPH - 7/99)
105 !
106 ! tol is a nonnegative input variable. termination occurs
107 ! when the algorithm estimates either that the relative
108 ! error in the sum of squares is at most tol or that
109 ! the relative error between x and the solution is at
110 ! most tol.
111 !
112 ! info is an INTEGER output variable. IF the user has
113 ! terminated execution, info is set to the (negative)
114 ! value of iflag. see description of fcn.
115 !
116 ! lwa is a positive INTEGER input variable not less than
117 ! m*n+5*n+m.
118 !
119 ! subprograms called
120 !
121 ! user-supplied ...... fcn
122 !
123 ! minpack-supplied ... lmdif
124 !
125 ! argonne national laboratory. MINpack project. march 1980.
126 ! burton s. garbow, kenneth e. hillstrom, jorge j. more
127 !
128 ! modified to accept improvements from jacobian calc. MZarnstorff Oct 2001
129 ! modified to flip sign of jacobian offsets for more efficient search
130 ! and start with an exponential levenberg spread to settle on scale
131 ! M. Zarnstorff Jan 2002
132 !
133 ! **********
134 !
135 ! CALL lmdif.
136 !
137  IF (lwa .lt. m*n+5*n+m) stop 'lwa too small'
138 
139  ALLOCATE (wa(lwa), iwa(n), stat=info)
140  IF (info .NE. 0) stop 'Allocation error in lmdif1!'
141 
142 #if !defined(MPI_OPT)
143 !
144 ! Load fdjac module values
145 !
146  maxj_processors = max(max_processors,1)
147  numj_lm_params = max(num_lm_params,1)
148 #endif
149  maxfev = 200*(n + 1)
150  maxfev = min(maxfev, nfev_end) !!SPH-Added 7/99
151  ftol = tol
152  xtol = tol
153  gtol = zero
154 
155 !! ADDED BY SPH -- PASSED IN ARG LIST(2/97)
156 !! epsfcn = zero
157 !! mode = 1 (DAS, passed through arg list 9/13/00)
158 
159  nprint = 0
160  mp5n = m + 5*n
161  fvec = 0
162  CALL lmdif (fcn, m, n, x, fvec, ftol, xtol, gtol, maxfev, &
163  epsfcn, diag, mode, factor, nprint, info, nfev, &
164  wa(mp5n+1), m, iwa, wa(n+1), wa(2*n+1), wa(3*n+1), &
165  wa(4*n+1), wa(5*n+1))
166 
167 #if !defined(MPI_OPT)
168  IF (info .eq. 8) info = 4
169 #endif
170  DEALLOCATE(wa, iwa)
171 
172  END SUBROUTINE lmdif1