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!> Atomic weights should be read in "atomic mass units" (u) (not to
21!! be confused with mass in "atomic units"), that is, it should be given
22!! the relative atomic weight). 1 u is roughly the mass of the proton,
23!! and exactly one twelfth of mass of the ^{12}C isotope. The relation of the
24!! atomic mass unit and the atomic unit of mass, au_[mass], is:
25!!
26!! 1 au_[mass] = 5.485799110e-4 u
27!!
28!! The atomic unit of mass is the mass of the electron. Unfortunately, the
29!! code uses units of mass of (eV/A^2)(h/(2pieV))^2, which are related to
30!! atomic units through 1 cu_[mass] = 7.619963358 au_[mass] . So:
31!!
32!! 1 u = (1/5.485799110e-4) au_[mass] = (1/5.485799110e-4) *
33!!      (1/7.619963358) cu_[mass] = 239.225360 cu_[mass].
34
35#include "global.h"
36
37module unit_oct_m
38
39  implicit none
40
41  private
42  public ::            &
43    unit_t,            &
44    units_to_atomic,   &
45    units_from_atomic, &
46    units_abbrev,      &
47    operator(*),       &
48    operator(/),       &
49    operator(**),      &
50    sqrt
51
52  type unit_t
53    ! Components are public by default
54    FLOAT             :: factor
55    character(len=20) :: abbrev !< common abbreviation of the unit name
56    character(len=50) :: name   !< common name
57  end type unit_t
58
59  interface operator (*)
60    module procedure units_multiply
61  end interface operator (*)
62
63  interface operator (/)
64    module procedure units_divide
65  end interface operator (/)
66
67  interface operator (**)
68    module procedure units_pow
69  end interface operator (**)
70
71  interface units_to_atomic
72    module procedure dunits_to_atomic, zunits_to_atomic
73  end interface units_to_atomic
74
75  interface units_from_atomic
76    module procedure dunits_from_atomic, zunits_from_atomic
77  end interface units_from_atomic
78
79  interface sqrt
80    module procedure units_sqrt
81  end interface sqrt
82
83contains
84
85  !-----------------------------------------------
86
87  FLOAT elemental pure function dunits_to_atomic(this, val) result(res)
88    type(unit_t), intent(in) :: this
89    FLOAT,        intent(in) :: val
90
91    res = val*this%factor
92
93  end function dunits_to_atomic
94
95  !-----------------------------------------------
96
97  CMPLX elemental pure function zunits_to_atomic(this, val) result(res)
98    type(unit_t), intent(in) :: this
99    CMPLX,        intent(in) :: val
100
101    res = val*this%factor
102
103  end function zunits_to_atomic
104
105  !-----------------------------------------------
106
107  FLOAT elemental pure function dunits_from_atomic(this, val) result(res)
108    type(unit_t), intent(in) :: this
109    FLOAT,      intent(in) :: val
110
111    res = val/this%factor
112
113  end function dunits_from_atomic
114
115  !-----------------------------------------------
116
117  CMPLX elemental pure function zunits_from_atomic(this, val) result(res)
118    type(unit_t), intent(in) :: this
119    CMPLX,   intent(in) :: val
120
121    res = val/this%factor
122
123  end function zunits_from_atomic
124
125  !-----------------------------------------------
126
127  character(len=20) pure function units_abbrev(this) result(abbrev)
128    type(unit_t), intent(in) :: this
129
130    abbrev = this%abbrev
131  end function units_abbrev
132
133  !-----------------------------------------------
134
135  type(unit_t) pure function units_multiply(aa, bb) result(cc)
136    type(unit_t), intent(in) :: aa
137    type(unit_t), intent(in) :: bb
138
139    cc%factor = aa%factor*bb%factor
140    cc%abbrev = trim(aa%abbrev)//'*'//trim(bb%abbrev)
141
142  end function units_multiply
143
144  !-----------------------------------------------
145
146  type(unit_t) pure function units_divide(aa, bb) result(cc)
147    type(unit_t), intent(in) :: aa
148    type(unit_t), intent(in) :: bb
149
150    cc%factor = aa%factor/bb%factor
151    cc%abbrev = trim(aa%abbrev)//'/'//trim(bb%abbrev)
152
153  end function units_divide
154  !-----------------------------------------------
155
156  type(unit_t) pure function units_pow(aa, nn) result(cc)
157    type(unit_t), intent(in) :: aa
158    integer,      intent(in) :: nn
159
160    cc%factor = aa%factor**nn
161
162    ! We have to do the conversion by hand. This is ugly, but we
163    ! cannot use write here since this function might be called inside
164    ! another write (stupid Fortran).
165
166    select case(nn)
167    case(-3)
168      cc%abbrev = trim(aa%abbrev)//'^-3'
169    case(-2)
170      cc%abbrev = trim(aa%abbrev)//'^-2'
171    case(-1)
172      cc%abbrev = trim(aa%abbrev)//'^-1'
173    case(0)
174      cc%abbrev = '1'
175    case(1)
176      cc%abbrev = trim(aa%abbrev)
177    case(2)
178      cc%abbrev = trim(aa%abbrev)//'^2'
179    case(3)
180      cc%abbrev = trim(aa%abbrev)//'^3'
181    case(4)
182      cc%abbrev = trim(aa%abbrev)//'^4'
183    case(5)
184      cc%abbrev = trim(aa%abbrev)//'^5'
185    case default
186      cc%abbrev = trim(aa%abbrev)//'^n'
187    end select
188
189  end function units_pow
190
191
192  !-----------------------------------------------
193
194  type(unit_t) pure function units_sqrt(aa) result(cc)
195    type(unit_t), intent(in) :: aa
196
197    cc%factor = sqrt(aa%factor)
198    cc%abbrev = 'sqrt('//trim(aa%abbrev)//')'
199
200  end function units_sqrt
201
202end module unit_oct_m
203
204!! Local Variables:
205!! mode: f90
206!! coding: utf-8
207!! End:
208