Skip to content

File diffusion.h

File List > code_source > cosmolattice > include > CosmoInterface > definitions > defectsmodule > diffusion.h

Go to the documentation of this file

#ifndef COSMOINTERFACE_DEFINITIONS_DEFECTSMODULE_DIFFUSION_H
#define COSMOINTERFACE_DEFINITIONS_DEFECTSMODULE_DIFFUSION_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): Jorge Baeza-Ballesteros,  Year: 2026

#include "TempLat/util/exception.h"
#include "CosmoInterface/evolvers/evolver.h"
#include "CosmoInterface/evolvers/rk2nstoragefields.h"

namespace TempLat
{

  MakeException(DiffusionEvolverInvalid);

  class Diffusion
  {
  public:
    // Put public methods here. These should change very little over time.

    Diffusion() = delete;

    template <typename Model, typename T>
    static void diffuse(Model &model, RunParameters<T> &rPar, FilesManager<Model::NDim> &filesManager,
                        ExtraFields<Model> extraFields)
    {

      bool iAmRoot = model.getToolBox()->amIRoot();
      typename Model::FloatType auxg;

      if constexpr (Model::DefectsModel && Model::Ns == 1) {
        auxg = model.g;
        model.g = 0;
      }

      if (!RK2NStorageParameters<T>::isRK2n(rPar.diffType))
        throw(DiffusionEvolverInvalid(
            "You need to choose a RK integrator to diffuse initial conditions for defect simulations. Abort."));
      if (iAmRoot) say << "Diffusing initial defect conditions";

      auto diffuser = RK2NStorageFields(model, rPar.diffType);

      std::optional<DefectsMeasurer<T>> measurerS;
      std::optional<ComplexScalarMeasurer<T>> measurerCS;
      std::optional<U1Measurer<T>> measurerU1;

      if constexpr (Model::Ns > 0) measurerS.emplace(model, filesManager, rPar, rPar.appendMode, "_diffusion", true);
      if constexpr (Model::NCs > 0) measurerCS.emplace(model, filesManager, rPar, rPar.appendMode, "_diffusion", false);
      if constexpr (Model::NU1 > 0)
        measurerU1.emplace(model, filesManager, rPar, rPar.appendMode, "_diffusion", false, false);
      EnergiesMeasurer<T> measurerE(model, filesManager, rPar, rPar.appendMode, "_diffusion", false);
      EnergySnapshotsMeasurer<Model> snapshots(model, rPar, filesManager, rPar.energySnapshotMeasDiffusion,
                                               "_diffusion");

      model.dt = rPar.dtdiff;
      T tdiff = 0.;
      ptrdiff_t outputFreqDiffusion = static_cast<int>(round(rPar.tOutFreqDiff / rPar.dtdiff));
      ptrdiff_t outputRareFreqDiffusion = static_cast<int>(round(rPar.tOutRareFreqDiff / rPar.dtdiff));

      for (int i = 0; tdiff < rPar.tmaxdiff + rPar.dtdiff * T(0.5); i++) {
        if (i % outputFreqDiffusion == 0) {
          ForEachConjugateMomenta(
              Model, fld, n,
              model.getField(fld)(n) =
                  Kernels::get(fld, model, n,
                               KernelsTypes::Diffusion<Model>())); // Sets the conjugate momenta fields, which are used
                                                                   // as auxiliary variables for the evolution, to zero.
          if (iAmRoot) say << "Diffusion step " << i << " completed. Current diffusion time " << tdiff << "\n";
          if constexpr (Model::Ns > 0) measurerS->measure(model, tdiff);
          if constexpr (Model::NCs > 0) measurerCS->measureStandard(model, tdiff);
          if constexpr (Model::NU1 > 0) measurerU1->measureStandard(model, tdiff);
          measurerE.measure(model, tdiff, i == 0);
        }
        if (i % outputRareFreqDiffusion == 0) snapshots.measure(model, tdiff);

        diffuser.evolve(model, tdiff, KernelsTypes::Diffusion<Model>());
        tdiff += rPar.dtdiff;
      }

      ForLoop(n, 0, Model::Ns - 1, model.piS(n) = 0.;);
      ForLoop(n, 0, Model::NCs - 1, model.piCS(n) = Complexify(0., 0.););
      ForLoop(n, 0, Model::NU1 - 1, ForLoop(i, 1, Model::NDim, model.piU1(n)(i) = 0.;));

      model.dt = rPar.dt;

      if constexpr (Model::DefectsModel && Model::Ns == 1) {
        model.g = auxg;
      }
    }
  };

} // namespace TempLat

#endif