How To Use Physical Units

For numerical simulations, all quantities should be described in a consistent internal unit system that brings quantities as close to \(10^{0}\) as possible, in order to minimize floating point rounding errors. The optimal unit-system is domain-specific, depending on the typical energy, time, and length scales. For quantum dynamical simulations of atoms or molecules, atomic units are generally the most appropriate unit system.

QDYN is designed according to the principle that all quantities are converted to internal units on input, as early as possible, and converted to physical units again only on output, when writing to screen or file. All calculations are performed fully in internal units; there must be no unit conversion anywhere except in input/output routines.

The conversion factors from internal units are specified in a plain text file that is read a runtime. The default system of internal units is atomic units, specified in the file units_files/atomic_units.txt. It is possible to specify alternative internal unit conversion files.

On input, conversion must happen when reading values from a config file and also when reading a data file, e.g. a pulse or potential. In the config file, every floating point value should be tagged with a unit. For example, a time grid could be specified as

tgrid: n = 1
1 : t_start = 0.0, t_stop = 200.0_ns, nt = 1000

In general, the unit is specified by appending an underscore and the name of any unit defined in the units conversion file. Unitless numbers should be marked with _unitless. Numbers that are not tagged with a unit will not be converted, i.e. they are assumed to be in the internal unit system already. As this makes the config file dependent on the choice of internal units, it should be avoided.

QDYN developers must ensure that all routines that read columns of data from a text file, e.g. read_pulse, behave according to the following principles:

  • The routine must take optional parameters that specify the unit of each column in the data file

  • If these arguments are not specified, the units should be determined from the header of in the file. The data file should contain a comment that describes the data in each column, which each column label ending with the name of the unit enclosed in square brackets. E.g. a pulse file should have the header line

    #               time [ns]          Abs(ampl) [MHz]
    

    The routine must be able to understand the header as it is written by the corresponding QDYN-routine that generated the file

  • If no arguments specifying the units are given and the units cannot be determined by the header, a warning must be displayed, and the file is read without any conversion (i.e. it is assumed to be in internal units)

  • If the unit is specified both by an argument to the read-routine and in the header of the data file, but the information from both sources does not match, the program must abort with an error message

Since read-routines such as read_pulse are usually called as part of the init routine, based on information in the config file, any references in the config file to a data file should also specify the units. E.g.

pulse: n = 1
1: type = file, filename=pulse.dat, id = 1, &
time_unit = ns, ampl_unit = MHz, is_complex = F

Routines that write data files, such as write_pulse, must take non-optional arguments that specify the unit in which the columns are to be written out. They must write a header to the file that contains the unit, and that will be understood by the corresponding read-routine. Only debug-routines should ever write out unconverted internal units.

Users of QDYN should expect the behavior described above and submit any behavior that differs from it as a bug.

Initialization and Specification of Internal Units

Every program that builds on QDYN should call the routine init_unit_conversion early on (before the QDYN init routine). The routine takes the filename for an alternative list of internal unit conversion factors as an optional argument. If called without an argument, as init_unit_conversion(), it initializes atomic units, specified in units_files/atomic_units.txt as the internal units system.

If given a filename, conversion factors are loaded from that file. The file must be present in one of the following locations:

  1. the current working directory,

  2. the directory specified by the environment variable QDYN_UNITS,

  3. the default directory <prefix>/lib/qdyn/units_files, where <prefix> is the prefix in which the QDYN library has been installed (determined by the configure script)

The first file that is found will be used.

If init_unit_conversion is not called explicitly in the program, the unit system will be initialized with the atomic units by the QDYN init routine, and any other I/O routine. To use an alternative or augmented specification of internal units, init_unit_conversion must be called explicitly before any other QDYN routine, with the appropriate filename as an argument.

Atomic Units and Alternative Internal Units Systems

The default internal unit systems is atomic units, defined in atomic_units.txt. These units are characterized by \(\hbar\), electron mass, elementary charge, and Coulomb’s constant all equal to 1, which is generally assumed in any formula implemented in QDYN.

The four primary quantities used in QDYN are energy, time, length, and mass. Specifically for energy, it is common to use an energy equivalent, e.g. wavenumbers (\(E(\lambda) = h \frac{c}{\lambda}\)), frequency (\(E(\nu) = h \nu\)), or temperature (\(E(T) = k_b T\)).

Beyond that, there are relevant units for coupling operators with a field. For these, the combination of the operator and the field yields an energy. The simplest example is the single-photon electric dipole coupling, where the operator is given in units of dipole strength (e.g. Debeye or Coulomb-meter) and the field is given in electric field strength (e.g. Volt per meter). However is may also be convenient to leave the operator unitless (with a value of 1, or 0.5 in the RWA) and to specify the control directly in units of energy. For coupling operators that are non-linear in the field, different units are necessary. For example, the magnitude of the Stark shift (quadratic in the field) is given in terms of the polarizability. The field is still given in units of electric field strength, and the product of the polarizability and the square of the field yields an energy. Note that QDYN will know to square the pulse when applying a Stark shift operator. Thus, in the config file, the field connected to that operator should be given in units of field strength and not field intensity.

Any alternative internal unit system must use the same constants as atomic units. The two central conditions are that the dynamic phase of a quantum state \(\phi = -\frac{E}{\hbar} t\) must be invariant under changes in the internal unit system (always with \(\hbar = 1\)). Energy and time are reciprocal in this sense. When energy scales are on the order of GHz, it can be useful to use GHz/\(2\pi\) as the internal energy unit, and ns as the time unit. The factor of \(2 \pi\) is necessary because we require \(\hbar = 1\), not \(h = 1\) (\(E = \hbar \omega = \frac{h}{2\pi} \nu\)). This unit system is included in QDYN as GHz_units.txt. It can be used by initializing the unit system with

call init_unit_conversion('GHz_units.txt')

In GHz_units.txt, only energy and time are defined in alternative units, length and mass are still in a.u. Using an appropriate internal unit system, specifically with regard to energy and time may influence the convergence of the time propagation. Even more importantly, it is essential for optimization with the LBFGS algorithm that the controls take values on the order of \(10^0\) in internal units: the updates calculated by LBFGS will be of this order of magnitude, independent of the order of magnitude of the guess field.

The unit name ‘au’ (atomic units), is only unambiguous if atomic units are also used as internal units throughout. Otherwise it is not clear whether atomic length units (Bohr), atomic energy units (Hartree), etc. are used. The file GHz_units.txt therefore defines no au unit. It is generally recommended to use hartree, bohr, etc. as unambiguous labels in config or data files.

Generally, the kinetic operator implies a dependence of the internal mass and length unit, as \(\Op{T} = -\frac{\hbar}{2m} \, \frac{\partial^2}{\partial x^2}\) (\(\hbar = 1\)) must remain invariant under changes in the pulse. It is the user’s responsibility when writing new internal unit systems to ensure that the internal units are fully consistent with the conventions of QDYN.

Conversion Routines

QDYN provides the functions conv_from_iu and conv_to_iu, or the combined unit_conv to convert between internal units and a physical unit. These are useful when writing to screen, e.g.

write(*,'("max(E) = ",F8.4," MHz")') conv_from_iu(pulse%E_max, 'MHz')

Note that the unit conversion is relatively expensive. When converting a large quantity of numbers, such as when writing an array to file, it is recommended to obtain the conversion factor only once. This is achieved with the conv_factor function.