|
4 | 4 | # This file contains various physical constants and functions to convert units |
5 | 5 | # from the atomic units |
6 | 6 |
|
7 | | -__all__ = ["length_to", "time_to", "freq_to", "ir_ints_to", "raman_ints_to", |
8 | | - "edipole_to", "equadrupole_to"] |
| 7 | +__all__ = ["convert_length", "convert_time", "convert_freq", "convert_ir_ints", |
| 8 | + "convert_raman_ints", "convert_edipole", "convert_equadrupole"] |
9 | 9 |
|
10 | 10 | # 1 atomic unit in SI |
11 | 11 | LENGTH = 5.29177210903e-11 # m |
|
81 | 81 |
|
82 | 82 | def _avail_keys(converter: Dict[str, float]) -> str: |
83 | 83 | # returns the available keys in a string of list of string |
84 | | - return str(list(_length_converter.keys())) |
| 84 | + return str(list(converter.keys())) |
85 | 85 |
|
86 | 86 | def _add_docstr_to(phys: str, converter: Dict[str, float]) -> Callable: |
87 | 87 | # automatically add docstring for converter functions |
88 | 88 |
|
89 | 89 | def decorator(callable: Callable): |
90 | 90 | callable.__doc__ = f""" |
91 | | - Convert the {phys} from atomic unit to the given unit. |
92 | | - Available units are (case-insensitive): {_avail_keys(converter)} |
| 91 | + Convert the {phys} from a unit to another unit. |
| 92 | + Available units are (case-insensitive): ``{_avail_keys(converter)}`` |
| 93 | +
|
| 94 | + Arguments |
| 95 | + --------- |
| 96 | + a: torch.Tensor |
| 97 | + The tensor to be converter. |
| 98 | + from_unit: str or None |
| 99 | + The unit of ``a``. If ``None``, it is assumed to be in atomic unit. |
| 100 | + to_unit: str or None |
| 101 | + The unit for ``a`` to be converted to. If ``None``, it is assumed |
| 102 | + to be converted to the atomic unit. |
| 103 | +
|
| 104 | + Returns |
| 105 | + ------- |
| 106 | + torch.Tensor |
| 107 | + The tensor in the new unit. |
93 | 108 | """ |
94 | 109 | return callable |
95 | 110 | return decorator |
96 | 111 |
|
97 | 112 | @_add_docstr_to("time", _time_converter) |
98 | | -def time_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 113 | +def convert_time(a: PhysVarType, from_unit: UnitType = None, |
| 114 | + to_unit: UnitType = None) -> PhysVarType: |
99 | 115 | # convert unit time from atomic unit to the given unit |
100 | | - return _converter_to(a, unit, _time_converter) |
| 116 | + return _converter(a, from_unit, to_unit, _time_converter) |
101 | 117 |
|
102 | 118 | @_add_docstr_to("frequency", _freq_converter) |
103 | | -def freq_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 119 | +def convert_freq(a: PhysVarType, from_unit: UnitType = None, |
| 120 | + to_unit: UnitType = None) -> PhysVarType: |
104 | 121 | # convert unit frequency from atomic unit to the given unit |
105 | | - return _converter_to(a, unit, _freq_converter) |
| 122 | + return _converter(a, from_unit, to_unit, _freq_converter) |
106 | 123 |
|
107 | 124 | @_add_docstr_to("IR intensity", _ir_ints_converter) |
108 | | -def ir_ints_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 125 | +def convert_ir_ints(a: PhysVarType, from_unit: UnitType = None, |
| 126 | + to_unit: UnitType = None) -> PhysVarType: |
109 | 127 | # convert unit IR intensity from atomic unit to the given unit |
110 | | - return _converter_to(a, unit, _ir_ints_converter) |
| 128 | + return _converter(a, from_unit, to_unit, _ir_ints_converter) |
111 | 129 |
|
112 | 130 | @_add_docstr_to("Raman intensity", _raman_ints_converter) |
113 | | -def raman_ints_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 131 | +def convert_raman_ints(a: PhysVarType, from_unit: UnitType = None, |
| 132 | + to_unit: UnitType = None) -> PhysVarType: |
114 | 133 | # convert unit IR intensity from atomic unit to the given unit |
115 | | - return _converter_to(a, unit, _raman_ints_converter) |
| 134 | + return _converter(a, from_unit, to_unit, _raman_ints_converter) |
116 | 135 |
|
117 | 136 | @_add_docstr_to("length", _length_converter) |
118 | | -def length_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 137 | +def convert_length(a: PhysVarType, from_unit: UnitType = None, |
| 138 | + to_unit: UnitType = None) -> PhysVarType: |
119 | 139 | # convert unit length from atomic unit to the given unit |
120 | | - return _converter_to(a, unit, _length_converter) |
| 140 | + return _converter(a, from_unit, to_unit, _length_converter) |
121 | 141 |
|
122 | 142 | @_add_docstr_to("electric dipole", _edipole_converter) |
123 | | -def edipole_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 143 | +def convert_edipole(a: PhysVarType, from_unit: UnitType = None, |
| 144 | + to_unit: UnitType = None) -> PhysVarType: |
124 | 145 | # convert unit electric dipole from atomic unit to the given unit |
125 | | - return _converter_to(a, unit, _edipole_converter) |
| 146 | + return _converter(a, from_unit, to_unit, _edipole_converter) |
126 | 147 |
|
127 | 148 | @_add_docstr_to("electric quadrupole", _equadrupole_converter) |
128 | | -def equadrupole_to(a: PhysVarType, unit: UnitType) -> PhysVarType: |
| 149 | +def convert_equadrupole(a: PhysVarType, from_unit: UnitType = None, |
| 150 | + to_unit: UnitType = None) -> PhysVarType: |
129 | 151 | # convert unit electric dipole from atomic unit to the given unit |
130 | | - return _converter_to(a, unit, _equadrupole_converter) |
131 | | - |
132 | | -def _converter_to(a: PhysVarType, unit: UnitType, converter: Dict[str, float]) -> PhysVarType: |
133 | | - # converter from the atomic unit |
134 | | - if unit is None: |
| 152 | + return _converter(a, from_unit, to_unit, _equadrupole_converter) |
| 153 | + |
| 154 | +def _converter(a: PhysVarType, from_unit: UnitType, to_unit: UnitType, |
| 155 | + converter: Dict[str, float]) -> PhysVarType: |
| 156 | + # converter from a unit to another unit |
| 157 | + from_unit = _preproc_unit(from_unit) |
| 158 | + to_unit = _preproc_unit(to_unit) |
| 159 | + if from_unit == to_unit: |
135 | 160 | return a |
136 | | - u = unit.lower() |
137 | | - try: |
138 | | - return a * converter[u] |
139 | | - except KeyError: |
| 161 | + if from_unit is not None: |
| 162 | + a = a / _get_converter_value(converter, from_unit) |
| 163 | + if to_unit is not None: |
| 164 | + a = a * _get_converter_value(converter, to_unit) |
| 165 | + return a |
| 166 | + |
| 167 | +def _get_converter_value(converter: Dict[str, float], unit: UnitType) -> float: |
| 168 | + if unit not in converter: |
140 | 169 | avail_units = _avail_keys(converter) |
141 | 170 | raise ValueError(f"Unknown unit: {unit}. Available units are: {avail_units}") |
| 171 | + return converter[unit] |
| 172 | + |
| 173 | +def _preproc_unit(unit: UnitType): |
| 174 | + if unit is None: |
| 175 | + return unit |
| 176 | + else: |
| 177 | + return ''.join(unit.lower().split()) |
0 commit comments