PartMC  2.6.1
util.F90
Go to the documentation of this file.
1 ! Copyright (C) 2005-2016 Nicole Riemer and Matthew West
2 ! Licensed under the GNU General Public License version 2 or (at your
3 ! option) any later version. See the file COPYING for details.
4 
5 !> \file
6 !> The pmc_util module.
7 
8 !> Common utility subroutines.
9 module pmc_util
10 
11  use pmc_constants
12 #ifdef PMC_USE_MPI
13  use mpi
14 #endif
15 #ifdef PMC_USE_C_SORT
16  use iso_c_binding
17 #endif
18 
19  !> Maximum number of IO units usable simultaneously.
20  integer, parameter :: max_units = 200
21  !> Minimum unit number to allocate.
22  integer, parameter :: unit_offset = 10
23  !> Table of unit numbers storing allocation status.
24  logical, save :: unit_used(max_units) = .false.
25 
26  !> Length of string for converting numbers.
27  integer, parameter :: pmc_util_convert_string_len = 100
28  !> Maximum length of filenames.
29  integer, parameter :: pmc_max_filename_len = 300
30 
31 contains
32 
33 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
34 
35  !> Prints a warning message.
36  subroutine warn_msg(code, warning_msg, already_warned)
37 
38  !> Status code to use.
39  integer, intent(in) :: code
40  !> Message to display.
41  character(len=*), intent(in) :: warning_msg
42  !> Flag to control warning only once (should be a save variable).
43  logical, intent(inout), optional :: already_warned
44 
45  if (present(already_warned)) then
46  if (already_warned) return
47  ! set already_warned so next time we will immediately return
48  already_warned = .true.
49  end if
50  write(0,'(a)') 'WARNING (PartMC-' // trim(integer_to_string(code)) &
51  // '): ' // trim(warning_msg)
52 
53  end subroutine warn_msg
54 
55 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
56 
57  !> Prints a warning message if condition_ok is false.
58  subroutine warn_assert_msg(code, condition_ok, warning_msg)
59 
60  !> Status code to use.
61  integer, intent(in) :: code
62  !> Whether the assertion is ok.
63  logical, intent(in) :: condition_ok
64  !> Message to display.
65  character(len=*), intent(in) :: warning_msg
66 
67  if (.not. condition_ok) then
68  call warn_msg(code, warning_msg)
69  end if
70 
71  end subroutine warn_assert_msg
72 
73 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
74 
75  !> Errors unless condition_ok is true.
76  subroutine assert_msg(code, condition_ok, error_msg)
77 
78  !> Status code to use if assertion fails.
79  integer, intent(in) :: code
80  !> Whether the assertion is ok.
81  logical, intent(in) :: condition_ok
82  !> Msg if assertion fails.
83  character(len=*), intent(in) :: error_msg
84 
85  integer :: ierr
86 
87  if (.not. condition_ok) then
88  write(0,'(a)') 'ERROR (PartMC-' // trim(integer_to_string(code)) &
89  // '): ' // trim(error_msg)
90 #ifdef PMC_USE_MPI
91  call mpi_abort(mpi_comm_world, code, ierr)
92 #else
93  stop 3
94 #endif
95  end if
96 
97  end subroutine assert_msg
98 
99 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100 
101  !> Errors unless condition_ok is true.
102  subroutine assert(code, condition_ok)
103 
104  !> Status code to use if assertion fails.
105  integer, intent(in) :: code
106  !> Whether the assertion is ok.
107  logical, intent(in) :: condition_ok
108 
109  if (.not. condition_ok) then
110  ! much faster with gfortran 4.4.5 to do this extra test
111  ! FIXME: is it still faster now that assert_msg doesn't
112  ! unconditionally construct a code_str?
113  call assert_msg(code, condition_ok, 'assertion failed')
114  end if
115 
116  end subroutine assert
117 
118 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119 
120  !> Error immediately.
121  subroutine die(code)
122 
123  !> Status code to use if assertion fails.
124  integer, intent(in) :: code
125 
126  call assert(code, .false.)
127 
128  end subroutine die
129 
130 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
131 
132  !> Error immediately.
133  subroutine die_msg(code, error_msg)
134 
135  !> Status code to use if assertion fails.
136  integer, intent(in) :: code
137  !> Msg if assertion fails.
138  character(len=*), intent(in) :: error_msg
139 
140  call assert_msg(code, .false., error_msg)
141 
142  end subroutine die_msg
143 
144 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
145 
146  !> Returns an available unit number. This should be freed by free_unit().
147  integer function get_unit()
148 
149  integer i
150  logical found_unit
151 
152  found_unit = .false.
153  do i = 1,max_units
154  if (.not. unit_used(i)) then
155  found_unit = .true.
156  exit
157  end if
158  end do
159  if (.not. found_unit) then
160  call die_msg(690355443, &
161  'no more units available - need to free_unit()')
162  end if
163  unit_used(i) = .true.
164  get_unit = i + unit_offset
165 
166  end function get_unit
167 
168 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
169 
170  !> Frees a unit number returned by get_unit().
171  subroutine free_unit(unit)
172 
173  integer, intent(in) :: unit
174 
175  unit_used(unit - unit_offset) = .false.
176 
177  end subroutine free_unit
178 
179 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
180 
181  !> Open a file for reading with an automatically assigned unit and
182  !> test that it succeeds. The file should be closed with
183  !> close_file().
184  subroutine open_file_read(filename, unit)
185 
186  !> Filename to open.
187  character(len=*), intent(in) :: filename
188  !> Unit assigned to file.
189  integer, intent(out) :: unit
190 
191  integer :: ios
192 
193  unit = get_unit()
194  open(unit=unit, file=filename, status='old', action='read', iostat=ios)
195  call assert_msg(544344918, ios == 0, 'unable to open file ' &
196  // trim(filename) // ' for reading: ' // integer_to_string(ios))
197 
198  end subroutine open_file_read
199 
200 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
201 
202  !> Open a file for writing with an automatically assigned unit and
203  !> test that it succeeds. The file should be closed with
204  !> close_file().
205  subroutine open_file_write(filename, unit)
206 
207  !> Filename to open.
208  character(len=*), intent(in) :: filename
209  !> Unit assigned to file.
210  integer, intent(out) :: unit
211 
212  integer :: ios
213 
214  unit = get_unit()
215  open(unit=unit, file=filename, status='replace', action='write', &
216  iostat=ios)
217  call assert_msg(609624199, ios == 0, 'unable to open file ' &
218  // trim(filename) // ' for writing: ' // integer_to_string(ios))
219 
220  end subroutine open_file_write
221 
222 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
223 
224  !> Close a file and de-assign the unit.
225  subroutine close_file(unit)
226 
227  !> Unit to close.
228  integer, intent(in) :: unit
229 
230  close(unit)
231  call free_unit(unit)
232 
233  end subroutine close_file
234 
235 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
236 
237  !> Convert mass-equivalent volume \f$V\f$ (m^3) to geometric radius
238  !> \f$R_{\rm geo}\f$ (m) for spherical particles.
239  real(kind=dp) elemental function sphere_vol2rad(v)
240 
241  !> Particle mass-equivalent volume (m^3).
242  real(kind=dp), intent(in) :: v
243 
244  sphere_vol2rad = (3d0 * v / 4d0 / const%pi)**(1d0 / 3d0)
245 
246  end function sphere_vol2rad
247 
248 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
249 
250  !> Convert radius (m) to diameter (m).
251  real(kind=dp) elemental function rad2diam(r)
252 
253  !> Radius (m).
254  real(kind=dp), intent(in) :: r
255 
256  rad2diam = 2d0 * r
257 
258  end function rad2diam
259 
260 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
261 
262  !> Convert geometric radius \f$R_{\rm geo}\f$ (m) to mass-equivalent volume
263  !> \f$V\f$ (m^3) for spherical particles.
264  real(kind=dp) elemental function sphere_rad2vol(r)
265 
266  !> Geometric radius (m).
267  real(kind=dp), intent(in) :: r
268 
269  sphere_rad2vol = 4d0 * const%pi * r**3 / 3d0
270 
271  end function sphere_rad2vol
272 
273 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
274 
275  !> Convert diameter (m) to radius (m).
276  real(kind=dp) elemental function diam2rad(d)
277 
278  !> Diameter (m).
279  real(kind=dp), intent(in) :: d
280 
281  diam2rad = d / 2d0
282 
283  end function diam2rad
284 
285 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
286 
287  !> Calculate air molecular mean free path \f$l\f$ (m).
288  real(kind=dp) function air_mean_free_path(temp, pressure)
289 
290  !> Temperature (K).
291  real(kind=dp), intent(in) :: temp
292  !> Pressure (Pa).
293  real(kind=dp), intent(in) :: pressure
294 
295  real(kind=dp) :: boltz, avogad, mwair, rgas, rhoair, viscosd, &
296  viscosk, gasspeed
297 
298  boltz = const%boltzmann
299  avogad = const%avagadro
300  mwair = const%air_molec_weight
301  rgas = const%univ_gas_const
302 
303  rhoair = (pressure * mwair) / (rgas * temp)
304 
305  viscosd = (1.8325d-5 * (296.16d0 + 120d0) / (temp + 120d0)) &
306  * (temp / 296.16d0)**1.5d0
307  viscosk = viscosd / rhoair
308  gasspeed = sqrt(8d0 * boltz * temp * avogad / (const%pi * mwair))
309  air_mean_free_path = 2d0 * viscosk / gasspeed
310 
311  end function air_mean_free_path
312 
313 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
314 
315  !> Tests whether two real numbers are almost equal using only a
316  !> relative tolerance.
317  logical function almost_equal(d1, d2)
318 
319  !> First number to compare.
320  real(kind=dp), intent(in) :: d1
321  !> Second number to compare.
322  real(kind=dp), intent(in) :: d2
323 
324  !> Relative tolerance.
325  real(kind=dp), parameter :: eps = 1d-8
326 
327  ! handle the 0.0 case
328  if (d1 .eq. d2) then
329  almost_equal = .true.
330  else
331  if (abs(d1 - d2) / (abs(d1) + abs(d2)) .lt. eps) then
332  almost_equal = .true.
333  else
334  almost_equal = .false.
335  end if
336  end if
337 
338  end function almost_equal
339 
340 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
341 
342  !> Tests whether two real numbers are almost equal using an
343  !> absolute and relative tolerance.
344  logical function almost_equal_abs(d1, d2, abs_tol)
345 
346  !> First number to compare.
347  real(kind=dp), intent(in) :: d1
348  !> Second number to compare.
349  real(kind=dp), intent(in) :: d2
350  !> Tolerance for when d1 equals d2.
351  real(kind=dp), intent(in) :: abs_tol
352 
353  !> Relative tolerance.
354  real(kind=dp), parameter :: eps = 1d-8
355 
356  ! handle the 0.0 case
357  if (d1 .eq. d2) then
358  almost_equal_abs = .true.
359  else
360  if ((abs(d1 - d2) .lt. abs_tol) .or. &
361  (abs(d1 - d2) / (abs(d1) + abs(d2)) .lt. eps)) then
362  almost_equal_abs = .true.
363  else
364  almost_equal_abs = .false.
365  end if
366  end if
367 
368  end function almost_equal_abs
369 
370 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
371 
372  !> Check that the first time interval is close to an integer
373  !> multiple of the second, and warn if it is not.
374  subroutine check_time_multiple(first_name, first_time, &
375  second_name, second_time)
376 
377  !> Name of the first time variable.
378  character(len=*), intent(in) :: first_name
379  !> First time variable (s).
380  real(kind=dp), intent(in) :: first_time
381  !> Name of the second time variable.
382  character(len=*), intent(in) :: second_name
383  !> Second time variable (s).
384  real(kind=dp), intent(in) :: second_time
385 
386  real(kind=dp) :: ratio
387 
388  ratio = first_time / second_time
389  if (abs(ratio - aint(ratio)) > 1d-6) then
390  call warn_msg(952299377, trim(first_name) &
391  // " is not an integer multiple of " // trim(second_name))
392  end if
393 
394  end subroutine check_time_multiple
395 
396 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
397 
398  !> Computes whether an event is scheduled to take place.
399  !!
400  !! The events should occur ideally at times 0, interval, 2*interval,
401  !! etc. The events are guaranteed to occur at least interval * (1 -
402  !! tolerance) apart, and if at least interval time has passed then
403  !! the next call is guaranteed to do the event. Otherwise the
404  !! timestep is used to guess whether to do the event.
405  subroutine check_event(time, timestep, interval, last_time, &
406  do_event)
407 
408  !> Current time.
409  real(kind=dp), intent(in) :: time
410  !> Estimate of the time to the next call.
411  real(kind=dp), intent(in) :: timestep
412  !> How often the event should be done.
413  real(kind=dp), intent(in) :: interval
414  !> When the event was last done.
415  real(kind=dp), intent(inout) :: last_time
416  !> Whether the event should be done.
417  logical, intent(out) :: do_event
418 
419  !> Fuzz for event occurance.
420  real(kind=dp), parameter :: tolerance = 1d-6
421 
422  real(kind=dp) closest_interval_time
423 
424  ! if we are at time 0 then do the event unconditionally
425  if (time .eq. 0d0) then
426  do_event = .true.
427  else
428  ! if we are too close to the last time then don't do it
429  if ((time - last_time) .lt. interval * (1d0 - tolerance)) then
430  do_event = .false.
431  else
432  ! if it's been too long since the last time then do it
433  if ((time - last_time) .ge. interval) then
434  do_event = .true.
435  else
436  ! gray area -- if we are closer than we will be next
437  ! time then do it
438  closest_interval_time = anint(time / interval) * interval
439  if (abs(time - closest_interval_time) &
440  .lt. abs(time + timestep - closest_interval_time)) &
441  then
442  do_event = .true.
443  else
444  do_event = .false.
445  end if
446  end if
447  end if
448  end if
449 
450  if (do_event) then
451  last_time = time
452  end if
453 
454  end subroutine check_event
455 
456 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
457 
458  !> Makes a linearly spaced array from min to max.
459  function linspace(min_x, max_x, n)
460 
461  !> Minimum array value.
462  real(kind=dp), intent(in) :: min_x
463  !> Maximum array value.
464  real(kind=dp), intent(in) :: max_x
465  !> Length of array to create.
466  integer, intent(in) :: n
467 
468  !> Return value.
469  real(kind=dp), allocatable :: linspace(:)
470 
471  integer :: i
472  real(kind=dp) :: a
473 
474  allocate(linspace(n))
475  call assert(999299119, n >= 0)
476  do i = 2, (n - 1)
477  a = real(i - 1, kind=dp) / real(n - 1, kind=dp)
478  linspace(i) = (1d0 - a) * min_x + a * max_x
479  end do
480  if (n > 0) then
481  ! make sure these values are exact
482  linspace(1) = min_x
483  linspace(n) = max_x
484  end if
485 
486  end function linspace
487 
488 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
489 
490  !> Makes a logarithmically spaced array of length n from min to max.
491  function logspace(min_x, max_x, n)
492 
493  !> Minimum array value.
494  real(kind=dp), intent(in) :: min_x
495  !> Maximum array value.
496  real(kind=dp), intent(in) :: max_x
497  !> Length of array to create.
498  integer, intent(in) :: n
499 
500  !> Return value.
501  real(kind=dp), allocatable :: logspace(:)
502 
503  real(kind=dp), allocatable :: log_x(:)
504 
505  allocate(logspace(n))
506 
507  call assert(804623592, n >= 0)
508  if (n == 0) return
509  call assert(548290438, min_x > 0d0)
510  call assert(805259035, max_x > 0d0)
511  log_x = linspace(log(min_x), log(max_x), n)
512  logspace = exp(log_x)
513  ! make sure these values are exact
514  logspace(1) = min_x
515  logspace(n) = max_x
516 
517  end function logspace
518 
519 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
520 
521  !> Find the position of a real number in a 1D linear array.
522  !!
523  !! If xa is the array allocated by linspace(min_x, max_x, xa) then i
524  !! = linspace_find(min_x, max_x, n, x) returns the index i
525  !! satisfying xa(i) <= x < xa(i+1) for min_x <= x < max_x. If x ==
526  !! max_x then i = n - 1. If x > max_x then i = n. If x < min_x then
527  !! i = 0. Thus 0 <= i <= n. Here n is the length of xa.
528  !!
529  !! This is equivalent to using find_1d() but much faster if the
530  !! array is linear.
531  integer function linspace_find(min_x, max_x, n, x)
532 
533  !> Minimum array value.
534  real(kind=dp), intent(in) :: min_x
535  !> Maximum array value.
536  real(kind=dp), intent(in) :: max_x
537  !> Number of entries.
538  integer, intent(in) :: n
539  !> Value.
540  real(kind=dp), intent(in) :: x
541 
542  if (x == max_x) then
543  linspace_find = n - 1
544  return
545  end if
546  linspace_find = floor((x - min_x) / (max_x - min_x) &
547  * real(n - 1, kind=dp)) + 1
548  linspace_find = min(linspace_find, n)
549  linspace_find = max(linspace_find, 0)
550 
551  end function linspace_find
552 
553 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
554 
555  !> Find the position of a real number in a 1D logarithmic array.
556  !!
557  !! If xa is the array allocated by logspace(min_x, max_x, xa) then i
558  !! = logspace_find(min_x, max_x, n, x) returns the index i
559  !! satisfying xa(i) <= x < xa(i+1) for min_x <= x < max_x. If x >=
560  !! max_x then i = n. If x < min_x then i = 0. Thus 0 <= i <=
561  !! n. Here n is the length of xa.
562  !!
563  !! This is equivalent to using find_1d() but much faster if the
564  !! array is logarithmic.
565  integer function logspace_find(min_x, max_x, n, x)
566 
567  !> Minimum array value.
568  real(kind=dp), intent(in) :: min_x
569  !> Maximum array value.
570  real(kind=dp), intent(in) :: max_x
571  !> Number of entries.
572  integer, intent(in) :: n
573  !> Value.
574  real(kind=dp), intent(in) :: x
575 
576  logspace_find = linspace_find(log(min_x), log(max_x), n, log(x))
577 
578  end function logspace_find
579 
580 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
581 
582  !> Find the position of a real number in an arbitrary 1D array.
583  !!
584  !! Takes an array of x_vals, and a single x value, and returns the
585  !! position p such that x_vals(p) <= x < x_vals(p+1). If p == 0 then
586  !! x < x_vals(1) and if p == n then x_vals(n) <= x. x_vals must be
587  !! sorted in increasing order.
588  !!
589  !! If the array is known to be linearly or logarithmically spaced
590  !! then linspace_find() or logspace_find() will be much faster.
591  integer function find_1d(n, x_vals, x)
592 
593  !> Number of values.
594  integer, intent(in) :: n
595  !> X value array, must be sorted.
596  real(kind=dp), intent(in) :: x_vals(n)
597  !> Value to interpolate at.
598  real(kind=dp), intent(in) :: x
599 
600  integer p
601 
602  if (n == 0) then
603  find_1d = 0
604  return
605  end if
606  p = 1
607  do while (x >= x_vals(p))
608  p = p + 1
609  if (p > n) then
610  exit
611  end if
612  end do
613  p = p - 1
614  find_1d = p
615 
616  end function find_1d
617 
618 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
619 
620  !> 1D linear interpolation.
621  !!
622  !! Takes an array of x and y, and a single x value, and returns the
623  !! corresponding y using linear interpolation. x_vals must be
624  !! sorted.
625  real(kind=dp) function interp_1d(x_vals, y_vals, x)
626 
627  !> X value array, must be sorted.
628  real(kind=dp), intent(in) :: x_vals(:)
629  !> Y value array.
630  real(kind=dp), intent(in) :: y_vals(size(x_vals))
631  !> Value to interpolate at.
632  real(kind=dp), intent(in) :: x
633 
634  integer :: n, p
635  real(kind=dp) :: y, alpha
636 
637  n = size(x_vals)
638  p = find_1d(n, x_vals, x)
639  if (p == 0) then
640  y = y_vals(1)
641  elseif (p == n) then
642  y = y_vals(n)
643  else
644  if (y_vals(p) == y_vals(p+1)) then
645  y = y_vals(p)
646  else
647  alpha = (x - x_vals(p)) / (x_vals(p+1) - x_vals(p))
648  y = (1d0 - alpha) * y_vals(p) + alpha * y_vals(p+1)
649  end if
650  end if
651  interp_1d = y
652 
653  end function interp_1d
654 
655 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
656 
657  !> Linear interpolation over discrete indices.
658  !!
659  !! Takes real values \c x_1 and \c x_n and integers \c n and \c i
660  !! and returns the linear interpolation so that \c x_1 is returned
661  !! when \c i = 1 and \c x_n is returned when \c i = \c n.
662  real(kind=dp) function interp_linear_disc(x_1, x_n, n, i)
663 
664  !> Value of \c x when \c i = 1.
665  real(kind=dp), intent(in) :: x_1
666  !> Value of \c x when \c i = n.
667  real(kind=dp), intent(in) :: x_n
668  !> Number of points to interpolate over.
669  integer, intent(in) :: n
670  !> Index to interpolate at.
671  integer, intent(in) :: i
672 
673  real(kind=dp) :: alpha
674 
675  if (x_1 == x_n) then
676  interp_linear_disc = x_1
677  else
678  alpha = real(i - 1, kind=dp) / real(n - 1, kind=dp)
679  interp_linear_disc = (1d0 - alpha) * x_1 + alpha * x_n
680  end if
681 
682  end function interp_linear_disc
683 
684 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
685 
686  !> Convert a string to an integer.
687  integer function string_to_integer(string)
688 
689  !> String to convert.
690  character(len=*), intent(in) :: string
691 
692  integer :: val
693  integer :: ios
694  character(len=len(string)+300) :: error_msg
695 
696  call assert_msg(447772570, len_trim(string) <= 20, &
697  'error converting "' // trim(string) &
698  // '" to integer: string too long')
699  read(string, '(i20)', iostat=ios) val
700  call assert_msg(895881873, ios == 0, &
701  'error converting "' // trim(string) &
702  // '" to integer: IOSTAT = ' // trim(integer_to_string(ios)))
703  string_to_integer = val
704 
705  end function string_to_integer
706 
707 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
708 
709  !> Convert a string to a real.
710  real(kind=dp) function string_to_real(string)
711 
712  !> String to convert.
713  character(len=*), intent(in) :: string
714 
715  real(kind=dp) :: val
716  integer :: ios
717  character(len=len(string)+300) :: error_msg
718 
719  call assert_msg(733728030, len_trim(string) <= 30, &
720  'error converting "' // trim(string) // '" to real: string too long')
721  read(string, '(f30.0)', iostat=ios) val
722  call assert_msg(727430097, ios == 0, &
723  'error converting "' // trim(string) &
724  // '" to real: IOSTAT = ' // trim(integer_to_string(ios)))
725  string_to_real = val
726 
727  end function string_to_real
728 
729 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
730 
731  !> Convert a string to a logical.
732  logical function string_to_logical(string)
733 
734  !> String to convert.
735  character(len=*), intent(in) :: string
736 
737  logical :: val
738  integer :: ios
739  character(len=len(string)+300) :: error_msg
740 
741  val = .false.
742  if ((trim(string) == 'yes') &
743  .or. (trim(string) == 'y') &
744  .or. (trim(string) == 'true') &
745  .or. (trim(string) == 't') &
746  .or. (trim(string) == '1')) then
747  val = .true.
748  elseif ((trim(string) == 'no') &
749  .or. (trim(string) == 'n') &
750  .or. (trim(string) == 'false') &
751  .or. (trim(string) == 'f') &
752  .or. (trim(string) == '0')) then
753  val = .false.
754  else
755  call die_msg(985010153, 'error converting "' // trim(string) &
756  // '" to logical')
757  end if
758  string_to_logical = val
759 
760  end function string_to_logical
761 
762 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
763 
764  !> Convert an integer to a string format.
765  character(len=PMC_UTIL_CONVERT_STRING_LEN) function integer_to_string(val)
766 
767  !> Value to convert.
768  integer, intent(in) :: val
769 
770  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
771 
772  ret_val = ""
773  write(ret_val, '(i30)') val
774  integer_to_string = adjustl(ret_val)
775 
776  end function integer_to_string
777 
778 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
779 
780  !> Convert a real to a string format.
781  character(len=PMC_UTIL_CONVERT_STRING_LEN) function real_to_string(val)
782 
783  !> Value to convert.
784  real(kind=dp), intent(in) :: val
785 
786  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
787 
788  ret_val = ""
789  write(ret_val, '(g30.20)') val
790  real_to_string = adjustl(ret_val)
791 
792  end function real_to_string
793 
794 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
795 
796  !> Convert a logical to a string format.
797  character(len=PMC_UTIL_CONVERT_STRING_LEN) function logical_to_string(val)
798 
799  !> Value to convert.
800  logical, intent(in) :: val
801 
802  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
803 
804  ret_val = ""
805  if (val) then
806  ret_val = "TRUE"
807  else
808  ret_val = "FALSE"
809  end if
810  logical_to_string = ret_val
811 
812  end function logical_to_string
813 
814 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
815 
816  !> Convert a complex to a string format.
817  character(len=PMC_UTIL_CONVERT_STRING_LEN) function complex_to_string(val)
818 
819  !> Value to convert.
820  complex(kind=dc), intent(in) :: val
821 
822  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
823 
824  ret_val = ""
825  ret_val = "(" // trim(real_to_string(real(val))) &
826  // ", " // trim(real_to_string(aimag(val))) // ")"
827  complex_to_string = adjustl(ret_val)
828 
829  end function complex_to_string
830 
831 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
832 
833  !> Convert an integer to a string format of maximum length.
834  character(len=PMC_UTIL_CONVERT_STRING_LEN) &
835  function integer_to_string_max_len(val, max_len)
836 
837  !> Value to convert.
838  integer, intent(in) :: val
839  !> Maximum length of resulting string.
840  integer, intent(in) :: max_len
841 
842  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
843 
844  ret_val = integer_to_string(val)
845  if (len_trim(ret_val) > max_len) then
846  ret_val = real_to_string_max_len(real(val, kind=dp), max_len)
847  end if
848  integer_to_string_max_len = adjustl(ret_val)
849 
850  end function integer_to_string_max_len
851 
852 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
853 
854  !> Convert a real to a string format of maximum length.
855  character(len=PMC_UTIL_CONVERT_STRING_LEN) &
856  function real_to_string_max_len(val, max_len)
857 
858  !> Value to convert.
859  real(kind=dp), intent(in) :: val
860  !> Maximum length of resulting string.
861  integer, intent(in) :: max_len
862 
863  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val, exp_str, frac_str
864  integer :: exp_val, exp_len, frac_len, use_frac_len, min_frac_len, i
865  real(kind=dp) :: frac_val
866 
867  ret_val = ""
868  if (val == 0d0) then
869  if (max_len >= 3) then
870  ret_val = "0e0"
871  else
872  do i = 1,max_len
873  ret_val(i:i) = "*"
874  end do
875  end if
876  real_to_string_max_len = adjustl(ret_val)
877  return
878  end if
879 
880  exp_val = floor(log10(abs(val)))
881  frac_val = val / 10d0**exp_val
882  exp_str = integer_to_string(exp_val)
883  frac_str = real_to_string(frac_val)
884 
885  exp_len = len_trim(exp_str)
886  frac_len = len_trim(frac_str)
887  use_frac_len = max_len - 1 - exp_len
888  if (use_frac_len > frac_len) then
889  use_frac_len = frac_len
890  end if
891  if (val < 0d0) then
892  min_frac_len = 2
893  else
894  min_frac_len = 1
895  end if
896  if (use_frac_len < min_frac_len) then
897  do i = 1,max_len
898  ret_val(i:i) = "*"
899  end do
900  else
901  ret_val = frac_str(1:use_frac_len) // "e" // trim(exp_str)
902  end if
903  real_to_string_max_len = adjustl(ret_val)
904 
905  end function real_to_string_max_len
906 
907 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
908 
909  !> Convert a time to a string format of maximum length.
910  character(len=PMC_UTIL_CONVERT_STRING_LEN) &
911  function time_to_string_max_len(time, max_len)
912 
913  !> Time to convert (s).
914  real(kind=dp), intent(in) :: time
915  !> Maximum length of resulting string.
916  integer, intent(in) :: max_len
917 
918  integer, dimension(4), parameter :: scale = (/ 1, 60, 60, 24 /)
919  character, dimension(4), parameter :: unit = (/ "s", "m", "h", "d" /)
920 
921  character(len=PMC_UTIL_CONVERT_STRING_LEN) :: ret_val
922  integer :: i
923  logical :: len_ok
924  real(kind=dp) :: scaled_time
925 
926  scaled_time = time
927  len_ok = .false.
928  do i = 1,4
929  scaled_time = scaled_time / real(scale(i), kind=dp)
930  ret_val = trim(integer_to_string(nint(scaled_time))) // unit(i)
931  if (len_trim(ret_val) <= max_len) then
932  len_ok = .true.
933  exit
934  end if
935  end do
936  if (.not. len_ok) then
937  ret_val = ""
938  do i = 1,max_len
939  ret_val(i:i) = "*"
940  end do
941  end if
942  time_to_string_max_len = adjustl(ret_val)
943 
944  end function time_to_string_max_len
945 
946 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
947 
948  !> Convert a real-valued vector into an integer-valued vector.
949  !!
950  !! Use n_samp samples. Returns discrete vector whose relative entry
951  !! sizes are \f$ \ell_1 \f$ closest to the continuous vector.
952  subroutine vec_cts_to_disc(n, vec_cts, n_samp, vec_disc)
953 
954  !> Number of entries in vectors.
955  integer, intent(in) :: n
956  !> Continuous vector.
957  real(kind=dp), intent(in) :: vec_cts(n)
958  !> Number of discrete samples to use.
959  integer, intent(in) :: n_samp
960  !> Discretized vector.
961  integer, intent(out) :: vec_disc(n)
962 
963  integer :: k(1)
964  real(kind=dp) :: vec_tot
965 
966  vec_tot = sum(vec_cts)
967 
968  ! assign a best guess for each bin independently
969  vec_disc = nint(vec_cts / vec_tot * real(n_samp, kind=dp))
970 
971  ! if we have too few particles then add more
972  do while (sum(vec_disc) < n_samp)
973  k = minloc(abs(real(vec_disc + 1, kind=dp) - vec_cts) &
974  - abs(real(vec_disc, kind=dp) - vec_cts))
975  vec_disc(k) = vec_disc(k) + 1
976  end do
977 
978  ! if we have too many particles then remove some
979  do while (sum(vec_disc) > n_samp)
980  k = minloc(abs(real(vec_disc - 1, kind=dp) - vec_cts) &
981  - abs(real(vec_disc, kind=dp) - vec_cts))
982  vec_disc(k) = vec_disc(k) - 1
983  end do
984 
985  call assert_msg(323412496, sum(vec_disc) == n_samp, &
986  'generated incorrect number of samples')
987 
988  end subroutine vec_cts_to_disc
989 
990 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
991 
992  !> Computes the average of an array of integer numbers.
993  subroutine average_integer(int_vec, int_avg)
994 
995  !> Array of integer numbers.
996  integer, intent(in) :: int_vec(:)
997  !> Average of int_vec.
998  integer, intent(out) :: int_avg
999 
1000  int_avg = sum(int_vec) / size(int_vec)
1001 
1002  end subroutine average_integer
1003 
1004 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1005 
1006  !> Computes the average of an array of real numbers.
1007  subroutine average_real(real_vec, real_avg)
1008 
1009  !> Array of real numbers.
1010  real(kind=dp), intent(in) :: real_vec(:)
1011  !> Average of real_vec.
1012  real(kind=dp), intent(out) :: real_avg
1013 
1014  real_avg = sum(real_vec) / real(size(real_vec), kind=dp)
1015 
1016  end subroutine average_real
1017 
1018 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1019 
1020  !> Return the index of the first occurance of the given value in the
1021  !> array, or 0 if it is not present.
1022  integer function string_array_find(array, val)
1023 
1024  !> Array of values.
1025  character(len=*), intent(in) :: array(:)
1026  !> Value to find.
1027  character(len=*), intent(in) :: val
1028 
1029  do string_array_find = 1,size(array)
1030  if (trim(array(string_array_find)) == trim(val)) return
1031  end do
1032  string_array_find = 0
1033 
1034  end function string_array_find
1035 
1036 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1037 
1038  !> Allocate or reallocate the given array to ensure it is of the
1039  !> given size, preserving any data and/or initializing to 0.
1040  subroutine ensure_real_array_size(x, n, only_grow)
1041 
1042  !> Array of real numbers.
1043  real(kind=dp), intent(inout), allocatable :: x(:)
1044  !> Desired size of array.
1045  integer, intent(in) :: n
1046  !> Whether to only increase the array size (default .true.).
1047  logical, intent(in), optional :: only_grow
1048 
1049  integer :: new_n
1050  real(kind=dp), allocatable :: tmp_x(:)
1051 
1052  if (allocated(x)) then
1053  new_n = n
1054  if (present(only_grow)) then
1055  new_n = max(new_n, size(x))
1056  end if
1057  if (size(x) /= new_n) then
1058  allocate(tmp_x(new_n))
1059  tmp_x = 0d0
1060  tmp_x(1:min(new_n, size(x))) = x(1:min(new_n, size(x)))
1061  call move_alloc(tmp_x, x)
1062  end if
1063  else
1064  allocate(x(n))
1065  x = 0d0
1066  end if
1067 
1068  end subroutine ensure_real_array_size
1069 
1070 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1071 
1072  !> Allocate or reallocate the given array to ensure it is of the
1073  !> given size, preserving any data and/or initializing to 0.
1074  subroutine ensure_real_array_2d_size(x, n1, n2, only_grow)
1075 
1076  !> Array of real numbers.
1077  real(kind=dp), intent(inout), allocatable :: x(:, :)
1078  !> Desired first size of array.
1079  integer, intent(in) :: n1
1080  !> Desired second size of array.
1081  integer, intent(in) :: n2
1082  !> Whether to only increase the array size (default .true.).
1083  logical, intent(in), optional :: only_grow
1084 
1085  integer :: new_n1, new_n2, n1_min, n2_min
1086  real(kind=dp), allocatable :: tmp_x(:, :)
1087 
1088  if (allocated(x)) then
1089  new_n1 = n1
1090  new_n2 = n2
1091  if (present(only_grow)) then
1092  new_n1 = max(new_n1, size(x, 1))
1093  new_n2 = max(new_n2, size(x, 2))
1094  end if
1095  if ((size(x, 1) /= new_n1) .or. (size(x, 2) /= new_n2)) then
1096  allocate(tmp_x(new_n1, new_n2))
1097  n1_min = min(new_n1, size(x, 1))
1098  n2_min = min(new_n2, size(x, 2))
1099  tmp_x = 0d0
1100  tmp_x(1:n1_min, 1:n2_min) = x(1:n1_min, 1:n2_min)
1101  call move_alloc(tmp_x, x)
1102  end if
1103  else
1104  allocate(x(n1, n2))
1105  x = 0d0
1106  end if
1107 
1108  end subroutine ensure_real_array_2d_size
1109 
1110 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1111 
1112  !> Allocate or reallocate the given array to ensure it is of the
1113  !> given size, preserving any data and/or initializing to 0.
1114  subroutine ensure_integer_array_size(x, n, only_grow)
1115 
1116  !> Array of integer numbers.
1117  integer, intent(inout), allocatable :: x(:)
1118  !> Desired size of array.
1119  integer, intent(in) :: n
1120  !> Whether to only increase the array size (default .true.).
1121  logical, intent(in), optional :: only_grow
1122 
1123  integer :: new_n
1124  integer, allocatable :: tmp_x(:)
1125 
1126  if (allocated(x)) then
1127  new_n = n
1128  if (present(only_grow)) then
1129  new_n = max(new_n, size(x))
1130  end if
1131  if (size(x) /= new_n) then
1132  allocate(tmp_x(new_n))
1133  tmp_x = 0
1134  tmp_x(1:min(new_n, size(x))) = x(1:min(new_n, size(x)))
1135  call move_alloc(tmp_x, x)
1136  end if
1137  else
1138  allocate(x(n))
1139  x = 0
1140  end if
1141 
1142  end subroutine ensure_integer_array_size
1143 
1144 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1145 
1146  !> Allocate or reallocate the given array to ensure it is of the
1147  !> given size, preserving any data and/or initializing to 0.
1148  subroutine ensure_integer_array_2d_size(x, n1, n2, only_grow)
1149 
1150  !> Array of integer numbers.
1151  integer, intent(inout), allocatable :: x(:, :)
1152  !> Desired first size of array.
1153  integer, intent(in) :: n1
1154  !> Desired second size of array.
1155  integer, intent(in) :: n2
1156  !> Whether to only increase the array size (default .true.).
1157  logical, intent(in), optional :: only_grow
1158 
1159  integer :: new_n1, new_n2, n1_min, n2_min
1160  integer, allocatable :: tmp_x(:, :)
1161 
1162  if (allocated(x)) then
1163  new_n1 = n1
1164  new_n2 = n2
1165  if (present(only_grow)) then
1166  new_n1 = max(new_n1, size(x, 1))
1167  new_n2 = max(new_n2, size(x, 2))
1168  end if
1169  if ((size(x, 1) /= new_n1) .or. (size(x, 2) /= new_n2)) then
1170  allocate(tmp_x(new_n1, new_n2))
1171  n1_min = min(new_n1, size(x, 1))
1172  n2_min = min(new_n2, size(x, 2))
1173  tmp_x = 0
1174  tmp_x(1:n1_min, 1:n2_min) = x(1:n1_min, 1:n2_min)
1175  call move_alloc(tmp_x, x)
1176  end if
1177  else
1178  allocate(x(n1, n2))
1179  x = 0
1180  end if
1181 
1182  end subroutine ensure_integer_array_2d_size
1183 
1184 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1185 
1186  !> Allocate or reallocate the given array to ensure it is of the
1187  !> given size, without preserving data.
1188  subroutine ensure_string_array_size(x, n)
1189 
1190  !> Array of strings numbers.
1191  character(len=*), intent(inout), allocatable :: x(:)
1192  !> Desired size of array.
1193  integer, intent(in) :: n
1194 
1195  if (allocated(x)) then
1196  if (size(x) /= n) then
1197  deallocate(x)
1198  allocate(x(n))
1199  end if
1200  else
1201  allocate(x(n))
1202  end if
1203 
1204  end subroutine ensure_string_array_size
1205 
1206 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1207 
1208  !> Strip the extension to find the basename.
1209  !!
1210  !! The filename is assumed to be of the form basename.extension,
1211  !! where extension contains no periods. If there is no period in
1212  !! filename then basename is the whole filename.
1213  subroutine get_basename(filename, basename)
1214 
1215  !> Full filename.
1216  character(len=*), intent(in) :: filename
1217  !> Basename.
1218  character(len=*), intent(out) :: basename
1219 
1220  integer :: i
1221  logical :: found_period
1222 
1223  basename = filename
1224  i = len_trim(basename)
1225  found_period = .false.
1226  do while ((i > 0) .and. (.not. found_period))
1227  ! Fortran .and. does not short-circuit, so we can't do the
1228  ! obvious do while ((i > 0) .and. (basename(i:i) /= ".")),
1229  ! instead we have to use this hack with the found_period
1230  ! logical variable.
1231  if (basename(i:i) == ".") then
1232  found_period = .true.
1233  else
1234  i = i - 1
1235  end if
1236  end do
1237  if (i > 0) then
1238  basename(i:) = ""
1239  end if
1240 
1241  end subroutine get_basename
1242 
1243 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1244 
1245  !> Current date and time in ISO 8601 format.
1246  subroutine iso8601_date_and_time(date_time)
1247 
1248  !> Result string.
1249  character(len=*), intent(out) :: date_time
1250 
1251  character(len=10) :: date, time, zone
1252 
1253  call assert_msg(893219839, len(date_time) >= 29, &
1254  "date_time string must have length at least 29")
1255  call date_and_time(date, time, zone)
1256  date_time = ""
1257  write(date_time, '(14a)') date(1:4), "-", date(5:6), "-", &
1258  date(7:8), "T", time(1:2), ":", time(3:4), ":", &
1259  time(5:10), zone(1:3), ":", zone(4:5)
1260 
1261  end subroutine iso8601_date_and_time
1262 
1263 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1264 
1265  !> Convert degrees to radians.
1266  real(kind=dp) function deg2rad(deg)
1267 
1268  !> Input degrees.
1269  real(kind=dp), intent(in) :: deg
1270 
1271  deg2rad = deg / 180d0 * const%pi
1272 
1273  end function deg2rad
1274 
1275 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1276 
1277  !> Convert radians to degrees.
1278  real(kind=dp) function rad2deg(rad)
1279 
1280  !> Input radians.
1281  real(kind=dp), intent(in) :: rad
1282 
1283  rad2deg = rad / const%pi * 180d0
1284 
1285  end function rad2deg
1286 
1287 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1288 
1289  !> Sort the given data array and return the permutation defining the sort.
1290  !!
1291  !! If \c data is the original data array, \c new_data is the sorted
1292  !! value of data, and \c perm is the returned permutation, then
1293  !! <tt>new_data(i) = data(perm(i))</tt>.
1294  subroutine integer_sort(data, perm)
1295 
1296  !> Data array to sort, sorted on exit.
1297  integer, intent(inout) :: data(:)
1298  !> Permutation defining the sort: <tt>new_data(i) = data(perm(i))</tt>.
1299  integer, intent(out) :: perm(size(data))
1300 
1301 #ifdef PMC_USE_C_SORT
1302  integer(kind=c_int) :: n_c
1303  integer(kind=c_int), target :: data_c(size(data))
1304  integer(kind=c_int), target :: perm_c(size(data))
1305  type(c_ptr) :: data_ptr, perm_ptr
1306 
1307 #ifndef DOXYGEN_SKIP_DOC
1308  interface
1309  subroutine integer_sort_c(n_c, data_ptr, perm_ptr) bind(c)
1310  use iso_c_binding
1311  integer(kind=c_int), value :: n_c
1312  type(c_ptr), value :: data_ptr, perm_ptr
1313  end subroutine integer_sort_c
1314  end interface
1315 #endif
1316 
1317  data_c = int(data, kind=c_int)
1318  perm_c = 0_c_int
1319  n_c = int(size(data), kind=c_int)
1320  data_ptr = c_loc(data_c)
1321  perm_ptr = c_loc(perm_c)
1322  call integer_sort_c(n_c, data_ptr, perm_ptr)
1323  data = int(data_c)
1324  perm = int(perm_c)
1325 #endif
1326 
1327  end subroutine integer_sort
1328 
1329 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1330 
1331  !> Load a real array from a text file.
1332  subroutine loadtxt(filename, data)
1333 
1334  !> Filename to read from.
1335  character(len=*), intent(in) :: filename
1336  !> Array to store data in.
1337  real(kind=dp), intent(inout), allocatable :: data(:,:)
1338 
1339  integer :: unit, row, col
1340  logical :: eol, eof
1341  character(len=1000) :: word
1342 
1343  deallocate(data)
1344  allocate(data(1,0))
1345  call open_file_read(filename, unit)
1346 
1347  eof = .false.
1348  row = 1
1349  col = 1
1350  do while (.not. eof)
1351  call read_word_raw(unit, word, eol, eof)
1352  if (len_trim(word) > 0) then
1353  if (row == 1) then
1354  if (col > size(data, 2)) then
1355  call reallocate_real_array2d(data, 1, 2 * col)
1356  end if
1357  else
1358  if (col > size(data, 2)) then
1359  call assert_msg(516120334, col <= size(data, 2), &
1360  trim(filename) // ": line " &
1361  // trim(integer_to_string(row)) // " too long")
1362  end if
1363  end if
1364  if (row > size(data, 1)) then
1365  call reallocate_real_array2d(data, 2 * row, size(data, 2))
1366  end if
1367  data(row, col) = string_to_real(word)
1368  col = col + 1
1369  end if
1370  if (eol .or. eof) then
1371  if (row == 1) then
1372  call reallocate_real_array2d(data, 1, col - 1)
1373  else
1374  call assert_msg(266924956, &
1375  (col == 1) .or. (col == size(data, 2) + 1), &
1376  trim(filename) // ": line " &
1377  // trim(integer_to_string(row)) // " too short")
1378  end if
1379  end if
1380  if (eol) then
1381  row = row + 1
1382  col = 1
1383  end if
1384  end do
1385 
1386  if (col == 1) then
1387  call reallocate_real_array2d(data, row - 1, size(data, 2))
1388  end if
1389  call close_file(unit)
1390 
1391  end subroutine loadtxt
1392 
1393 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1394 
1395  !> Write a real 1D array to a text file.
1396  subroutine savetxt_1d(filename, data)
1397 
1398  !> Filename to write to.
1399  character(len=*), intent(in) :: filename
1400  !> Array of data to write.
1401  real(kind=dp), intent(in) :: data(:)
1402 
1403  integer :: unit, i
1404 
1405  call open_file_write(filename, unit)
1406  do i = 1,size(data)
1407  write(unit, '(e30.15e3)') data(i)
1408  end do
1409  call close_file(unit)
1410 
1411  end subroutine savetxt_1d
1412 
1413 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1414 
1415  !> Write a real 2D array to a text file.
1416  subroutine savetxt_2d(filename, data)
1417 
1418  !> Filename to write to.
1419  character(len=*), intent(in) :: filename
1420  !> Array of data to write.
1421  real(kind=dp), intent(in) :: data(:,:)
1422 
1423  integer :: unit, i, j
1424 
1425  call open_file_write(filename, unit)
1426  do i = 1,size(data, 1)
1427  do j = 1,size(data, 2)
1428  write(unit, '(e30.15e3)', advance='no') data(i, j)
1429  end do
1430  write(unit, *) ''
1431  end do
1432  call close_file(unit)
1433 
1434  end subroutine savetxt_2d
1435 
1436 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1437 
1438  !> Reallocate a 2D real array to the given size, preserving the contents.
1439  subroutine reallocate_real_array2d(data, rows, cols)
1440 
1441  !> Array to reallocate.
1442  real(kind=dp), allocatable, intent(inout) :: data(:,:)
1443  !> New leading dimension.
1444  integer, intent(in) :: rows
1445  !> New trailing dimension.
1446  integer, intent(in) :: cols
1447 
1448  real(kind=dp) :: tmp_data(rows, cols)
1449  integer :: data_rows, data_cols
1450 
1451  data_rows = min(rows, size(data, 1))
1452  data_cols = min(cols, size(data, 2))
1453  tmp_data(1:data_rows, 1:data_cols) = data(1:data_rows, 1:data_cols)
1454  deallocate(data)
1455  allocate(data(rows, cols))
1456  data(1:data_rows, 1:data_cols) = tmp_data(1:data_rows, 1:data_cols)
1457 
1458  end subroutine reallocate_real_array2d
1459 
1460 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1461 
1462  !> Read a single character from a file, signaling if we have hit
1463  !> end-of-line (EOL) or end-of-file (EOF). If EOL or EOF are true
1464  !> then the character value should be ignored.
1465  !!
1466  !! Testing with gfortran 4.5.3 and different length files shows:
1467  !!
1468  !! Empty file (total file length 0):
1469  !! * eol = .false., eof = .true.
1470  !! * subsequent calls error
1471  !!
1472  !! File containing a single 'A' character (total file length 1):
1473  !! * char = 'A', eol = .false., eof = .false.
1474  !! * eol = .false., eof = .true.
1475  !! * subsequent calls error
1476  !!
1477  !! File containing a single newline '\n' (total file length 1):
1478  !! * eol = .true., eof = .false.
1479  !! * eol = .false., eof = .true.
1480  !! * subsequent calls error
1481  !!
1482  !! File containing a character and newline 'A\n' (total file length 2):
1483  !! * char = 'A', eol = .false., eof = .false.
1484  !! * eol = .true., eof = .false.
1485  !! * eol = .false., eof = .true.
1486  !! * subsequent calls error
1487  subroutine read_char_raw(unit, char, eol, eof)
1488 
1489  !> Unit number to read from.
1490  integer, intent(in) :: unit
1491  !> Character read.
1492  character, intent(out) :: char
1493  !> True if at EOL (end of line).
1494  logical, intent(out) :: eol
1495  !> True if at EOF (end of file).
1496  logical, intent(out) :: eof
1497 
1498  integer :: ios, n_read
1499  character(len=1) :: read_char
1500 
1501  eol = .false.
1502  eof = .false.
1503  char = " " ! shut up uninitialized variable warnings
1504  read_char = "" ! needed for pgf95 for reading blank lines
1505  read(unit=unit, fmt='(a)', advance='no', end=100, eor=110, &
1506  iostat=ios) read_char
1507  if (ios /= 0) then
1508  write(0,*) 'ERROR: reading file: IOSTAT = ', ios
1509  stop 2
1510  end if
1511  ! only reach here if we didn't hit end-of-record (end-of-line) in
1512  ! the above read
1513  char = read_char
1514  goto 120
1515 
1516 100 eof = .true. ! goto here if end-of-file was encountered immediately
1517  goto 120
1518 
1519 110 eol = .true. ! goto here if end-of-record, meaning end-of-line
1520 
1521 120 return
1522 
1523  end subroutine read_char_raw
1524 
1525 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1526 
1527  !> Read a white-space delimited word from a file, signaling if we
1528  !> have EOL or EOF. If EOL or EOF are true then the word will still
1529  !> be meaningful data. If there was no data to be read then
1530  !> len(word) will be 0.
1531  subroutine read_word_raw(unit, word, eol, eof)
1532 
1533  !> Unit number to read from.
1534  integer, intent(in) :: unit
1535  !> Word read.
1536  character(len=*), intent(out) :: word
1537  !> True if at EOL (end of line).
1538  logical, intent(out) :: eol
1539  !> True if at EOF (end of file).
1540  logical, intent(out) :: eof
1541 
1542  integer :: i
1543  character :: char
1544 
1545  word = ""
1546 
1547  ! skip over spaces
1548  call read_char_raw(unit, char, eol, eof)
1549  do while (((ichar(char) == 9) .or. (ichar(char) == 32)) &
1550  .and. (.not. eol) .and. (.not. eof))
1551  call read_char_raw(unit, char, eol, eof)
1552  end do
1553  if (eol .or. eof) return
1554 
1555  ! char is now the first word character
1556  i = 1
1557  word(i:i) = char
1558  call read_char_raw(unit, char, eol, eof)
1559  do while ((ichar(char) /= 9) .and. (ichar(char) /= 32) &
1560  .and. (.not. eol) .and. (.not. eof) .and. (i < len(word)))
1561  i = i + 1
1562  word(i:i) = char
1563  if (i < len(word)) then
1564  call read_char_raw(unit, char, eol, eof)
1565  end if
1566  end do
1567 
1568  end subroutine read_word_raw
1569 
1570 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1571 
1572  !> Checks whether a string starts with a given other string.
1573  !!
1574  !! <tt>starts_with(A, B)</tt> returns \c true if string \c A starts
1575  !! with string \c B.
1576  logical function starts_with(string, start_string)
1577 
1578  !> String to test.
1579  character(len=*), intent(in) :: string
1580  !> Starting string.
1581  character(len=*), intent(in) :: start_string
1582 
1583  if (len(string) < len(start_string)) then
1584  starts_with = .false.
1585  return
1586  end if
1587  if (string(1:len(start_string)) == start_string) then
1588  starts_with = .true.
1589  else
1590  starts_with = .false.
1591  end if
1592 
1593  end function starts_with
1594 
1595 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1596 
1597  !> Compute the harmonic mean of two numbers.
1598  elemental real(kind=dp) function harmonic_mean(x1, x2)
1599 
1600  !> First number to average.
1601  real(kind=dp), intent(in) :: x1
1602  !> Second number to average.
1603  real(kind=dp), intent(in) :: x2
1604 
1605  harmonic_mean = 1d0 / (1d0 / x1 + 1d0 / x2)
1606 
1607  end function harmonic_mean
1608 
1609 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1610 
1611  !> Compute \f$ - p \ln p\f$ for computing entropy.
1612  elemental real(kind=dp) function nplogp(p)
1613 
1614  !> Probability \f$p\f$.
1615  real(kind=dp), intent(in) :: p
1616 
1617  if (p <= 0d0) then
1618  nplogp = 0d0
1619  else
1620  nplogp = - p * log(p)
1621  end if
1622 
1623  end function nplogp
1624 
1625 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1626 
1627  !> Compute the entropy of a probability mass function (non
1628  !> necessarily normalized).
1629  real(kind=dp) function entropy(p)
1630 
1631  !> Probability mass function, will be normalized before use.
1632  real(kind=dp), intent(in) :: p(:)
1633 
1634  entropy = sum(nplogp(p / sum(p)))
1635 
1636  end function entropy
1637 
1638 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1639 
1640  !> Return the least power-of-2 that is at least equal to n.
1641  integer function pow2_above(n)
1642 
1643  !> Lower bound on the power of 2.
1644  integer, intent(in) :: n
1645 
1646  if (n <= 0) then
1647  pow2_above = 0
1648  return
1649  end if
1650 
1651  ! LEADZ is in Fortran 2008
1652  pow2_above = ibset(0, bit_size(n) - leadz(n - 1))
1653 
1654  end function pow2_above
1655 
1656 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1657 
1658 end module pmc_util
pmc_util::open_file_read
subroutine open_file_read(filename, unit)
Open a file for reading with an automatically assigned unit and test that it succeeds....
Definition: util.F90:185
pmc_util::linspace_find
integer function linspace_find(min_x, max_x, n, x)
Find the position of a real number in a 1D linear array.
Definition: util.F90:532
read_char_raw
subroutine read_char_raw(unit, char, eol, eof)
Read a single character from a file, signaling if we have hit EOL or EOF. If EOL or EOF are true then...
Definition: numeric_average.F90:153
pmc_util::real_to_string_max_len
character(len=pmc_util_convert_string_len) function real_to_string_max_len(val, max_len)
Convert a real to a string format of maximum length.
Definition: util.F90:857
pmc_util::time_to_string_max_len
character(len=pmc_util_convert_string_len) function time_to_string_max_len(time, max_len)
Convert a time to a string format of maximum length.
Definition: util.F90:912
pmc_util::logical_to_string
character(len=pmc_util_convert_string_len) function logical_to_string(val)
Convert a logical to a string format.
Definition: util.F90:798
pmc_util::string_to_logical
logical function string_to_logical(string)
Convert a string to a logical.
Definition: util.F90:733
pmc_util::rad2diam
real(kind=dp) elemental function rad2diam(r)
Convert radius (m) to diameter (m).
Definition: util.F90:252
pmc_util::complex_to_string
character(len=pmc_util_convert_string_len) function complex_to_string(val)
Convert a complex to a string format.
Definition: util.F90:818
pmc_util::starts_with
logical function starts_with(string, start_string)
Checks whether a string starts with a given other string.
Definition: util.F90:1577
pmc_util::integer_sort
subroutine integer_sort(data, perm)
Sort the given data array and return the permutation defining the sort.
Definition: util.F90:1295
pmc_util::get_unit
integer function get_unit()
Returns an available unit number. This should be freed by free_unit().
Definition: util.F90:148
pmc_util::integer_to_string_max_len
character(len=pmc_util_convert_string_len) function integer_to_string_max_len(val, max_len)
Convert an integer to a string format of maximum length.
Definition: util.F90:836
pmc_util::nplogp
elemental real(kind=dp) function nplogp(p)
Compute for computing entropy.
Definition: util.F90:1613
pmc_util::open_file_write
subroutine open_file_write(filename, unit)
Open a file for writing with an automatically assigned unit and test that it succeeds....
Definition: util.F90:206
pmc_util::sphere_rad2vol
real(kind=dp) elemental function sphere_rad2vol(r)
Convert geometric radius (m) to mass-equivalent volume (m^3) for spherical particles.
Definition: util.F90:265
pmc_util::warn_assert_msg
subroutine warn_assert_msg(code, condition_ok, warning_msg)
Prints a warning message if condition_ok is false.
Definition: util.F90:59
pmc_util::die_msg
subroutine die_msg(code, error_msg)
Error immediately.
Definition: util.F90:134
pmc_util::unit_offset
integer, parameter unit_offset
Minimum unit number to allocate.
Definition: util.F90:22
pmc_constants::dp
integer, parameter dp
Kind of a double precision real number.
Definition: constants.F90:12
pmc_util::ensure_real_array_size
subroutine ensure_real_array_size(x, n, only_grow)
Allocate or reallocate the given array to ensure it is of the given size, preserving any data and/or ...
Definition: util.F90:1041
pmc_util::interp_1d
real(kind=dp) function interp_1d(x_vals, y_vals, x)
1D linear interpolation.
Definition: util.F90:626
pmc_util::pow2_above
integer function pow2_above(n)
Return the least power-of-2 that is at least equal to n.
Definition: util.F90:1642
pmc_util::get_basename
subroutine get_basename(filename, basename)
Strip the extension to find the basename.
Definition: util.F90:1214
pmc_util::assert
subroutine assert(code, condition_ok)
Errors unless condition_ok is true.
Definition: util.F90:103
integer_sort_c
int integer_sort_c(int n, int *data, int *perm)
Sort the given data array and return the permutation.
Definition: sort.c:40
pmc_util::string_to_integer
integer function string_to_integer(string)
Convert a string to an integer.
Definition: util.F90:688
pmc_util::logspace
real(kind=dp) function, dimension(:), allocatable logspace(min_x, max_x, n)
Makes a logarithmically spaced array of length n from min to max.
Definition: util.F90:492
pmc_util::interp_linear_disc
real(kind=dp) function interp_linear_disc(x_1, x_n, n, i)
Linear interpolation over discrete indices.
Definition: util.F90:663
pmc_util::reallocate_real_array2d
subroutine reallocate_real_array2d(data, rows, cols)
Reallocate a 2D real array to the given size, preserving the contents.
Definition: util.F90:1440
pmc_util::sphere_vol2rad
real(kind=dp) elemental function sphere_vol2rad(v)
Convert mass-equivalent volume (m^3) to geometric radius (m) for spherical particles.
Definition: util.F90:240
pmc_util::linspace
real(kind=dp) function, dimension(:), allocatable linspace(min_x, max_x, n)
Makes a linearly spaced array from min to max.
Definition: util.F90:460
pmc_util::warn_msg
subroutine warn_msg(code, warning_msg, already_warned)
Prints a warning message.
Definition: util.F90:37
pmc_util::harmonic_mean
elemental real(kind=dp) function harmonic_mean(x1, x2)
Compute the harmonic mean of two numbers.
Definition: util.F90:1599
pmc_util::ensure_real_array_2d_size
subroutine ensure_real_array_2d_size(x, n1, n2, only_grow)
Allocate or reallocate the given array to ensure it is of the given size, preserving any data and/or ...
Definition: util.F90:1075
pmc_util::pmc_max_filename_len
integer, parameter pmc_max_filename_len
Maximum length of filenames.
Definition: util.F90:29
pmc_util::check_time_multiple
subroutine check_time_multiple(first_name, first_time, second_name, second_time)
Check that the first time interval is close to an integer multiple of the second, and warn if it is n...
Definition: util.F90:376
pmc_util::integer_to_string
character(len=pmc_util_convert_string_len) function integer_to_string(val)
Convert an integer to a string format.
Definition: util.F90:766
pmc_util::real_to_string
character(len=pmc_util_convert_string_len) function real_to_string(val)
Convert a real to a string format.
Definition: util.F90:782
pmc_util::assert_msg
subroutine assert_msg(code, condition_ok, error_msg)
Errors unless condition_ok is true.
Definition: util.F90:77
pmc_util::diam2rad
real(kind=dp) elemental function diam2rad(d)
Convert diameter (m) to radius (m).
Definition: util.F90:277
pmc_util::deg2rad
real(kind=dp) function deg2rad(deg)
Convert degrees to radians.
Definition: util.F90:1267
pmc_constants::const
type(const_t), save const
Fixed variable for accessing the constant's values.
Definition: constants.F90:73
pmc_util::average_real
subroutine average_real(real_vec, real_avg)
Computes the average of an array of real numbers.
Definition: util.F90:1008
pmc_util::rad2deg
real(kind=dp) function rad2deg(rad)
Convert radians to degrees.
Definition: util.F90:1279
pmc_util::unit_used
logical, dimension(max_units), save unit_used
Table of unit numbers storing allocation status.
Definition: util.F90:24
pmc_util::logspace_find
integer function logspace_find(min_x, max_x, n, x)
Find the position of a real number in a 1D logarithmic array.
Definition: util.F90:566
pmc_util::ensure_string_array_size
subroutine ensure_string_array_size(x, n)
Allocate or reallocate the given array to ensure it is of the given size, without preserving data.
Definition: util.F90:1189
pmc_util::max_units
integer, parameter max_units
Maximum number of IO units usable simultaneously.
Definition: util.F90:20
pmc_util::entropy
real(kind=dp) function entropy(p)
Compute the entropy of a probability mass function (non necessarily normalized).
Definition: util.F90:1630
pmc_constants
Physical constants.
Definition: constants.F90:9
pmc_util::ensure_integer_array_2d_size
subroutine ensure_integer_array_2d_size(x, n1, n2, only_grow)
Allocate or reallocate the given array to ensure it is of the given size, preserving any data and/or ...
Definition: util.F90:1149
pmc_util::loadtxt
subroutine loadtxt(filename, data)
Load a real array from a text file.
Definition: util.F90:1333
pmc_util
Common utility subroutines.
Definition: util.F90:9
pmc_util::check_event
subroutine check_event(time, timestep, interval, last_time, do_event)
Computes whether an event is scheduled to take place.
Definition: util.F90:407
pmc_util::string_array_find
integer function string_array_find(array, val)
Return the index of the first occurance of the given value in the array, or 0 if it is not present.
Definition: util.F90:1023
pmc_util::almost_equal
logical function almost_equal(d1, d2)
Tests whether two real numbers are almost equal using only a relative tolerance.
Definition: util.F90:318
pmc_util::air_mean_free_path
real(kind=dp) function air_mean_free_path(temp, pressure)
Calculate air molecular mean free path (m).
Definition: util.F90:289
pmc_util::average_integer
subroutine average_integer(int_vec, int_avg)
Computes the average of an array of integer numbers.
Definition: util.F90:994
pmc_util::free_unit
subroutine free_unit(unit)
Frees a unit number returned by get_unit().
Definition: util.F90:172
pmc_util::die
subroutine die(code)
Error immediately.
Definition: util.F90:122
pmc_util::close_file
subroutine close_file(unit)
Close a file and de-assign the unit.
Definition: util.F90:226
pmc_util::iso8601_date_and_time
subroutine iso8601_date_and_time(date_time)
Current date and time in ISO 8601 format.
Definition: util.F90:1247
pmc_util::savetxt_2d
subroutine savetxt_2d(filename, data)
Write a real 2D array to a text file.
Definition: util.F90:1417
pmc_util::almost_equal_abs
logical function almost_equal_abs(d1, d2, abs_tol)
Tests whether two real numbers are almost equal using an absolute and relative tolerance.
Definition: util.F90:345
pmc_util::savetxt_1d
subroutine savetxt_1d(filename, data)
Write a real 1D array to a text file.
Definition: util.F90:1397
pmc_util::vec_cts_to_disc
subroutine vec_cts_to_disc(n, vec_cts, n_samp, vec_disc)
Convert a real-valued vector into an integer-valued vector.
Definition: util.F90:953
pmc_util::pmc_util_convert_string_len
integer, parameter pmc_util_convert_string_len
Length of string for converting numbers.
Definition: util.F90:27
string_to_real
real(kind=dp) function string_to_real(string)
Convert a string to a real.
Definition: numeric_average.F90:108
read_word_raw
subroutine read_word_raw(unit, word, eol, eof)
Read a white-space delimited word from a file, signaling if we have EOL or EOF. If EOL or EOF are tru...
Definition: numeric_average.F90:197
pmc_util::ensure_integer_array_size
subroutine ensure_integer_array_size(x, n, only_grow)
Allocate or reallocate the given array to ensure it is of the given size, preserving any data and/or ...
Definition: util.F90:1115
pmc_util::find_1d
integer function find_1d(n, x_vals, x)
Find the position of a real number in an arbitrary 1D array.
Definition: util.F90:592