Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief unit conversion facility
10 : !>
11 : !> Units are complex, this module does not try to be very smart, for
12 : !> example SI prefixes are not supported automatically, and
13 : !> which kinds are really basic can change depending on the system of
14 : !> units chosen, and equivalences are not always catched.
15 : !>
16 : !> This is thought as a simple conversion facility for the input and output.
17 : !> If you need something more you are probably better off using the
18 : !> physcon module directly.
19 : !> \note
20 : !> One design choice was not to use dynamically allocated elements to
21 : !> reduce the possibility of leaks.
22 : !> Needs to be extended (for example charge, dipole,...)
23 : !> I just added the units and kinds that I needed.
24 : !> Used by the parser
25 : !> Should keep an unsorted/uncompressed version for nicer labels?
26 : !> \par History
27 : !> 01.2005 created [fawzi]
28 : !> \author fawzi
29 : ! **************************************************************************************************
30 : MODULE cp_units
31 :
32 : USE cp_log_handling, ONLY: cp_to_string
33 : USE kinds, ONLY: dp
34 : USE mathconstants, ONLY: radians,&
35 : twopi
36 : USE physcon, ONLY: &
37 : atm, bar, bohr, e_mass, evolt, femtoseconds, joule, kcalmol, kelvin, kjmol, massunit, &
38 : newton, pascal, picoseconds, seconds, wavenumbers
39 : USE string_utilities, ONLY: compress,&
40 : s2a,&
41 : uppercase
42 : #include "../base/base_uses.f90"
43 :
44 : IMPLICIT NONE
45 : PRIVATE
46 :
47 : LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
48 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_units'
49 :
50 : INTEGER, PARAMETER, PUBLIC :: cp_ukind_none = 0, &
51 : cp_ukind_energy = 1, &
52 : cp_ukind_length = 2, &
53 : cp_ukind_temperature = 3, &
54 : cp_ukind_angle = 4, &
55 : cp_ukind_pressure = 5, &
56 : cp_ukind_time = 6, &
57 : cp_ukind_mass = 7, &
58 : cp_ukind_undef = 8, &
59 : cp_ukind_potential = 9, &
60 : cp_ukind_force = 10, &
61 : cp_ukind_max = 10
62 :
63 : ! General
64 : INTEGER, PARAMETER, PUBLIC :: cp_units_none = 100, &
65 : cp_units_au = 101
66 : ! Mass
67 : INTEGER, PARAMETER, PUBLIC :: cp_units_m_e = 110, &
68 : cp_units_amu = 111, &
69 : cp_units_kg = 112
70 : ! Energy
71 : INTEGER, PARAMETER, PUBLIC :: cp_units_hartree = 130, &
72 : cp_units_wavenum = 131, &
73 : cp_units_joule = 132, &
74 : cp_units_kcalmol = 133, &
75 : cp_units_Ry = 134, &
76 : cp_units_eV = 135, &
77 : cp_units_kjmol = 136, &
78 : cp_units_jmol = 137, &
79 : cp_units_keV = 138
80 :
81 : ! Length
82 : INTEGER, PARAMETER, PUBLIC :: cp_units_bohr = 140, &
83 : cp_units_angstrom = 141, &
84 : cp_units_m = 142, &
85 : cp_units_pm = 143, &
86 : cp_units_nm = 144
87 :
88 : ! Temperature
89 : INTEGER, PARAMETER, PUBLIC :: cp_units_k = 150
90 :
91 : ! Pressure
92 : INTEGER, PARAMETER, PUBLIC :: cp_units_bar = 161
93 : INTEGER, PARAMETER, PUBLIC :: cp_units_atm = 162
94 : INTEGER, PARAMETER, PUBLIC :: cp_units_kbar = 163
95 : INTEGER, PARAMETER, PUBLIC :: cp_units_Pa = 164
96 : INTEGER, PARAMETER, PUBLIC :: cp_units_MPa = 165
97 : INTEGER, PARAMETER, PUBLIC :: cp_units_GPa = 166
98 :
99 : ! Angles
100 : INTEGER, PARAMETER, PUBLIC :: cp_units_rad = 170, &
101 : cp_units_deg = 171
102 :
103 : ! Time
104 : INTEGER, PARAMETER, PUBLIC :: cp_units_fs = 180, &
105 : cp_units_s = 181, &
106 : cp_units_wn = 182, &
107 : cp_units_ps = 183
108 :
109 : ! Potential
110 : INTEGER, PARAMETER, PUBLIC :: cp_units_volt = 190
111 :
112 : ! Force
113 : INTEGER, PARAMETER, PUBLIC :: cp_units_Newton = 200, &
114 : cp_units_mNewton = 201
115 :
116 : INTEGER, PARAMETER, PUBLIC :: cp_unit_max_kinds = 8, cp_unit_basic_desc_length = 15, &
117 : cp_unit_desc_length = cp_unit_max_kinds*cp_unit_basic_desc_length
118 :
119 : PUBLIC :: cp_unit_type, cp_unit_set_type
120 : PUBLIC :: cp_unit_create, cp_unit_release, &
121 : cp_unit_to_cp2k, cp_unit_from_cp2k, cp_unit_desc, &
122 : cp_unit_set_create, cp_unit_set_release, &
123 : cp_unit_to_cp2k1, cp_unit_from_cp2k1, cp_unit_compatible, export_units_as_xml
124 :
125 : ! **************************************************************************************************
126 : !> \brief stores a unit
127 : !> \param kind the kind of unit (energy, length,...)
128 : !> \param unit the actual unit (Joule, eV,...)
129 : !> \author fawzi
130 : ! **************************************************************************************************
131 : TYPE cp_unit_type
132 : INTEGER :: n_kinds = -1
133 : INTEGER, DIMENSION(cp_unit_max_kinds):: kind_id = -1, unit_id = -1, power = -1
134 : END TYPE cp_unit_type
135 :
136 : ! **************************************************************************************************
137 : !> \brief represent a pointer to a unit (to build arrays of pointers)
138 : !> \param unit the pointer to the unit
139 : !> \author fawzi
140 : ! **************************************************************************************************
141 : TYPE cp_unit_p_type
142 : TYPE(cp_unit_type), POINTER :: unit => NULL()
143 : END TYPE cp_unit_p_type
144 :
145 : ! **************************************************************************************************
146 : !> \brief stores the default units to be used
147 : !> \author fawzi
148 : ! **************************************************************************************************
149 : TYPE cp_unit_set_type
150 : TYPE(cp_unit_p_type), DIMENSION(cp_ukind_max) :: units = cp_unit_p_type()
151 : END TYPE cp_unit_set_type
152 :
153 : CONTAINS
154 :
155 : ! **************************************************************************************************
156 : !> \brief creates a unit parsing a string
157 : !> \param unit the unit to initialize
158 : !> \param string the string containing the description of the unit
159 : !> \author fawzi
160 : ! **************************************************************************************************
161 493885450 : SUBROUTINE cp_unit_create(unit, string)
162 : TYPE(cp_unit_type), INTENT(OUT) :: unit
163 : CHARACTER(len=*), INTENT(in) :: string
164 :
165 : CHARACTER(LEN=40) :: formatstr
166 : CHARACTER(LEN=cp_unit_desc_length) :: desc
167 19755418 : CHARACTER(LEN=LEN(string)) :: unit_string
168 : INTEGER :: i_high, i_low, i_unit, len_string, &
169 : next_power
170 : INTEGER, DIMENSION(cp_unit_max_kinds) :: kind_id, power, unit_id
171 :
172 177798762 : unit_id = cp_units_none
173 19755418 : kind_id = cp_ukind_none
174 19755418 : power = 0
175 19755418 : i_low = 1
176 19755418 : i_high = 1
177 19755418 : len_string = LEN(string)
178 19755418 : i_unit = 0
179 19755418 : next_power = 1
180 19755418 : DO WHILE (i_low < len_string)
181 18880944 : IF (string(i_low:i_low) /= ' ') EXIT
182 18880944 : i_low = i_low + 1
183 : END DO
184 : i_high = i_low
185 130012517 : DO WHILE (i_high <= len_string)
186 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
187 112392368 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
188 110257168 : i_high = i_high + 1
189 : END DO
190 : DO
191 20691580 : IF (i_high <= i_low .OR. i_low > len_string) EXIT
192 20635855 : i_unit = i_unit + 1
193 20635855 : IF (i_unit > cp_unit_max_kinds) THEN
194 0 : CPABORT("Maximum number of combined units exceeded")
195 0 : EXIT
196 : END IF
197 : ! read unit
198 20635855 : unit_string = string(i_low:i_high - 1)
199 20635855 : CALL uppercase(unit_string)
200 21543663 : SELECT CASE (TRIM(unit_string))
201 : CASE ("INTERNAL_CP2K")
202 907808 : unit_id(i_unit) = cp_units_none
203 907808 : kind_id(i_unit) = cp_ukind_undef
204 : CASE ("HARTREE")
205 960909 : unit_id(i_unit) = cp_units_hartree
206 960909 : kind_id(i_unit) = cp_ukind_energy
207 : CASE ("AU_E")
208 108912 : unit_id(i_unit) = cp_units_au
209 108912 : kind_id(i_unit) = cp_ukind_energy
210 : CASE ("WAVENUMBER_E")
211 0 : unit_id(i_unit) = cp_units_wavenum
212 0 : kind_id(i_unit) = cp_ukind_energy
213 : CASE ("JOULE", "J")
214 0 : unit_id(i_unit) = cp_units_joule
215 0 : kind_id(i_unit) = cp_ukind_energy
216 : CASE ("KCALMOL")
217 369641 : unit_id(i_unit) = cp_units_kcalmol
218 369641 : kind_id(i_unit) = cp_ukind_energy
219 : CASE ("KJMOL")
220 2248 : unit_id(i_unit) = cp_units_kjmol
221 2248 : kind_id(i_unit) = cp_ukind_energy
222 : CASE ("JMOL")
223 0 : unit_id(i_unit) = cp_units_jmol
224 0 : kind_id(i_unit) = cp_ukind_energy
225 : CASE ("RY")
226 295560 : unit_id(i_unit) = cp_units_Ry
227 295560 : kind_id(i_unit) = cp_ukind_energy
228 : CASE ("EV")
229 2833964 : unit_id(i_unit) = cp_units_eV
230 2833964 : kind_id(i_unit) = cp_ukind_energy
231 : CASE ("KEV")
232 29624 : unit_id(i_unit) = cp_units_keV
233 29624 : kind_id(i_unit) = cp_ukind_energy
234 : CASE ("K_E")
235 312692 : unit_id(i_unit) = cp_units_k
236 312692 : kind_id(i_unit) = cp_ukind_energy
237 : CASE ("ENERGY")
238 0 : unit_id(i_unit) = cp_units_none
239 0 : kind_id(i_unit) = cp_ukind_energy
240 : CASE ("AU_L")
241 278 : unit_id(i_unit) = cp_units_au
242 278 : kind_id(i_unit) = cp_ukind_length
243 : CASE ("BOHR")
244 2405610 : unit_id(i_unit) = cp_units_bohr
245 2405610 : kind_id(i_unit) = cp_ukind_length
246 : CASE ("M")
247 48263 : unit_id(i_unit) = cp_units_m
248 48263 : kind_id(i_unit) = cp_ukind_length
249 : CASE ("PM")
250 2 : unit_id(i_unit) = cp_units_pm
251 2 : kind_id(i_unit) = cp_ukind_length
252 : CASE ("NM")
253 19340 : unit_id(i_unit) = cp_units_nm
254 19340 : kind_id(i_unit) = cp_ukind_length
255 : CASE ("ANGSTROM")
256 8445814 : unit_id(i_unit) = cp_units_angstrom
257 8445814 : kind_id(i_unit) = cp_ukind_length
258 : CASE ("LENGTH")
259 0 : unit_id(i_unit) = cp_units_none
260 0 : kind_id(i_unit) = cp_ukind_length
261 : CASE ("K", "K_TEMP")
262 854586 : unit_id(i_unit) = cp_units_k
263 854586 : kind_id(i_unit) = cp_ukind_temperature
264 : CASE ("AU_TEMP")
265 4 : unit_id(i_unit) = cp_units_au
266 4 : kind_id(i_unit) = cp_ukind_temperature
267 : CASE ("TEMPERATURE")
268 0 : unit_id(i_unit) = cp_units_none
269 0 : kind_id(i_unit) = cp_ukind_temperature
270 : CASE ("ATM")
271 0 : unit_id(i_unit) = cp_units_atm
272 0 : kind_id(i_unit) = cp_ukind_pressure
273 : CASE ("BAR")
274 150843 : unit_id(i_unit) = cp_units_bar
275 150843 : kind_id(i_unit) = cp_ukind_pressure
276 : CASE ("KBAR")
277 16 : unit_id(i_unit) = cp_units_kbar
278 16 : kind_id(i_unit) = cp_ukind_pressure
279 : CASE ("PA")
280 18568 : unit_id(i_unit) = cp_units_Pa
281 18568 : kind_id(i_unit) = cp_ukind_pressure
282 : CASE ("MPA")
283 0 : unit_id(i_unit) = cp_units_MPa
284 0 : kind_id(i_unit) = cp_ukind_pressure
285 : CASE ("GPA")
286 9579 : unit_id(i_unit) = cp_units_GPa
287 9579 : kind_id(i_unit) = cp_ukind_pressure
288 : CASE ("AU_P")
289 0 : unit_id(i_unit) = cp_units_au
290 0 : kind_id(i_unit) = cp_ukind_pressure
291 : CASE ("PRESSURE")
292 0 : unit_id(i_unit) = cp_units_none
293 0 : kind_id(i_unit) = cp_ukind_pressure
294 : CASE ("RAD")
295 229897 : unit_id(i_unit) = cp_units_rad
296 229897 : kind_id(i_unit) = cp_ukind_angle
297 : CASE ("DEG")
298 271438 : unit_id(i_unit) = cp_units_deg
299 271438 : kind_id(i_unit) = cp_ukind_angle
300 : CASE ("ANGLE")
301 0 : unit_id(i_unit) = cp_units_none
302 0 : kind_id(i_unit) = cp_ukind_angle
303 : CASE ("S")
304 141095 : unit_id(i_unit) = cp_units_s
305 141095 : kind_id(i_unit) = cp_ukind_time
306 : CASE ("FS")
307 1504469 : unit_id(i_unit) = cp_units_fs
308 1504469 : kind_id(i_unit) = cp_ukind_time
309 : CASE ("PS")
310 428870 : unit_id(i_unit) = cp_units_ps
311 428870 : kind_id(i_unit) = cp_ukind_time
312 : CASE ("WAVENUMBER_T")
313 34 : unit_id(i_unit) = cp_units_wn
314 34 : kind_id(i_unit) = cp_ukind_time
315 : CASE ("AU_T")
316 107331 : unit_id(i_unit) = cp_units_au
317 107331 : kind_id(i_unit) = cp_ukind_time
318 : CASE ("TIME")
319 0 : unit_id(i_unit) = cp_units_none
320 0 : kind_id(i_unit) = cp_ukind_time
321 : CASE ("KG")
322 0 : unit_id(i_unit) = cp_units_kg
323 0 : kind_id(i_unit) = cp_ukind_mass
324 : CASE ("AMU")
325 9434 : unit_id(i_unit) = cp_units_amu
326 9434 : kind_id(i_unit) = cp_ukind_mass
327 : CASE ("M_E")
328 0 : unit_id(i_unit) = cp_units_m_e
329 0 : kind_id(i_unit) = cp_ukind_mass
330 : CASE ("AU_M")
331 29620 : unit_id(i_unit) = cp_units_au
332 29620 : kind_id(i_unit) = cp_ukind_mass
333 : CASE ("MASS")
334 0 : unit_id(i_unit) = cp_units_none
335 0 : kind_id(i_unit) = cp_ukind_mass
336 : CASE ("VOLT")
337 120776 : unit_id(i_unit) = cp_units_volt
338 120776 : kind_id(i_unit) = cp_ukind_potential
339 : CASE ("AU_POT")
340 0 : unit_id(i_unit) = cp_units_au
341 0 : kind_id(i_unit) = cp_ukind_potential
342 : CASE ("POTENTIAL")
343 0 : unit_id(i_unit) = cp_units_none
344 0 : kind_id(i_unit) = cp_ukind_potential
345 : CASE ("N", "NEWTON")
346 10 : unit_id(i_unit) = cp_units_Newton
347 10 : kind_id(i_unit) = cp_ukind_force
348 : CASE ("MN", "MNEWTON")
349 18620 : unit_id(i_unit) = cp_units_mNewton
350 18620 : kind_id(i_unit) = cp_ukind_force
351 : CASE ("AU_F")
352 0 : unit_id(i_unit) = cp_units_au
353 0 : kind_id(i_unit) = cp_ukind_force
354 : CASE ("FORCE")
355 0 : unit_id(i_unit) = cp_units_none
356 0 : kind_id(i_unit) = cp_ukind_force
357 : CASE ("AU")
358 : CALL cp_abort(__LOCATION__, &
359 : "au unit without specifying its kind not accepted, use "// &
360 0 : "(au_e, au_f, au_t, au_temp, au_l, au_m, au_p, au_pot)")
361 : CASE default
362 20635855 : CPABORT("Unknown unit: "//string(i_low:i_high - 1))
363 : END SELECT
364 20635855 : power(i_unit) = next_power
365 : ! parse op
366 20635855 : i_low = i_high
367 20671079 : DO WHILE (i_low <= len_string)
368 2963420 : IF (string(i_low:i_low) /= ' ') EXIT
369 2963420 : i_low = i_low + 1
370 : END DO
371 : i_high = i_low
372 20635855 : DO WHILE (i_high <= len_string)
373 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
374 2928196 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
375 0 : i_high = i_high + 1
376 : END DO
377 20635855 : IF (i_high < i_low .OR. i_low > len_string) EXIT
378 :
379 2928196 : IF (i_high <= len_string) THEN
380 2928196 : IF (string(i_low:i_high) == '^') THEN
381 2029411 : i_low = i_high + 1
382 2029411 : DO WHILE (i_low <= len_string)
383 2029411 : IF (string(i_low:i_low) /= ' ') EXIT
384 2029411 : i_low = i_low + 1
385 : END DO
386 : i_high = i_low
387 5924309 : DO WHILE (i_high <= len_string)
388 1992034 : SELECT CASE (string(i_high:i_high))
389 : CASE ('+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
390 3894898 : i_high = i_high + 1
391 : CASE default
392 3932275 : EXIT
393 : END SELECT
394 : END DO
395 2029411 : IF (i_high <= i_low .OR. i_low > len_string) THEN
396 0 : CPABORT("an integer number is expected after a '^'")
397 0 : EXIT
398 : END IF
399 2029411 : formatstr = "(i"//cp_to_string(i_high - i_low + 1)//")"
400 : READ (string(i_low:i_high - 1), formatstr) &
401 2029411 : next_power
402 2029411 : power(i_unit) = power(i_unit)*next_power
403 : ! next op
404 2029411 : i_low = i_high
405 2038367 : DO WHILE (i_low < len_string)
406 46312 : IF (string(i_low:i_low) /= ' ') EXIT
407 46312 : i_low = i_low + 1
408 : END DO
409 : i_high = i_low
410 2030605 : DO WHILE (i_high <= len_string)
411 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
412 38369 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
413 1215 : i_high = i_high + 1
414 : END DO
415 : END IF
416 : END IF
417 2928196 : IF (i_low > len_string) EXIT
418 936162 : next_power = 1
419 20691580 : IF (i_high <= len_string) THEN
420 935960 : IF (string(i_low:i_high) == "*" .OR. string(i_low:i_high) == '/') THEN
421 935939 : IF (string(i_low:i_high) == '/') next_power = -1
422 935939 : i_low = i_high + 1
423 935939 : DO WHILE (i_low <= len_string)
424 935939 : IF (string(i_low:i_low) /= ' ') EXIT
425 935939 : i_low = i_low + 1
426 : END DO
427 : i_high = i_low
428 4963701 : DO WHILE (i_high <= len_string)
429 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
430 4820758 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
431 4170726 : i_high = i_high + 1
432 : END DO
433 : END IF
434 : END IF
435 : END DO
436 : CALL cp_unit_create2(unit, kind_id=kind_id, unit_id=unit_id, &
437 19755418 : power=power)
438 19755418 : desc = cp_unit_desc(unit)
439 19755418 : END SUBROUTINE cp_unit_create
440 :
441 : ! **************************************************************************************************
442 : !> \brief creates and initializes the given unit of mesure (performs some error
443 : !> check)
444 : !> \param unit the unit descriptor to be initialized
445 : !> \param kind_id the kind of unit (length,energy,...), use the constants
446 : !> cp_ukind_*
447 : !> \param unit_id the actual unit (use constants cp_units_*)
448 : !> \param power ...
449 : !> \author fawzi
450 : ! **************************************************************************************************
451 556001824 : SUBROUTINE cp_unit_create2(unit, kind_id, unit_id, power)
452 : TYPE(cp_unit_type), INTENT(OUT) :: unit
453 : INTEGER, DIMENSION(:), INTENT(in) :: kind_id, unit_id
454 : INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: power
455 :
456 : INTEGER :: i, j, max_kind, max_pos
457 : LOGICAL :: repeat
458 :
459 19857208 : CPASSERT(SIZE(kind_id) <= cp_unit_max_kinds)
460 19857208 : CPASSERT(SIZE(unit_id) <= cp_unit_max_kinds)
461 178002342 : unit%kind_id(1:SIZE(kind_id)) = kind_id
462 20569738 : unit%kind_id(SIZE(kind_id) + 1:) = cp_ukind_none
463 178002342 : unit%unit_id(1:SIZE(unit_id)) = unit_id
464 40426946 : unit%unit_id(SIZE(unit_id):) = cp_units_none
465 19857208 : IF (PRESENT(power)) THEN
466 178002342 : unit%power(1:SIZE(power)) = power
467 20569738 : unit%power(SIZE(power) + 1:) = 0
468 178714872 : DO i = 1, SIZE(unit%power)
469 178714872 : IF (unit%power(i) == 0) THEN
470 138120019 : unit%kind_id(i) = cp_ukind_none
471 138120019 : unit%unit_id(i) = cp_units_none
472 : END IF
473 : END DO
474 : ELSE
475 0 : DO i = 1, SIZE(unit%power)
476 0 : IF (unit%unit_id(i) /= 0) THEN
477 0 : unit%power(i) = 1
478 : ELSE
479 0 : unit%power(i) = 0
480 : END IF
481 : END DO
482 : END IF
483 :
484 : ! remove unnecessary units
485 : ! reorder & compress
486 19857208 : unit%n_kinds = 0
487 178714872 : DO i = 1, SIZE(unit%kind_id)
488 : ! find max and compress in the rest
489 : DO
490 158857664 : max_kind = unit%kind_id(i)
491 158857664 : max_pos = i
492 158857664 : repeat = .FALSE.
493 714859488 : DO j = i + 1, SIZE(unit%kind_id)
494 714859488 : IF (unit%kind_id(j) >= max_kind) THEN
495 412691739 : IF (unit%kind_id(j) /= 0 .AND. unit%kind_id(j) == max_kind .AND. &
496 : unit%unit_id(j) == unit%unit_id(max_pos)) THEN
497 0 : unit%power(max_pos) = unit%power(max_pos) + unit%power(j)
498 0 : unit%kind_id(j) = cp_ukind_none
499 0 : unit%unit_id(j) = cp_units_none
500 0 : unit%power(j) = 0
501 0 : IF (unit%power(max_pos) == 0) THEN
502 0 : unit%kind_id(max_pos) = cp_ukind_none
503 0 : unit%unit_id(max_pos) = cp_units_none
504 0 : unit%power(max_pos) = 0
505 0 : repeat = .TRUE.
506 0 : EXIT
507 : END IF
508 412691739 : ELSE IF (unit%kind_id(j) > max_kind .OR. &
509 : (unit%kind_id(j) == max_kind .AND. &
510 : unit%unit_id(j) > unit%unit_id(max_pos))) THEN
511 898717 : max_kind = unit%kind_id(j)
512 898717 : max_pos = j
513 : END IF
514 : END IF
515 : END DO
516 158857664 : IF (.NOT. repeat) EXIT
517 : END DO
518 158857664 : IF (max_kind /= 0) unit%n_kinds = unit%n_kinds + 1
519 : ! put the max at pos i
520 158857664 : IF (max_pos /= i) THEN
521 880145 : unit%kind_id(max_pos) = unit%kind_id(i)
522 880145 : unit%kind_id(i) = max_kind
523 880145 : max_kind = unit%unit_id(max_pos)
524 880145 : unit%unit_id(max_pos) = unit%unit_id(i)
525 880145 : unit%unit_id(i) = max_kind
526 880145 : max_kind = unit%power(max_pos)
527 880145 : unit%power(max_pos) = unit%power(i)
528 880145 : unit%power(i) = max_kind
529 : END IF
530 : ! check unit
531 : CALL cp_basic_unit_check(basic_kind=unit%kind_id(i), &
532 178714872 : basic_unit=unit%unit_id(i))
533 : END DO
534 19857208 : END SUBROUTINE cp_unit_create2
535 :
536 : ! **************************************************************************************************
537 : !> \brief releases the given unit
538 : !> \param unit the unit to release
539 : !> \author fawzi
540 : !> \note
541 : !> at the moment not needed, there for completeness
542 : ! **************************************************************************************************
543 19857208 : ELEMENTAL SUBROUTINE cp_unit_release(unit)
544 : TYPE(cp_unit_type), INTENT(IN) :: unit
545 :
546 : MARK_USED(unit)
547 :
548 19857208 : END SUBROUTINE cp_unit_release
549 :
550 : ! **************************************************************************************************
551 : !> \brief controls that the kind and contains meaningful information
552 : !> \param basic_kind the kind of the unit
553 : !> \param basic_unit the unit to check
554 : !> \author fawzi
555 : ! **************************************************************************************************
556 158857664 : SUBROUTINE cp_basic_unit_check(basic_kind, basic_unit)
557 : INTEGER, INTENT(in) :: basic_kind, basic_unit
558 :
559 159775651 : SELECT CASE (basic_kind)
560 : CASE (cp_ukind_undef)
561 5841716 : SELECT CASE (basic_unit)
562 : CASE (cp_units_none)
563 : CASE default
564 917987 : CPABORT("unknown undef unit:"//TRIM(cp_to_string(basic_unit)))
565 : END SELECT
566 : CASE (cp_ukind_energy)
567 15853215 : SELECT CASE (basic_unit)
568 : CASE (cp_units_hartree, cp_units_wavenum, cp_units_joule, cp_units_kcalmol, &
569 : cp_units_kjmol, cp_units_Ry, cp_units_eV, cp_units_keV, cp_units_au, cp_units_k, &
570 : cp_units_jmol, cp_units_none)
571 : CASE default
572 4923729 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
573 : END SELECT
574 : CASE (cp_ukind_length)
575 11794255 : SELECT CASE (basic_unit)
576 : CASE (cp_units_bohr, cp_units_angstrom, cp_units_au, cp_units_none, cp_units_m, &
577 : cp_units_pm, cp_units_nm)
578 : CASE default
579 10929486 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
580 : END SELECT
581 : CASE (cp_ukind_temperature)
582 1053954 : SELECT CASE (basic_unit)
583 : CASE (cp_units_k, cp_units_au, cp_units_none)
584 : CASE default
585 864769 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
586 : END SELECT
587 : CASE (cp_ukind_pressure)
588 700699 : SELECT CASE (basic_unit)
589 : CASE (cp_units_bar, cp_units_atm, cp_units_kbar, cp_units_Pa, cp_units_MPa, cp_units_GPa, cp_units_au, cp_units_none)
590 : CASE default
591 189185 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
592 : END SELECT
593 : CASE (cp_ukind_angle)
594 2703492 : SELECT CASE (basic_unit)
595 : CASE (cp_units_rad, cp_units_deg, cp_units_none)
596 : CASE default
597 511514 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
598 : END SELECT
599 : CASE (cp_ukind_time)
600 2241211 : SELECT CASE (basic_unit)
601 : CASE (cp_units_s, cp_units_fs, cp_units_ps, cp_units_au, cp_units_wn, cp_units_none)
602 : CASE default
603 2191978 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
604 : END SELECT
605 : CASE (cp_ukind_mass)
606 180188 : SELECT CASE (basic_unit)
607 : CASE (cp_units_kg, cp_units_amu, cp_units_m_e, cp_units_au, cp_units_none)
608 : CASE default
609 49233 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
610 : END SELECT
611 : CASE (cp_ukind_potential)
612 159764 : SELECT CASE (basic_unit)
613 : CASE (cp_units_volt, cp_units_au, cp_units_none)
614 : CASE default
615 130955 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
616 : END SELECT
617 : CASE (cp_ukind_force)
618 138148828 : SELECT CASE (basic_unit)
619 : CASE (cp_units_Newton, cp_units_mNewton, cp_units_au, cp_units_none)
620 : CASE default
621 28809 : CPABORT("unknown force unit:"//TRIM(cp_to_string(basic_unit)))
622 : END SELECT
623 : CASE (cp_ukind_none)
624 138120019 : IF (basic_unit /= cp_units_none) &
625 : CALL cp_abort(__LOCATION__, &
626 : "if the kind of the unit is none also unit must be undefined,not:" &
627 0 : //TRIM(cp_to_string(basic_unit)))
628 : CASE default
629 158857664 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
630 : END SELECT
631 158857664 : END SUBROUTINE cp_basic_unit_check
632 :
633 : ! **************************************************************************************************
634 : !> \brief converts a value to the internal cp2k units
635 : !> \param value the value to convert
636 : !> \param basic_kind the kind of the unit of the value
637 : !> \param basic_unit the unit of the value
638 : !> \param power the power of the unit (defaults to 1)
639 : !> \return ...
640 : !> \author fawzi
641 : ! **************************************************************************************************
642 7644349 : FUNCTION cp_basic_unit_to_cp2k(value, basic_kind, basic_unit, power) RESULT(res)
643 : REAL(kind=dp), INTENT(in) :: value
644 : INTEGER, INTENT(in) :: basic_kind, basic_unit
645 : INTEGER, INTENT(in), OPTIONAL :: power
646 : REAL(kind=dp) :: res
647 :
648 : INTEGER :: my_power
649 :
650 7644349 : my_power = 1
651 7644349 : IF (PRESENT(power)) my_power = power
652 7644349 : IF (basic_unit == cp_units_none .AND. basic_kind /= cp_ukind_undef) THEN
653 0 : IF (basic_kind /= cp_units_none) &
654 : CALL cp_abort(__LOCATION__, &
655 : "unit not yet fully specified, unit of kind "// &
656 0 : TRIM(cp_to_string(basic_unit)))
657 : END IF
658 7711080 : SELECT CASE (basic_kind)
659 : CASE (cp_ukind_undef)
660 1705577 : SELECT CASE (basic_unit)
661 : CASE (cp_units_none)
662 66731 : res = value
663 : CASE default
664 66731 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
665 : END SELECT
666 : CASE (cp_ukind_energy)
667 4495689 : SELECT CASE (basic_unit)
668 : CASE (cp_units_hartree, cp_units_au)
669 186367 : res = value
670 : CASE (cp_units_wavenum)
671 0 : res = wavenumbers**(-my_power)*value
672 : CASE (cp_units_joule)
673 0 : res = joule**(-my_power)*value
674 : CASE (cp_units_kcalmol)
675 230435 : res = kcalmol**(-my_power)*value
676 : CASE (cp_units_kjmol)
677 2248 : res = kjmol**(-my_power)*value
678 : CASE (cp_units_jmol)
679 0 : res = (kjmol*1.0E+3_dp)**(-my_power)*value
680 : CASE (cp_units_Ry)
681 43217 : res = 0.5_dp**my_power*value
682 : CASE (cp_units_eV)
683 1153160 : res = evolt**(-my_power)*value
684 : CASE (cp_units_keV)
685 8 : res = (1.0E-3_dp*evolt)**(-my_power)*value
686 : CASE (cp_units_k)
687 23411 : res = kelvin**(-my_power)*value
688 : CASE default
689 1638846 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
690 : END SELECT
691 : CASE (cp_ukind_length)
692 758318 : SELECT CASE (basic_unit)
693 : CASE (cp_units_bohr, cp_units_au)
694 442870 : res = value
695 : CASE (cp_units_m)
696 54 : res = value*(1.0E10_dp*bohr)**my_power
697 : CASE (cp_units_pm)
698 2 : res = value*(0.01_dp*bohr)**my_power
699 : CASE (cp_units_nm)
700 10066 : res = value*(10.0_dp*bohr)**my_power
701 : CASE (cp_units_angstrom)
702 3856330 : res = value*bohr**my_power
703 : CASE default
704 4309322 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
705 : END SELECT
706 : CASE (cp_ukind_temperature)
707 402266 : SELECT CASE (basic_unit)
708 : CASE (cp_units_k)
709 315444 : res = kelvin**(-my_power)*value
710 : CASE (cp_units_au)
711 4 : res = value
712 : CASE default
713 315448 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
714 : END SELECT
715 : CASE (cp_ukind_pressure)
716 379218 : SELECT CASE (basic_unit)
717 : CASE (cp_units_bar)
718 77242 : res = bar**(-my_power)*value
719 : CASE (cp_units_atm)
720 0 : res = atm**(-my_power)*value
721 : CASE (cp_units_kbar)
722 16 : res = (1.0E-3_dp*bar)**(-my_power)*value
723 : CASE (cp_units_Pa)
724 9284 : res = pascal**(-my_power)*value
725 : CASE (cp_units_MPa)
726 0 : res = (1.0E-6_dp*pascal)**(-my_power)*value
727 : CASE (cp_units_GPa)
728 280 : res = (1.0E-9_dp*pascal)**(-my_power)*value
729 : CASE (cp_units_au)
730 0 : res = value
731 : CASE default
732 86822 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
733 : END SELECT
734 : CASE (cp_ukind_angle)
735 994999 : SELECT CASE (basic_unit)
736 : CASE (cp_units_rad)
737 70095 : res = value
738 : CASE (cp_units_deg)
739 231881 : res = value*(radians)**my_power
740 : CASE default
741 301976 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
742 : END SELECT
743 : CASE (cp_ukind_time)
744 215 : SELECT CASE (basic_unit)
745 : CASE (cp_units_s)
746 24 : res = value*seconds**(-my_power)
747 : CASE (cp_units_fs)
748 545847 : res = value*femtoseconds**(-my_power)
749 : CASE (cp_units_ps)
750 330730 : res = value*picoseconds**(-my_power)
751 : CASE (cp_units_au)
752 48269 : res = value
753 : CASE (cp_units_wn)
754 34 : res = (twopi*wavenumbers)**(my_power)/value
755 : CASE default
756 924904 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
757 : END SELECT
758 : CASE (cp_ukind_mass)
759 77 : SELECT CASE (basic_unit)
760 : CASE (cp_units_kg)
761 0 : res = e_mass**my_power*value
762 : CASE (cp_units_amu)
763 182 : res = massunit**my_power*value
764 : CASE (cp_units_m_e, cp_units_au)
765 9 : res = value
766 : CASE default
767 191 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
768 : END SELECT
769 : CASE (cp_ukind_potential)
770 109 : SELECT CASE (basic_unit)
771 : CASE (cp_units_volt)
772 77 : res = evolt**(-my_power)*value
773 : CASE (cp_units_au)
774 0 : res = value
775 : CASE default
776 77 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
777 : END SELECT
778 : CASE (cp_ukind_force)
779 10 : SELECT CASE (basic_unit)
780 : CASE (cp_units_Newton)
781 10 : res = value*newton**(-my_power)
782 : CASE (cp_units_mNewton)
783 22 : res = value*(1.0E+3*newton)**(-my_power)
784 : CASE (cp_units_au)
785 0 : res = value
786 : CASE default
787 32 : CPABORT("unknown force unit:"//TRIM(cp_to_string(basic_unit)))
788 : END SELECT
789 : CASE (cp_ukind_none)
790 : CALL cp_abort(__LOCATION__, &
791 : "if the kind of the unit is none also unit must be undefined,not:" &
792 0 : //TRIM(cp_to_string(basic_unit)))
793 : CASE default
794 7644349 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
795 : END SELECT
796 7644349 : END FUNCTION cp_basic_unit_to_cp2k
797 :
798 : ! **************************************************************************************************
799 : !> \brief returns the label of the current basic unit
800 : !> \param basic_kind the kind of the unit of the value
801 : !> \param basic_unit the unit of the value
802 : !> \param power the power of the unit (defaults to 1)
803 : !> \param accept_undefined ...
804 : !> \return ...
805 : !> \author fawzi
806 : ! **************************************************************************************************
807 20635855 : FUNCTION cp_basic_unit_desc(basic_kind, basic_unit, power, accept_undefined) &
808 : RESULT(res)
809 : INTEGER, INTENT(in) :: basic_kind, basic_unit
810 : INTEGER, INTENT(in), OPTIONAL :: power
811 : LOGICAL, INTENT(in), OPTIONAL :: accept_undefined
812 : CHARACTER(len=cp_unit_basic_desc_length) :: res
813 :
814 : INTEGER :: a, my_power
815 : LOGICAL :: my_accept_undefined
816 :
817 20635855 : my_power = 1
818 20635855 : res = ""
819 20635855 : my_accept_undefined = .FALSE.
820 20635855 : IF (accept_undefined) my_accept_undefined = accept_undefined
821 20635855 : IF (PRESENT(power)) my_power = power
822 20635855 : IF (basic_unit == cp_units_none) THEN
823 907808 : IF (.NOT. my_accept_undefined .AND. basic_kind == cp_units_none) &
824 : CALL cp_abort(__LOCATION__, "unit not yet fully specified, unit of kind "// &
825 0 : TRIM(cp_to_string(basic_kind)))
826 : END IF
827 21543663 : SELECT CASE (basic_kind)
828 : CASE (cp_ukind_undef)
829 5821358 : SELECT CASE (basic_unit)
830 : CASE (cp_units_none)
831 907808 : res = "internal_cp2k"
832 : CASE DEFAULT
833 : CALL cp_abort(__LOCATION__, &
834 : "unit not yet fully specified, unit of kind "// &
835 907808 : TRIM(res))
836 : END SELECT
837 : CASE (cp_ukind_energy)
838 11989128 : SELECT CASE (basic_unit)
839 : CASE (cp_units_hartree, cp_units_au)
840 1069821 : res = "hartree"
841 : CASE (cp_units_wavenum)
842 0 : res = "wavenumber_e"
843 : CASE (cp_units_joule)
844 0 : res = "joule"
845 : CASE (cp_units_kcalmol)
846 369641 : res = "kcalmol"
847 : CASE (cp_units_kjmol)
848 2248 : res = "kjmol"
849 : CASE (cp_units_jmol)
850 0 : res = "jmol"
851 : CASE (cp_units_Ry)
852 295560 : res = "Ry"
853 : CASE (cp_units_eV)
854 2833964 : res = "eV"
855 : CASE (cp_units_keV)
856 29624 : res = "keV"
857 : CASE (cp_units_k)
858 312692 : res = "K_e"
859 : CASE (cp_units_none)
860 0 : res = "energy"
861 0 : IF (.NOT. my_accept_undefined) &
862 : CALL cp_abort(__LOCATION__, &
863 : "unit not yet fully specified, unit of kind "// &
864 0 : TRIM(res))
865 : CASE default
866 4913550 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
867 : END SELECT
868 : CASE (cp_ukind_length)
869 3260478 : SELECT CASE (basic_unit)
870 : CASE (cp_units_bohr, cp_units_au)
871 2405888 : res = "bohr"
872 : CASE (cp_units_m)
873 48263 : res = "m"
874 : CASE (cp_units_pm)
875 2 : res = "pm"
876 : CASE (cp_units_nm)
877 19340 : res = "nm"
878 : CASE (cp_units_angstrom)
879 8445814 : res = "angstrom"
880 : CASE default
881 0 : res = "length"
882 10919307 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
883 : END SELECT
884 : CASE (cp_ukind_temperature)
885 1033592 : SELECT CASE (basic_unit)
886 : CASE (cp_units_k)
887 854586 : res = "K"
888 : CASE (cp_units_au)
889 4 : res = "au_temp"
890 : CASE (cp_units_none)
891 0 : res = "temperature"
892 0 : IF (.NOT. my_accept_undefined) &
893 : CALL cp_abort(__LOCATION__, &
894 : "unit not yet fully specified, unit of kind "// &
895 0 : TRIM(res))
896 : CASE default
897 854590 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
898 : END SELECT
899 : CASE (cp_ukind_pressure)
900 652178 : SELECT CASE (basic_unit)
901 : CASE (cp_units_bar)
902 150843 : res = "bar"
903 : CASE (cp_units_atm)
904 0 : res = "atm"
905 : CASE (cp_units_kbar)
906 16 : res = "kbar"
907 : CASE (cp_units_Pa)
908 18568 : res = "Pa"
909 : CASE (cp_units_MPa)
910 0 : res = "MPa"
911 : CASE (cp_units_GPa)
912 9579 : res = "GPa"
913 : CASE (cp_units_au)
914 0 : res = "au_p"
915 : CASE (cp_units_none)
916 0 : res = "pressure"
917 0 : IF (.NOT. my_accept_undefined) &
918 : CALL cp_abort(__LOCATION__, &
919 : "unit not yet fully specified, unit of kind "// &
920 0 : TRIM(res))
921 : CASE default
922 179006 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
923 : END SELECT
924 : CASE (cp_ukind_angle)
925 2411696 : SELECT CASE (basic_unit)
926 : CASE (cp_units_rad)
927 229897 : res = "rad"
928 : CASE (cp_units_deg)
929 271438 : res = "deg"
930 : CASE (cp_units_none)
931 0 : res = "angle"
932 0 : IF (.NOT. my_accept_undefined) &
933 : CALL cp_abort(__LOCATION__, &
934 : "unit not yet fully specified, unit of kind "// &
935 0 : TRIM(res))
936 : CASE default
937 501335 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
938 : END SELECT
939 : CASE (cp_ukind_time)
940 180149 : SELECT CASE (basic_unit)
941 : CASE (cp_units_s)
942 141095 : res = "s"
943 : CASE (cp_units_fs)
944 1504469 : res = "fs"
945 : CASE (cp_units_ps)
946 428870 : res = "ps"
947 : CASE (cp_units_au)
948 107331 : res = "au_t"
949 : CASE (cp_units_wn)
950 34 : res = "wavenumber_t"
951 : CASE (cp_units_none)
952 0 : res = "time"
953 0 : IF (.NOT. my_accept_undefined) &
954 : CALL cp_abort(__LOCATION__, &
955 : "unit not yet fully specified, unit of kind "// &
956 0 : TRIM(res))
957 : CASE default
958 2181799 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
959 : END SELECT
960 : CASE (cp_ukind_mass)
961 120776 : SELECT CASE (basic_unit)
962 : CASE (cp_units_kg)
963 0 : res = "kg"
964 : CASE (cp_units_amu)
965 9434 : res = "amu"
966 : CASE (cp_units_m_e, cp_units_au)
967 29620 : res = "m_e"
968 : CASE (cp_units_none)
969 0 : res = "mass"
970 0 : IF (.NOT. my_accept_undefined) &
971 : CALL cp_abort(__LOCATION__, &
972 : "unit not yet fully specified, unit of kind "// &
973 0 : TRIM(res))
974 : CASE default
975 39054 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
976 : END SELECT
977 : CASE (cp_ukind_potential)
978 139406 : SELECT CASE (basic_unit)
979 : CASE (cp_units_volt)
980 120776 : res = "volt"
981 : CASE (cp_units_au)
982 0 : res = "au_pot"
983 : CASE (cp_units_none)
984 0 : res = "potential"
985 0 : IF (.NOT. my_accept_undefined) &
986 : CALL cp_abort(__LOCATION__, &
987 : "unit not yet fully specified, unit of kind "// &
988 0 : TRIM(res))
989 : CASE default
990 120776 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
991 : END SELECT
992 : CASE (cp_ukind_force)
993 10 : SELECT CASE (basic_unit)
994 : CASE (cp_units_Newton)
995 10 : res = "N"
996 : CASE (cp_units_mNewton)
997 18620 : res = "mN"
998 : CASE (cp_units_au)
999 0 : res = "au_f"
1000 : CASE (cp_units_none)
1001 0 : res = "force"
1002 0 : IF (.NOT. my_accept_undefined) &
1003 : CALL cp_abort(__LOCATION__, &
1004 : "unit not yet fully specified, unit of kind "// &
1005 0 : TRIM(res))
1006 : CASE default
1007 18630 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
1008 : END SELECT
1009 : CASE (cp_ukind_none)
1010 : CALL cp_abort(__LOCATION__, &
1011 : "if the kind of the unit is none also unit must be undefined,not:" &
1012 0 : //TRIM(cp_to_string(basic_unit)))
1013 : CASE default
1014 20635855 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
1015 : END SELECT
1016 20635855 : IF (my_power /= 1) THEN
1017 2153772 : a = LEN_TRIM(res)
1018 2153772 : CPASSERT(LEN(res) - a >= 3)
1019 2153772 : WRITE (res(a + 1:), "('^',i3)") my_power
1020 2153772 : CALL compress(res, .TRUE.)
1021 : END IF
1022 20635855 : END FUNCTION cp_basic_unit_desc
1023 :
1024 : ! **************************************************************************************************
1025 : !> \brief returns the "name" of the given unit
1026 : !> \param unit the unit to describe
1027 : !> \param defaults defaults for the undefined units, optional
1028 : !> \param accept_undefined if defaults is not present or is not associated
1029 : !> whether undefined units should be accepted (defaults to false)
1030 : !> \return ...
1031 : !> \author fawzi
1032 : ! **************************************************************************************************
1033 19755418 : FUNCTION cp_unit_desc(unit, defaults, accept_undefined) &
1034 : RESULT(res)
1035 : TYPE(cp_unit_type), INTENT(IN) :: unit
1036 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1037 : LOGICAL, INTENT(in), OPTIONAL :: accept_undefined
1038 : CHARACTER(len=cp_unit_desc_length) :: res
1039 :
1040 : INTEGER :: i, my_unit, pos
1041 : LOGICAL :: check, has_defaults, my_accept_undefined
1042 :
1043 19755418 : res = ""
1044 19755418 : pos = 1
1045 19755418 : my_accept_undefined = .FALSE.
1046 19755418 : IF (PRESENT(accept_undefined)) my_accept_undefined = accept_undefined
1047 40391273 : DO i = 1, unit%n_kinds
1048 20635855 : CPASSERT(unit%kind_id(i) /= 0)
1049 20635855 : CPASSERT(pos < LEN(res))
1050 20635855 : my_unit = unit%unit_id(i)
1051 20635855 : has_defaults = .FALSE.
1052 20635855 : IF (PRESENT(defaults)) has_defaults = ASSOCIATED(defaults%units(1)%unit)
1053 20635855 : IF (my_unit == 0) THEN
1054 0 : IF (has_defaults) THEN
1055 0 : my_unit = defaults%units(unit%kind_id(i))%unit%unit_id(1)
1056 : ELSE
1057 0 : check = my_accept_undefined .OR. unit%kind_id(i) /= 0
1058 0 : CPASSERT(check)
1059 : END IF
1060 : END IF
1061 20635855 : IF (i > 1) THEN
1062 936141 : res(pos:pos) = "*"
1063 936141 : pos = pos + 1
1064 : END IF
1065 : res(pos:) = TRIM(cp_basic_unit_desc(basic_kind=unit%kind_id(i), &
1066 : basic_unit=my_unit, accept_undefined=my_accept_undefined, &
1067 20635855 : power=unit%power(i)))
1068 40391273 : pos = LEN_TRIM(res) + 1
1069 : END DO
1070 :
1071 19755418 : END FUNCTION cp_unit_desc
1072 :
1073 : ! **************************************************************************************************
1074 : !> \brief transform a value to the internal cp2k units
1075 : !> \param value the value to convert
1076 : !> \param unit the unit of the result
1077 : !> \param defaults the defaults unit for those that are left free
1078 : !> (cp_units_none)
1079 : !> \param power the power of the unit (defaults to 1)
1080 : !> \return ...
1081 : !> \author fawzi
1082 : ! **************************************************************************************************
1083 7096019 : FUNCTION cp_unit_to_cp2k1(value, unit, defaults, power) RESULT(res)
1084 : REAL(kind=dp), INTENT(in) :: value
1085 : TYPE(cp_unit_type), INTENT(IN) :: unit
1086 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1087 : INTEGER, INTENT(in), OPTIONAL :: power
1088 : REAL(kind=dp) :: res
1089 :
1090 : INTEGER :: i_unit, my_basic_unit, my_power
1091 :
1092 7096019 : my_power = 1
1093 7096019 : IF (PRESENT(power)) my_power = power
1094 7096019 : res = value
1095 14740368 : DO i_unit = 1, unit%n_kinds
1096 7644349 : CPASSERT(unit%kind_id(i_unit) > 0)
1097 7644349 : my_basic_unit = unit%unit_id(i_unit)
1098 7644349 : IF (my_basic_unit == 0 .AND. unit%kind_id(i_unit) /= cp_ukind_undef) THEN
1099 0 : CPASSERT(PRESENT(defaults))
1100 0 : CPASSERT(ASSOCIATED(defaults%units(unit%kind_id(i_unit))%unit))
1101 0 : my_basic_unit = defaults%units(unit%kind_id(i_unit))%unit%unit_id(1)
1102 : END IF
1103 : res = cp_basic_unit_to_cp2k(value=res, basic_unit=my_basic_unit, &
1104 : basic_kind=unit%kind_id(i_unit), &
1105 14740368 : power=my_power*unit%power(i_unit))
1106 : END DO
1107 7096019 : END FUNCTION cp_unit_to_cp2k1
1108 :
1109 : ! **************************************************************************************************
1110 : !> \brief converts from the internal cp2k units to the given unit
1111 : !> \param value the value to convert
1112 : !> \param unit the unit of the result
1113 : !> \param defaults the defaults unit for those that are left free
1114 : !> (cp_units_none)
1115 : !> \param power the power of the unit (defaults to 1)
1116 : !> \return ...
1117 : !> \author fawzi
1118 : ! **************************************************************************************************
1119 769087 : FUNCTION cp_unit_from_cp2k1(value, unit, defaults, power) RESULT(res)
1120 : REAL(kind=dp), INTENT(in) :: value
1121 : TYPE(cp_unit_type), INTENT(IN) :: unit
1122 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1123 : INTEGER, INTENT(in), OPTIONAL :: power
1124 : REAL(kind=dp) :: res
1125 :
1126 : INTEGER :: my_power
1127 :
1128 769087 : my_power = 1
1129 769087 : IF (PRESENT(power)) my_power = power
1130 769087 : IF (PRESENT(defaults)) THEN
1131 : res = cp_unit_to_cp2k1(value=value, unit=unit, defaults=defaults, &
1132 0 : power=-my_power)
1133 : ELSE
1134 769087 : res = cp_unit_to_cp2k1(value=value, unit=unit, power=-my_power)
1135 : END IF
1136 769087 : END FUNCTION cp_unit_from_cp2k1
1137 :
1138 : ! **************************************************************************************************
1139 : !> \brief converts to the internal cp2k units to the given unit
1140 : !> \param value the value to convert
1141 : !> \param unit_str the unit of the result as string
1142 : !> \param defaults the defaults unit for those that are left free
1143 : !> (cp_units_none)
1144 : !> \param power the power of the unit (defaults to 1)
1145 : !> \return ...
1146 : !> \author fawzi
1147 : ! **************************************************************************************************
1148 6220293 : FUNCTION cp_unit_to_cp2k(value, unit_str, defaults, power) RESULT(res)
1149 : REAL(kind=dp), INTENT(in) :: value
1150 : CHARACTER(len=*), INTENT(in) :: unit_str
1151 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1152 : INTEGER, INTENT(in), OPTIONAL :: power
1153 : REAL(kind=dp) :: res
1154 :
1155 : TYPE(cp_unit_type) :: my_unit
1156 :
1157 6220293 : CALL cp_unit_create(my_unit, unit_str)
1158 6220293 : IF (PRESENT(defaults)) THEN
1159 : res = cp_unit_to_cp2k1(value=value, unit=my_unit, defaults=defaults, &
1160 0 : power=power)
1161 : ELSE
1162 6220293 : res = cp_unit_to_cp2k1(value=value, unit=my_unit, power=power)
1163 : END IF
1164 6220293 : CALL cp_unit_release(my_unit)
1165 167947911 : END FUNCTION cp_unit_to_cp2k
1166 :
1167 : ! **************************************************************************************************
1168 : !> \brief converts from the internal cp2k units to the given unit
1169 : !> \param value the value to convert
1170 : !> \param unit_str the unit of the result as string
1171 : !> \param defaults the defaults unit for those that are left free
1172 : !> (cp_units_none)
1173 : !> \param power the power of the unit (defaults to 1)
1174 : !> \return ...
1175 : !> \author fawzi
1176 : ! **************************************************************************************************
1177 565327 : FUNCTION cp_unit_from_cp2k(value, unit_str, defaults, power) RESULT(res)
1178 : REAL(kind=dp), INTENT(in) :: value
1179 : CHARACTER(len=*), INTENT(in) :: unit_str
1180 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1181 : INTEGER, INTENT(in), OPTIONAL :: power
1182 : REAL(kind=dp) :: res
1183 :
1184 : TYPE(cp_unit_type) :: my_unit
1185 :
1186 565327 : CALL cp_unit_create(my_unit, unit_str)
1187 565327 : IF (PRESENT(defaults)) THEN
1188 : res = cp_unit_from_cp2k1(value=value, unit=my_unit, defaults=defaults, &
1189 0 : power=power)
1190 : ELSE
1191 565327 : res = cp_unit_from_cp2k1(value=value, unit=my_unit, power=power)
1192 : END IF
1193 565327 : CALL cp_unit_release(my_unit)
1194 15263829 : END FUNCTION cp_unit_from_cp2k
1195 :
1196 : ! **************************************************************************************************
1197 : !> \brief returs true if the two units are compatible
1198 : !> \param ref_unit ...
1199 : !> \param unit ...
1200 : !> \return ...
1201 : !> \author Teodoro Laino [tlaino] - 11.2007 - University of Zurich
1202 : ! **************************************************************************************************
1203 106639 : FUNCTION cp_unit_compatible(ref_unit, unit) RESULT(res)
1204 : TYPE(cp_unit_type), INTENT(IN) :: ref_unit, unit
1205 : LOGICAL :: res
1206 :
1207 : INTEGER :: i
1208 :
1209 106639 : res = .TRUE.
1210 959751 : DO i = 1, SIZE(ref_unit%kind_id)
1211 853112 : IF (ref_unit%kind_id(i) == unit%kind_id(i)) CYCLE
1212 5200 : IF ((ref_unit%kind_id(1) == cp_ukind_undef) .AND. (ALL(ref_unit%kind_id(2:) == cp_ukind_none))) CYCLE
1213 : res = .FALSE.
1214 959751 : EXIT
1215 : END DO
1216 :
1217 106639 : END FUNCTION cp_unit_compatible
1218 :
1219 : ! **************************************************************************************************
1220 : !> \brief initializes the given unit set
1221 : !> \param unit_set the set to initialize
1222 : !> \param name the name of the set, used for the dafault initialization of
1223 : !> the various units
1224 : !> \author fawzi
1225 : ! **************************************************************************************************
1226 111969 : SUBROUTINE cp_unit_set_create(unit_set, name)
1227 : TYPE(cp_unit_set_type), INTENT(OUT) :: unit_set
1228 : CHARACTER(len=*), INTENT(in) :: name
1229 :
1230 : CHARACTER(len=cp_unit_desc_length) :: my_name
1231 : INTEGER :: i
1232 :
1233 10179 : my_name = name
1234 10179 : CALL uppercase(my_name)
1235 :
1236 111969 : DO i = 1, cp_ukind_max
1237 101790 : NULLIFY (unit_set%units(i)%unit)
1238 2554929 : ALLOCATE (unit_set%units(i)%unit)
1239 : END DO
1240 111969 : DO i = 1, cp_ukind_max
1241 10179 : SELECT CASE (name)
1242 : CASE ('ATOM', 'ATOMIC', 'INTERNAL', 'CP2K')
1243 0 : IF (i == cp_ukind_angle) THEN
1244 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], &
1245 0 : unit_id=[cp_units_rad], power=[1])
1246 : ELSE
1247 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], &
1248 0 : unit_id=[cp_units_au], power=[1])
1249 : END IF
1250 : CASE ('OUTPUT')
1251 10179 : SELECT CASE (i)
1252 : CASE (cp_ukind_undef)
1253 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_none], &
1254 20358 : power=[1])
1255 : CASE (cp_ukind_energy)
1256 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_hartree], &
1257 20358 : power=[1])
1258 : CASE (cp_ukind_length)
1259 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_angstrom], &
1260 20358 : power=[1])
1261 : CASE (cp_ukind_temperature)
1262 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_k], &
1263 20358 : power=[1])
1264 : CASE (cp_ukind_angle)
1265 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_deg], &
1266 20358 : power=[1])
1267 : CASE (cp_ukind_pressure)
1268 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_bar], &
1269 20358 : power=[1])
1270 : CASE (cp_ukind_time)
1271 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_fs], &
1272 20358 : power=[1])
1273 : CASE (cp_ukind_mass)
1274 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_amu], &
1275 20358 : power=[1])
1276 : CASE (cp_ukind_potential)
1277 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_volt], &
1278 20358 : power=[1])
1279 : CASE (cp_ukind_force)
1280 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_newton], &
1281 20358 : power=[1])
1282 : CASE default
1283 0 : CPABORT("unhandled unit type "//TRIM(cp_to_string(i)))
1284 101790 : EXIT
1285 : END SELECT
1286 : CASE default
1287 101790 : CPABORT('unknown parameter set name '//TRIM(name))
1288 : END SELECT
1289 : END DO
1290 10179 : END SUBROUTINE cp_unit_set_create
1291 :
1292 : ! **************************************************************************************************
1293 : !> \brief releases the given unit set
1294 : !> \param unit_set the unit set to release
1295 : !> \author fawzi
1296 : ! **************************************************************************************************
1297 10179 : SUBROUTINE cp_unit_set_release(unit_set)
1298 : TYPE(cp_unit_set_type), INTENT(INOUT) :: unit_set
1299 :
1300 : INTEGER :: i
1301 :
1302 111969 : DO i = 1, SIZE(unit_set%units)
1303 101790 : CALL cp_unit_release(unit_set%units(i)%unit)
1304 111969 : DEALLOCATE (unit_set%units(i)%unit)
1305 : END DO
1306 :
1307 10179 : END SUBROUTINE cp_unit_set_release
1308 :
1309 : ! **************************************************************************************************
1310 : !> \brief Exports all available units as XML.
1311 : !> \param iw ...
1312 : !> \author Ole Schuett
1313 : ! **************************************************************************************************
1314 0 : SUBROUTINE export_units_as_xml(iw)
1315 : INTEGER, INTENT(IN) :: iw
1316 :
1317 : CALL format_units_as_xml("energy", s2a("hartree", "wavenumber_e", "joule", "kcalmol", &
1318 0 : "kjmol", "Ry", "eV", "keV", "K_e"), iw)
1319 0 : CALL format_units_as_xml("length", s2a("bohr", "m", "pm", "nm", "angstrom"), iw)
1320 0 : CALL format_units_as_xml("temperature", s2a("K", "au_temp"), iw)
1321 0 : CALL format_units_as_xml("pressure", s2a("bar", "atm", "kbar", "Pa", "MPa", "GPa", "au_p"), iw)
1322 0 : CALL format_units_as_xml("angle", s2a("rad", "deg"), iw)
1323 0 : CALL format_units_as_xml("time", s2a("s", "fs", "ps", "au_t", "wavenumber_t"), iw)
1324 0 : CALL format_units_as_xml("mass", s2a("kg", "amu", "m_e"), iw)
1325 0 : CALL format_units_as_xml("potential", s2a("volt", "au_pot"), iw)
1326 0 : CALL format_units_as_xml("force", s2a("N", "Newton", "mN", "mNewton", "au_f"), iw)
1327 :
1328 0 : END SUBROUTINE export_units_as_xml
1329 :
1330 : ! **************************************************************************************************
1331 : !> \brief Format units as xml.
1332 : !> \param unit_kind ...
1333 : !> \param units_set ...
1334 : !> \param iw ...
1335 : !> \author Ole Schuett
1336 : ! **************************************************************************************************
1337 0 : SUBROUTINE format_units_as_xml(unit_kind, units_set, iw)
1338 : CHARACTER(LEN=*), INTENT(IN) :: unit_kind
1339 : CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: units_set
1340 : INTEGER, INTENT(IN) :: iw
1341 :
1342 : INTEGER :: i
1343 :
1344 0 : WRITE (iw, FMT='(T2,A)') '<UNIT_KIND name="'//TRIM(unit_kind)//'">'
1345 0 : DO i = 1, SIZE(units_set)
1346 0 : WRITE (iw, FMT='(T3,A)') '<UNIT>'//TRIM(units_set(i))//'</UNIT>'
1347 : END DO
1348 0 : WRITE (iw, FMT='(T3,A)') '<UNIT>'//TRIM(unit_kind)//'</UNIT>' ! internal unit
1349 0 : WRITE (iw, FMT='(T2,A)') '</UNIT_KIND>'
1350 0 : END SUBROUTINE format_units_as_xml
1351 :
1352 0 : END MODULE cp_units
|