Octopus
unit_system.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19
20
21#include "global.h"
22!
34 use debug_oct_m
35 use global_oct_m
36 use io_oct_m
37 use, intrinsic :: iso_fortran_env
40 use parser_oct_m
41 use unit_oct_m
43
44 implicit none
45
46 private
47 public :: &
52
53 type unit_system_t
54 ! Components are public by default
55 type(unit_t) :: length
56 type(unit_t) :: length_xyz_file
57 type(unit_t) :: energy
58 type(unit_t) :: time
59 type(unit_t) :: velocity
60 type(unit_t) :: mass
61 type(unit_t) :: force
62 type(unit_t) :: acceleration
63 type(unit_t) :: polarizability
64 type(unit_t) :: hyperpolarizability
65 end type unit_system_t
66
68 type(unit_system_t), public :: units_inp, units_out
69
71 type(unit_t), public :: unit_one
72 type(unit_t), public :: unit_angstrom
73 type(unit_t), public :: unit_ppm
74 type(unit_t), public :: unit_debye
75 type(unit_t), public :: unit_invcm
76 type(unit_t), public :: unit_susc_ppm_cgs
77 type(unit_t), public :: unit_kelvin
78 type(unit_t), public :: unit_femtosecond
79 type(unit_t), public :: unit_amu
80 type(unit_t), public :: unit_kilobytes
81 type(unit_t), public :: unit_megabytes
82 type(unit_t), public :: unit_gigabytes
83 type(unit_t), public :: unit_eV
84 type(unit_t), public :: unit_GPa
85
86 integer, parameter, public :: UNITS_ATOMIC = 0, units_eva = 1, units_fs = 2
87
88contains
89
90
91 ! ---------------------------------------------------------
92 subroutine unit_system_init(namespace)
93 type(namespace_t), intent(in) :: namespace
94
95 integer :: cc, cinp, cout, xyz_units
96
97 push_sub(unit_system_init)
98
99 !%Variable Units
100 !%Type virtual
101 !%Default atomic
102 !%Section Execution::Units
103 !%Description
104 !% (Virtual) These are the units that can be used in the input file.
105 !%
106 !%Option angstrom 1.8897261328856432
107 !%Option pm 0.018897261328856432
108 !%Option picometer 0.018897261328856432
109 !%Option nm 18.897261328856432
110 !%Option nanometer 18.897261328856432
111 !%Option ry 0.5
112 !%Option rydberg 0.5
113 !%Option ev 0.03674932539796232
114 !%Option electronvolt 0.03674932539796232
115 !%Option invcm 4.5563353e-06
116 !%Option kelvin 3.1668105e-06
117 !%Option kjoule_mol 0.00038087988
118 !%Option kcal_mol 0.0015936014
119 !%Option as 0.0413413737896
120 !%Option attosecond 0.0413413737896
121 !%Option fs 41.3413737896
122 !%Option femtosecond 41.3413737896
123 !%Option ps 41341.3737896
124 !%Option picosecond 41341.3737896
125 !%Option c 137.035999139
126 !%Option gpa 0.339892967545026635270e-4
127 !%End
128
129 !%Variable UnitsOutput
130 !%Type integer
131 !%Default atomic
132 !%Section Execution::Units
133 !%Description
134 !% This variable selects the units that Octopus use for output.
135 !%
136 !% Atomic units seem to be the preferred system in the atomic and
137 !% molecular physics community. Internally, the code works in
138 !% atomic units. However, for output, some people like
139 !% to use a system based on electron-Volts (eV) for energies
140 !% and Angstroms (Å) for length.
141 !%
142 !% Normally time units are derived from energy and length units,
143 !% so it is measured in <math>\hbar</math>/Hartree or
144 !% <math>\hbar</math>/eV.
145 !%
146 !% Warning 1: All files read on input will also be treated using
147 !% these units, including XYZ geometry files.
148 !%
149 !% Warning 2: Some values are treated in their most common units,
150 !% for example atomic masses (a.m.u.), electron effective masses
151 !% (electron mass), vibrational frequencies
152 !% (cm<sup>-1</sup>) or temperatures (Kelvin). The unit of charge is always
153 !% the electronic charge <i>e</i>.
154 !%
155 !%Option atomic 0
156 !% Atomic units.
157 !%Option ev_angstrom 1
158 !% Electronvolts for energy, Angstroms for length, the rest of the
159 !% units are derived from these and <math>\hbar=1</math>.
160 !%End
162 if (parse_is_defined(namespace, 'Units') .or. parse_is_defined(namespace, 'Units')) then
163 call messages_write("The 'Units' variable is obsolete. Now Octopus always works in atomic", new_line = .true.)
164 call messages_write("units. For different units you can use values like 'angstrom', 'eV' ", new_line = .true.)
165 call messages_write("and others in the input file.")
167 end if
169 call messages_obsolete_variable(namespace, 'Units')
170 call messages_obsolete_variable(namespace, 'UnitsInput')
172 cinp = units_atomic
174 call parse_variable(namespace, 'UnitsOutput', units_atomic, cc)
175 if (.not. varinfo_valid_option('Units', cc, is_flag = .true.)) call messages_input_error(namespace, 'UnitsOutput')
176 cout = cc
178 ! TODO(Alex). Issue 884. Default constructors should be used for special units
179 ! and pressure conversion should be added
180 unit_one%factor = m_one
181 unit_one%abbrev = '1'
182 unit_one%name = 'one'
183
184 unit_angstrom%factor = p_ang ! 1 a.u. = 0.529 A
185 unit_angstrom%abbrev = "A"
186 unit_angstrom%name = "Angstrom"
187
188 unit_ppm%factor = 1e-6_real64
189 unit_ppm%abbrev = 'ppm a.u.'
190 unit_ppm%name = 'parts per million'
191
192 unit_susc_ppm_cgs%factor = 1e-6_real64/8.9238878e-2_real64
193 unit_susc_ppm_cgs%abbrev = 'ppm cgs/mol'
194 unit_susc_ppm_cgs%name = 'magnetic susceptibility parts per million cgs'
195
196 unit_debye%factor = m_one/2.5417462_real64
197 unit_debye%abbrev = 'Debye'
198 unit_debye%name = 'Debye'
199
200 ! this is the factor to convert 1 Ha to hc/cm in energy units
201 unit_invcm%factor = m_one/219474.63_real64
202 unit_invcm%abbrev = 'cm^-1'
203 unit_invcm%name = 'h times c over centimeters'
204
205 unit_kelvin%factor = p_kb
206 unit_kelvin%abbrev = 'K'
207 unit_kelvin%name = 'degrees Kelvin'
208
209 !atomic mass units
210 unit_amu%factor = m_one/5.485799110e-4_real64
211 unit_amu%abbrev = 'u'
212 unit_amu%name = '1/12 of the mass of C^12'
213
214 unit_femtosecond%factor = 1.0_real64/0.024188843_real64
215 unit_femtosecond%abbrev = 'fs'
216 unit_femtosecond%name = 'femtoseconds'
217
218 unit_kilobytes%factor = 2.0_real64**10
219 unit_kilobytes%abbrev = 'KiB'
220 unit_kilobytes%name = 'kibibytes'
221
222 unit_megabytes%factor = 2.0_real64**20
223 unit_megabytes%abbrev = 'MiB'
224 unit_megabytes%name = 'mebibytes'
225
226 unit_gigabytes%factor = 2.0_real64**30
227 unit_gigabytes%abbrev = 'GiB'
228 unit_gigabytes%name = 'gibibytes'
229
230 unit_ev%abbrev = "eV"
231 unit_ev%name = "electronvolt"
232 unit_ev%factor = m_one/(m_two*p_ry) ! 1 a.u. = 27.2 eV
233
234 unit_gpa%abbrev = "GPa"
235 unit_gpa%name = "gigapascal"
236 unit_gpa%factor = 0.339892967545026635270e-4_real64
237
238 call unit_system_get(units_inp, cinp)
239 call unit_system_get(units_out, cout)
240
241 !%Variable UnitsXYZFiles
242 !%Type integer
243 !%Default angstrom_units
244 !%Section Execution::Units
245 !%Description
246 !% This variable selects in which units I/O of XYZ files should be
247 !% performed.
248 !%Option bohr_units 0
249 !% The XYZ will be assumed to be in Bohr atomic units.
250 !%Option angstrom_units 1
251 !% XYZ files will be assumed to be always in Angstrom,
252 !% independently of the units used by Octopus. This ensures
253 !% compatibility with most programs, that assume XYZ files have
254 !% coordinates in Angstrom.
255 !%End
256
257 call parse_variable(namespace, 'UnitsXYZFiles', option__unitsxyzfiles__angstrom_units, xyz_units)
258
259 if (.not. varinfo_valid_option('UnitsXYZFiles', xyz_units)) then
260 call messages_input_error(namespace, 'UnitsXYZFiles', 'Invalid option')
261 end if
262
263 select case (xyz_units)
264
265 case (option__unitsxyzfiles__bohr_units)
266 ! Use units_inp%length for initialization, as units_inp are always in atomic units.
267 units_inp%length_xyz_file = units_inp%length
268 units_out%length_xyz_file = units_inp%length
269
270 case (option__unitsxyzfiles__angstrom_units)
271 units_inp%length_xyz_file = unit_angstrom
272 units_out%length_xyz_file = unit_angstrom
273
274 case default
275 assert(.false.)
276 end select
277
278 pop_sub(unit_system_init)
279
280 end subroutine unit_system_init
281
282 ! ---------------------------------------------------------
283 subroutine unit_system_get(uu, cc)
284 type(unit_system_t), intent(out) :: uu
285 integer, intent(in) :: cc
286
287 push_sub(unit_system_get)
288
289 select case (cc)
290 case (units_atomic)
292 case (units_eva)
294 case default
295 message(1) = "Unknown units in unit_system_get"
296 call messages_fatal(1)
297 end select
298
299 pop_sub(unit_system_get)
300 end subroutine unit_system_get
301
302
303 ! ---------------------------------------------------------
306 ! ---------------------------------------------------------
307 subroutine unit_system_init_atomic(uu)
308 type(unit_system_t), intent(out) :: uu
309
311
312 uu%length%abbrev = "b"
313 uu%length%name = "Bohr"
314 uu%length%factor = m_one
315
316 uu%energy%abbrev = "H"
317 uu%energy%name = "Hartree"
318 uu%energy%factor = m_one
319
320 uu%time%abbrev = "hbar/H"
321 uu%time%name = "hbar/Hartree"
322 uu%time%factor = m_one/uu%energy%factor
323
324 uu%velocity%abbrev = "bH(2pi/h)"
325 uu%velocity%name = "Bohr times Hartree over hbar"
326 uu%velocity%factor = m_one
327
328 uu%mass%abbrev = "me"
329 uu%mass%name = "electron mass"
330 uu%mass%factor = m_one
331
332 uu%force%abbrev = "H/b"
333 uu%force%name = "Hartree/Bohr"
334 uu%force%factor = m_one
335
336 uu%acceleration%abbrev = "bH(2pi/h)^2"
337 uu%acceleration%name = "Bohr times (Hartree over h bar) squared"
338 uu%acceleration%factor = m_one
339
340 uu%polarizability%abbrev = "b^3"
341 uu%polarizability%name = "Bohr^3"
342 uu%polarizability%factor = m_one
343 ! By convention, this unit appears more commonly than the
344 ! equivalent b^2/H. It does not depend on the dimensionality
345 ! of the system, despite analogies to a volume.
346
347 uu%hyperpolarizability%abbrev = "b^5"
348 uu%hyperpolarizability%name = "Bohr^5"
349 uu%hyperpolarizability%factor = m_one
350
352 end subroutine unit_system_init_atomic
353
354
355 ! ---------------------------------------------------------
356 subroutine unit_system_init_ev_ang(uu)
357 type(unit_system_t), intent(out) :: uu
358
360
361 uu%length%abbrev = "A"
362 uu%length%name = "Angstrom"
363 uu%length%factor = p_ang ! 1 a.u. = 0.529 A
364
365 uu%energy%abbrev = "eV"
366 uu%energy%name = "electronvolt"
367 uu%energy%factor = m_one/(m_two*p_ry) ! 1 a.u. = 27.2 eV
368
369 uu%time%abbrev = "hbar/eV"
370 uu%time%name = "hbar/electronvolt"
371 uu%time%factor = m_one/uu%energy%factor
372
373 uu%velocity%abbrev = "A eV/hbar"
374 uu%velocity%name = "Angstrom times electronvolts over hbar"
375 uu%velocity%factor = uu%length%factor*uu%energy%factor
377 uu%mass%abbrev = "hbar^2/(eV A^2)"
378 uu%mass%name = "hbar^2/(electronvolt * Angstrom^2)"
379 uu%mass%factor = m_one/(uu%energy%factor * uu%length%factor**2)
380
381 uu%force%abbrev = "eV/A"
382 uu%force%name = "electronvolt/Angstrom"
383 uu%force%factor = uu%energy%factor/uu%length%factor
384
385 uu%acceleration%abbrev = "A (eV/hbar)^2"
386 uu%acceleration%name = "Angstrom times (electronvolt over hbar) squared"
387 uu%acceleration%factor = uu%length%factor/uu%time%factor**2
388
389 uu%polarizability = uu%length**3
390 uu%hyperpolarizability = uu%length**5
391
393 end subroutine unit_system_init_ev_ang
394
395
396 ! ---------------------------------------------------------
402 ! ---------------------------------------------------------
403 subroutine unit_system_from_file(uu, fname, namespace, ierr)
404 type(unit_system_t), intent(inout) :: uu
405 character(len=*), intent(in) :: fname
406 type(namespace_t), intent(in) :: namespace
407 integer, intent(inout) :: ierr
408
409 integer :: iunit, ios
410 character(len=256) :: line
411
412 push_sub(unit_system_from_file)
413
414 iunit = io_open(trim(fname), namespace, action='read', status='old', die=.false.)
415 if (iunit == -1) then
416 ierr = -2
417 pop_sub(unit_system_from_file)
418 return
419 end if
420
421 ierr = 0
422 do
423 read(iunit, '(a)', iostat = ios) line
424 if (ios /= 0) exit
425 if (index(line,'[A]') /= 0 .or. index(line,'eV') /= 0) then
426 call unit_system_get(uu, units_eva)
427 pop_sub(unit_system_from_file)
428 return
429 else if (index(line,'[b]') /= 0) then
430 call unit_system_get(uu, units_atomic)
431 pop_sub(unit_system_from_file)
432 return
433 end if
434 end do
435
436 ierr = -1
437
438 pop_sub(unit_system_from_file)
439 end subroutine unit_system_from_file
440
441end module unit_system_oct_m
442
443!! Local Variables:
444!! mode: f90
445!! coding: utf-8
446!! End:
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public p_ry
Definition: global.F90:221
real(real64), parameter, public p_ang
Definition: global.F90:220
real(real64), parameter, public p_kb
Boltzmann constant in Ha/K.
Definition: global.F90:223
real(real64), parameter, public m_one
Definition: global.F90:189
Definition: io.F90:114
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:352
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1045
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:160
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:414
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:713
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:502
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
subroutine, public unit_system_from_file(uu, fname, namespace, ierr)
This is a very primitive procedure that attempts to find out which units were used to write an octopu...
integer, parameter, public units_fs
subroutine, public unit_system_get(uu, cc)
subroutine, public unit_system_init(namespace)
subroutine unit_system_init_ev_ang(uu)
integer, parameter, public units_eva
subroutine unit_system_init_atomic(uu)
These routines output the unit-conversion factors, defined by [a.u.] = input*u.unit,...
int true(void)