MONC
conversions.F90
Go to the documentation of this file.
1 
7  implicit none
8 
9 #ifndef TEST_MODE
10  private
11 #endif
12 
13  ! This is the rounding applied when going from single to double precision numbers
14  integer, parameter :: real_rounding_precision=int(1e8)
15 
23  interface conv_to_generic
25  end interface conv_to_generic
26 
36  interface conv_to_string
38  end interface conv_to_string
39 
47  interface conv_to_integer
49  end interface conv_to_integer
50 
58  interface conv_to_real
60  end interface conv_to_real
61 
69  interface conv_to_logical
71  end interface conv_to_logical
72 
79  interface conv_is_integer
80  module procedure string_is_integer
81  end interface conv_is_integer
82 
89  interface conv_is_real
90  module procedure string_is_real
91  end interface conv_is_real
92 
98  interface conv_is_logical
99  module procedure string_is_logical
100  end interface conv_is_logical
101 
104 
105 contains
106 
111  real(kind=DOUBLE_PRECISION) function conv_single_real_to_double(input_real)
112  real(kind=SINGLE_PRECISION), intent(in) :: input_real
113 
114  conv_single_real_to_double=dnint(real(input_real, kind=DEFAULT_PRECISION) * &
115  REAL_ROUNDING_PRECISION) / real_rounding_precision
116  end function conv_single_real_to_double
117 
118 
122  logical function string_is_integer(string)
123  character(len=*), intent(in) :: string
124 
125  integer :: integer_value, ierr
126 
127  if (len(trim(string)) .ne. 0) then
128  read(string, '(i10)', iostat=ierr ) integer_value
129  string_is_integer = ierr == 0
130  else
131  string_is_integer=.false.
132  end if
133  end function string_is_integer
134 
138  logical function string_is_real(string)
139  character(len=*), intent(in) :: string
140 
141  integer :: ierr
142  real :: real_value
143 
144  if (len(trim(string)) .ne. 0) then
145  read(string, '(f10.2)', iostat=ierr ) real_value
146  string_is_real = ierr == 0
147  else
148  string_is_real=.false.
149  end if
150  end function string_is_real
151 
155  logical function string_is_logical(string)
156  character(len=*), intent(in) :: string
157 
158  string_is_logical = .false.
159  if (trim(adjustl(string)) .eq. "true" .or. trim(adjustl(string)) .eq. "false" .or. &
160  trim(adjustl(string)) .eq. ".true." .or. trim(adjustl(string)) .eq. ".false." .or. &
161  trim(adjustl(string)) .eq. ".true" .or. trim(adjustl(string)) .eq. "true." .or. &
162  trim(adjustl(string)) .eq. ".false" .or. trim(adjustl(string)) .eq. "false.") string_is_logical = .true.
163  end function string_is_logical
164 
170  function generic_to_string(generic, makecopy, str_length)
171  class(*), pointer, intent(in) :: generic
172  logical, intent(in) :: makecopy
173  integer, intent(in) :: str_length
174  character(len=str_length), pointer :: generic_to_string, temporary_generic_ptr
175 
176  select type(generic)
177  type is (character(len=*))
178  if (makecopy) then
179  ! Need to do this to enforce string length information
180  temporary_generic_ptr=>generic
181  allocate(generic_to_string, source=temporary_generic_ptr)
182  else
183  generic_to_string=>generic
184  end if
185  class default
186  generic_to_string=>null()
187  end select
188  end function generic_to_string
189 
193  function integer_to_string(input)
194  integer, intent(in) :: input
195  character(len=15) :: integer_to_string
196 
197  write(integer_to_string, '(i15)' ) input
198  integer_to_string = trim(adjustl(integer_to_string))
199  end function integer_to_string
200 
204  function real_single_to_string(input, decimal_places, exponent, exponent_small_numbers)
205  real(kind=SINGLE_PRECISION), intent(in) :: input
206  character(len=30) :: real_single_to_string
207  integer, optional :: decimal_places
208  logical, optional :: exponent, exponent_small_numbers
209 
210  logical :: transformed
211  transformed=.false.
212 
213  if (present(exponent)) then
214  if (exponent) then
215  write(real_single_to_string, '(es30.10)' ) input
216  transformed=.true.
217  end if
218  end if
219  if (present(exponent_small_numbers)) then
220  if (exponent_small_numbers) then
221  write(real_single_to_string, '(g30.10)' ) input
222  transformed=.true.
223  end if
224  end if
225  if (.not. transformed) then
226  write(real_single_to_string, '(f30.10)' ) input
227  if (scan(real_single_to_string, "*") .ne. 0) write(real_single_to_string, '(es30.10)' ) input
228  end if
229  call trim_trailing_zeros(real_single_to_string, 2)
230  if (present(decimal_places)) call limit_to_decimal_places(real_single_to_string, decimal_places)
231 
232  real_single_to_string = trim(adjustl(real_single_to_string))
233  end function real_single_to_string
234 
238  function real_double_to_string(input, decimal_places, exponent, exponent_small_numbers)
239  real(kind=DOUBLE_PRECISION), intent(in) :: input
240  character(len=30) :: real_double_to_string
241  integer, optional :: decimal_places
242  logical, optional :: exponent, exponent_small_numbers
243 
244  logical :: transformed
245  transformed=.false.
246 
247  if (present(exponent)) then
248  if (exponent) then
249  write(real_double_to_string, '(es30.10)' ) input
250  transformed=.true.
251  end if
252  end if
253  if (present(exponent_small_numbers)) then
254  if (exponent_small_numbers) then
255  write(real_double_to_string, '(g30.10)' ) input
256  transformed=.true.
257  end if
258  end if
259  if (.not. transformed) then
260  write(real_double_to_string, '(f30.10)' ) input
261  if (scan(real_double_to_string, "*") .ne. 0) write(real_double_to_string, '(es30.10)' ) input
262  end if
263  call trim_trailing_zeros(real_double_to_string, 2)
264  if (present(decimal_places)) then
265  call limit_to_decimal_places(real_double_to_string, decimal_places)
266  end if
267 
268  real_double_to_string = trim(adjustl(real_double_to_string))
269  end function real_double_to_string
270 
275  subroutine limit_to_decimal_places(string_to_parse, decimal_places)
276  character(len=*), intent(inout) :: string_to_parse
277  integer, intent(in) :: decimal_places
278 
279  integer :: decimal_posn, exp_posn
280 
281  string_to_parse=adjustl(string_to_parse)
282  decimal_posn=index(string_to_parse, ".")
283  exp_posn=index(string_to_parse, "E")
284  if (decimal_posn .ne. 0 .and. decimal_posn+decimal_places+1 .le. len(string_to_parse)) then
285  if (exp_posn .eq. 0) then
286  string_to_parse(decimal_posn+decimal_places+1:)=" "
287  else
288  string_to_parse(decimal_posn+decimal_places+1:)=string_to_parse(exp_posn:)
289  string_to_parse(decimal_posn+decimal_places+1+(len(string_to_parse)-exp_posn)+1:)=" "
290  end if
291  end if
292  end subroutine limit_to_decimal_places
293 
298  subroutine trim_trailing_zeros(string_to_parse, zeros_to_retain)
299  character(len=*), intent(inout) :: string_to_parse
300  integer, intent(in) :: zeros_to_retain
301 
302  integer :: decimal_posn, i, zero_count, nonzero_hit
303 
304  zero_count=0
305 
306  decimal_posn=index(string_to_parse, ".")
307  if (decimal_posn .ne. 0 .and. decimal_posn .lt. len(string_to_parse)) then
308  do i=len(trim(string_to_parse)), decimal_posn, -1
309  if (string_to_parse(i:i) .ne. "0") then
310  nonzero_hit=i
311  exit
312  else
313  zero_count=zero_count+1
314  end if
315  end do
316  if (zero_count .gt. zeros_to_retain) then
317  string_to_parse(nonzero_hit+zeros_to_retain:)=""
318  end if
319  end if
320  end subroutine trim_trailing_zeros
321 
325  function logical_to_string(input)
326  logical, intent(in) :: input
327  character(len=5) :: logical_to_string
328 
329  if (input) then
330  logical_to_string = "true"
331  else
332  logical_to_string = "false"
333  end if
334  end function logical_to_string
335 
340  function generic_to_logical(generic, makecopy)
341  class(*), pointer, intent(in) :: generic
342  logical, intent(in) :: makecopy
343  logical, pointer :: generic_to_logical
344 
345  select type(generic)
346  type is (logical)
347  if (makecopy) then
348  allocate(generic_to_logical, source=generic)
349  else
350  generic_to_logical=>generic
351  end if
352  class default
353  generic_to_logical=>null()
354  end select
355  end function generic_to_logical
356 
360  logical function string_to_logical(string)
361  character(len=*), intent(in) :: string
362 
363  if (trim(adjustl(string)) .eq. "true" .or. trim(adjustl(string)) .eq. ".true." .or. &
364  trim(adjustl(string)) .eq. ".true" .or. trim(adjustl(string)) .eq. "true.") then
365  string_to_logical = .true.
366  else
367  string_to_logical = .false.
368  end if
369  end function string_to_logical
370 
374  logical function integer_to_logical(input)
375  integer, intent(in) :: input
376 
377  if (input .ge. 1) then
378  integer_to_logical = .true.
379  else
380  integer_to_logical = .false.
381  end if
382  end function integer_to_logical
383 
387  logical function real_to_logical(input)
388  real, intent(in) :: input
389 
390  if (input .ge. 1.0) then
391  real_to_logical = .true.
392  else
393  real_to_logical = .false.
394  end if
395  end function real_to_logical
396 
401  function generic_to_double_real(generic, makecopy)
402  class(*), pointer, intent(in) :: generic
403  logical, intent(in) :: makecopy
404  real(kind=DEFAULT_PRECISION), pointer :: generic_to_double_real
405 
406  select type(generic)
407  type is (real(kind=default_precision))
408  if (makecopy) then
409  allocate(generic_to_double_real, source=generic)
410  else
411  generic_to_double_real=>generic
412  end if
413  class default
414  generic_to_double_real=>null()
415  end select
416  end function generic_to_double_real
417 
422  function generic_to_real(generic, makecopy)
423  class(*), pointer, intent(in) :: generic
424  logical, intent(in) :: makecopy
425  real, pointer :: generic_to_real
426 
427  select type(generic)
428  type is (real)
429  if (makecopy) then
430  allocate(generic_to_real, source=generic)
431  else
432  generic_to_real=>generic
433  end if
434  type is (integer)
435  allocate(generic_to_real)
436  generic_to_real=conv_to_real(generic)
437  class default
438  generic_to_real=>null()
439  end select
440  end function generic_to_real
441 
445  real function string_to_real(string)
446  character(len=*), intent(in) :: string
447 
448  if (scan(string, "E") .ne. 0 .or. scan(string, "e") .ne. 0) then
449  read(string, '(es30.10)' ) string_to_real
450  else
451  read(string, '(f10.0)' ) string_to_real
452  end if
453  end function string_to_real
454 
458  real function integer_to_real(input)
459  integer, intent(in) :: input
460 
461  integer_to_real = real(input)
462  end function integer_to_real
463 
467  real function logical_to_real(input)
468  logical, intent(in) :: input
469 
470  if (input) then
471  logical_to_real = 1.0
472  else
473  logical_to_real = 0.0
474  end if
475  end function logical_to_real
476 
481  function generic_to_integer(generic, makecopy)
482  class(*), pointer, intent(in) :: generic
483  logical, intent(in) :: makecopy
484  integer, pointer :: generic_to_integer
485 
486  select type(generic)
487  type is (integer)
488  if (makecopy) then
489  allocate(generic_to_integer, source=generic)
490  else
491  generic_to_integer=>generic
492  end if
493  class default
494  generic_to_integer=>null()
495  end select
496  end function generic_to_integer
497 
501  integer function string_to_integer(string)
502  character(len=*), intent(in) :: string
503 
504  read(string, '(i15)' ) string_to_integer
505  end function string_to_integer
506 
510  integer function real_to_integer(input)
511  real, intent(in) :: input
512 
513  real_to_integer = int(input)
514  end function real_to_integer
515 
519  integer function logical_to_integer(input)
520  logical, intent(in) :: input
521 
522  if (input) then
524  else
526  end if
527  end function logical_to_integer
528 
533  function string_to_generic(string, makecopy)
534  character(len=*), target, intent(in) :: string
535  logical, intent(in) :: makecopy
536  class(*), pointer :: string_to_generic
537 
538  if (makecopy) then
539  allocate(string_to_generic, source=string)
540  else
541  string_to_generic=>string
542  end if
543  end function string_to_generic
544 
549  function integer_to_generic(input, makecopy)
550  integer, target , intent(in) :: input
551  logical, intent(in) :: makecopy
552  class(*), pointer :: integer_to_generic
553 
554  if (makecopy) then
555  allocate(integer_to_generic, source=input)
556  else
557  integer_to_generic=>input
558  end if
559  end function integer_to_generic
560 
565  function real_single_to_generic(input, makecopy)
566  real(kind=SINGLE_PRECISION), target, intent(in) :: input
567  logical, intent(in) :: makecopy
568  class(*), pointer :: real_single_to_generic
569 
570  if (makecopy) then
571  allocate(real_single_to_generic, source=input)
572  else
573  real_single_to_generic=>input
574  end if
575  end function real_single_to_generic
576 
581  function real_double_to_generic(input, makecopy)
582  real(kind=DOUBLE_PRECISION), target, intent(in) :: input
583  logical, intent(in) :: makecopy
584  class(*), pointer :: real_double_to_generic
585 
586  if (makecopy) then
587  allocate(real_double_to_generic, source=input)
588  else
589  real_double_to_generic=>input
590  end if
591  end function real_double_to_generic
592 
597  function logical_to_generic(input, makecopy)
598  logical, target, intent(in) :: input
599  logical, intent(in) :: makecopy
600  class(*), pointer :: logical_to_generic
601 
602  if (makecopy) then
603  allocate(logical_to_generic, source=input)
604  else
605  logical_to_generic=>input
606  end if
607  end function logical_to_generic
608 end module conversions_mod
class(*) function, pointer logical_to_generic(input, makecopy)
Converts a logical into its generic data representation.
real function string_to_real(string)
Converts a string to a real.
class(*) function, pointer integer_to_generic(input, makecopy)
Converts an integer into its generic data representation.
logical function integer_to_logical(input)
Converts an integer to a logical.
logical function string_is_real(string)
Determines whether a string is a real or not.
logical function, pointer generic_to_logical(generic, makecopy)
Converts a generic to a logical.
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
Definition: datadefn.F90:17
Converts a data type into the generic (class *) form.
Definition: conversions.F90:23
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
real function logical_to_real(input)
Converts a logical to a real.
subroutine trim_trailing_zeros(string_to_parse, zeros_to_retain)
A helper subroutine which trims training zeros from the string after a decimal place this is to make ...
Conversion between common inbuilt FORTRAN data types.
Definition: conversions.F90:5
Converts data types to strings.
Definition: conversions.F90:36
integer, parameter, public single_precision
Single precision (32 bit) kind.
Definition: datadefn.F90:13
integer function logical_to_integer(input)
Converts a logical to an integer.
logical function string_is_logical(string)
Determines whether a string is a logical or not.
Converts data types to logical.
Definition: conversions.F90:69
character(len=30) function real_single_to_string(input, decimal_places, exponent, exponent_small_numbers)
Converts a single precision real to a string.
integer, parameter, public double_precision
Double precision (64 bit) kind.
Definition: datadefn.F90:14
logical function string_to_logical(string)
Converts a string to a logical.
character(len=30) function real_double_to_string(input, decimal_places, exponent, exponent_small_numbers)
Converts a double precision real to a string.
integer function string_to_integer(string)
Converts a string to an integer.
Determines whether a data item can be represented as a logical or not.
Definition: conversions.F90:98
character(len=str_length) function, pointer generic_to_string(generic, makecopy, str_length)
Converts a generic to a string.
logical function string_is_integer(string)
Determines whether a string is an integer or not.
Determines whether a data item can be represented as an integer or not.
Definition: conversions.F90:79
Converts data types to real.
Definition: conversions.F90:58
logical function real_to_logical(input)
Converts a real to a logical.
real function, pointer generic_to_real(generic, makecopy)
Converts a generic to a real. If this is infact an integer then will do a conversion and allocate poi...
subroutine limit_to_decimal_places(string_to_parse, decimal_places)
Helper subroutine which trims the string down to an upper limit of decimal places, with all numbers beyond this point removed.
real(kind=default_precision) function, pointer, public generic_to_double_real(generic, makecopy)
Converts a generic to a double real.
class(*) function, pointer string_to_generic(string, makecopy)
Converts a string into its generic data representation.
character(len=15) function integer_to_string(input)
Converts an integer to a string.
integer function real_to_integer(input)
Converts a real to an integer.
class(*) function, pointer real_double_to_generic(input, makecopy)
Converts a double real into its generic data representation.
Determines whether a data item can be represented as a real or not.
Definition: conversions.F90:89
character(len=5) function logical_to_string(input)
Converts a logical to a string.
class(*) function, pointer real_single_to_generic(input, makecopy)
Converts a single real into its generic data representation.
integer, parameter real_rounding_precision
Definition: conversions.F90:14
Converts data types to integers.
Definition: conversions.F90:47
integer function, pointer generic_to_integer(generic, makecopy)
Converts a generic to an integer.
real(kind=double_precision) function, public conv_single_real_to_double(input_real)
Converts from a single to double precision real. This applies some rounding to a certain number of de...
real function integer_to_real(input)
Converts an integer to a real.