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
85 integer, parameter, public :: UNITS_ATOMIC = 0, units_eva = 1, units_fs = 2
86
87contains
88
89
90 ! ---------------------------------------------------------
91 subroutine unit_system_init(namespace)
92 type(namespace_t), intent(in) :: namespace
93
94 integer :: cc, cinp, cout, xyz_units
95
96 push_sub(unit_system_init)
97
98 !%Variable Units
99 !%Type virtual
100 !%Default atomic
101 !%Section Execution::Units
102 !%Description
103 !% (Virtual) These are the units that can be used in the input file.
104 !%
105 !%Option angstrom 1.8897261328856432
106 !%Option pm 0.018897261328856432
107 !%Option picometer 0.018897261328856432
108 !%Option nm 18.897261328856432
109 !%Option nanometer 18.897261328856432
110 !%Option ry 0.5
111 !%Option rydberg 0.5
112 !%Option ev 0.03674932539796232
113 !%Option electronvolt 0.03674932539796232
114 !%Option invcm 4.5563353e-06
115 !%Option kelvin 3.1668105e-06
116 !%Option kjoule_mol 0.00038087988
117 !%Option kcal_mol 0.0015936014
118 !%Option as 0.0413413737896
119 !%Option attosecond 0.0413413737896
120 !%Option fs 41.3413737896
121 !%Option femtosecond 41.3413737896
122 !%Option ps 41341.3737896
123 !%Option picosecond 41341.3737896
124 !%Option c 137.035999139
125 !%End
127 !%Variable UnitsOutput
128 !%Type integer
129 !%Default atomic
130 !%Section Execution::Units
131 !%Description
132 !% This variable selects the units that Octopus use for output.
133 !%
134 !% Atomic units seem to be the preferred system in the atomic and
135 !% molecular physics community. Internally, the code works in
136 !% atomic units. However, for output, some people like
137 !% to use a system based on electron-Volts (eV) for energies
138 !% and Angstroms (Å) for length.
139 !%
140 !% Normally time units are derived from energy and length units,
141 !% so it is measured in <math>\hbar</math>/Hartree or
142 !% <math>\hbar</math>/eV.
143 !%
144 !% Warning 1: All files read on input will also be treated using
145 !% these units, including XYZ geometry files.
146 !%
147 !% Warning 2: Some values are treated in their most common units,
148 !% for example atomic masses (a.m.u.), electron effective masses
149 !% (electron mass), vibrational frequencies
150 !% (cm<sup>-1</sup>) or temperatures (Kelvin). The unit of charge is always
151 !% the electronic charge <i>e</i>.
152 !%
153 !%Option atomic 0
154 !% Atomic units.
155 !%Option ev_angstrom 1
156 !% Electronvolts for energy, Angstroms for length, the rest of the
157 !% units are derived from these and <math>\hbar=1</math>.
158 !%End
159
160 if (parse_is_defined(namespace, 'Units') .or. parse_is_defined(namespace, 'Units')) then
161 call messages_write("The 'Units' variable is obsolete. Now Octopus always works in atomic", new_line = .true.)
162 call messages_write("units. For different units you can use values like 'angstrom', 'eV' ", new_line = .true.)
163 call messages_write("and others in the input file.")
165 end if
167 call messages_obsolete_variable(namespace, 'Units')
168 call messages_obsolete_variable(namespace, 'UnitsInput')
170 cinp = units_atomic
172 call parse_variable(namespace, 'UnitsOutput', units_atomic, cc)
173 if (.not. varinfo_valid_option('Units', cc, is_flag = .true.)) call messages_input_error(namespace, 'UnitsOutput')
174 cout = cc
176 ! TODO(Alex). Issue 884. Default constructors should be used for special units
177 ! and pressure conversion should be added
178 unit_one%factor = m_one
179 unit_one%abbrev = '1'
180 unit_one%name = 'one'
181
182 unit_angstrom%factor = p_ang ! 1 a.u. = 0.529 A
183 unit_angstrom%abbrev = "A"
184 unit_angstrom%name = "Angstrom"
185
186 unit_ppm%factor = 1e-6_real64
187 unit_ppm%abbrev = 'ppm a.u.'
188 unit_ppm%name = 'parts per million'
189
190 unit_susc_ppm_cgs%factor = 1e-6_real64/8.9238878e-2_real64
191 unit_susc_ppm_cgs%abbrev = 'ppm cgs/mol'
192 unit_susc_ppm_cgs%name = 'magnetic susceptibility parts per million cgs'
193
194 unit_debye%factor = m_one/2.5417462_real64
195 unit_debye%abbrev = 'Debye'
196 unit_debye%name = 'Debye'
197
198 ! this is the factor to convert 1 Ha to hc/cm in energy units
199 unit_invcm%factor = m_one/219474.63_real64
200 unit_invcm%abbrev = 'cm^-1'
201 unit_invcm%name = 'h times c over centimeters'
202
203 unit_kelvin%factor = p_kb
204 unit_kelvin%abbrev = 'K'
205 unit_kelvin%name = 'degrees Kelvin'
206
207 !atomic mass units
208 unit_amu%factor = m_one/5.485799110e-4_real64
209 unit_amu%abbrev = 'u'
210 unit_amu%name = '1/12 of the mass of C^12'
211
212 unit_femtosecond%factor = 1.0_real64/0.024188843_real64
213 unit_femtosecond%abbrev = 'fs'
214 unit_femtosecond%name = 'femtoseconds'
215
216 unit_kilobytes%factor = 2.0_real64**10
217 unit_kilobytes%abbrev = 'KiB'
218 unit_kilobytes%name = 'kibibytes'
219
220 unit_megabytes%factor = 2.0_real64**20
221 unit_megabytes%abbrev = 'MiB'
222 unit_megabytes%name = 'mebibytes'
223
224 unit_gigabytes%factor = 2.0_real64**30
225 unit_gigabytes%abbrev = 'GiB'
226 unit_gigabytes%name = 'gibibytes'
227
228 unit_ev%abbrev = "eV"
229 unit_ev%name = "electronvolt"
230 unit_ev%factor = m_one/(m_two*p_ry) ! 1 a.u. = 27.2 eV
231
232 call unit_system_get(units_inp, cinp)
233 call unit_system_get(units_out, cout)
234
235 !%Variable UnitsXYZFiles
236 !%Type integer
237 !%Default angstrom_units
238 !%Section Execution::Units
239 !%Description
240 !% This variable selects in which units I/O of XYZ files should be
241 !% performed.
242 !%Option bohr_units 0
243 !% The XYZ will be assumed to be in Bohr atomic units.
244 !%Option angstrom_units 1
245 !% XYZ files will be assumed to be always in Angstrom,
246 !% independently of the units used by Octopus. This ensures
247 !% compatibility with most programs, that assume XYZ files have
248 !% coordinates in Angstrom.
249 !%End
250
251 call parse_variable(namespace, 'UnitsXYZFiles', option__unitsxyzfiles__angstrom_units, xyz_units)
252
253 if (.not. varinfo_valid_option('UnitsXYZFiles', xyz_units)) then
254 call messages_input_error(namespace, 'UnitsXYZFiles', 'Invalid option')
255 end if
256
257 select case (xyz_units)
258
259 case (option__unitsxyzfiles__bohr_units)
260 ! Use units_inp%length for initialization, as units_inp are always in atomic units.
261 units_inp%length_xyz_file = units_inp%length
262 units_out%length_xyz_file = units_inp%length
263
264 case (option__unitsxyzfiles__angstrom_units)
265 units_inp%length_xyz_file = unit_angstrom
266 units_out%length_xyz_file = unit_angstrom
267
268 case default
269 assert(.false.)
270 end select
271
272 pop_sub(unit_system_init)
273
274 end subroutine unit_system_init
275
276 ! ---------------------------------------------------------
277 subroutine unit_system_get(uu, cc)
278 type(unit_system_t), intent(out) :: uu
279 integer, intent(in) :: cc
280
281 push_sub(unit_system_get)
282
283 select case (cc)
284 case (units_atomic)
286 case (units_eva)
288 case default
289 message(1) = "Unknown units in unit_system_get"
290 call messages_fatal(1)
291 end select
292
293 pop_sub(unit_system_get)
294 end subroutine unit_system_get
295
296
297 ! ---------------------------------------------------------
300 ! ---------------------------------------------------------
301 subroutine unit_system_init_atomic(uu)
302 type(unit_system_t), intent(out) :: uu
303
305
306 uu%length%abbrev = "b"
307 uu%length%name = "Bohr"
308 uu%length%factor = m_one
309
310 uu%energy%abbrev = "H"
311 uu%energy%name = "Hartree"
312 uu%energy%factor = m_one
313
314 uu%time%abbrev = "hbar/H"
315 uu%time%name = "hbar/Hartree"
316 uu%time%factor = m_one/uu%energy%factor
317
318 uu%velocity%abbrev = "bH(2pi/h)"
319 uu%velocity%name = "Bohr times Hartree over hbar"
320 uu%velocity%factor = m_one
321
322 uu%mass%abbrev = "me"
323 uu%mass%name = "electron mass"
324 uu%mass%factor = m_one
325
326 uu%force%abbrev = "H/b"
327 uu%force%name = "Hartree/Bohr"
328 uu%force%factor = m_one
329
330 uu%acceleration%abbrev = "bH(2pi/h)^2"
331 uu%acceleration%name = "Bohr times (Hartree over h bar) squared"
332 uu%acceleration%factor = m_one
333
334 uu%polarizability%abbrev = "b^3"
335 uu%polarizability%name = "Bohr^3"
336 uu%polarizability%factor = m_one
337 ! By convention, this unit appears more commonly than the
338 ! equivalent b^2/H. It does not depend on the dimensionality
339 ! of the system, despite analogies to a volume.
340
341 uu%hyperpolarizability%abbrev = "b^5"
342 uu%hyperpolarizability%name = "Bohr^5"
343 uu%hyperpolarizability%factor = m_one
344
346 end subroutine unit_system_init_atomic
347
348
349 ! ---------------------------------------------------------
350 subroutine unit_system_init_ev_ang(uu)
351 type(unit_system_t), intent(out) :: uu
352
354
355 uu%length%abbrev = "A"
356 uu%length%name = "Angstrom"
357 uu%length%factor = p_ang ! 1 a.u. = 0.529 A
358
359 uu%energy%abbrev = "eV"
360 uu%energy%name = "electronvolt"
361 uu%energy%factor = m_one/(m_two*p_ry) ! 1 a.u. = 27.2 eV
362
363 uu%time%abbrev = "hbar/eV"
364 uu%time%name = "hbar/electronvolt"
365 uu%time%factor = m_one/uu%energy%factor
366
367 uu%velocity%abbrev = "A eV/hbar"
368 uu%velocity%name = "Angstrom times electronvolts over hbar"
369 uu%velocity%factor = uu%length%factor*uu%energy%factor
371 uu%mass%abbrev = "hbar^2/(eV A^2)"
372 uu%mass%name = "hbar^2/(electronvolt * Angstrom^2)"
373 uu%mass%factor = m_one/(uu%energy%factor * uu%length%factor**2)
374
375 uu%force%abbrev = "eV/A"
376 uu%force%name = "electronvolt/Angstrom"
377 uu%force%factor = uu%energy%factor/uu%length%factor
378
379 uu%acceleration%abbrev = "A (eV/hbar)^2"
380 uu%acceleration%name = "Angstrom times (electronvolt over hbar) squared"
381 uu%acceleration%factor = uu%length%factor/uu%time%factor**2
382
383 uu%polarizability = uu%length**3
384 uu%hyperpolarizability = uu%length**5
385
387 end subroutine unit_system_init_ev_ang
388
389
390 ! ---------------------------------------------------------
396 ! ---------------------------------------------------------
397 subroutine unit_system_from_file(uu, fname, namespace, ierr)
398 type(unit_system_t), intent(inout) :: uu
399 character(len=*), intent(in) :: fname
400 type(namespace_t), intent(in) :: namespace
401 integer, intent(inout) :: ierr
402
403 integer :: iunit, ios
404 character(len=256) :: line
405
406 push_sub(unit_system_from_file)
407
408 iunit = io_open(trim(fname), namespace, action='read', status='old', die=.false.)
409 if (iunit < 0) then
410 ierr = -2
411 pop_sub(unit_system_from_file)
412 return
413 end if
414
415 ierr = 0
416 do
417 read(iunit, '(a)', iostat = ios) line
418 if (ios /= 0) exit
419 if (index(line,'[A]') /= 0 .or. index(line,'eV') /= 0) then
420 call unit_system_get(uu, units_eva)
421 pop_sub(unit_system_from_file)
422 return
423 else if (index(line,'[b]') /= 0) then
424 call unit_system_get(uu, units_atomic)
425 pop_sub(unit_system_from_file)
426 return
427 end if
428 end do
429
430 ierr = -1
431
432 pop_sub(unit_system_from_file)
433 end subroutine unit_system_from_file
434
435end module unit_system_oct_m
436
437!! Local Variables:
438!! mode: f90
439!! coding: utf-8
440!! End:
real(real64), parameter, public m_two
Definition: global.F90:189
real(real64), parameter, public p_ry
Definition: global.F90:220
real(real64), parameter, public p_ang
Definition: global.F90:219
real(real64), parameter, public p_kb
Boltzmann constant in Ha/K.
Definition: global.F90:222
real(real64), parameter, public m_one
Definition: global.F90:188
Definition: io.F90:114
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:395
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1057
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:420
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:723
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)