.. SPDX-FileCopyrightText: 1992-2026 NWO-I/SRON Space Research Organisation Netherlands .. .. SPDX-License-Identifier: CC-BY-4.0 Energy Unit Conversions (energy) ================================== **Module**: ``utils_energy`` Overview -------- Provides functions to convert between different energy and wavelength units used in X-ray spectroscopy. Uses CODATA 2018 physical constants for high precision. Key Features ------------ - Convert between 7 different units: keV, eV, Rydberg, Joules, Hz, Angstroms, nanometers - High precision calculations using double precision arithmetic - Handles edge cases (e.g., very small wavelengths) - Based on CODATA 2018 physical constants Supported Units --------------- .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Unit Code - Full Name - Description * - ``'kev'`` - Kiloelectron volts - Standard X-ray energy unit * - ``'ev'`` - Electron volts - 1/1000 of keV * - ``'ryd'`` - Rydberg - Atomic energy unit * - ``'j'`` - Joules - SI energy unit * - ``'hz'`` - Hertz - Frequency unit * - ``'ang'`` - Angstroms - Wavelength unit (10⁻¹⁰ m) * - ``'nm'`` - Nanometers - Wavelength unit (10⁻⁹ m) API Reference ------------- Constants ~~~~~~~~~ **Conversion Factors** .. list-table:: :widths: 20 30 50 :header-rows: 1 * - Constant - Value - Description * - ``kevtohz`` - 2.41798924208492e17_dp - keV to Hz (e/h, CODATA 2018) * - ``kevtoang`` - 12.39841984332_dp - keV to Angstroms (hc/e, CODATA 2018) * - ``rydtokev`` - 0.013605693122994_dp - Rydberg to keV * - ``ktokev`` - 8.61733326214518e-8_dp - Kelvin to keV Functions ~~~~~~~~~ **calc_energy** .. function:: calc_energy(x1, x2, unit1, unit2) Convert energy/wavelength between different units :param x1: Input value (real(dp)) :param x2: Output value (real(dp)) :param unit1: Input unit (character*3) :param unit2: Output unit (character*3) :return: x2 contains converted value Converts from unit1 to unit2 through keV as intermediate representation. Usage Examples -------------- **Basic Energy Conversion** .. code-block:: fortran use utils_energy use utils_cspex, only: dp real(dp) :: energy_kev, wavelength_ang, frequency_hz ! Convert 1 keV to Angstroms call calc_energy(1.0_dp, wavelength_ang, 'kev', 'ang') write(*,*) '1 keV = ', wavelength_ang, ' Angstroms' ! Convert 1 keV to Hz call calc_energy(1.0_dp, frequency_hz, 'kev', 'hz') write(*,*) '1 keV = ', frequency_hz, ' Hz' **Wavelength to Energy** .. code-block:: fortran use utils_energy use utils_cspex, only: dp real(dp) :: energy_kev, wavelength_nm ! Convert 10 nm to keV wavelength_nm = 10.0_dp call calc_energy(wavelength_nm, energy_kev, 'nm', 'kev') write(*,*) wavelength_nm, ' nm = ', energy_kev, ' keV' **Unit Round-Trip** .. code-block:: fortran use utils_energy use utils_cspex, only: dp real(dp) :: original_kev, converted_kev, temp_ang original_kev = 6.4_dp ! Fe K-alpha line ! Convert keV to Angstroms and back call calc_energy(original_kev, temp_ang, 'kev', 'ang') call calc_energy(temp_ang, converted_kev, 'ang', 'kev') write(*,*) 'Original: ', original_kev, ' keV' write(*,*) 'Round-trip: ', converted_kev, ' keV' write(*,*) 'Difference: ', abs(original_kev - converted_kev) **Common X-ray Lines** .. code-block:: fortran use utils_energy use utils_cspex, only: dp real(dp) :: energy_kev, wavelength_ang ! Fe K-alpha line (6.4 keV) call calc_energy(6.4_dp, wavelength_ang, 'kev', 'ang') write(*,*) 'Fe K-alpha: 6.4 keV = ', wavelength_ang, ' Angstroms' ! O K-alpha line (0.525 keV) call calc_energy(0.525_dp, wavelength_ang, 'kev', 'ang') write(*,*) 'O K-alpha: 0.525 keV = ', wavelength_ang, ' Angstroms' Notes ----- **Precision Considerations** - All calculations use double precision (dp) for maximum accuracy - Uses ``tiny(x)`` to avoid division by zero for very small wavelengths - CODATA 2018 constants ensure scientific accuracy **Performance** - Simple arithmetic operations - very fast - No memory allocation - suitable for tight loops - Minimal branching - good for modern CPUs **Error Handling** - No explicit error checking for invalid unit codes - Invalid units may produce incorrect results - Consider adding validation for production code **Best Practices** 1. Always use ``_dp`` suffix for literal values 2. Check that output values are reasonable 3. For critical applications, validate unit codes 4. Use intermediate variables for complex conversions See Also -------- - :doc:`../core/constants` - Mathematical constants used in calculations - :doc:`../io/files` - File operations for saving/loading energy data - :doc:`../core/messages` - Error handling for invalid conversions