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