5use ddx,
only:
ddinit, ddx_type, closest_supported_lebedev_grid
37subroutine ddfromfile(fname, ddx_data, tol, charges, ddx_error)
39 character(len=*),
intent(in) :: fname
40 type(ddx_type),
intent(out) :: ddx_data
41 real(dp),
intent(out) :: tol
42 real(dp),
allocatable,
intent(out) :: charges(:)
45 character(len=512) :: line, key, val, msg, probe, error_text
46 character(len=255) :: output_filename
47 integer :: unit, io_info, lineno, index_comment, index_splitting, &
49 integer :: nproc, model, lmax, ngrid, force, fmm, pm, pl, &
50 & matvecmem, maxiter, jacobi_ndiis, switching
51 real(dp) :: eps, se, eta, kappa
52 real(dp),
allocatable :: csph(:, :), radii(:)
53 logical :: in_atoms, have_model, have_eps, have_se
55 open(newunit=unit, file=fname, status=
"old", action=
"read", &
56 & form=
"formatted", iostat=io_info)
57 if (io_info .ne. 0)
then
58 call update_error(ddx_error,
"Cannot open input file " // &
63 read(unit,
"(a)", iostat=io_info) line
64 index_comment = scan(line,
"#!")
65 if (index_comment .gt. 0) line(index_comment:) =
" "
66 if (io_info .ne. 0)
exit
68 if (len_trim(line) .eq. 0 .or. line(1:1) .eq.
"#") cycle
72 if (io_info .eq. 0)
then
76 if (probe(k:k) .eq. achar(9) .or. probe(k:k) .eq.
"=") &
79 probe = adjustl(probe)
80 index_splitting = index(trim(probe),
" ")
82 if (index_splitting .eq. 0)
then
96 matvecmem = default_incore
98 maxiter = default_maxiter
99 jacobi_ndiis = default_jacobi_ndiis
100 force = default_force
101 fmm = default_enable_fmm
104 switching = default_switching
116 read(unit,
"(a)", iostat=io_info) line
117 if (io_info .ne. 0)
exit
119 index_comment = scan(line,
"#!")
120 if (index_comment .gt. 0) line(index_comment:) =
" "
122 if (line(k:k) .eq. achar(9)) line(k:k) =
" "
125 if (len_trim(line) .eq. 0) cycle
131 read(line, *, iostat=io_info) charges(natoms), &
132 & csph(1, natoms), csph(2, natoms), csph(3, natoms), &
134 if (io_info .ne. 0) &
135 & error_text =
"expected `charge x y z radius`"
137 index_splitting = scan(line,
" =")
138 if (index_splitting .eq. 0)
then
142 key = line(1:index_splitting-1)
143 val = adjustl(line(index_splitting+1:))
144 if (val(1:1) .eq.
"=") val = adjustl(val(2:))
146 do k = 1, len_trim(key)
147 if (key(k:k) .ge.
"A" .and. key(k:k) .le.
"Z") &
148 & key(k:k) = achar(iachar(key(k:k)) + 32)
152 case (
"output",
"logfile")
153 output_filename = trim(val)
155 read(val, *, iostat=io_info) nproc
157 do k = 1, len_trim(val)
158 if (val(k:k) .ge.
"A" .and. val(k:k) .le.
"Z") &
159 & val(k:k) = achar(iachar(val(k:k)) + 32)
161 select case (trim(val))
169 read(val, *, iostat=io_info) model
173 read(val, *, iostat=io_info) lmax
175 read(val, *, iostat=io_info) ngrid
177 read(val, *, iostat=io_info) eps
180 read(val, *, iostat=io_info) se
183 read(val, *, iostat=io_info) eta
185 read(val, *, iostat=io_info) kappa
186 case (
"matvecmem",
"incore")
187 read(val, *, iostat=io_info) matvecmem
189 read(val, *, iostat=io_info) tol
191 read(val, *, iostat=io_info) maxiter
192 case (
"jacobi_ndiis")
193 read(val, *, iostat=io_info) jacobi_ndiis
195 read(val, *, iostat=io_info) force
197 read(val, *, iostat=io_info) fmm
199 read(val, *, iostat=io_info) pm
201 read(val, *, iostat=io_info) pl
203 read(val, *, iostat=io_info) switching
205 read(val, *, iostat=io_info) nsph
206 if (io_info .eq. 0 .and. nsph .le. 0) &
207 & error_text =
"`nsph` must be positive"
209 if (nsph .le. 0)
then
210 error_text =
"`nsph` must be given before `atoms`"
212 allocate(charges(nsph), csph(3, nsph), radii(nsph))
216 error_text =
"unknown key `" // trim(key) //
"`"
218 if (io_info .ne. 0 .and. len_trim(error_text) .eq. 0) &
219 & error_text =
"invalid value for `" // trim(key) //
"`"
222 if (len_trim(error_text) .gt. 0)
then
223 write(msg,
"(a,a,i0,a,a)") trim(fname),
", line ", lineno, &
224 &
": ", trim(error_text)
225 call update_error(ddx_error, trim(msg))
229 if (in_atoms .and. natoms .eq. nsph)
exit
232 if (ddx_error % flag .ne. 0)
return
234 if (.not. have_model) &
235 &
call update_error(ddx_error,
"missing key `model`")
236 if (have_model .and. (model .lt. 1 .or. model .gt. 3)) &
237 &
call update_error(ddx_error,
"`model` must be cosmo," // &
238 &
" pcm, lpb or 1..3")
239 if (.not. have_eps) &
240 &
call update_error(ddx_error,
"missing key `eps`")
241 if (.not. in_atoms)
then
242 call update_error(ddx_error,
"missing `atoms` section")
243 else if (natoms .lt. nsph)
then
244 write(msg,
"(a,i0,a,i0,a)")
"`nsph` is ", nsph,
" but only ", &
245 & natoms,
" atom lines were found"
246 call update_error(ddx_error, trim(msg))
249 &
call update_error(ddx_error,
"`nproc` must be non-negative")
251 &
call update_error(ddx_error,
"`lmax` must be non-negative")
253 &
call update_error(ddx_error,
"`ngrid` must be non-negative")
254 if (have_eps .and. eps .lt. zero) &
255 &
call update_error(ddx_error,
"`eps` must be non-negative")
256 if (se .lt. -one .or. se .gt. one) &
257 &
call update_error(ddx_error,
"`se` must be in [-1, 1]")
258 if (eta .lt. zero .or. eta .gt. one) &
259 &
call update_error(ddx_error,
"`eta` must be in [0, 1]")
260 if (kappa .lt. zero) &
261 &
call update_error(ddx_error,
"`kappa` must be non-negative")
262 if (matvecmem .lt. 0 .or. matvecmem .gt. 1) &
263 &
call update_error(ddx_error,
"`matvecmem` must be 0 or 1")
264 if (tol .lt. 1d-14 .or. tol .gt. one) &
265 &
call update_error(ddx_error,
"`tol` must be in [1d-14, 1]")
266 if (maxiter .le. 0) &
267 &
call update_error(ddx_error,
"`maxiter` must be positive")
268 if (jacobi_ndiis .lt. 0) &
269 &
call update_error(ddx_error,
"`jacobi_ndiis` must be" // &
271 if (force .lt. 0 .or. force .gt. 1) &
272 &
call update_error(ddx_error,
"`force` must be 0 or 1")
273 if (fmm .lt. 0 .or. fmm .gt. 1) &
274 &
call update_error(ddx_error,
"`fmm` must be 0 or 1")
275 if (pm .lt. 0 .or. pl .lt. 0) &
276 &
call update_error(ddx_error,
"`pm` and `pl` must be" // &
278 if (ddx_error % flag .ne. 0)
return
281 if (.not.have_se) se = default_se(model)
283 radii = radii * tobohr
284 kappa = kappa / tobohr
285 call closest_supported_lebedev_grid(ngrid)
287 call ddinit(model, nsph, csph, radii, eps, ddx_data, ddx_error, &
288 & force=force, kappa=kappa, eta=eta, shift=se, lmax=lmax, &
289 & ngrid=ngrid, incore=matvecmem, maxiter=maxiter, &
290 & jacobi_ndiis=jacobi_ndiis, enable_fmm=fmm, pm=pm, pl=pl, &
291 & nproc=nproc, logfile=output_filename, switching=switching)
292 if (ddx_error % flag .ne. 0)
then
293 call update_error(ddx_error,
"ddinit returned an error," // &
311 character(len=*),
intent(in) :: fname
312 type(ddx_type),
intent(out) :: ddx_data
313 real(dp),
intent(out) :: tol
314 real(dp),
allocatable,
intent(out) :: charges(:)
317 integer :: nproc, model, lmax, ngrid, force, fmm, pm, pl, &
318 & nsph, i, matvecmem, maxiter, jacobi_ndiis, &
320 real(dp) :: eps, se, eta, kappa
321 real(dp),
allocatable :: csph(:, :), radii(:)
322 character(len=255) :: output_filename
324 write(6, *)
"Warning: the legacy input file is deprecated, not" // &
325 &
" every parameter can be set with it."
329 open(unit=100, file=fname, form=
"formatted", access=
"sequential")
331 read(100, *) output_filename
334 if(nproc .lt. 0)
then
335 call update_error(ddx_error,
"Error on the 2nd line of a config " // &
336 &
"file " // trim(fname) //
": `nproc` must be a positive " // &
341 if((model .lt. 1) .or. (model .gt. 3))
then
342 call update_error(ddx_error,
"Error on the 3rd line of a config file " // &
343 & trim(fname) //
": `model` must be an integer of a value " // &
349 call update_error(ddx_error,
"Error on the 4th line of a config file " // &
350 & trim(fname) //
": `lmax` must be a non-negative integer value.")
354 if(ngrid .lt. 0)
then
355 call update_error(ddx_error,
"Error on the 5th line of a config file " // &
356 & trim(fname) //
": `ngrid` must be a non-negative integer value.")
360 if(eps .lt. zero)
then
361 call update_error(ddx_error,
"Error on the 6th line of a config file " // &
362 & trim(fname) //
": `eps` must be a non-negative floating " // &
367 if((se .lt. -one) .or. (se .gt. one))
then
368 call update_error(ddx_error,
"Error on the 7th line of a config file " // &
369 & trim(fname) //
": `se` must be a floating point value in a " // &
374 if((eta .lt. zero) .or. (eta .gt. one))
then
375 call update_error(ddx_error,
"Error on the 8th line of a config file " // &
376 & trim(fname) //
": `eta` must be a floating point value " // &
377 &
"in a range [0, 1].")
381 if(kappa .lt. zero)
then
382 call update_error(ddx_error,
"Error on the 9th line of a config file " // &
383 & trim(fname) //
": `kappa` must be a non-negative floating " // &
388 read(100, *) matvecmem
389 if((matvecmem.lt. 0) .or. (matvecmem .gt. 1))
then
390 call update_error(ddx_error,
"Error on the 10th line of a config " // &
391 &
"file " // trim(fname) //
": `matvecmem` must be an " // &
392 &
"integer value of a value 0 or 1.")
396 if((tol .lt. 1d-14) .or. (tol .gt. one))
then
397 call update_error(ddx_error,
"Error on the 12th line of a config " // &
398 &
"file " // trim(fname) //
": `tol` must be a floating " // &
399 &
"point value in a range [1d-14, 1].")
403 if((maxiter .le. 0))
then
404 call update_error(ddx_error,
"Error on the 13th line of a config " // &
405 &
"file " // trim(fname) //
": `maxiter` must be a positive " // &
409 read(100, *) jacobi_ndiis
410 if((jacobi_ndiis .lt. 0))
then
411 call update_error(ddx_error,
"Error on the 14th line of a config " // &
412 &
"file " // trim(fname) //
": `jacobi_ndiis` must be a " // &
413 &
"non-negative integer value.")
417 if((force .lt. 0) .or. (force .gt. 1))
then
418 call update_error(ddx_error,
"Error on the 17th line of a config " // &
419 &
"file " // trim(fname) //
": `force` must be an integer " // &
420 "value of a value 0 or 1.")
424 if((fmm .lt. 0) .or. (fmm .gt. 1))
then
425 call update_error(ddx_error,
"Error on the 18th line of a config " // &
426 &
"file " // trim(fname) //
": `fmm` must be an integer " // &
427 &
"value of a value 0 or 1.")
432 call update_error(ddx_error,
"Error on the 19th line of a config " // &
433 &
"file " // trim(fname) //
": `pm` must be a non-negative " // &
439 call update_error(ddx_error,
"Error on the 20th line of a config " // &
440 &
"file " // trim(fname) //
": `pl` must be a non-negative " // &
446 call update_error(ddx_error,
"Error on the 21th line of a config " // &
447 &
"file " // trim(fname) //
": `nsph` must be a positive " // &
452 if (ddx_error % flag .ne. 0)
return
455 allocate(charges(nsph), csph(3, nsph), radii(nsph), stat=istatus)
456 if(istatus .ne. 0)
then
457 call update_error(ddx_error,
"Could not allocate space for " // &
458 &
"coordinates, radii and charges of atoms.")
462 read(100, *) charges(i), csph(1, i), csph(2, i), csph(3, i), radii(i)
468 radii = radii * tobohr
469 kappa = kappa / tobohr
472 call closest_supported_lebedev_grid(ngrid)
475 call ddinit(model, nsph, csph, radii, eps, ddx_data, ddx_error, &
476 & force=force, kappa=kappa, eta=eta, shift=se, lmax=lmax, &
477 & ngrid=ngrid, incore=matvecmem, maxiter=maxiter, &
478 & jacobi_ndiis=jacobi_ndiis, enable_fmm=fmm, pm=pm, pl=pl, &
479 & nproc=nproc, logfile=output_filename)
481 if (ddx_error % flag .ne. 0)
then
482 call update_error(ddx_error,
"ddinit returned an error, exiting")
486 deallocate(radii, csph, stat=istatus)
487 if(istatus .ne. 0)
then
488 call update_error(ddx_error,
"Could not deallocate space for " // &
489 &
"coordinates, radii and charges of atoms")
subroutine ddinit(model, nsph, coords, radii, eps, ddx_data, ddx_error, force, kappa, eta, shift, lmax, ngrid, incore, maxiter, jacobi_ndiis, enable_fmm, pm, pl, nproc, logfile, adjoint, eps_int, switching)
Wrapper to the initialization routine which supports optional arguments. This will make future mainte...
subroutine ddfromfile(fname, ddx_data, tol, charges, ddx_error)
Read the configuration from ddX input file and return a ddx_data structure.
subroutine ddfromfile_legacy(fname, ddx_data, tol, charges, ddx_error)
Read the configuration from ddX input file and return a ddx_data structure.
Module defining default parameters, for consistency between the various initialization routines.
Compile-time constants and definitions.
High-level module of the ddX software.
ddX type for containing ddx_error information