LCOV - code coverage report
Current view: top level - utils - units.hpp (source / functions) Coverage Total Hit
Test: Palace Coverage Report Lines: 92.6 % 27 25
Test Date: 2025-10-23 22:45:05 Functions: 100.0 % 5 5
Legend: Lines: hit not hit

            Line data    Source code
       1              : // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : #ifndef PALACE_UTILS_UNITS_HPP
       5              : #define PALACE_UTILS_UNITS_HPP
       6              : 
       7              : #include <algorithm>
       8              : #include <array>
       9              : #include <vector>
      10              : 
      11              : #include "utils/constants.hpp"
      12              : 
      13              : namespace palace
      14              : {
      15              : 
      16              : class Units
      17              : {
      18              :   // Mesh unit length from config["Model"]["L0"] in [m]. Sets length of mesh coordinate.
      19              :   double L0_m;
      20              : 
      21              :   // Characteristic reference length [m] and time [ns] for (non)dimensionalization.
      22              :   // Note: In input, config["Model"]["Lc"] is measured in units of L0; here Lc_m is in [m].
      23              :   double Lc_m;   // [m]
      24              :   double tc_ns;  // [ns]
      25              : 
      26              :   // Characteristic reference magnetic field strength Hc² = 1 / (Zc * Lc²) A/m (with Ec =
      27              :   // Hc Zc). Yields Pc = Hc² Zc Lc² = 1 W. Precompute.
      28              :   double Hc;
      29              : 
      30              : public:
      31              :   Units(double L0_, double Lc_)
      32           67 :     : L0_m(L0_), Lc_m(Lc_), tc_ns(1.0e9 * Lc_m / electromagnetics::c0_),
      33           41 :       Hc(1.0 / std::sqrt(electromagnetics::Z0_ * Lc_m * Lc_m)) {};
      34              : 
      35              :   // Return the mesh scaling factor in units L0 x [m] for mesh IO.
      36          210 :   double GetMeshLengthRelativeScale() const { return Lc_m / L0_m; }
      37              : 
      38              :   // Redimensionalize values for output. Outputs which depend on the fields assume a
      39              :   // characteristic reference magnetic field strength Hc such that Pc = 1 W, where Pc is the
      40              :   // characteristic reference power.
      41              :   enum class ValueType : std::uint8_t
      42              :   {
      43              :     TIME,          // [ns]
      44              :     FREQUENCY,     // [GHz]
      45              :     LENGTH,        // [m]
      46              :     IMPEDANCE,     // [Ω]
      47              :     INDUCTANCE,    // [H] = [Ωs]
      48              :     CAPACITANCE,   // [F] = [s/Ω]
      49              :     CONDUCTIVITY,  // [S/m]
      50              :     VOLTAGE,       // [V]
      51              :     CURRENT,       // [A]
      52              :     POWER,         // [W]
      53              :     ENERGY,        // [J]
      54              :     FIELD_E,       // [V/m]
      55              :     FIELD_D,       // [C/m²] = [A⋅s/m²]
      56              :     FIELD_H,       // [A/m]
      57              :     FIELD_B        // [Wb/m²] = [V⋅s/m²]
      58              :   };
      59              : 
      60              :   // Helper class to essentially allow static_assert(false) in constexpr if branch.
      61              :   // static_assert(false) fixed as defect report for C++23 (P2593).
      62              :   template <ValueType T>
      63              :   struct always_false : std::false_type
      64              :   {
      65              :   };
      66              : 
      67              :   template <ValueType unit>
      68              :   double GetScaleFactor() const
      69              :   {
      70              :     if constexpr (unit == ValueType::TIME)
      71              :     {
      72           29 :       return tc_ns;  // [ns]
      73              :     }
      74              :     else if constexpr (unit == ValueType::FREQUENCY)
      75              :     {
      76          132 :       return 1.0 / (2.0 * M_PI * tc_ns);  // [GHz/rad]
      77              :     }
      78              :     else if constexpr (unit == ValueType::LENGTH)
      79              :     {
      80     17280060 :       return Lc_m;  // [m]
      81              :     }
      82              :     else if constexpr (unit == ValueType::IMPEDANCE)
      83              :     {
      84              :       return electromagnetics::Z0_;  // [Ω]
      85              :     }
      86              :     else if constexpr (unit == ValueType::INDUCTANCE)
      87              :     {
      88           56 :       return electromagnetics::mu0_ * Lc_m;  // [H]
      89              :     }
      90              :     else if constexpr (unit == ValueType::CAPACITANCE)
      91              :     {
      92           60 :       return electromagnetics::epsilon0_ * Lc_m;  // [F]
      93              :     }
      94              :     else if constexpr (unit == ValueType::CONDUCTIVITY)
      95              :     {
      96           26 :       return 1.0 / (electromagnetics::Z0_ * Lc_m);  // [S/m]
      97              :     }
      98              :     else if constexpr (unit == ValueType::VOLTAGE)
      99              :     {
     100         6168 :       return Hc * electromagnetics::Z0_ * Lc_m;  // [V]
     101              :     }
     102              :     else if constexpr (unit == ValueType::CURRENT)
     103              :     {
     104           40 :       return Hc * Lc_m;  // [A]
     105              :     }
     106              :     else if constexpr (unit == ValueType::POWER)
     107              :     {
     108           34 :       return Hc * Hc * electromagnetics::Z0_ * Lc_m * Lc_m;  // [W]
     109              :     }
     110              :     else if constexpr (unit == ValueType::ENERGY)
     111              :     {
     112          106 :       return Hc * Hc * electromagnetics::Z0_ * Lc_m * Lc_m * tc_ns;  // [J]
     113              :     }
     114              :     else if constexpr (unit == ValueType::FIELD_E)
     115              :     {
     116      8640026 :       return Hc * electromagnetics::Z0_;  // [V/m]
     117              :     }
     118              :     else if constexpr (unit == ValueType::FIELD_D)
     119              :     {
     120              :       return electromagnetics::epsilon0_ * Hc * electromagnetics::Z0_;  // [C/m²]
     121              :     }
     122              :     else if constexpr (unit == ValueType::FIELD_H)
     123              :     {
     124              :       return Hc;  // [A/m]
     125              :     }
     126              :     else if constexpr (unit == ValueType::FIELD_B)
     127              :     {
     128      8640010 :       return electromagnetics::mu0_ * Hc;  // [Wb/m²]
     129              :     }
     130              :     else
     131              :     {
     132              :       static_assert(always_false<unit>::value, "ValueType unkown");
     133              :     }
     134              :   }
     135              : 
     136              :   template <ValueType unit, typename T>
     137              :   auto Dimensionalize(T value) const
     138              :   {
     139     17280220 :     return value * GetScaleFactor<unit>();
     140              :   }
     141              : 
     142              :   template <ValueType unit, typename T, std::size_t N>
     143              :   auto Dimensionalize(const std::array<T, N> &value) const
     144              :   {
     145         2052 :     auto out = value;
     146              :     std::transform(out.begin(), out.end(), out.begin(),
     147              :                    [this](T v) { return Dimensionalize<unit>(v); });
     148              :     return out;
     149              :   }
     150              : 
     151              :   template <ValueType unit, typename T>
     152           22 :   auto Dimensionalize(const std::vector<T> &value) const
     153              :   {
     154           22 :     auto out = value;
     155              :     std::transform(out.begin(), out.end(), out.begin(),
     156              :                    [this](T v) { return Dimensionalize<unit>(v); });
     157           22 :     return out;
     158              :   }
     159              : 
     160              :   template <ValueType unit, typename T>
     161              :   auto Nondimensionalize(T value) const
     162              :   {
     163           27 :     return value / GetScaleFactor<unit>();
     164              :   }
     165              : 
     166              :   template <ValueType unit, typename T, std::size_t N>
     167              :   auto Nondimensionalize(const std::array<T, N> &value) const
     168              :   {
     169            0 :     auto out = value;
     170              :     std::transform(out.begin(), out.end(), out.begin(),
     171              :                    [this](T v) { return Nondimensionalize<unit>(v); });
     172              :     return out;
     173              :   }
     174              : 
     175              :   template <ValueType unit, typename T>
     176           14 :   auto Nondimensionalize(const std::vector<T> &value) const
     177              :   {
     178           14 :     auto out = value;
     179           12 :     std::transform(out.begin(), out.end(), out.begin(),
     180            0 :                    [this](T v) { return Nondimensionalize<unit>(v); });
     181           14 :     return out;
     182              :   }
     183              : };
     184              : 
     185              : }  // namespace palace
     186              : 
     187              : #endif  // PALACE_UTILS_UNITS_HPP
        

Generated by: LCOV version 2.0-1