Skip to content

File axioncouplings.h

File List > code_source > cosmolattice > include > CosmoInterface > definitions > axioncouplings.h

Go to the documentation of this file

#ifndef COSMOINTERFACE_HELPERS_AXIONCOUPLINGS_H
#define COSMOINTERFACE_HELPERS_AXIONCOUPLINGS_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): Nicolas Loayza, Ander Urio, Adrien Florio,  Year: 2025

#include "CosmoInterface/couplingsmanager.h"

#include "TempLat/util/rangeiteration/make_list_tag.h"
#include "TempLat/util/staticif.h"
#include "TempLat/lattice/algebra/complexalgebra/complexfieldshift.h"
#include "TempLat/lattice/algebra/su2algebra/su2shift.h"
#include "TempLat/lattice/algebra/su2algebra/su2doubletshift.h"
#include "TempLat/util/rangeiteration/sum_in_range.h"

#include "TempLat/lattice/algebra/spatialderivatives/backdiff.h"
#include "TempLat/lattice/algebra/spatialderivatives/forwdiff.h"
#include "TempLat/lattice/algebra/spatialderivatives/latticelaplacian.h"
#include "TempLat/lattice/algebra/axionalgebra/magneticfield4.h"
#include "TempLat/lattice/algebra/axionalgebra/electricfield2.h"
#include "TempLat/lattice/algebra/constants/symbols.h"

namespace TempLat
{

  class AxionCouplings
  {
  public:
    /* Put public methods here. These should change very little over time. */
    AxionCouplings() = default;


    // Primary signature with tMinust0
    template <class Model, int N>
    static auto ScalarAxionSource(Model &model, Tag<N> n, typename Model::FloatType tMinust0)
    {

      auto AxionCouplScalar =
          Total(a, 0, Model::NU1 - 1,
                IfElse(Model::ScalarU1AxionCouplings::couples(Tag<N>(), a),
                       model.alphaLambda_SU1(n, a) * Total(i, 1, Model::NDim,
                                                           electricField2(model.piU1(n), i) *
                                                               magneticField4(magneticField(model.fldU1(n), i), i)),
                       ZeroType()));

      const double NonLinearSwitch = (tMinust0 > model.tNonLinearAxionU1) ? 1.0 : 0.0;

      return AxionCouplScalar * NonLinearSwitch;
    }

    // Backward-compatible wrapper
    template <class Model, int N> static auto ScalarAxionSource(Model &model, Tag<N> n)
    {
      return ScalarAxionSource(model, n, 0.0);
    }


    // Primary signature with tMinust0
    template <class Model, int N, int I>
    static auto U1AxionCoupling(Model &model, Tag<N> n, Tag<I> i, typename Model::FloatType tMinust0)
    {

      auto AxionCoupl1 =
          -0.5 * Total(a, 0, Model::Ns - 1,
                       IfElse(Model::ScalarU1AxionCouplings::couples(a, Tag<N>()),
                              model.alphaLambda_SU1(a, n) *
                                  (model.piS(a) * magneticField4(magneticField(model.fldU1(n), i), i) +
                                   shift(model.piS(a) * magneticField4(magneticField(model.fldU1(n), i), i), i)),
                              ZeroType()));

      auto AxionCoupl2 =
          0.25 *
          Total(
              a, 0, Model::Ns - 1,
              IfElse(
                  Model::ScalarU1AxionCouplings::couples(a, Tag<N>()),
                  model.alphaLambda_SU1(a, n) *
                      (Total(j, 1, Model::NDim,
                             Total(k, 1, Model::NDim,
                                   Symbols::epsilon(i, j, k) *
                                       (shift(forwDiff(model.fldS(a), j) * shift(electricField2(model.piU1(n), k), j),
                                              i) +
                                        forwDiff(model.fldS(a), j) * shift(electricField2(model.piU1(n), k), j)))) +
                       Total(j, 1, Model::NDim,
                             Total(k, 1, Model::NDim,
                                   Symbols::epsilon(i, j, k) *
                                       (shift(backDiff(model.fldS(a), j) * shift(electricField2(model.piU1(n), k), -j),
                                              i) +
                                        backDiff(model.fldS(a), j) * shift(electricField2(model.piU1(n), k), -j))))),
                  ZeroType()));

      const double NonLinearSwitch = (tMinust0 > model.tNonLinearAxionU1) ? 1.0 : 0.0;

      return (pow(model.aI, model.alpha - 3) * AxionCoupl1 +
              pow(model.aI, -1 + model.alpha) * NonLinearSwitch * AxionCoupl2);
    }

    // Backward-compatible wrapper
    template <class Model, int N, int I> static auto U1AxionCoupling(Model &model, Tag<N> n, Tag<I> i)
    {
      return U1AxionCoupling(model, n, i, 0.0);
    }


    template <class Model, int N> static auto ScalarAxionGaussLaw(Model &model, Tag<N> n)
    { // N is the Nth U1 abelian field, i is the spatial component.
      return Total(a, 0, Model::Ns - 1,
                   IfElse(Model::ScalarU1AxionCouplings::couples(a, Tag<N>()),
                          -(model.alphaLambda_SU1(a, n)) * (model.fStar / Model::MPl) *
                              Total(i, 1, Model::NDim,
                                    (forwDiff(model.fldS(a), i) *
                                     shift(magneticField4(magneticField(model.fldU1(n), i), i), i)) +
                                        (backDiff(model.fldS(a), i) *
                                         shift(magneticField4(magneticField(model.fldU1(n), i), i), -i))) *
                              0.5,
                          ZeroType()));
    }

    // Primary signature with tMinust0
    template <class Model, int N>
    static auto U1AxionCoupling(Model &model, Tag<N> t, typename Model::FloatType tMinust0)
    {
      return MakeVector(i, 1, Model::NDim, U1AxionCoupling(model, t, i, tMinust0));
    }

    // Backward-compatible wrapper
    template <class Model, int N> static auto U1AxionCoupling(Model &model, Tag<N> t)
    {
      return U1AxionCoupling(model, t, 0.0);
    }

  private:
    /* Put all member variables and private methods here. These may change arbitrarily. */
  };

} // namespace TempLat

#endif