Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 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_efield = 11, &
62 : cp_ukind_max = 11
63 :
64 : ! General
65 : INTEGER, PARAMETER, PUBLIC :: cp_units_none = 100, &
66 : cp_units_au = 101
67 : ! Mass
68 : INTEGER, PARAMETER, PUBLIC :: cp_units_m_e = 110, &
69 : cp_units_amu = 111, &
70 : cp_units_kg = 112
71 : ! Energy
72 : INTEGER, PARAMETER, PUBLIC :: cp_units_hartree = 130, &
73 : cp_units_wavenum = 131, &
74 : cp_units_joule = 132, &
75 : cp_units_kcalmol = 133, &
76 : cp_units_Ry = 134, &
77 : cp_units_eV = 135, &
78 : cp_units_kjmol = 136, &
79 : cp_units_jmol = 137, &
80 : cp_units_keV = 138
81 :
82 : ! Length
83 : INTEGER, PARAMETER, PUBLIC :: cp_units_bohr = 140, &
84 : cp_units_angstrom = 141, &
85 : cp_units_m = 142, &
86 : cp_units_pm = 143, &
87 : cp_units_nm = 144
88 :
89 : ! Temperature
90 : INTEGER, PARAMETER, PUBLIC :: cp_units_k = 150
91 :
92 : ! Pressure
93 : INTEGER, PARAMETER, PUBLIC :: cp_units_bar = 161
94 : INTEGER, PARAMETER, PUBLIC :: cp_units_atm = 162
95 : INTEGER, PARAMETER, PUBLIC :: cp_units_kbar = 163
96 : INTEGER, PARAMETER, PUBLIC :: cp_units_Pa = 164
97 : INTEGER, PARAMETER, PUBLIC :: cp_units_MPa = 165
98 : INTEGER, PARAMETER, PUBLIC :: cp_units_GPa = 166
99 :
100 : ! Angles
101 : INTEGER, PARAMETER, PUBLIC :: cp_units_rad = 170, &
102 : cp_units_deg = 171
103 :
104 : ! Time
105 : INTEGER, PARAMETER, PUBLIC :: cp_units_fs = 180, &
106 : cp_units_s = 181, &
107 : cp_units_wn = 182, &
108 : cp_units_ps = 183
109 :
110 : ! Potential
111 : INTEGER, PARAMETER, PUBLIC :: cp_units_volt = 190
112 :
113 : ! Force
114 : INTEGER, PARAMETER, PUBLIC :: cp_units_Newton = 200, &
115 : cp_units_mNewton = 201
116 :
117 : ! Electric Field
118 : INTEGER, PARAMETER, PUBLIC :: cp_units_volt_per_m = 202, &
119 : cp_units_volt_per_nm = 203, &
120 : cp_units_volt_per_angstrom = 204
121 :
122 : INTEGER, PARAMETER, PUBLIC :: cp_unit_max_kinds = 8, cp_unit_basic_desc_length = 15, &
123 : cp_unit_desc_length = cp_unit_max_kinds*cp_unit_basic_desc_length
124 :
125 : PUBLIC :: cp_unit_type, cp_unit_set_type
126 : PUBLIC :: cp_unit_create, cp_unit_release, &
127 : cp_unit_to_cp2k, cp_unit_from_cp2k, cp_unit_desc, &
128 : cp_unit_set_create, cp_unit_set_release, &
129 : cp_unit_to_cp2k1, cp_unit_from_cp2k1, cp_unit_compatible, export_units_as_xml
130 :
131 : ! **************************************************************************************************
132 : !> \brief stores a unit
133 : !> \param kind the kind of unit (energy, length,...)
134 : !> \param unit the actual unit (Joule, eV,...)
135 : !> \author fawzi
136 : ! **************************************************************************************************
137 : TYPE cp_unit_type
138 : INTEGER :: n_kinds = -1
139 : INTEGER, DIMENSION(cp_unit_max_kinds):: kind_id = -1, unit_id = -1, power = -1
140 : END TYPE cp_unit_type
141 :
142 : ! **************************************************************************************************
143 : !> \brief represent a pointer to a unit (to build arrays of pointers)
144 : !> \param unit the pointer to the unit
145 : !> \author fawzi
146 : ! **************************************************************************************************
147 : TYPE cp_unit_p_type
148 : TYPE(cp_unit_type), POINTER :: unit => NULL()
149 : END TYPE cp_unit_p_type
150 :
151 : ! **************************************************************************************************
152 : !> \brief stores the default units to be used
153 : !> \author fawzi
154 : ! **************************************************************************************************
155 : TYPE cp_unit_set_type
156 : TYPE(cp_unit_p_type), DIMENSION(cp_ukind_max) :: units = cp_unit_p_type()
157 : END TYPE cp_unit_set_type
158 :
159 : CONTAINS
160 :
161 : ! **************************************************************************************************
162 : !> \brief creates a unit parsing a string
163 : !> \param unit the unit to initialize
164 : !> \param string the string containing the description of the unit
165 : !> \author fawzi
166 : ! **************************************************************************************************
167 547470375 : SUBROUTINE cp_unit_create(unit, string)
168 : TYPE(cp_unit_type), INTENT(OUT) :: unit
169 : CHARACTER(len=*), INTENT(in) :: string
170 :
171 : CHARACTER(LEN=40) :: formatstr
172 : CHARACTER(LEN=cp_unit_desc_length) :: desc
173 21898815 : CHARACTER(LEN=LEN(string)) :: unit_string
174 : INTEGER :: i_high, i_low, i_unit, len_string, &
175 : next_power
176 : INTEGER, DIMENSION(cp_unit_max_kinds) :: kind_id, power, unit_id
177 :
178 197089335 : unit_id = cp_units_none
179 21898815 : kind_id = cp_ukind_none
180 21898815 : power = 0
181 21898815 : i_low = 1
182 21898815 : i_high = 1
183 21898815 : len_string = LEN(string)
184 21898815 : i_unit = 0
185 21898815 : next_power = 1
186 21898815 : DO WHILE (i_low < len_string)
187 20862074 : IF (string(i_low:i_low) /= ' ') EXIT
188 21898815 : i_low = i_low + 1
189 : END DO
190 : i_high = i_low
191 143566401 : DO WHILE (i_high <= len_string)
192 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
193 124010218 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
194 141223818 : i_high = i_high + 1
195 : END DO
196 : DO
197 22869209 : IF (i_high <= i_low .OR. i_low > len_string) EXIT
198 22807248 : i_unit = i_unit + 1
199 22807248 : IF (i_unit > cp_unit_max_kinds) THEN
200 0 : CPABORT("Maximum number of combined units exceeded")
201 0 : EXIT
202 : END IF
203 : ! read unit
204 22807248 : unit_string = string(i_low:i_high - 1)
205 22807248 : CALL uppercase(unit_string)
206 23826564 : SELECT CASE (TRIM(unit_string))
207 : CASE ("INTERNAL_CP2K")
208 1019316 : unit_id(i_unit) = cp_units_none
209 1019316 : kind_id(i_unit) = cp_ukind_undef
210 : CASE ("HARTREE")
211 1069698 : unit_id(i_unit) = cp_units_hartree
212 1069698 : kind_id(i_unit) = cp_ukind_energy
213 : CASE ("AU_E")
214 170140 : unit_id(i_unit) = cp_units_au
215 170140 : kind_id(i_unit) = cp_ukind_energy
216 : CASE ("WAVENUMBER_E")
217 0 : unit_id(i_unit) = cp_units_wavenum
218 0 : kind_id(i_unit) = cp_ukind_energy
219 : CASE ("JOULE", "J")
220 0 : unit_id(i_unit) = cp_units_joule
221 0 : kind_id(i_unit) = cp_ukind_energy
222 : CASE ("KCALMOL")
223 387341 : unit_id(i_unit) = cp_units_kcalmol
224 387341 : kind_id(i_unit) = cp_ukind_energy
225 : CASE ("KJMOL")
226 2248 : unit_id(i_unit) = cp_units_kjmol
227 2248 : kind_id(i_unit) = cp_ukind_energy
228 : CASE ("JMOL")
229 0 : unit_id(i_unit) = cp_units_jmol
230 0 : kind_id(i_unit) = cp_ukind_energy
231 : CASE ("RY")
232 328868 : unit_id(i_unit) = cp_units_Ry
233 328868 : kind_id(i_unit) = cp_ukind_energy
234 : CASE ("EV")
235 3205132 : unit_id(i_unit) = cp_units_eV
236 3205132 : kind_id(i_unit) = cp_ukind_energy
237 : CASE ("KEV")
238 30636 : unit_id(i_unit) = cp_units_keV
239 30636 : kind_id(i_unit) = cp_ukind_energy
240 : CASE ("K_E")
241 340688 : unit_id(i_unit) = cp_units_k
242 340688 : kind_id(i_unit) = cp_ukind_energy
243 : CASE ("ENERGY")
244 0 : unit_id(i_unit) = cp_units_none
245 0 : kind_id(i_unit) = cp_ukind_energy
246 : CASE ("AU_L")
247 278 : unit_id(i_unit) = cp_units_au
248 278 : kind_id(i_unit) = cp_ukind_length
249 : CASE ("BOHR")
250 2740076 : unit_id(i_unit) = cp_units_bohr
251 2740076 : kind_id(i_unit) = cp_ukind_length
252 : CASE ("M")
253 51355 : unit_id(i_unit) = cp_units_m
254 51355 : kind_id(i_unit) = cp_ukind_length
255 : CASE ("PM")
256 2 : unit_id(i_unit) = cp_units_pm
257 2 : kind_id(i_unit) = cp_ukind_length
258 : CASE ("NM")
259 20378 : unit_id(i_unit) = cp_units_nm
260 20378 : kind_id(i_unit) = cp_ukind_length
261 : CASE ("ANGSTROM")
262 9217036 : unit_id(i_unit) = cp_units_angstrom
263 9217036 : kind_id(i_unit) = cp_ukind_length
264 : CASE ("LENGTH")
265 0 : unit_id(i_unit) = cp_units_none
266 0 : kind_id(i_unit) = cp_ukind_length
267 : CASE ("K", "K_TEMP")
268 1010613 : unit_id(i_unit) = cp_units_k
269 1010613 : kind_id(i_unit) = cp_ukind_temperature
270 : CASE ("AU_TEMP")
271 0 : unit_id(i_unit) = cp_units_au
272 0 : kind_id(i_unit) = cp_ukind_temperature
273 : CASE ("TEMPERATURE")
274 0 : unit_id(i_unit) = cp_units_none
275 0 : kind_id(i_unit) = cp_ukind_temperature
276 : CASE ("ATM")
277 0 : unit_id(i_unit) = cp_units_atm
278 0 : kind_id(i_unit) = cp_ukind_pressure
279 : CASE ("BAR")
280 155244 : unit_id(i_unit) = cp_units_bar
281 155244 : kind_id(i_unit) = cp_ukind_pressure
282 : CASE ("KBAR")
283 16 : unit_id(i_unit) = cp_units_kbar
284 16 : kind_id(i_unit) = cp_ukind_pressure
285 : CASE ("PA")
286 20648 : unit_id(i_unit) = cp_units_Pa
287 20648 : kind_id(i_unit) = cp_ukind_pressure
288 : CASE ("MPA")
289 0 : unit_id(i_unit) = cp_units_MPa
290 0 : kind_id(i_unit) = cp_ukind_pressure
291 : CASE ("GPA")
292 10629 : unit_id(i_unit) = cp_units_GPa
293 10629 : kind_id(i_unit) = cp_ukind_pressure
294 : CASE ("AU_P")
295 0 : unit_id(i_unit) = cp_units_au
296 0 : kind_id(i_unit) = cp_ukind_pressure
297 : CASE ("PRESSURE")
298 0 : unit_id(i_unit) = cp_units_none
299 0 : kind_id(i_unit) = cp_ukind_pressure
300 : CASE ("RAD")
301 248625 : unit_id(i_unit) = cp_units_rad
302 248625 : kind_id(i_unit) = cp_ukind_angle
303 : CASE ("DEG")
304 303740 : unit_id(i_unit) = cp_units_deg
305 303740 : kind_id(i_unit) = cp_ukind_angle
306 : CASE ("ANGLE")
307 0 : unit_id(i_unit) = cp_units_none
308 0 : kind_id(i_unit) = cp_ukind_angle
309 : CASE ("S")
310 154587 : unit_id(i_unit) = cp_units_s
311 154587 : kind_id(i_unit) = cp_ukind_time
312 : CASE ("FS")
313 1566725 : unit_id(i_unit) = cp_units_fs
314 1566725 : kind_id(i_unit) = cp_ukind_time
315 : CASE ("PS")
316 437022 : unit_id(i_unit) = cp_units_ps
317 437022 : kind_id(i_unit) = cp_ukind_time
318 : CASE ("WAVENUMBER_T")
319 34 : unit_id(i_unit) = cp_units_wn
320 34 : kind_id(i_unit) = cp_ukind_time
321 : CASE ("AU_T")
322 109719 : unit_id(i_unit) = cp_units_au
323 109719 : kind_id(i_unit) = cp_ukind_time
324 : CASE ("TIME")
325 0 : unit_id(i_unit) = cp_units_none
326 0 : kind_id(i_unit) = cp_ukind_time
327 : CASE ("KG")
328 0 : unit_id(i_unit) = cp_units_kg
329 0 : kind_id(i_unit) = cp_ukind_mass
330 : CASE ("AMU")
331 10476 : unit_id(i_unit) = cp_units_amu
332 10476 : kind_id(i_unit) = cp_ukind_mass
333 : CASE ("M_E")
334 0 : unit_id(i_unit) = cp_units_m_e
335 0 : kind_id(i_unit) = cp_ukind_mass
336 : CASE ("AU_M")
337 30632 : unit_id(i_unit) = cp_units_au
338 30632 : kind_id(i_unit) = cp_ukind_mass
339 : CASE ("MASS")
340 0 : unit_id(i_unit) = cp_units_none
341 0 : kind_id(i_unit) = cp_ukind_mass
342 : CASE ("VOLT")
343 134296 : unit_id(i_unit) = cp_units_volt
344 134296 : kind_id(i_unit) = cp_ukind_potential
345 : CASE ("AU_POT")
346 0 : unit_id(i_unit) = cp_units_au
347 0 : kind_id(i_unit) = cp_ukind_potential
348 : CASE ("POTENTIAL")
349 0 : unit_id(i_unit) = cp_units_none
350 0 : kind_id(i_unit) = cp_ukind_potential
351 : CASE ("N", "NEWTON")
352 10 : unit_id(i_unit) = cp_units_Newton
353 10 : kind_id(i_unit) = cp_ukind_force
354 : CASE ("MN", "MNEWTON")
355 20700 : unit_id(i_unit) = cp_units_mNewton
356 20700 : kind_id(i_unit) = cp_ukind_force
357 : CASE ("AU_F")
358 0 : unit_id(i_unit) = cp_units_au
359 0 : kind_id(i_unit) = cp_ukind_force
360 : CASE ("FORCE")
361 0 : unit_id(i_unit) = cp_units_none
362 0 : kind_id(i_unit) = cp_ukind_force
363 : CASE ("VM-1", "VOLT_PER_M")
364 10340 : unit_id(i_unit) = cp_units_volt_per_m
365 10340 : kind_id(i_unit) = cp_ukind_efield
366 : CASE ("VNM-1", "VOLT_PER_NM")
367 0 : unit_id(i_unit) = cp_units_volt_per_nm
368 0 : kind_id(i_unit) = cp_ukind_efield
369 : CASE ("VA-1", "VOLT_PER_ANGSTROM")
370 0 : unit_id(i_unit) = cp_units_volt_per_angstrom
371 0 : kind_id(i_unit) = cp_ukind_efield
372 : CASE ("AU_EFIELD")
373 0 : unit_id(i_unit) = cp_units_au
374 0 : kind_id(i_unit) = cp_ukind_efield
375 : CASE ("EFIELD")
376 0 : unit_id(i_unit) = cp_units_none
377 0 : kind_id(i_unit) = cp_ukind_efield
378 : CASE ("AU")
379 : CALL cp_abort(__LOCATION__, &
380 : "au unit without specifying its kind not accepted, use "// &
381 : "(au_e, au_f, au_t, au_temp, au_l, au_m, au_p, au_pot, "// &
382 0 : "au_efield)")
383 : CASE default
384 22807248 : CPABORT("Unknown unit: "//string(i_low:i_high - 1))
385 : END SELECT
386 22807248 : power(i_unit) = next_power
387 : ! parse op
388 22807248 : i_low = i_high
389 22822128 : DO WHILE (i_low <= len_string)
390 3171146 : IF (string(i_low:i_low) /= ' ') EXIT
391 22822128 : i_low = i_low + 1
392 : END DO
393 : i_high = i_low
394 22807248 : DO WHILE (i_high <= len_string)
395 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
396 3156266 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
397 0 : i_high = i_high + 1
398 : END DO
399 22807248 : IF (i_high < i_low .OR. i_low > len_string) EXIT
400 :
401 3156266 : IF (i_high <= len_string) THEN
402 3156266 : IF (string(i_low:i_high) == '^') THEN
403 2227405 : i_low = i_high + 1
404 2227405 : DO WHILE (i_low <= len_string)
405 2227405 : IF (string(i_low:i_low) /= ' ') EXIT
406 2227405 : i_low = i_low + 1
407 : END DO
408 : i_high = i_low
409 6504462 : DO WHILE (i_high <= len_string)
410 2185872 : SELECT CASE (string(i_high:i_high))
411 : CASE ('+', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')
412 4277057 : i_high = i_high + 1
413 : CASE default
414 4318590 : EXIT
415 : END SELECT
416 : END DO
417 2227405 : IF (i_high <= i_low .OR. i_low > len_string) THEN
418 0 : CPABORT("an integer number is expected after a '^'")
419 0 : EXIT
420 : END IF
421 2227405 : formatstr = "(i"//cp_to_string(i_high - i_low + 1)//")"
422 : READ (string(i_low:i_high - 1), formatstr) &
423 2227405 : next_power
424 2227405 : power(i_unit) = power(i_unit)*next_power
425 : ! next op
426 2227405 : i_low = i_high
427 2232325 : DO WHILE (i_low < len_string)
428 46436 : IF (string(i_low:i_low) /= ' ') EXIT
429 2232325 : i_low = i_low + 1
430 : END DO
431 : i_high = i_low
432 2228599 : DO WHILE (i_high <= len_string)
433 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
434 42525 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
435 1211 : i_high = i_high + 1
436 : END DO
437 : END IF
438 : END IF
439 3156266 : IF (i_low > len_string) EXIT
440 970394 : next_power = 1
441 22869209 : IF (i_high <= len_string) THEN
442 970192 : IF (string(i_low:i_high) == "*" .OR. string(i_low:i_high) == '/') THEN
443 970175 : IF (string(i_low:i_high) == '/') next_power = -1
444 970175 : i_low = i_high + 1
445 970175 : DO WHILE (i_low <= len_string)
446 970175 : IF (string(i_low:i_low) /= ' ') EXIT
447 970175 : i_low = i_low + 1
448 : END DO
449 : i_high = i_low
450 5176409 : DO WHILE (i_high <= len_string)
451 : IF (string(i_high:i_high) == ' ' .OR. string(i_high:i_high) == '^' .OR. &
452 5019917 : string(i_high:i_high) == '*' .OR. string(i_high:i_high) == '/') EXIT
453 4362743 : i_high = i_high + 1
454 : END DO
455 : END IF
456 : END IF
457 : END DO
458 : CALL cp_unit_create2(unit, kind_id=kind_id, unit_id=unit_id, &
459 21898815 : power=power)
460 21898815 : desc = cp_unit_desc(unit)
461 21898815 : END SUBROUTINE cp_unit_create
462 :
463 : ! **************************************************************************************************
464 : !> \brief creates and initializes the given unit of mesure (performs some error
465 : !> check)
466 : !> \param unit the unit descriptor to be initialized
467 : !> \param kind_id the kind of unit (length,energy,...), use the constants
468 : !> cp_ukind_*
469 : !> \param unit_id the actual unit (use constants cp_units_*)
470 : !> \param power ...
471 : !> \author fawzi
472 : ! **************************************************************************************************
473 616623504 : SUBROUTINE cp_unit_create2(unit, kind_id, unit_id, power)
474 : TYPE(cp_unit_type), INTENT(OUT) :: unit
475 : INTEGER, DIMENSION(:), INTENT(in) :: kind_id, unit_id
476 : INTEGER, DIMENSION(:), INTENT(in), OPTIONAL :: power
477 :
478 : INTEGER :: i, j, max_kind, max_pos
479 : LOGICAL :: repeat
480 :
481 22022268 : CPASSERT(SIZE(kind_id) <= cp_unit_max_kinds)
482 22022268 : CPASSERT(SIZE(unit_id) <= cp_unit_max_kinds)
483 197336241 : unit%kind_id(1:SIZE(kind_id)) = kind_id
484 22886439 : unit%kind_id(SIZE(kind_id) + 1:) = cp_ukind_none
485 197336241 : unit%unit_id(1:SIZE(unit_id)) = unit_id
486 44908707 : unit%unit_id(SIZE(unit_id):) = cp_units_none
487 22022268 : IF (PRESENT(power)) THEN
488 197336241 : unit%power(1:SIZE(power)) = power
489 22886439 : unit%power(SIZE(power) + 1:) = 0
490 198200412 : DO i = 1, SIZE(unit%power)
491 198200412 : IF (unit%power(i) == 0) THEN
492 153247443 : unit%kind_id(i) = cp_ukind_none
493 153247443 : unit%unit_id(i) = cp_units_none
494 : END IF
495 : END DO
496 : ELSE
497 0 : DO i = 1, SIZE(unit%power)
498 0 : IF (unit%unit_id(i) /= 0) THEN
499 0 : unit%power(i) = 1
500 : ELSE
501 0 : unit%power(i) = 0
502 : END IF
503 : END DO
504 : END IF
505 :
506 : ! remove unnecessary units
507 : ! reorder & compress
508 22022268 : unit%n_kinds = 0
509 198200412 : DO i = 1, SIZE(unit%kind_id)
510 : ! find max and compress in the rest
511 : DO
512 176178144 : max_kind = unit%kind_id(i)
513 176178144 : max_pos = i
514 176178144 : repeat = .FALSE.
515 792801648 : DO j = i + 1, SIZE(unit%kind_id)
516 792801648 : IF (unit%kind_id(j) >= max_kind) THEN
517 458028419 : IF (unit%kind_id(j) /= 0 .AND. unit%kind_id(j) == max_kind .AND. &
518 : unit%unit_id(j) == unit%unit_id(max_pos)) THEN
519 0 : unit%power(max_pos) = unit%power(max_pos) + unit%power(j)
520 0 : unit%kind_id(j) = cp_ukind_none
521 0 : unit%unit_id(j) = cp_units_none
522 0 : unit%power(j) = 0
523 0 : IF (unit%power(max_pos) == 0) THEN
524 0 : unit%kind_id(max_pos) = cp_ukind_none
525 0 : unit%unit_id(max_pos) = cp_units_none
526 0 : unit%power(max_pos) = 0
527 0 : repeat = .TRUE.
528 0 : EXIT
529 : END IF
530 458028419 : ELSE IF (unit%kind_id(j) > max_kind .OR. &
531 : (unit%kind_id(j) == max_kind .AND. &
532 : unit%unit_id(j) > unit%unit_id(max_pos))) THEN
533 928793 : max_kind = unit%kind_id(j)
534 928793 : max_pos = j
535 : END IF
536 : END IF
537 : END DO
538 176178144 : IF (.NOT. repeat) EXIT
539 : END DO
540 176178144 : IF (max_kind /= 0) unit%n_kinds = unit%n_kinds + 1
541 : ! put the max at pos i
542 176178144 : IF (max_pos /= i) THEN
543 908141 : unit%kind_id(max_pos) = unit%kind_id(i)
544 908141 : unit%kind_id(i) = max_kind
545 908141 : max_kind = unit%unit_id(max_pos)
546 908141 : unit%unit_id(max_pos) = unit%unit_id(i)
547 908141 : unit%unit_id(i) = max_kind
548 908141 : max_kind = unit%power(max_pos)
549 908141 : unit%power(max_pos) = unit%power(i)
550 908141 : unit%power(i) = max_kind
551 : END IF
552 : ! check unit
553 : CALL cp_basic_unit_check(basic_kind=unit%kind_id(i), &
554 198200412 : basic_unit=unit%unit_id(i))
555 : END DO
556 22022268 : END SUBROUTINE cp_unit_create2
557 :
558 : ! **************************************************************************************************
559 : !> \brief releases the given unit
560 : !> \param unit the unit to release
561 : !> \author fawzi
562 : !> \note
563 : !> at the moment not needed, there for completeness
564 : ! **************************************************************************************************
565 22022268 : ELEMENTAL SUBROUTINE cp_unit_release(unit)
566 : TYPE(cp_unit_type), INTENT(IN) :: unit
567 :
568 : MARK_USED(unit)
569 :
570 22022268 : END SUBROUTINE cp_unit_release
571 :
572 : ! **************************************************************************************************
573 : !> \brief controls that the kind and contains meaningful information
574 : !> \param basic_kind the kind of the unit
575 : !> \param basic_unit the unit to check
576 : !> \author fawzi
577 : ! **************************************************************************************************
578 176178144 : SUBROUTINE cp_basic_unit_check(basic_kind, basic_unit)
579 : INTEGER, INTENT(in) :: basic_kind, basic_unit
580 :
581 177208683 : SELECT CASE (basic_kind)
582 : CASE (cp_ukind_undef)
583 6576513 : SELECT CASE (basic_unit)
584 : CASE (cp_units_none)
585 : CASE default
586 1030539 : CPABORT("unknown undef unit:"//TRIM(cp_to_string(basic_unit)))
587 : END SELECT
588 : CASE (cp_ukind_energy)
589 17586322 : SELECT CASE (basic_unit)
590 : CASE (cp_units_hartree, cp_units_wavenum, cp_units_joule, cp_units_kcalmol, &
591 : cp_units_kjmol, cp_units_Ry, cp_units_eV, cp_units_keV, cp_units_au, cp_units_k, &
592 : cp_units_jmol, cp_units_none)
593 : CASE default
594 5545974 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
595 : END SELECT
596 : CASE (cp_ukind_length)
597 13062184 : SELECT CASE (basic_unit)
598 : CASE (cp_units_bohr, cp_units_angstrom, cp_units_au, cp_units_none, cp_units_m, &
599 : cp_units_pm, cp_units_nm)
600 : CASE default
601 12040348 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
602 : END SELECT
603 : CASE (cp_ukind_temperature)
604 1219596 : SELECT CASE (basic_unit)
605 : CASE (cp_units_k, cp_units_au, cp_units_none)
606 : CASE default
607 1021836 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
608 : END SELECT
609 : CASE (cp_ukind_pressure)
610 761348 : SELECT CASE (basic_unit)
611 : 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)
612 : CASE default
613 197760 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
614 : END SELECT
615 : CASE (cp_ukind_angle)
616 2842898 : SELECT CASE (basic_unit)
617 : CASE (cp_units_rad, cp_units_deg, cp_units_none)
618 : CASE default
619 563588 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
620 : END SELECT
621 : CASE (cp_ukind_time)
622 2331641 : SELECT CASE (basic_unit)
623 : CASE (cp_units_s, cp_units_fs, cp_units_ps, cp_units_au, cp_units_wn, cp_units_none)
624 : CASE default
625 2279310 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
626 : END SELECT
627 : CASE (cp_ukind_mass)
628 197850 : SELECT CASE (basic_unit)
629 : CASE (cp_units_kg, cp_units_amu, cp_units_m_e, cp_units_au, cp_units_none)
630 : CASE default
631 52331 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
632 : END SELECT
633 : CASE (cp_ukind_potential)
634 177452 : SELECT CASE (basic_unit)
635 : CASE (cp_units_volt, cp_units_au, cp_units_none)
636 : CASE default
637 145519 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
638 : END SELECT
639 : CASE (cp_ukind_force)
640 53496 : SELECT CASE (basic_unit)
641 : CASE (cp_units_Newton, cp_units_mNewton, cp_units_au, cp_units_none)
642 : CASE default
643 31933 : CPABORT("unknown force unit:"//TRIM(cp_to_string(basic_unit)))
644 : END SELECT
645 : CASE (cp_ukind_efield)
646 153269006 : SELECT CASE (basic_unit)
647 : CASE (cp_units_volt_per_m, cp_units_volt_per_nm, &
648 : cp_units_volt_per_angstrom, cp_units_au, cp_units_none)
649 : CASE default
650 21563 : CPABORT("unknown electric field unit:"//TRIM(cp_to_string(basic_unit)))
651 : END SELECT
652 : CASE (cp_ukind_none)
653 153247443 : IF (basic_unit /= cp_units_none) &
654 : CALL cp_abort(__LOCATION__, &
655 : "if the kind of the unit is none also unit must be undefined,not:" &
656 0 : //TRIM(cp_to_string(basic_unit)))
657 : CASE default
658 176178144 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
659 : END SELECT
660 176178144 : END SUBROUTINE cp_basic_unit_check
661 :
662 : ! **************************************************************************************************
663 : !> \brief converts a value to the internal cp2k units
664 : !> \param value the value to convert
665 : !> \param basic_kind the kind of the unit of the value
666 : !> \param basic_unit the unit of the value
667 : !> \param power the power of the unit (defaults to 1)
668 : !> \return ...
669 : !> \author fawzi
670 : ! **************************************************************************************************
671 8141537 : FUNCTION cp_basic_unit_to_cp2k(value, basic_kind, basic_unit, power) RESULT(res)
672 : REAL(kind=dp), INTENT(in) :: value
673 : INTEGER, INTENT(in) :: basic_kind, basic_unit
674 : INTEGER, INTENT(in), OPTIONAL :: power
675 : REAL(kind=dp) :: res
676 :
677 : INTEGER :: my_power
678 :
679 8141537 : my_power = 1
680 8141537 : IF (PRESENT(power)) my_power = power
681 8141537 : IF (basic_unit == cp_units_none .AND. basic_kind /= cp_ukind_undef) THEN
682 0 : IF (basic_kind /= cp_units_none) &
683 : CALL cp_abort(__LOCATION__, &
684 : "unit not yet fully specified, unit of kind "// &
685 0 : TRIM(cp_to_string(basic_unit)))
686 : END IF
687 8212442 : SELECT CASE (basic_kind)
688 : CASE (cp_ukind_undef)
689 1849224 : SELECT CASE (basic_unit)
690 : CASE (cp_units_none)
691 70905 : res = value
692 : CASE default
693 70905 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
694 : END SELECT
695 : CASE (cp_ukind_energy)
696 4719984 : SELECT CASE (basic_unit)
697 : CASE (cp_units_hartree, cp_units_au)
698 176867 : res = value
699 : CASE (cp_units_wavenum)
700 0 : res = wavenumbers**(-my_power)*value
701 : CASE (cp_units_joule)
702 0 : res = joule**(-my_power)*value
703 : CASE (cp_units_kcalmol)
704 232535 : res = kcalmol**(-my_power)*value
705 : CASE (cp_units_kjmol)
706 2248 : res = kjmol**(-my_power)*value
707 : CASE (cp_units_jmol)
708 0 : res = (kjmol*1.0E+3_dp)**(-my_power)*value
709 : CASE (cp_units_Ry)
710 48727 : res = 0.5_dp**my_power*value
711 : CASE (cp_units_eV)
712 1294270 : res = evolt**(-my_power)*value
713 : CASE (cp_units_keV)
714 8 : res = (1.0E-3_dp*evolt)**(-my_power)*value
715 : CASE (cp_units_k)
716 23664 : res = kelvin**(-my_power)*value
717 : CASE default
718 1778319 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
719 : END SELECT
720 : CASE (cp_ukind_length)
721 855119 : SELECT CASE (basic_unit)
722 : CASE (cp_units_bohr, cp_units_au)
723 469484 : res = value
724 : CASE (cp_units_m)
725 54 : res = value*(1.0E10_dp*bohr)**my_power
726 : CASE (cp_units_pm)
727 2 : res = value*(0.01_dp*bohr)**my_power
728 : CASE (cp_units_nm)
729 10066 : res = value*(10.0_dp*bohr)**my_power
730 : CASE (cp_units_angstrom)
731 4063511 : res = value*bohr**my_power
732 : CASE default
733 4543117 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
734 : END SELECT
735 : CASE (cp_ukind_temperature)
736 472979 : SELECT CASE (basic_unit)
737 : CASE (cp_units_k)
738 385635 : res = kelvin**(-my_power)*value
739 : CASE (cp_units_au)
740 0 : res = value
741 : CASE default
742 385635 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
743 : END SELECT
744 : CASE (cp_ukind_pressure)
745 403317 : SELECT CASE (basic_unit)
746 : CASE (cp_units_bar)
747 76714 : res = bar**(-my_power)*value
748 : CASE (cp_units_atm)
749 0 : res = atm**(-my_power)*value
750 : CASE (cp_units_kbar)
751 16 : res = (1.0E-3_dp*bar)**(-my_power)*value
752 : CASE (cp_units_Pa)
753 10324 : res = pascal**(-my_power)*value
754 : CASE (cp_units_MPa)
755 0 : res = (1.0E-6_dp*pascal)**(-my_power)*value
756 : CASE (cp_units_GPa)
757 290 : res = (1.0E-9_dp*pascal)**(-my_power)*value
758 : CASE (cp_units_au)
759 0 : res = value
760 : CASE default
761 87344 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
762 : END SELECT
763 : CASE (cp_ukind_angle)
764 1019437 : SELECT CASE (basic_unit)
765 : CASE (cp_units_rad)
766 70123 : res = value
767 : CASE (cp_units_deg)
768 256480 : res = value*(radians)**my_power
769 : CASE default
770 326603 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
771 : END SELECT
772 : CASE (cp_ukind_time)
773 215 : SELECT CASE (basic_unit)
774 : CASE (cp_units_s)
775 24 : res = value*seconds**(-my_power)
776 : CASE (cp_units_fs)
777 565817 : res = value*femtoseconds**(-my_power)
778 : CASE (cp_units_ps)
779 334806 : res = value*picoseconds**(-my_power)
780 : CASE (cp_units_au)
781 48633 : res = value
782 : CASE (cp_units_wn)
783 34 : res = (twopi*wavenumbers)**(my_power)/value
784 : CASE default
785 949314 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
786 : END SELECT
787 : CASE (cp_ukind_mass)
788 77 : SELECT CASE (basic_unit)
789 : CASE (cp_units_kg)
790 0 : res = e_mass**my_power*value
791 : CASE (cp_units_amu)
792 182 : res = massunit**my_power*value
793 : CASE (cp_units_m_e, cp_units_au)
794 9 : res = value
795 : CASE default
796 191 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
797 : END SELECT
798 : CASE (cp_ukind_potential)
799 109 : SELECT CASE (basic_unit)
800 : CASE (cp_units_volt)
801 77 : res = evolt**(-my_power)*value
802 : CASE (cp_units_au)
803 0 : res = value
804 : CASE default
805 77 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
806 : END SELECT
807 : CASE (cp_ukind_force)
808 10 : SELECT CASE (basic_unit)
809 : CASE (cp_units_Newton)
810 10 : res = value*newton**(-my_power)
811 : CASE (cp_units_mNewton)
812 22 : res = value*(1.0E+3*newton)**(-my_power)
813 : CASE (cp_units_au)
814 0 : res = value
815 : CASE default
816 32 : CPABORT("unknown force unit:"//TRIM(cp_to_string(basic_unit)))
817 : END SELECT
818 : CASE (cp_ukind_efield)
819 0 : SELECT CASE (basic_unit)
820 : CASE (cp_units_volt_per_m)
821 0 : res = (1.0E+10_dp*evolt*bohr)**(-my_power)*value
822 : CASE (cp_units_volt_per_nm)
823 0 : res = (10.0_dp*evolt*bohr)**(-my_power)*value
824 : CASE (cp_units_volt_per_angstrom)
825 0 : res = (evolt*bohr)**(-my_power)*value
826 : CASE (cp_units_au)
827 0 : res = value
828 : CASE default
829 0 : CPABORT("unknown electric field unit:"//TRIM(cp_to_string(basic_unit)))
830 : END SELECT
831 : CASE (cp_ukind_none)
832 : CALL cp_abort(__LOCATION__, &
833 : "if the kind of the unit is none also unit must be undefined,not:" &
834 0 : //TRIM(cp_to_string(basic_unit)))
835 : CASE default
836 8141537 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
837 : END SELECT
838 8141537 : END FUNCTION cp_basic_unit_to_cp2k
839 :
840 : ! **************************************************************************************************
841 : !> \brief returns the label of the current basic unit
842 : !> \param basic_kind the kind of the unit of the value
843 : !> \param basic_unit the unit of the value
844 : !> \param power the power of the unit (defaults to 1)
845 : !> \param accept_undefined ...
846 : !> \return ...
847 : !> \author fawzi
848 : ! **************************************************************************************************
849 22807248 : FUNCTION cp_basic_unit_desc(basic_kind, basic_unit, power, accept_undefined) &
850 : RESULT(res)
851 : INTEGER, INTENT(in) :: basic_kind, basic_unit
852 : INTEGER, INTENT(in), OPTIONAL :: power
853 : LOGICAL, INTENT(in), OPTIONAL :: accept_undefined
854 : CHARACTER(len=cp_unit_basic_desc_length) :: res
855 :
856 : INTEGER :: a, my_power
857 : LOGICAL :: my_accept_undefined
858 :
859 22807248 : my_power = 1
860 22807248 : res = ""
861 22807248 : my_accept_undefined = .FALSE.
862 22807248 : IF (accept_undefined) my_accept_undefined = accept_undefined
863 22807248 : IF (PRESENT(power)) my_power = power
864 22807248 : IF (basic_unit == cp_units_none) THEN
865 1019316 : IF (.NOT. my_accept_undefined .AND. basic_kind == cp_units_none) &
866 : CALL cp_abort(__LOCATION__, "unit not yet fully specified, unit of kind "// &
867 0 : TRIM(cp_to_string(basic_kind)))
868 : END IF
869 23826564 : SELECT CASE (basic_kind)
870 : CASE (cp_ukind_undef)
871 6554067 : SELECT CASE (basic_unit)
872 : CASE (cp_units_none)
873 1019316 : res = "internal_cp2k"
874 : CASE DEFAULT
875 : CALL cp_abort(__LOCATION__, &
876 : "unit not yet fully specified, unit of kind "// &
877 1019316 : TRIM(res))
878 : END SELECT
879 : CASE (cp_ukind_energy)
880 13268963 : SELECT CASE (basic_unit)
881 : CASE (cp_units_hartree, cp_units_au)
882 1239838 : res = "hartree"
883 : CASE (cp_units_wavenum)
884 0 : res = "wavenumber_e"
885 : CASE (cp_units_joule)
886 0 : res = "joule"
887 : CASE (cp_units_kcalmol)
888 387341 : res = "kcalmol"
889 : CASE (cp_units_kjmol)
890 2248 : res = "kjmol"
891 : CASE (cp_units_jmol)
892 0 : res = "jmol"
893 : CASE (cp_units_Ry)
894 328868 : res = "Ry"
895 : CASE (cp_units_eV)
896 3205132 : res = "eV"
897 : CASE (cp_units_keV)
898 30636 : res = "keV"
899 : CASE (cp_units_k)
900 340688 : res = "K_e"
901 : CASE (cp_units_none)
902 0 : res = "energy"
903 0 : IF (.NOT. my_accept_undefined) &
904 : CALL cp_abort(__LOCATION__, &
905 : "unit not yet fully specified, unit of kind "// &
906 0 : TRIM(res))
907 : CASE default
908 5534751 : CPABORT("unknown energy unit:"//TRIM(cp_to_string(basic_unit)))
909 : END SELECT
910 : CASE (cp_ukind_length)
911 3750967 : SELECT CASE (basic_unit)
912 : CASE (cp_units_bohr, cp_units_au)
913 2740354 : res = "bohr"
914 : CASE (cp_units_m)
915 51355 : res = "m"
916 : CASE (cp_units_pm)
917 2 : res = "pm"
918 : CASE (cp_units_nm)
919 20378 : res = "nm"
920 : CASE (cp_units_angstrom)
921 9217036 : res = "angstrom"
922 : CASE default
923 0 : res = "length"
924 12029125 : CPABORT("unknown length unit:"//TRIM(cp_to_string(basic_unit)))
925 : END SELECT
926 : CASE (cp_ukind_temperature)
927 1197150 : SELECT CASE (basic_unit)
928 : CASE (cp_units_k)
929 1010613 : res = "K"
930 : CASE (cp_units_au)
931 0 : res = "au_temp"
932 : CASE (cp_units_none)
933 0 : res = "temperature"
934 0 : IF (.NOT. my_accept_undefined) &
935 : CALL cp_abort(__LOCATION__, &
936 : "unit not yet fully specified, unit of kind "// &
937 0 : TRIM(res))
938 : CASE default
939 1010613 : CPABORT("unknown temperature unit:"//TRIM(cp_to_string(basic_unit)))
940 : END SELECT
941 : CASE (cp_ukind_pressure)
942 707609 : SELECT CASE (basic_unit)
943 : CASE (cp_units_bar)
944 155244 : res = "bar"
945 : CASE (cp_units_atm)
946 0 : res = "atm"
947 : CASE (cp_units_kbar)
948 16 : res = "kbar"
949 : CASE (cp_units_Pa)
950 20648 : res = "Pa"
951 : CASE (cp_units_MPa)
952 0 : res = "MPa"
953 : CASE (cp_units_GPa)
954 10629 : res = "GPa"
955 : CASE (cp_units_au)
956 0 : res = "au_p"
957 : CASE (cp_units_none)
958 0 : res = "pressure"
959 0 : IF (.NOT. my_accept_undefined) &
960 : CALL cp_abort(__LOCATION__, &
961 : "unit not yet fully specified, unit of kind "// &
962 0 : TRIM(res))
963 : CASE default
964 186537 : CPABORT("unknown pressure unit:"//TRIM(cp_to_string(basic_unit)))
965 : END SELECT
966 : CASE (cp_ukind_angle)
967 2516712 : SELECT CASE (basic_unit)
968 : CASE (cp_units_rad)
969 248625 : res = "rad"
970 : CASE (cp_units_deg)
971 303740 : res = "deg"
972 : CASE (cp_units_none)
973 0 : res = "angle"
974 0 : IF (.NOT. my_accept_undefined) &
975 : CALL cp_abort(__LOCATION__, &
976 : "unit not yet fully specified, unit of kind "// &
977 0 : TRIM(res))
978 : CASE default
979 552365 : CPABORT("unknown angle unit:"//TRIM(cp_to_string(basic_unit)))
980 : END SELECT
981 : CASE (cp_ukind_time)
982 195695 : SELECT CASE (basic_unit)
983 : CASE (cp_units_s)
984 154587 : res = "s"
985 : CASE (cp_units_fs)
986 1566725 : res = "fs"
987 : CASE (cp_units_ps)
988 437022 : res = "ps"
989 : CASE (cp_units_au)
990 109719 : res = "au_t"
991 : CASE (cp_units_wn)
992 34 : res = "wavenumber_t"
993 : CASE (cp_units_none)
994 0 : res = "time"
995 0 : IF (.NOT. my_accept_undefined) &
996 : CALL cp_abort(__LOCATION__, &
997 : "unit not yet fully specified, unit of kind "// &
998 0 : TRIM(res))
999 : CASE default
1000 2268087 : CPABORT("unknown time unit:"//TRIM(cp_to_string(basic_unit)))
1001 : END SELECT
1002 : CASE (cp_ukind_mass)
1003 134296 : SELECT CASE (basic_unit)
1004 : CASE (cp_units_kg)
1005 0 : res = "kg"
1006 : CASE (cp_units_amu)
1007 10476 : res = "amu"
1008 : CASE (cp_units_m_e, cp_units_au)
1009 30632 : res = "m_e"
1010 : CASE (cp_units_none)
1011 0 : res = "mass"
1012 0 : IF (.NOT. my_accept_undefined) &
1013 : CALL cp_abort(__LOCATION__, &
1014 : "unit not yet fully specified, unit of kind "// &
1015 0 : TRIM(res))
1016 : CASE default
1017 41108 : CPABORT("unknown mass unit:"//TRIM(cp_to_string(basic_unit)))
1018 : END SELECT
1019 : CASE (cp_ukind_potential)
1020 155006 : SELECT CASE (basic_unit)
1021 : CASE (cp_units_volt)
1022 134296 : res = "volt"
1023 : CASE (cp_units_au)
1024 0 : res = "au_pot"
1025 : CASE (cp_units_none)
1026 0 : res = "potential"
1027 0 : IF (.NOT. my_accept_undefined) &
1028 : CALL cp_abort(__LOCATION__, &
1029 : "unit not yet fully specified, unit of kind "// &
1030 0 : TRIM(res))
1031 : CASE default
1032 134296 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
1033 : END SELECT
1034 : CASE (cp_ukind_force)
1035 10350 : SELECT CASE (basic_unit)
1036 : CASE (cp_units_Newton)
1037 10 : res = "N"
1038 : CASE (cp_units_mNewton)
1039 20700 : res = "mN"
1040 : CASE (cp_units_au)
1041 0 : res = "au_f"
1042 : CASE (cp_units_none)
1043 0 : res = "force"
1044 0 : IF (.NOT. my_accept_undefined) &
1045 : CALL cp_abort(__LOCATION__, &
1046 : "unit not yet fully specified, unit of kind "// &
1047 0 : TRIM(res))
1048 : CASE default
1049 20710 : CPABORT("unknown potential unit:"//TRIM(cp_to_string(basic_unit)))
1050 : END SELECT
1051 : CASE (cp_ukind_efield)
1052 10340 : SELECT CASE (basic_unit)
1053 : CASE (cp_units_volt_per_m)
1054 10340 : res = "Vm-1"
1055 : CASE (cp_units_volt_per_nm)
1056 0 : res = "Vnm-1"
1057 : CASE (cp_units_volt_per_angstrom)
1058 0 : res = "Vangstrom-1"
1059 : CASE (cp_units_au)
1060 0 : res = "au_efield"
1061 : CASE (cp_units_none)
1062 0 : res = "electric field"
1063 0 : IF (.NOT. my_accept_undefined) &
1064 : CALL cp_abort(__LOCATION__, &
1065 : "unit not yet fully specified, unit of kind "// &
1066 0 : TRIM(res))
1067 : CASE default
1068 10340 : CPABORT("unknown efield unit:"//TRIM(cp_to_string(basic_unit)))
1069 : END SELECT
1070 : CASE (cp_ukind_none)
1071 : CALL cp_abort(__LOCATION__, &
1072 : "if the kind of the unit is none also unit must be undefined,not:" &
1073 0 : //TRIM(cp_to_string(basic_unit)))
1074 : CASE default
1075 22807248 : CPABORT("unknown kind of unit:"//TRIM(cp_to_string(basic_kind)))
1076 : END SELECT
1077 22807248 : IF (my_power /= 1) THEN
1078 2363235 : a = LEN_TRIM(res)
1079 2363235 : CPASSERT(LEN(res) - a >= 3)
1080 2363235 : WRITE (res(a + 1:), "('^',i3)") my_power
1081 2363235 : CALL compress(res, .TRUE.)
1082 : END IF
1083 22807248 : END FUNCTION cp_basic_unit_desc
1084 :
1085 : ! **************************************************************************************************
1086 : !> \brief returns the "name" of the given unit
1087 : !> \param unit the unit to describe
1088 : !> \param defaults defaults for the undefined units, optional
1089 : !> \param accept_undefined if defaults is not present or is not associated
1090 : !> whether undefined units should be accepted (defaults to false)
1091 : !> \return ...
1092 : !> \author fawzi
1093 : ! **************************************************************************************************
1094 21898815 : FUNCTION cp_unit_desc(unit, defaults, accept_undefined) &
1095 : RESULT(res)
1096 : TYPE(cp_unit_type), INTENT(IN) :: unit
1097 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1098 : LOGICAL, INTENT(in), OPTIONAL :: accept_undefined
1099 : CHARACTER(len=cp_unit_desc_length) :: res
1100 :
1101 : INTEGER :: i, my_unit, pos
1102 : LOGICAL :: check, has_defaults, my_accept_undefined
1103 :
1104 21898815 : res = ""
1105 21898815 : pos = 1
1106 21898815 : my_accept_undefined = .FALSE.
1107 21898815 : IF (PRESENT(accept_undefined)) my_accept_undefined = accept_undefined
1108 44706063 : DO i = 1, unit%n_kinds
1109 22807248 : CPASSERT(unit%kind_id(i) /= 0)
1110 22807248 : CPASSERT(pos < LEN(res))
1111 22807248 : my_unit = unit%unit_id(i)
1112 22807248 : has_defaults = .FALSE.
1113 22807248 : IF (PRESENT(defaults)) has_defaults = ASSOCIATED(defaults%units(1)%unit)
1114 22807248 : IF (my_unit == 0) THEN
1115 0 : IF (has_defaults) THEN
1116 0 : my_unit = defaults%units(unit%kind_id(i))%unit%unit_id(1)
1117 : ELSE
1118 0 : check = my_accept_undefined .OR. unit%kind_id(i) /= 0
1119 0 : CPASSERT(check)
1120 : END IF
1121 : END IF
1122 22807248 : IF (i > 1) THEN
1123 970377 : res(pos:pos) = "*"
1124 970377 : pos = pos + 1
1125 : END IF
1126 : res(pos:) = TRIM(cp_basic_unit_desc(basic_kind=unit%kind_id(i), &
1127 : basic_unit=my_unit, accept_undefined=my_accept_undefined, &
1128 22807248 : power=unit%power(i)))
1129 44706063 : pos = LEN_TRIM(res) + 1
1130 : END DO
1131 :
1132 21898815 : END FUNCTION cp_unit_desc
1133 :
1134 : ! **************************************************************************************************
1135 : !> \brief transform a value to the internal cp2k units
1136 : !> \param value the value to convert
1137 : !> \param unit the unit of the result
1138 : !> \param defaults the defaults unit for those that are left free
1139 : !> (cp_units_none)
1140 : !> \param power the power of the unit (defaults to 1)
1141 : !> \return ...
1142 : !> \author fawzi
1143 : ! **************************************************************************************************
1144 7597062 : FUNCTION cp_unit_to_cp2k1(value, unit, defaults, power) RESULT(res)
1145 : REAL(kind=dp), INTENT(in) :: value
1146 : TYPE(cp_unit_type), INTENT(IN) :: unit
1147 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1148 : INTEGER, INTENT(in), OPTIONAL :: power
1149 : REAL(kind=dp) :: res
1150 :
1151 : INTEGER :: i_unit, my_basic_unit, my_power
1152 :
1153 7597062 : my_power = 1
1154 7597062 : IF (PRESENT(power)) my_power = power
1155 7597062 : res = value
1156 15738599 : DO i_unit = 1, unit%n_kinds
1157 8141537 : CPASSERT(unit%kind_id(i_unit) > 0)
1158 8141537 : my_basic_unit = unit%unit_id(i_unit)
1159 8141537 : IF (my_basic_unit == 0 .AND. unit%kind_id(i_unit) /= cp_ukind_undef) THEN
1160 0 : CPASSERT(PRESENT(defaults))
1161 0 : CPASSERT(ASSOCIATED(defaults%units(unit%kind_id(i_unit))%unit))
1162 0 : my_basic_unit = defaults%units(unit%kind_id(i_unit))%unit%unit_id(1)
1163 : END IF
1164 : res = cp_basic_unit_to_cp2k(value=res, basic_unit=my_basic_unit, &
1165 : basic_kind=unit%kind_id(i_unit), &
1166 15738599 : power=my_power*unit%power(i_unit))
1167 : END DO
1168 7597062 : END FUNCTION cp_unit_to_cp2k1
1169 :
1170 : ! **************************************************************************************************
1171 : !> \brief converts from the internal cp2k units to the given unit
1172 : !> \param value the value to convert
1173 : !> \param unit the unit of the result
1174 : !> \param defaults the defaults unit for those that are left free
1175 : !> (cp_units_none)
1176 : !> \param power the power of the unit (defaults to 1)
1177 : !> \return ...
1178 : !> \author fawzi
1179 : ! **************************************************************************************************
1180 827302 : FUNCTION cp_unit_from_cp2k1(value, unit, defaults, power) RESULT(res)
1181 : REAL(kind=dp), INTENT(in) :: value
1182 : TYPE(cp_unit_type), INTENT(IN) :: unit
1183 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1184 : INTEGER, INTENT(in), OPTIONAL :: power
1185 : REAL(kind=dp) :: res
1186 :
1187 : INTEGER :: my_power
1188 :
1189 827302 : my_power = 1
1190 827302 : IF (PRESENT(power)) my_power = power
1191 827302 : IF (PRESENT(defaults)) THEN
1192 : res = cp_unit_to_cp2k1(value=value, unit=unit, defaults=defaults, &
1193 0 : power=-my_power)
1194 : ELSE
1195 827302 : res = cp_unit_to_cp2k1(value=value, unit=unit, power=-my_power)
1196 : END IF
1197 827302 : END FUNCTION cp_unit_from_cp2k1
1198 :
1199 : ! **************************************************************************************************
1200 : !> \brief converts to the internal cp2k units to the given unit
1201 : !> \param value the value to convert
1202 : !> \param unit_str the unit of the result as string
1203 : !> \param defaults the defaults unit for those that are left free
1204 : !> (cp_units_none)
1205 : !> \param power the power of the unit (defaults to 1)
1206 : !> \return ...
1207 : !> \author fawzi
1208 : ! **************************************************************************************************
1209 6657425 : FUNCTION cp_unit_to_cp2k(value, unit_str, defaults, power) RESULT(res)
1210 : REAL(kind=dp), INTENT(in) :: value
1211 : CHARACTER(len=*), INTENT(in) :: unit_str
1212 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1213 : INTEGER, INTENT(in), OPTIONAL :: power
1214 : REAL(kind=dp) :: res
1215 :
1216 : TYPE(cp_unit_type) :: my_unit
1217 :
1218 6657425 : CALL cp_unit_create(my_unit, unit_str)
1219 6657425 : IF (PRESENT(defaults)) THEN
1220 : res = cp_unit_to_cp2k1(value=value, unit=my_unit, defaults=defaults, &
1221 0 : power=power)
1222 : ELSE
1223 6657425 : res = cp_unit_to_cp2k1(value=value, unit=my_unit, power=power)
1224 : END IF
1225 6657425 : CALL cp_unit_release(my_unit)
1226 179750475 : END FUNCTION cp_unit_to_cp2k
1227 :
1228 : ! **************************************************************************************************
1229 : !> \brief converts from the internal cp2k units to the given unit
1230 : !> \param value the value to convert
1231 : !> \param unit_str the unit of the result as string
1232 : !> \param defaults the defaults unit for those that are left free
1233 : !> (cp_units_none)
1234 : !> \param power the power of the unit (defaults to 1)
1235 : !> \return ...
1236 : !> \author fawzi
1237 : ! **************************************************************************************************
1238 628520 : FUNCTION cp_unit_from_cp2k(value, unit_str, defaults, power) RESULT(res)
1239 : REAL(kind=dp), INTENT(in) :: value
1240 : CHARACTER(len=*), INTENT(in) :: unit_str
1241 : TYPE(cp_unit_set_type), INTENT(IN), OPTIONAL :: defaults
1242 : INTEGER, INTENT(in), OPTIONAL :: power
1243 : REAL(kind=dp) :: res
1244 :
1245 : TYPE(cp_unit_type) :: my_unit
1246 :
1247 628520 : CALL cp_unit_create(my_unit, unit_str)
1248 628520 : IF (PRESENT(defaults)) THEN
1249 : res = cp_unit_from_cp2k1(value=value, unit=my_unit, defaults=defaults, &
1250 0 : power=power)
1251 : ELSE
1252 628520 : res = cp_unit_from_cp2k1(value=value, unit=my_unit, power=power)
1253 : END IF
1254 628520 : CALL cp_unit_release(my_unit)
1255 16970040 : END FUNCTION cp_unit_from_cp2k
1256 :
1257 : ! **************************************************************************************************
1258 : !> \brief returs true if the two units are compatible
1259 : !> \param ref_unit ...
1260 : !> \param unit ...
1261 : !> \return ...
1262 : !> \author Teodoro Laino [tlaino] - 11.2007 - University of Zurich
1263 : ! **************************************************************************************************
1264 112335 : FUNCTION cp_unit_compatible(ref_unit, unit) RESULT(res)
1265 : TYPE(cp_unit_type), INTENT(IN) :: ref_unit, unit
1266 : LOGICAL :: res
1267 :
1268 : INTEGER :: i
1269 :
1270 112335 : res = .TRUE.
1271 1011015 : DO i = 1, SIZE(ref_unit%kind_id)
1272 898680 : IF (ref_unit%kind_id(i) == unit%kind_id(i)) CYCLE
1273 5200 : IF ((ref_unit%kind_id(1) == cp_ukind_undef) .AND. (ALL(ref_unit%kind_id(2:) == cp_ukind_none))) CYCLE
1274 : res = .FALSE.
1275 1011015 : EXIT
1276 : END DO
1277 :
1278 112335 : END FUNCTION cp_unit_compatible
1279 :
1280 : ! **************************************************************************************************
1281 : !> \brief initializes the given unit set
1282 : !> \param unit_set the set to initialize
1283 : !> \param name the name of the set, used for the dafault initialization of
1284 : !> the various units
1285 : !> \author fawzi
1286 : ! **************************************************************************************************
1287 134676 : SUBROUTINE cp_unit_set_create(unit_set, name)
1288 : TYPE(cp_unit_set_type), INTENT(OUT) :: unit_set
1289 : CHARACTER(len=*), INTENT(in) :: name
1290 :
1291 : CHARACTER(len=cp_unit_desc_length) :: my_name
1292 : INTEGER :: i
1293 :
1294 11223 : my_name = name
1295 11223 : CALL uppercase(my_name)
1296 :
1297 134676 : DO i = 1, cp_ukind_max
1298 123453 : NULLIFY (unit_set%units(i)%unit)
1299 3097548 : ALLOCATE (unit_set%units(i)%unit)
1300 : END DO
1301 134676 : DO i = 1, cp_ukind_max
1302 11223 : SELECT CASE (name)
1303 : CASE ('ATOM', 'ATOMIC', 'INTERNAL', 'CP2K')
1304 0 : IF (i == cp_ukind_angle) THEN
1305 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], &
1306 0 : unit_id=[cp_units_rad], power=[1])
1307 : ELSE
1308 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], &
1309 0 : unit_id=[cp_units_au], power=[1])
1310 : END IF
1311 : CASE ('OUTPUT')
1312 11223 : SELECT CASE (i)
1313 : CASE (cp_ukind_undef)
1314 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_none], &
1315 22446 : power=[1])
1316 : CASE (cp_ukind_energy)
1317 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_hartree], &
1318 22446 : power=[1])
1319 : CASE (cp_ukind_length)
1320 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_angstrom], &
1321 22446 : power=[1])
1322 : CASE (cp_ukind_temperature)
1323 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_k], &
1324 22446 : power=[1])
1325 : CASE (cp_ukind_angle)
1326 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_deg], &
1327 22446 : power=[1])
1328 : CASE (cp_ukind_pressure)
1329 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_bar], &
1330 22446 : power=[1])
1331 : CASE (cp_ukind_time)
1332 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_fs], &
1333 22446 : power=[1])
1334 : CASE (cp_ukind_mass)
1335 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_amu], &
1336 22446 : power=[1])
1337 : CASE (cp_ukind_potential)
1338 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_volt], &
1339 22446 : power=[1])
1340 : CASE (cp_ukind_force)
1341 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_newton], &
1342 22446 : power=[1])
1343 : CASE (cp_ukind_efield)
1344 : CALL cp_unit_create2(unit_set%units(i)%unit, kind_id=[i], unit_id=[cp_units_volt_per_m], &
1345 22446 : power=[1])
1346 : CASE default
1347 0 : CPABORT("unhandled unit type "//TRIM(cp_to_string(i)))
1348 123453 : EXIT
1349 : END SELECT
1350 : CASE default
1351 123453 : CPABORT('unknown parameter set name '//TRIM(name))
1352 : END SELECT
1353 : END DO
1354 11223 : END SUBROUTINE cp_unit_set_create
1355 :
1356 : ! **************************************************************************************************
1357 : !> \brief releases the given unit set
1358 : !> \param unit_set the unit set to release
1359 : !> \author fawzi
1360 : ! **************************************************************************************************
1361 11223 : SUBROUTINE cp_unit_set_release(unit_set)
1362 : TYPE(cp_unit_set_type), INTENT(INOUT) :: unit_set
1363 :
1364 : INTEGER :: i
1365 :
1366 134676 : DO i = 1, SIZE(unit_set%units)
1367 123453 : CALL cp_unit_release(unit_set%units(i)%unit)
1368 134676 : DEALLOCATE (unit_set%units(i)%unit)
1369 : END DO
1370 :
1371 11223 : END SUBROUTINE cp_unit_set_release
1372 :
1373 : ! **************************************************************************************************
1374 : !> \brief Exports all available units as XML.
1375 : !> \param iw ...
1376 : !> \author Ole Schuett
1377 : ! **************************************************************************************************
1378 0 : SUBROUTINE export_units_as_xml(iw)
1379 : INTEGER, INTENT(IN) :: iw
1380 :
1381 : CALL format_units_as_xml("energy", s2a("hartree", "wavenumber_e", "joule", "kcalmol", &
1382 0 : "kjmol", "Ry", "eV", "keV", "K_e"), iw)
1383 0 : CALL format_units_as_xml("length", s2a("bohr", "m", "pm", "nm", "angstrom"), iw)
1384 0 : CALL format_units_as_xml("temperature", s2a("K", "au_temp"), iw)
1385 0 : CALL format_units_as_xml("pressure", s2a("bar", "atm", "kbar", "Pa", "MPa", "GPa", "au_p"), iw)
1386 0 : CALL format_units_as_xml("angle", s2a("rad", "deg"), iw)
1387 0 : CALL format_units_as_xml("time", s2a("s", "fs", "ps", "au_t", "wavenumber_t"), iw)
1388 0 : CALL format_units_as_xml("mass", s2a("kg", "amu", "m_e"), iw)
1389 0 : CALL format_units_as_xml("potential", s2a("volt", "au_pot"), iw)
1390 0 : CALL format_units_as_xml("force", s2a("N", "Newton", "mN", "mNewton", "au_f"), iw)
1391 : CALL format_units_as_xml("efield", s2a("Vm-1", "Vnm-1", "VA-1", "volt_per_m", "volt_per_nm", &
1392 0 : "volt_per_angstrom", "au_efield"), iw)
1393 :
1394 0 : END SUBROUTINE export_units_as_xml
1395 :
1396 : ! **************************************************************************************************
1397 : !> \brief Format units as xml.
1398 : !> \param unit_kind ...
1399 : !> \param units_set ...
1400 : !> \param iw ...
1401 : !> \author Ole Schuett
1402 : ! **************************************************************************************************
1403 0 : SUBROUTINE format_units_as_xml(unit_kind, units_set, iw)
1404 : CHARACTER(LEN=*), INTENT(IN) :: unit_kind
1405 : CHARACTER(LEN=*), DIMENSION(:), INTENT(IN) :: units_set
1406 : INTEGER, INTENT(IN) :: iw
1407 :
1408 : INTEGER :: i
1409 :
1410 0 : WRITE (iw, FMT='(T2,A)') '<UNIT_KIND name="'//TRIM(unit_kind)//'">'
1411 0 : DO i = 1, SIZE(units_set)
1412 0 : WRITE (iw, FMT='(T3,A)') '<UNIT>'//TRIM(units_set(i))//'</UNIT>'
1413 : END DO
1414 0 : WRITE (iw, FMT='(T3,A)') '<UNIT>'//TRIM(unit_kind)//'</UNIT>' ! internal unit
1415 0 : WRITE (iw, FMT='(T2,A)') '</UNIT_KIND>'
1416 0 : END SUBROUTINE format_units_as_xml
1417 :
1418 0 : END MODULE cp_units
|