Skip to content

File energysnapshotmeasurer.h

File List > code_source > cosmolattice > include > CosmoInterface > measurements > energysnapshotmeasurer.h

Go to the documentation of this file

#ifndef COSMOINTERFACE_MEASUREMENTS_ENERGYSNAPSHOTSMEASURER_H
#define COSMOINTERFACE_MEASUREMENTS_ENERGYSNAPSHOTSMEASURER_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/lattice/IO/fileio.h"
#include "TempLat/util/isincontainer.h"
#include "TempLat/util/rangeiteration/for_in_range.h"
#include "CosmoInterface/definitions/fieldfunctionals.h"
#include "CosmoInterface/definitions/energies.h"
#include "CosmoInterface/definitions/potential.h"
#include "CosmoInterface/measurements/measurementsIO/filesmanager.h"

namespace TempLat
{
  template <typename Model> class EnergySnapshotsMeasurer
  {
  public:
    // Put public methods here. These should change very little over time.
    // @label:energysnapshotsmeasurer_constructor
    template<typename runParameters>
    EnergySnapshotsMeasurer(Model &model, runParameters& pars, FilesManager<Model::NDim> &fm,
                            std::vector<std::string> toSave, std::string postfix = "")
        : mRoot(fm.getWorkingDir() + fm.getTag())
    {
      // This checks which energies are specified in the string "toSave" (passed as a parameter), and creates the
      // corresponding h5 files to save the snapshots.

#ifdef HAVE_HDF5
      saveScalar = IsInContainer::check("S", toSave);              // value of the scalar singlets
      saveScalarNorm = (IsInContainer::check("Snorm", toSave) && Model::DefectsModel) ;              // value of the scalar singlets
      saveScalarK = IsInContainer::check("E_S_K", toSave);         // kinetic energy of the scalar singlets
      saveScalarG = IsInContainer::check("E_S_G", toSave);         // gradient energy of the scalar singlets
      saveComplexScalar = IsInContainer::check("CS", toSave);      // modulus of the complex scalars
      saveComplexScalarK = IsInContainer::check("E_CS_K", toSave); // kinetic energy of the complex scalars
      saveComplexScalarG = IsInContainer::check("E_CS_G", toSave); // gradient energy of the complex scalars
      saveSU2DoubletK = IsInContainer::check("E_SU2D_K", toSave);  // kinetic energy of the SU(2) doublets
      saveSU2DoubletG = IsInContainer::check("E_SU2D_G", toSave);  // gradient energy of the SU(2) doublets
      saveU1El = IsInContainer::check("E_A_K", toSave);            // electric energy of the U(1) gauge sector
      saveU1Mag = IsInContainer::check("E_A_G", toSave);           // magnetic energy of the U(1) gauge sector
      saveSU2El = IsInContainer::check("E_B_K", toSave);           // electric energy of the SU(2) gauge sector
      saveSU2Mag = IsInContainer::check("E_B_G", toSave);          // magnetic energy of the SU(2) gauge sector
      savePot = IsInContainer::check("E_V", toSave);               // potential energy
      saveETotal = IsInContainer::check("E", toSave);              // total energy energy

      if (saveScalar || saveScalarNorm || saveScalarK || saveScalarG || saveComplexScalar || saveComplexScalarK || saveComplexScalarG ||
          saveSU2DoubletK || saveSU2DoubletG || saveU1El || saveU1Mag || saveSU2El || saveSU2Mag || savePot ||
          saveETotal)
        fIO.setSaverLimits(pars.snapLower, pars.snapUpper, pars.snapStep);

      auto createIfFresh = [&](const std::string &name) {
        if (fm.prepareOutputFile(name)) {
          fIO.saver.create(name, Exclusive);
          fIO.saver.close();
        }
      };

      if (saveScalar) { nameScalar = mRoot + "snapshot_scalar_singlet" + postfix + ".h5"; createIfFresh(nameScalar); }
      if (saveScalarNorm) { nameScalarNorm = mRoot + "snapshot_scalar_singlet_norm" + postfix + ".h5"; createIfFresh(nameScalarNorm); }
      if (saveScalarK) { nameScalarK = mRoot + "kinetic_energy_snapshot_scalar" + postfix + ".h5"; createIfFresh(nameScalarK); }
      if (saveScalarG) { nameScalarG = mRoot + "gradient_energy_snapshot_scalar" + postfix + ".h5"; createIfFresh(nameScalarG); }
      if (saveComplexScalar) { nameComplexScalar = mRoot + "snapshot_complex_scalar" + postfix + ".h5"; createIfFresh(nameComplexScalar); }
      if (saveComplexScalarK) { nameComplexScalarK = mRoot + "kinetic_energy_snapshot_complex_scalar" + postfix + ".h5"; createIfFresh(nameComplexScalarK); }
      if (saveComplexScalarG) { nameComplexScalarG = mRoot + "gradient_energy_snapshot_complex_scalar" + postfix + ".h5"; createIfFresh(nameComplexScalarG); }
      if (saveSU2DoubletK) { nameSU2DoubletK = mRoot + "kinetic_energy_snapshot_SU2_doublet" + postfix + ".h5"; createIfFresh(nameSU2DoubletK); }
      if (saveSU2DoubletG) { nameSU2DoubletG = mRoot + "gradient_energy_snapshot_SU2_doublet" + postfix + ".h5"; createIfFresh(nameSU2DoubletG); }
      if (saveU1El) { nameU1El = mRoot + "electric_energy_snapshot_U1" + postfix + ".h5"; createIfFresh(nameU1El); }
      if (saveU1Mag) { nameU1Mag = mRoot + "magnetic_energy_snapshot_U1" + postfix + ".h5"; createIfFresh(nameU1Mag); }
      if (saveSU2El) { nameSU2El = mRoot + "electric_energy_snapshot_SU2" + postfix + ".h5"; createIfFresh(nameSU2El); }
      if (saveSU2Mag) { nameSU2Mag = mRoot + "magnetic_energy_snapshot_SU2" + postfix + ".h5"; createIfFresh(nameSU2Mag); }
      if (savePot) { namePot = mRoot + "potential_energy_snapshot" + postfix + ".h5"; createIfFresh(namePot); }
      if (saveETotal) { nameETotal = mRoot + "total_energy_snapshot" + postfix + ".h5"; createIfFresh(nameETotal); }
#endif
    }
    // @endlabel

    // This saves the energy snapshots at the corresponding HDF5 files
    template <typename T> void measure(Model &model, T t)
    {
#ifdef HAVE_HDF5
      // @label:energysnapshotsmeasurer_measure
      if (saveScalar) { // kinetic energy of the scalar singlets
        ForLoop(i, 0, Model::Ns - 1, fIO.saver.open(nameScalar);
                fIO.saver.save(t, model.fldS(i), "S_" + std::to_string(i)); fIO.saver.close(););
      }
      if (saveScalarNorm) { // norm of the scalar singlets
        if constexpr (Model::Ns > 0) {
          fIO.saver.open(nameScalarNorm);
          fIO.saver.save(t, sqrt(Total(i, 0, Model::Ns-1, pow<2>(model.fldS(i));)), "S_norm");
          fIO.saver.close();
        }
      }
      if (saveScalarK) { // kinetic energy of the scalar singlets
        ForLoop(i, 0, Model::Ns - 1, fIO.saver.open(nameScalarK); fIO.saver.save(
            t, Energies::kineticS(model, FieldFunctionals::pi2S(model, i)), "E_S_K_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveScalarG) { // gradient energy of the scalar singlets
        ForLoop(i, 0, Model::Ns - 1, fIO.saver.open(nameScalarG); fIO.saver.save(
            t, Energies::gradientS(model, FieldFunctionals::grad2S(model, i)), "E_S_G_" + std::to_string(i));
                fIO.saver.close(););
      }
      // @endlabel
      if (saveComplexScalar) { // kinetic energy of the complex scalars
        ForLoop(i, 0, Model::NCs - 1, fIO.saver.open(nameComplexScalar);
                fIO.saver.save(t, norm(model.fldCS(i)), "CS_" + std::to_string(i)); fIO.saver.close(););
      }
      if (saveComplexScalarK) { // kinetic energy of the complex scalars
        ForLoop(i, 0, Model::NCs - 1, fIO.saver.open(nameComplexScalarK); fIO.saver.save(
            t, Energies::kineticCS(model, FieldFunctionals::pi2CS(model, i)), "E_CS_K_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveComplexScalarG) { // gradient energy of the complex scalars
        ForLoop(i, 0, Model::NCs - 1, fIO.saver.open(nameComplexScalarG); fIO.saver.save(
            t, Energies::gradientCS(model, FieldFunctionals::grad2CS(model, i)), "E_CS_G_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveSU2DoubletK) { // kinetic energy of the SU(2) doublets
        ForLoop(i, 0, Model::NSU2Doublet - 1,
                auto toSave = Energies::kineticSU2Doublet(model, FieldFunctionals::pi2SU2Doublet(model, i));
                fIO.saver.open(nameSU2DoubletK); fIO.saver.save(t, toSave, "E_SU2D_K_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveSU2DoubletG) { // gradient energy of the SU(2) doublets
        ForLoop(i, 0, Model::NSU2Doublet - 1, fIO.saver.open(nameSU2DoubletG);
                fIO.saver.save(t, Energies::gradientSU2Doublet(model, FieldFunctionals::grad2SU2Doublet(model, i)),
                               "E_SU2D_G_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveU1El) { // electric energy of the U(1) gauge sector
        ForLoop(i, 0, Model::NU1 - 1, fIO.saver.open(nameU1El); fIO.saver.save(
            t, Energies::electricU1(model, FieldFunctionals::pi2U1(model, i)), "E_A_K_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveU1Mag) { // magnetic energy of the U(1) gauge sector
        ForLoop(i, 0, Model::NU1 - 1, fIO.saver.open(nameU1Mag); fIO.saver.save(
            t, Energies::magneticU1(model, FieldFunctionals::B2U1(model, i)), "E_A_G_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveSU2El) { // electric energy of the SU(2) gauge sector
        ForLoop(i, 0, Model::NSU2 - 1, fIO.saver.open(nameSU2El); fIO.saver.save(
            t, Energies::electricSU2(model, FieldFunctionals::pi2SU2(model, i)), "E_B_K_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (saveSU2Mag) { // magnetic energy of the SU(2) gauge sector
        ForLoop(i, 0, Model::NSU2 - 1, fIO.saver.open(nameSU2Mag); fIO.saver.save(
            t, Energies::magneticSU2(model, FieldFunctionals::B2SU2(model, i)), "E_B_G_" + std::to_string(i));
                fIO.saver.close(););
      }
      if (savePot) {
        if constexpr (Model::NPotTerms == 0)
          throw(FileIOException(
              "You tried to save the potential energy, but your model does not have any potential term. Abort."));
        if constexpr (Model::NPotTerms > 0) {
          fIO.saver.open(namePot);
          fIO.saver.save(t, Potential::potential(model), "E_V");
          fIO.saver.close();
        }
      }
      if (saveETotal) {
        fIO.saver.open(nameETotal);
        fIO.saver.save(t, Energies::totalEnergy(model), "E_Total");
        fIO.saver.close();
      }
#else
      if (saveScalar || saveScalarNorm || saveScalarK || saveScalarG || saveComplexScalar || saveComplexScalarK || saveComplexScalarG || saveSU2DoubletK ||
          saveSU2DoubletG || saveU1El || saveU1Mag || saveSU2El || saveSU2Mag || savePot) {
        std::stringstream ss;
        if (saveScalar) ss << "\n- Value of the scalar singlets.";
        if (saveScalarNorm) ss << "\n- Norm of all the scalar singlets, treated as a vector of scalars.";
        if (saveScalarK) ss << "\n- Kinetic energy of the scalar singlets.";
        if (saveScalarG) ss << "\n- Gradient energy of the scalar singlets.";
        if (saveComplexScalar) ss << "\n- Magnitude of the complex scalars.";
        if (saveComplexScalarK) ss << "\n- Kinetic energy of the complex scalars.";
        if (saveComplexScalarG) ss << "\n- Gradient energy of the complex scalars.";
        if (saveSU2DoubletK) ss << "\n- Kinetic energy of the SU(2) doublets.";
        if (saveSU2DoubletG) ss << "\n- Gradient energy of the SU(2) doublets.";
        if (saveU1El) ss << "\n- Electric energy of the U(1) gauge sector.";
        if (saveU1Mag) ss << "\n- Magnetic energy of the U(1) gauge sector.";
        if (saveSU2El) ss << "\n- Electric energy of the SU(2  ) gauge sector.";
        if (saveSU2Mag) ss << "\n- Magnetic energy of the SU(2) gauge sector.";
        if (savePot) ss << "\n- Potential energy.";
        if (saveETotal) ss << "\n- Total energy.";

        throw(FileIOException("You tried to save an energy snapshot to a file, but the HDF5 library is not available. "
                              "Make sure you have it installed and that you compiled CosmoLattice with it." +
                              ss.str()));
      }
#endif
    }

  private:
    /* Put all member variables and private methods here. These may change arbitrarily. */
    FileIO<Model::NDim> fIO;
    std::string mRoot;

    bool saveScalar = false, saveScalarNorm = false, saveScalarG = false, saveScalarK = false;
    bool saveComplexScalar = false, saveComplexScalarG = false, saveComplexScalarK = false;
    bool saveSU2DoubletG = false, saveSU2DoubletK = false;
    bool saveU1Mag = false, saveU1El = false;
    bool saveSU2Mag = false, saveSU2El = false;
    bool savePot = false, saveETotal = false;

    std::string nameScalar, nameScalarNorm, nameScalarG, nameScalarK;
    std::string nameComplexScalar, nameComplexScalarG, nameComplexScalarK;
    std::string nameSU2DoubletG, nameSU2DoubletK;
    std::string nameU1Mag, nameU1El;
    std::string nameSU2Mag, nameSU2El;
    std::string namePot, nameETotal;
  };
} // namespace TempLat

#endif