Skip to content

File scalarsingletinitializer.h

File List > code_source > cosmolattice > include > CosmoInterface > initializers > scalarsingletinitializer.h

Go to the documentation of this file

#ifndef COSMOINTERFACE_INITIALIZERS_SCALARINITIALIZER_H
#define COSMOINTERFACE_INITIALIZERS_SCALARINITIALIZER_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/for_in_range.h"
#include "CosmoInterface/initializers/fluctuationsgenerator.h"
#include "CosmoInterface/initializers/externalpowerspectruminitializer.h"
#include "CosmoInterface/fieldsnumbering.h"

namespace TempLat
{
  MakeException(SICNotImplemented);
  class ScalarSingletInitializer
  {
  public:
    // Put public methods here. These should change very little over time.
    ScalarSingletInitializer() = delete;

    // @label:initializescalars
    template <class Model, typename T>
    static void initializeScalars(Model &model, const FluctuationsGenerator<T> &fg,
                                  const ExternalPowerSpectrumInitializer<T> &extps, RunParameters<T> &rPar)
    {

      auto flagSIC = rPar.SIC;

      if (Model::DefectsModel && ( flagSIC != InitialConditionsType::S::DefectsNetwork && flagSIC != InitialConditionsType::S::DefectsWhiteNoise))
        throw(RunParametersInconsistent("You are running a simulation with cosmic defects. Initial conditions specified via the ICtype_S must be either DefectsNetwork or WhiteNoise. We also recomment using an initial diffusion phase."));

      if (rPar.SIC == InitialConditionsType::S::Default) flagSIC = InitialConditionsType::S::RandomWithMatter;

        if (flagSIC == InitialConditionsType::S::RandomWithMatter) {
          initializeRandomScalar(model, fg, extps, rPar, rPar.SIC == InitialConditionsType::S::Default);
          model.fldS = model.getFluctuationRatio(FieldsNumbering::fldS()) * model.fldS;
          model.piS = model.getFluctuationRatio(FieldsNumbering::piS()) * model.piS;
        }
        else if (flagSIC == InitialConditionsType::S::DefectsNetwork)
          initializeScalarDefectsNetwork(model, fg, rPar.lcorr);
        else if (flagSIC == InitialConditionsType::S::DefectsWhiteNoise)
          initializeScalarDefectsWhiteNoise(model, fg, rPar.kCutoff, rPar.deltaNoise);
        else if (flagSIC != InitialConditionsType::S::Homogeneous)
          throw(SICNotImplemented("The initial condition provided for scalars is not implemented."));

      // We set the initial homogeneous components of the fields and derivatives.
      // model.fldS0(i) and model.piS0(i) are introduced in physical
      // (dimensionful variables), so we transform them to program variables
      // by dividing them by f_* and f_* omega_* respectively.
      // @endlabel

      // @label:default_scalar_homogeneous_modes
      model.fldS += model.fldS0 / model.fStar;                  // from the default ones.
      model.piS += model.piS0 / model.fStar / model.omegaStar ;
      // @endlabel

    }

  private:

    // @label:initializerandomscalar
    template <class Model, typename T>
    static void initializeRandomScalar(Model &model, const FluctuationsGenerator<T> &fg,
                                       const ExternalPowerSpectrumInitializer<T> &extps, RunParameters<T> &rPar,
                                       bool useAxionU1HomogeneousDefault)
    {
      ForLoop(i, 0, Model::Ns - 1, {
        if (!(useAxionU1HomogeneousDefault && isAxionU1CoupledScalar<Model>(i))) {
          auto &s = model.extPS[i];
          if (s == Constants::defaultString || s.empty() || s == "None" || s == "none") {
            // @endlabel
            // @label:default_scalar_dispatch
            fg.conjugateGaussianFluctuations(model, model.fldS(i), model.piS(i), model.masses2S[i], model.aDotI,
                                             rPar.kCutoff);
            // @endlabel
          } else {
            // @label:externalps_scalar_dispatch
            extps.conjugateGaussianInputFluctuations(model, model.fldS(i), model.piS(i), s, rPar.kCutoff,
                                                     rPar.powerSpectrumType);
            // @endlabel
          }
        }
      });
    }

    template <class Model, int N> static bool isAxionU1CoupledScalar(Tag<N> n)
    {
      if constexpr (Model::IsAxionU1Coupled) {
        bool isCoupled = false;
        ForLoop(a, 0, Model::NU1 - 1, isCoupled = isCoupled || Model::ScalarU1AxionCouplings::couples(n, a););
        return isCoupled;
      } else {
        return false;
      }
    }

    template <class Model, typename T>
    static void initializeScalarDefectsNetwork(Model &model, const FluctuationsGenerator<T> &fg, T lcorr)
    {
      auto toolBox = model.getToolBox();
      using RGF = RandomGaussianField<T,Model::NDim>;

      ForLoop(i, 0, Model::Ns - 1,

              // 1. Norm of both real and imaginarry components:
              auto fFluctuationNormDefect =  fg.getFluctuationsNormDefect(model,model.fldS(i),lcorr); // component 0

              // 2. To obtain the amplitude at each point,multiply by a random Gaussian
              auto a0 = fFluctuationNormDefect * RGF(fg.getBaseSeed() + "norm0" + model.fldS(i).toString(),toolBox); // component 0

              model.fldS(i).inFourierSpace() = a0 / sqrt(Model::Ns); // component 0
              model.fldS(i).inFourierSpace().setZeroMode(0);
              model.piS(i) =  0;
      );
    }

    template <class Model, typename T>
    static void initializeScalarDefectsWhiteNoise(Model &model, const FluctuationsGenerator<T> &fg, T kCutoff, T delta)
    {
      auto toolBox = model.getToolBox();
      using RGF = RandomGaussianField<T,Model::NDim>;

      ForLoop(i, 0, Model::Ns - 1,

              // 1. Norm of both real and imaginarry components:
              auto fFluctuationNormDefect =  fg.getFluctuationsNormWhiteNoise(model, model.fldS(i), kCutoff, delta); // component 0

              // 2. To obtain the amplitude at each point, multiply by a random Gaussian
              auto a0 = fFluctuationNormDefect * RGF(fg.getBaseSeed() + "norm0" + model.fldS(i).toString(),toolBox); // component 0

              model.fldS(i).inFourierSpace() = a0 / sqrt(Model::Ns); // component 0
              model.fldS(i).inFourierSpace().setZeroMode(0);
              model.piS(i) =  0;
      );
    }

  };
} // namespace TempLat

#endif