3 INTEGER :: nscan, ldfjac
4 INTEGER,
DIMENSION(:),
POINTER :: ipvt
5 REAL(rprec) :: pnorm, fnorm1, delta, par, spread_ratio
6 REAL(rprec),
DIMENSION(:),
POINTER :: wa2p, wa3p, wa4p
7 REAL(rprec),
DIMENSION(:),
POINTER :: diag, qtf
8 REAL(rprec),
DIMENSION(:,:),
POINTER :: fjac
13 SUBROUTINE levmarq_param_mp(x, wa1, wa2, wa3, wa4,
14 1 nfev, m, n, iflag, fcn)
15 USE fdjac_mod,
ONLY: flag_cleanup
22 INTEGER,
INTENT(in) :: n, m
23 INTEGER :: iflag, nfev
24 REAL(rprec),
INTENT(in) :: x(n)
25 REAL(rprec) :: wa1(n), wa2(n), wa3(n), wa4(m)
31 REAL(rprec),
PARAMETER :: zero = 0, one = 1
32 REAL(rprec),
DIMENSION(11),
PARAMETER :: factors =
33 1 (/ 1.0_dp, 0.5_dp, 0.25_dp, 0.128_dp, 0.75_dp,
34 2 1.25_dp, 1.5_dp, 0.9_dp, 1.1_dp, 1.75_dp, 2.1_dp /)
38 INTEGER :: iproc, iproc_min, nfact, num_lev, istat, ierr, j,
40 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iflag_array
41 REAL(rprec) :: scale_factor
42 REAL(rprec),
DIMENSION(:),
ALLOCATABLE :: fnorm_array
43 CHARACTER(LEN=1) :: ext, low_mark
47 REAL(rprec),
EXTERNAL :: enorm
57 ALLOCATE (iflag_array(numprocs), fnorm_array(numprocs),
59 IF (istat .ne. 0) stop
'Allocation error in levmarq_param_mp'
62 IF (lfirst_lm .and. num_lev > 2)
THEN
66 scale_factor = 10._dp**(-iproc)
69 ELSE IF (num_lev > 2*nfact)
THEN
70 scale_factor = ((iproc+1)*maxval(factors))/num_lev
71 ELSE IF (iproc .lt. nfact)
THEN
72 scale_factor = factors(iproc+1)
74 scale_factor = ((iproc-nfact)*minval(factors))/
78 delta = scale_factor*delta
80 CALL lmpar (n, fjac, ldfjac, ipvt, diag, qtf,
81 1 delta, par, wa1, wa2, wa3, wa4)
85 IF (par .eq. zero) wa1 = wa1*scale_factor
96 mpi_comm_workers = mpi_comm_world
98 CALL fcn (m, n, wa2, wa4, iflag, nfev)
103 CALL mpi_allgather(iflag, 1, mpi_integer, iflag_array, 1,
104 1 mpi_integer, mpi_comm_world, ierr)
105 IF (ierr .ne. 0) stop
'MPI_ALLGATHER failed in levmarq_param_mp'
107 fnorm1 = enorm(m,wa4)
112 CALL mpi_allgather(fnorm1, 1, mpi_real8, fnorm_array, 1,
113 1 mpi_real8, mpi_comm_world, ierr)
114 IF (ierr .ne. 0) stop
'MPI_ALLGATHER failed in LMDIF'
115 iflag_min = minloc(fnorm_array)
116 iproc_min = iflag_min(1) - 1
123 IF (myid .eq. master) ext =
'*'
124 IF (iproc .eq. iproc_min) low_mark =
'*'
126 WRITE(6,
'(2x,i6,8x,i3,4x,2(3x,1es12.4,a),3x,1es12.4)')
127 1 iproc+nfev, iproc, fnorm1**2, low_mark, par, ext,
132 fnorm1 = minval(fnorm_array)
136 DEALLOCATE (iflag_array, fnorm_array)
144 CALL mpi_bcast(pnorm,1,mpi_real8,iproc_min,
145 1 mpi_comm_world,ierr)
146 IF (ierr .ne. 0)
GOTO 3000
147 CALL mpi_bcast(par,1,mpi_real8,iproc_min,
148 1 mpi_comm_world,ierr)
149 IF (ierr .ne. 0)
GOTO 3000
150 CALL mpi_bcast(delta,1,mpi_real8,iproc_min,
151 1 mpi_comm_world,ierr)
152 IF (ierr .ne. 0)
GOTO 3000
153 CALL mpi_bcast(wa1,n,mpi_real8,iproc_min,
154 1 mpi_comm_world,ierr)
155 IF (ierr .ne. 0)
GOTO 3000
156 CALL mpi_bcast(wa2,n,mpi_real8,iproc_min,
157 1 mpi_comm_world,ierr)
158 IF (ierr .ne. 0)
GOTO 3000
159 CALL mpi_bcast(wa4,m,mpi_real8,iproc_min,
160 1 mpi_comm_world,ierr)
161 IF (ierr .ne. 0)
GOTO 3000
167 IF (myid .eq. iproc_min) wa3(:n) = fjac(:n,j)
168 CALL mpi_bcast(wa3, n, mpi_real8, iproc_min,
169 1 mpi_comm_world, ierr)
170 IF (ierr .ne. 0)
GOTO 3000
171 IF (myid .ne. iproc_min) fjac(:n,j) = wa3(:n)
178 CALL fcn (m, n, x, wa4, iflag, nfev)
180 nfev = nfev + num_lev
186 WRITE (6, *)
'MPI_BCAST error in LEVMARQ_PARAM_MP, ierr = ', ierr
189 END SUBROUTINE levmarq_param_mp
191 SUBROUTINE levmarq_param(x, wa1, wa2, wa3, wa4,
192 1 time, nfev, m, n, iflag, fcn)
198 INTEGER :: nfev, n, m, iflag
200 REAL(rprec),
TARGET :: x(n), wa1(n), wa2(n), wa3(n), wa4(m)
202 #if !defined(MPI_OPT)
206 REAL(rprec),
PARAMETER :: zero=0
210 INTEGER :: j, istat, iread, ic1, ic2, irate, count_max,
212 REAL(rprec),
DIMENSION(num_lm_params) ::
213 1 fnorm_min, pnorm_min, delta_min, par_min
214 CHARACTER(LEN=1) :: ext, low_mark
218 EXTERNAL multiprocess, lmpar_parallel
232 CALL system_clock(ic1, irate)
234 CALL multiprocess(num_lm_params, max_processors,
235 1 lmpar_parallel, fcn)
237 CALL system_clock(ic2, irate, count_max)
238 IF (ic2 .lt. ic1) ic2 = ic2 + count_max
240 nfev = nfev + num_lm_params
245 DO j = 1, num_lm_params
247 READ (j+1000, iostat=iread) istat, iflag, pnorm_min(j),
248 1 fnorm_min(j), par_min(j), delta_min(j)
249 IF (iread .ne. 0)
THEN
250 WRITE (6, *)
'Error reading from file fort.', j+1000,
251 1
' in levmarq_param',
' IOSTAT = ', iread
253 ELSE IF (j .ne. istat)
THEN
255 1
'Incorrect value READ in for INDEX j in levmarq_param'
259 IF (iflag .NE. 0)
RETURN
261 IF (j .EQ. 1) fnorm1 = fnorm_min(j)
262 IF (fnorm_min(j) .LE. fnorm1)
THEN
264 fnorm1 = fnorm_min(jmin)
265 pnorm = pnorm_min(jmin)
267 delta = delta_min(jmin)
270 READ (j+1000) wa1(k), wa2(k)
272 READ (j+1000) fjac(k, istat)
279 READ (j+1000) wa1, wa2, wa4, fjac(1:n, 1:n)
284 CLOSE (j+1000, status=
'delete')
288 DO j = 1, num_lm_params
291 IF (j .eq. 1) ext =
'*'
292 IF (j .eq. jmin) low_mark =
'*'
293 WRITE (6,
'(2x,i6,4x,2(3x,1es12.4,a),3x,1es12.4)') j+ncntp,
294 1 fnorm_min(j)**2, low_mark, par_min(j), ext, delta_min(j)
301 CALL fcn(m, n, x, wa4, iflag, ncntp)
303 time = time + real(ic2 - ic1)/real(irate)
305 END SUBROUTINE levmarq_param