source: trunk/LMDZ.COMMON/libf/evolution/utility.F90 @ 4110

Last change on this file since 4110 was 4110, checked in by jbclement, 3 days ago

PEM:

  • Introduction of a configurable display/logging system with options 'out2term', 'out2log', 'verbosity_lvl'. All messages now use verbosity levels ('LVL_NFO', 'LVL_WRN', 'LVL_ERR' and 'LVL_DBG').
  • Code encapsulation improvements with systematic privacy/protection of module variables.
  • Addition of workflow safety checks for required executables, dependencies (e.g. 'ncdump'), input files and callphys keys.
  • Renaming of PEM starting and diagnostic files ("startevol.nc" into "startevo.nc", "diagevol.nc" into "diagevo.nc").

JBC

File size: 8.3 KB
Line 
1MODULE utility
2!-----------------------------------------------------------------------
3! NAME
4!     utility
5!
6! DESCRIPTION
7!     Contains some utility functions.
8!
9! AUTHORS & DATE
10!     JB Clement, 2023-2025
11!
12! NOTES
13!
14!-----------------------------------------------------------------------
15
16! DEPENDENCIES
17! ------------
18use numerics, only: dp, qp, di, li, k4, minieps
19
20! DECLARATION
21! -----------
22implicit none
23
24! INTERFACES
25! ----------
26interface int2str
27    module procedure int2str_di, int2str_li
28end interface int2str
29
30interface real2str
31    module procedure real2str_dp, real2str_qp
32end interface real2str
33
34contains
35!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36
37!=======================================================================
38FUNCTION int2str_di(i) RESULT(str)
39!-----------------------------------------------------------------------
40! NAME
41!     int2str_di
42!
43! DESCRIPTION
44!     Convert a default integer into a string.
45!
46! AUTHORS & DATE
47!     JB Clement, 2023-2025
48!
49! NOTES
50!
51!-----------------------------------------------------------------------
52
53! DEPENDENCIES
54! ------------
55use stoppage, only: stop_clean
56
57! DECLARATION
58! -----------
59implicit none
60
61! ARGUMENTS
62! ---------
63integer(di), intent(in) :: i
64
65! LOCAL VARIABLES
66! ---------------
67character(20)             :: str_tmp
68character(:), allocatable :: str
69
70! CODE
71! ----
72if (nb_digits(real(i,dp)) > len(str_tmp)) call stop_clean(__FILE__,__LINE__,'invalid integer for conversion!',1)
73write(str_tmp,'(i0)') i
74str = trim(adjustl(str_tmp))
75
76END FUNCTION int2str_di
77!=======================================================================
78
79!=======================================================================
80FUNCTION int2str_li(i) RESULT(str)
81!-----------------------------------------------------------------------
82! NAME
83!     int2str_li
84!
85! DESCRIPTION
86!     Convert a long integer into a string.
87!
88! AUTHORS & DATE
89!     JB Clement, 2023-2025
90!
91! NOTES
92!
93!-----------------------------------------------------------------------
94
95! DEPENDENCIES
96! ------------
97use stoppage, only: stop_clean
98
99! DECLARATION
100! -----------
101implicit none
102
103! ARGUMENTS
104! ---------
105integer(li), intent(in) :: i
106
107! LOCAL VARIABLES
108! ---------------
109character(20)             :: str_tmp
110character(:), allocatable :: str
111
112! CODE
113! ----
114if (nb_digits(real(i,dp)) > len(str_tmp)) call stop_clean(__FILE__,__LINE__,'invalid integer for conversion!',1)
115write(str_tmp,'(i0)') i
116str = trim(adjustl(str_tmp))
117
118END FUNCTION int2str_li
119!=======================================================================
120
121!=======================================================================
122FUNCTION real2str_dp(x,frmt) RESULT(str)
123!-----------------------------------------------------------------------
124! NAME
125!     real2str_dp
126!
127! DESCRIPTION
128!     Convert a double precision real into a string.
129!
130! AUTHORS & DATE
131!     JB Clement, 02/2026
132!
133! NOTES
134!
135!-----------------------------------------------------------------------
136
137! DEPENDENCIES
138! ------------
139use stoppage, only: stop_clean
140
141! DECLARATION
142! -----------
143implicit none
144
145! ARGUMENTS
146! ---------
147real(dp),     intent(in)           :: x
148character(*), intent(in), optional :: frmt
149
150! LOCAL VARIABLES
151! ---------------
152!~ integer(di)               :: len_trimmed
153character(32)             :: str_tmp
154character(:), allocatable :: str
155
156! CODE
157! ----
158if (present(frmt)) then
159    write(str_tmp,frmt) x
160else
161    write(str_tmp,'(G0)') x
162end if
163
164!~ ! Remove trailing zeros after decimal
165!~ len_trimmed = len_trim(tmp)
166!~ do while (len_trimmed > 0)
167!~     if (str_tmp(len_trimmed:len_trimmed) == '0' .or. str_tmp(len_trimmed:len_trimmed) == ' ') then
168!~     len_trimmed = len_trimmed - 1
169!~     else
170!~         exit
171!~     end if
172!~ end do
173!~ str = str_tmp(1:len_trimmed)
174str = trim(adjustl(str_tmp))
175
176END FUNCTION real2str_dp
177!=======================================================================
178
179!=======================================================================
180FUNCTION real2str_qp(x,frmt) RESULT(str)
181!-----------------------------------------------------------------------
182! NAME
183!     real2str_qp
184!
185! DESCRIPTION
186!     Convert a quadruple precision real into a string.
187!
188! AUTHORS & DATE
189!     JB Clement, 02/2026
190!
191! NOTES
192!
193!-----------------------------------------------------------------------
194
195! DEPENDENCIES
196! ------------
197use stoppage, only: stop_clean
198
199! DECLARATION
200! -----------
201implicit none
202
203! ARGUMENTS
204! ---------
205real(qp),     intent(in)           :: x
206character(*), intent(in), optional :: frmt
207
208! LOCAL VARIABLES
209! ---------------
210!~ integer(di)               :: len_trimmed
211character(32)             :: str_tmp
212character(:), allocatable :: str
213
214! CODE
215! ----
216if (present(frmt)) then
217    write(str_tmp,frmt) x
218else
219    write(str_tmp,'(G0)') x
220end if
221
222!~ ! Remove trailing zeros after decimal
223!~ len_trimmed = len_trim(tmp)
224!~ do while (len_trimmed > 0)
225!~     if (str_tmp(len_trimmed:len_trimmed) == '0' .or. str_tmp(len_trimmed:len_trimmed) == ' ') then
226!~     len_trimmed = len_trimmed - 1
227!~     else
228!~         exit
229!~     end if
230!~ end do
231!~ str = str_tmp(1:len_trimmed)
232str = trim(adjustl(str_tmp))
233
234END FUNCTION real2str_qp
235!=======================================================================
236
237!=======================================================================
238FUNCTION bool2str(l) RESULT(str)
239!-----------------------------------------------------------------------
240! NAME
241!     bool2str
242!
243! DESCRIPTION
244!     Convert a logical into a string.
245!
246! AUTHORS & DATE
247!     JB Clement, 02/2026
248!
249! NOTES
250!
251!-----------------------------------------------------------------------
252
253! DECLARATION
254! -----------
255implicit none
256
257! ARGUMENTS
258! ---------
259logical(k4), intent(in) :: l
260
261! LOCAL VARIABLES
262! ---------------
263character(5) :: str
264
265! CODE
266! ----
267str = merge('true ','false',l)
268
269END FUNCTION bool2str
270!=======================================================================
271
272!=======================================================================
273FUNCTION nb_digits(x) RESULT(idigits)
274!-----------------------------------------------------------------------
275! NAME
276!     nb_digits
277!
278! DESCRIPTION
279!     Give the number of digits for the integer part of a real number.
280!
281! AUTHORS & DATE
282!     JB Clement, 2023-2025
283!
284! NOTES
285!
286!-----------------------------------------------------------------------
287
288! DECLARATION
289! -----------
290implicit none
291
292! ARGUMENTS
293! ---------
294real(dp), intent(in) :: x
295
296! LOCAL VARIABLES
297! ---------------
298integer(di) :: idigits
299
300! CODE
301! ----
302idigits = 1
303! If x /= 0 then:
304if (abs(x) >= minieps) idigits = int(log10(abs(x))) + 1
305
306END FUNCTION nb_digits
307!=======================================================================
308
309!=======================================================================
310FUNCTION is_id_1st_char(c) RESULT(valid_c)
311!-----------------------------------------------------------------------
312! NAME
313!     is_id_1st_char
314!
315! DESCRIPTION
316!     Detects valid first character for Fortran identifer.
317!
318! AUTHORS & DATE
319!     JB Clement, 01/2026
320!
321! NOTES
322!     A variable name is a Fortran identifier if it starts with a letter
323!     or _ and followed by letters, digits or _.
324!-----------------------------------------------------------------------
325
326! DECLARATION
327! -----------
328implicit none
329
330! ARGUMENTS
331! ---------
332character(1), intent(in) :: c
333
334! LOCAL VARIABLES
335! ---------------
336logical(k4) :: valid_c
337
338! CODE
339! ----
340valid_c = ('A' <= c .and. c <= 'Z') .or. ('a' <= c .and. c <= 'z') .or. (c == '_')
341
342END FUNCTION  is_id_1st_char
343!=======================================================================
344
345!=======================================================================
346FUNCTION is_id_char(c) RESULT(valid_c)
347!-----------------------------------------------------------------------
348! NAME
349!     is_id_char
350!
351! DESCRIPTION
352!     Detects valid character for Fortran identifer.
353!
354! AUTHORS & DATE
355!     JB Clement, 01/2026
356!
357! NOTES
358!     A variable name is a Fortran identifier if it starts with a letter
359!     or _ and followed by letters, digits or _.
360!-----------------------------------------------------------------------
361
362! DECLARATION
363! -----------
364implicit none
365
366! ARGUMENTS
367! ---------
368character(1), intent(in) :: c
369
370! LOCAL VARIABLES
371! ---------------
372logical(k4) :: valid_c
373
374! CODE
375! ----
376valid_c = is_id_1st_char(c) .or. ('0' <= c .and. c <= '9')
377
378END FUNCTION  is_id_char
379!=======================================================================
380
381END MODULE utility
Note: See TracBrowser for help on using the repository browser.