Skip to content

File couplingsmanager.h

File List > code_source > cosmolattice > include > CosmoInterface > couplingsmanager.h

Go to the documentation of this file

#ifndef COSMOINTERFACE_COUPLINGSMANAGER_H
#define COSMOINTERFACE_COUPLINGSMANAGER_H

/* This file is part of CosmoLattice, available at www.cosmolattice.net .
   Copyright Daniel G. Figueroa, Adrien Florio, Francisco Torrenti and Wessel Valkenburg.
   Released under the MIT license, see LICENSE.md. */

// File info: Main contributor(s): Daniel G. Figueroa, Adrien Florio, Francisco Torrenti,  Year: 2020

#include "TempLat/util/rangeiteration/tagliteral.h"
#include "TempLat/util/exception.h"

#include <array>
#include <vector>

namespace TempLat
{
  MakeException(NotEnoughChargesForThisCouplingsManager);
  MakeException(NotEnoughCouplingsForThisCouplingsManager);

  template <typename FloatType, int NMatter, int NGauge, bool... Bools> class CouplingsManagerContainer
  {
  public:
    static constexpr int nGauge = NGauge;

    CouplingsManagerContainer() = default;

    template <typename T>
    CouplingsManagerContainer(const std::vector<T> &charges, const std::vector<T> &couplings) : gs(couplings)
    {
      setEffectiveCharges(charges, couplings);
    }

    static constexpr bool active = true;

    void setEffectiveCharges(const std::vector<double> &charges, const std::vector<double> &couplings)
    {
      _setEffectiveCharges(charges, couplings);
    }
    void setEffectiveCharges(const std::vector<float> &charges, const std::vector<float> &couplings)
    {
      _setEffectiveCharges(charges, couplings);
    }

    template <typename T> void _setEffectiveCharges(const std::vector<T> &charges, const std::vector<T> &couplings)
    {
      if ((charges.size() != howManyCouples()) && (couplings.size() != 0))
        throw(NotEnoughChargesForThisCouplingsManager(
            std::to_string(charges.size()) + " charges were specified while " + std::to_string(howManyCouples()) +
            " non-trivial doesCouples are expected. Abort."));
      if (couplings.size() != NGauge && charges.size() != 0)
        throw(NotEnoughCouplingsForThisCouplingsManager(std::to_string(couplings.size()) +
                                                        " couplings were specified while " + std::to_string(NGauge) +
                                                        " gauge fields are present. Abort."));
      if constexpr (NGauge > 0) {
        // Set the gauge field couplings g and the effective charges g*Q for each matter-gauge coupling.
        for (size_t i = 0; i < NGauge && i < couplings.size(); ++i)
          gs[i] = couplings[i];

        size_t count = 0;
        for (size_t i = 0; i < doesCouples.size(); ++i) {
          if (doesCouples[i]) {
            effectiveCharges[i] = charges[count] * couplings[i % NGauge];
            ++count;
          } else
            effectiveCharges[i] = 0;
        }
      }
    }

    static constexpr size_t howManyCouples()
    {
      size_t c = 0;
      for (size_t i = 0; i < doesCouples.size(); ++i)
        c += doesCouples[i] ? 1 : 0;
      return c;
    }

    template <int nmat, int ng> auto operator()(Tag<nmat>, Tag<ng>) const
    {
      static_assert(nmat >= 0 && nmat < NMatter,
                    "Error: trying to access the coupling of a matter field which is not present in this "
                    "CouplingsManager. Abort.");
      static_assert(ng >= 0 && ng < NGauge, "Error: trying to access the coupling of a gauge field which is not "
                                            "present in this CouplingsManager. Abort.");
      if constexpr (sizeof...(Bools) == 0 || NGauge == 0) {
        return ZeroType();
      } else {
        return effectiveCharges[nmat * NGauge + ng];
      }
    }

    template <int ng> auto coupling(Tag<ng>) const
    {
      static_assert(ng >= 0 && ng < NGauge, "Error: trying to access the coupling of a gauge field which is not "
                                            "present in this CouplingsManager. Abort.");
      return gs[ng];
    }

    template <int nmat, int ng> static constexpr bool couples(Tag<nmat>, Tag<ng>)
    {
      static_assert(nmat >= 0 && nmat < NMatter,
                    "Error: trying to access the coupling of a matter field which is not present in this "
                    "CouplingsManager. Abort.");
      static_assert(ng >= 0 && ng < NGauge, "Error: trying to access the coupling of a gauge field which is not "
                                            "present in this CouplingsManager. Abort.");
      if constexpr (sizeof...(Bools) == 0 || NGauge == 0) {
        return false;
      } else {
        return doesCouples[nmat * NGauge + ng];
      }
    }

  private:
    // Compile-time accessible booleans which tell what couples to what.
    static constexpr std::array<bool, NGauge * NMatter> doesCouples = {Bools...};
    std::array<FloatType, NGauge * NMatter> effectiveCharges;
    std::array<FloatType, NGauge> gs;
  };

  template <int NMatter, int NGauge, bool... Bools> class CouplingsManager
  {
  public:
    template <typename FloatType> using Container = CouplingsManagerContainer<FloatType, NMatter, NGauge, Bools...>;

    static constexpr int nGauge = NGauge;
    static constexpr bool active = (Bools || ...);

    static constexpr size_t howManyCouples()
    {
      return (static_cast<size_t>(Bools) + ...);
    }

    template <int nmat, int ng> static constexpr bool couples(Tag<nmat>, Tag<ng>)
    {
      static_assert(nmat >= 0 && nmat < NMatter);
      static_assert(ng >= 0 && ng < NGauge);
      constexpr std::array<bool, NGauge * NMatter> doesCouples = {Bools...};
      return doesCouples[nmat * NGauge + ng];
    }
  };

  template <int NMatter, int NGauge> class CouplingsManager<NMatter, NGauge>
  {
  public:
    template <typename FloatType> using Container = CouplingsManager<NMatter, NGauge>;

    static constexpr int nGauge = 0;

    // Put public methods here. These should change very little over time.
    CouplingsManager() = default;

    template <typename T> CouplingsManager(const std::vector<T> &vec, std::array<T, 0> couplings) {}

    static constexpr bool active = false;

    void setEffectiveCharges(const std::vector<float> &charges, const std::vector<float> &couplings) {}
    void setEffectiveCharges(const std::vector<double> &charges, const std::vector<double> &couplings) {}

    static constexpr size_t howManyCouples() { return 0; }
    template <int nmat, int ng> ZeroType operator()(Tag<nmat>, Tag<ng>) const { return {}; }

    template <int ng> ZeroType coupling(Tag<ng>) const { return {}; }

    template <int nmat, int ng> static constexpr bool couples(Tag<nmat>, Tag<ng>) { return false; }

  private:
    static constexpr std::array<bool, 1> doesCouples = {false};
  };
} // namespace TempLat

#endif