[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/idefix-code/idefix/master/src/dataBlock/dataBlock.cpp [Back]  [Original]

// ***********************************************************************************
// Idefix MHD astrophysical code
//
// Source file src/dataBlock/dataBlock.cpp
//
// Last modified : 12/2025
//
// Copyright(C) by :
// - Geoffroy Lesur  (IPAG/UGA/CNRS - 2020 - 2025)
// - Soufiane Baghdadi  (IPAG/UGA/CNRS - 2020)
// - Clment Robert  (IPAG/UGA/CNRS - 2021 - 2024)
// - Gaylor Wafflard  (IPAG/UGA/CNRS - 2024)
// and other code contributors
//
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************

#include 
#include 
#include 
#include "idefix.hpp"
#include "dataBlock.hpp"
#include "fluid.hpp"
#include "gravity.hpp"
#include "planetarySystem.hpp"
#include "vtk.hpp"
#include "dump.hpp"
#ifdef WITH_HDF5
#include "xdmf.hpp"
#endif

DataBlock::DataBlock(Grid &grid, Input &input) {
  idfx::pushRegion("DataBlock::DataBlock");

  this->mygrid=&grid;

  // Make a local copy of the grid for future usage.
  GridHost gridHost(grid);
  gridHost.SyncFromDevice();


  // Get the number of points from the parent grid object
  for(int dir = 0 ; dir < 3 ; dir++) {
    nghost[dir] = grid.nghost[dir];
    // Domain decomposition: decompose the full domain size in grid by the number of processes
    // in that direction
    np_int[dir] = grid.np_int[dir]/grid.nproc[dir];
    np_tot[dir] = np_int[dir]+2*nghost[dir];

    // Boundary conditions
    if (grid.xproc[dir]==0) {
      lbound[dir] = grid.lbound[dir];
      if(lbound[dir]==axis) this->haveAxis = true;
    } else {
      lbound[dir] = internal;
    }

    if (grid.xproc[dir] == grid.nproc[dir]-1) {
      rbound[dir] = grid.rbound[dir];
      if(rbound[dir]==axis) this->haveAxis = true;
    } else {
      rbound[dir] = internal;
    }

    beg[dir] = grid.nghost[dir];
    end[dir] = grid.nghost[dir]+np_int[dir];

    // Where does this datablock starts and end in the grid?
    // This assumes even distribution of points between procs
    gbeg[dir] = grid.nghost[dir] + grid.xproc[dir]*np_int[dir];
    gend[dir] = grid.nghost[dir] + (grid.xproc[dir]+1)*np_int[dir];

    // Local start and end of current datablock
    xbeg[dir] = gridHost.xl[dir](gbeg[dir]);
    xend[dir] = gridHost.xr[dir](gend[dir]-1);
  }

  // Allocate the required fields
  std::string label;
  for(int dir = 0 ; dir < 3 ; dir++) {
    label = "DataBlock_x" + std::to_string(dir);
    x[dir] = IdefixArray1D(label, np_tot[dir]);

    label = "DataBlock_xr" + std::to_string(dir);
    xr[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_xl" + std::to_string(dir);
    xl[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_dx" + std::to_string(dir);
    dx[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_xgc" + std::to_string(dir);
    xgc[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_A" + std::to_string(dir);
    A[dir] = IdefixArray3D(label,
                                 np_tot[KDIR]+KOFFSET, np_tot[JDIR]+JOFFSET, np_tot[IDIR]+IOFFSET);
  }

  dV = IdefixArray3D("DataBlock_dV",np_tot[KDIR],np_tot[JDIR],np_tot[IDIR]);

#if GEOMETRY == SPHERICAL
  rt = IdefixArray1D("DataBlock_rt",np_tot[IDIR]);
  sinx2m = IdefixArray1D("DataBlock_sinx2m",np_tot[JDIR]);
  tanx2m = IdefixArray1D("DataBlock_tanx2m",np_tot[JDIR]);
  sinx2 = IdefixArray1D("DataBlock_sinx2",np_tot[JDIR]);
  tanx2 = IdefixArray1D("DataBlock_tanx2",np_tot[JDIR]);
  dmu = IdefixArray1D("DataBlock_dmu",np_tot[JDIR]);
#endif

  // Initialize our sub-domain
  this->ExtractSubdomain();

  // Initialize the geometry
  this->MakeGeometry();

  // Initialise the state containers
  // (by default, datablock only initialise the current state, which is a reference
  // to arrays in the daughter object

  this->states["current"] = StateContainer();

  // Initialize the Dump object
  this->dump = std::make_unique(input, this);

  // Initialize the VTK object
  this->vtk = std::make_unique(input, this, "data");

  // Init XDMF objects for HDF5 outputs
  #ifdef WITH_HDF5
    this->xdmf= std::make_unique(input,this);
  #endif


  // Initialize the hydro object attached to this datablock
  this->hydro = std::make_unique(grid, input, this);

  // Initialise Fargo if needed
  if(input.CheckBlock("Fargo")) {
    this->fargo = std::make_unique(input, DefaultPhysics::nvar, this);
    this->haveFargo = true;
  }

  // initialise planets if needed
  if(input.CheckBlock("Planet")) {
    this->planetarySystem = std::make_unique(input, this);
    this->haveplanetarySystem = true;
  }

  // Initialise gravity if needed (automatically if planets are present)
  if(input.CheckBlock("Gravity") || haveplanetarySystem) {
    this->gravity = std::make_unique(input, this);
    this->haveGravity = true;
  }

  // Initialise dust grains if needed
  if(input.CheckBlock("Dust")) {
    haveDust = true;
    int nSpecies = input.Get("Dust","nSpecies",0);
    for(int i = 0 ; i < nSpecies ; i++) {
      dust.emplace_back(std::make_unique(grid, input, this, i));
    }
  }
  // Register variables that need to be saved in case of restart dump
  dump->RegisterVariable(&t, "time");
  dump->RegisterVariable(&dt, "dt");

  idfx::popRegion();
}

/**
 * @brief Construct a new Data Block as a subgrid
 *
 * @param subgrid : subgrid from which the local datablock should be extracted from
 */
DataBlock::DataBlock(SubGrid *subgrid) {
  idfx::pushRegion("DataBlock:DataBlock(SubGrid)");
  Grid *grid = subgrid->parentGrid;
  this->mygrid = subgrid->grid.get();

  // Make a local copy of the grid for future usage.
  GridHost gridHost(*grid);
  gridHost.SyncFromDevice();


  // Get the number of points from the parent grid object
  for(int dir = 0 ; dir < 3 ; dir++) {
    nghost[dir] = grid->nghost[dir];
    // Domain decomposition: decompose the full domain size in grid by the number of processes
    // in that direction
    np_int[dir] = grid->np_int[dir]/grid->nproc[dir];
    np_tot[dir] = np_int[dir]+2*nghost[dir];

    // Boundary conditions
    if (grid->xproc[dir]==0) {
      lbound[dir] = grid->lbound[dir];
      if(lbound[dir]==axis) this->haveAxis = true;
    } else {
      lbound[dir] = internal;
    }

    if (grid->xproc[dir] == grid->nproc[dir]-1) {
      rbound[dir] = grid->rbound[dir];
      if(rbound[dir]==axis) this->haveAxis = true;
    } else {
      rbound[dir] = internal;
    }

    beg[dir] = grid->nghost[dir];
    end[dir] = grid->nghost[dir]+np_int[dir];

    // Where does this datablock starts and end in the grid?
    // This assumes even distribution of points between procs
    gbeg[dir] = grid->nghost[dir] + grid->xproc[dir]*np_int[dir];
    gend[dir] = grid->nghost[dir] + (grid->xproc[dir]+1)*np_int[dir];

    // Local start and end of current datablock
    xbeg[dir] = gridHost.xl[dir](gbeg[dir]);
    xend[dir] = gridHost.xr[dir](gend[dir]-1);
  }

  // Next we erase the info the slice direction
  int refdir = subgrid->direction;
  nghost[refdir] = 0;
  np_int[refdir] = 1;
  np_tot[refdir] = 1;
  beg[refdir] = 0;
  end[refdir] = 1;
  gbeg[refdir] = subgrid->index;
  gend[refdir] = subgrid->index+1;
  xbeg[refdir] = gridHost.x[refdir](subgrid->index);
  xend[refdir] = gridHost.x[refdir](subgrid->index);

  // Reset gbeg/gend so that they don't refer anymore to the parent grid
  gbeg[refdir] = 0;
  gend[refdir] = 1;


  // Allocate the required fields (only a limited set for a datablock from a subgrid)
  std::string label;
  for(int dir = 0 ; dir < 3 ; dir++) {
    label = "DataBlock_x" + std::to_string(dir);
    x[dir] = IdefixArray1D(label, np_tot[dir]);

    label = "DataBlock_xr" + std::to_string(dir);
    xr[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_xl" + std::to_string(dir);
    xl[dir] = IdefixArray1D(label,np_tot[dir]);

    label = "DataBlock_dx" + std::to_string(dir);
    dx[dir] = IdefixArray1D(label,np_tot[dir]);
  }

  // Initialize our sub-domain
  this->ExtractSubdomain();


  idfx::popRegion();
}

void DataBlock::ResetStage() {
  this->hydro->ResetStage();
  if(haveDust) {
    for(int i = 0 ; i < dust.size() ; i++) {
      dust[i]->ResetStage();
    }
  }
}

void DataBlock::ConsToPrim() {
  this->hydro->ConvertConsToPrim();
  if(haveDust) {
    for(int i = 0 ; i < dust.size() ; i++) {
      dust[i]->ConvertConsToPrim();
    }
  }
}

void DataBlock::PrimToCons() {
  this->hydro->ConvertPrimToCons();
  if(haveDust) {
    for(int i = 0 ; i < dust.size() ; i++) {
      dust[i]->ConvertPrimToCons();
    }
  }
}

// Set the boundaries of the data structures in this datablock
void DataBlock::SetBoundaries() {
  if(haveGridCoarsening) {
    ComputeGridCoarseningLevels();
    hydro->CoarsenFlow(hydro->Vc);
    #if MHD==YES
      hydro->CoarsenMagField(hydro->Vs);
    #endif
    if(haveDust) {
      for(int i = 0 ; i < dust.size() ; i++) {
        dust[i]->CoarsenFlow(dust[i]->Vc);
      }
    }
  }
  if(haveDust) {
    for(int i = 0 ; i < dust.size() ; i++) {
      dust[i]->boundary->SetBoundaries(t);
    }
  }
  hydro->boundary->SetBoundaries(t);
}


void DataBlock::ShowConfig() {
  if(idfx::psize>1) {
    idfx::cout dt);
    else
      IDEFIX_ERROR("UserStepLast not properly initialized");
    idfx::popRegion();
  }
}

void DataBlock::EnrollUserStepLast(StepFunc func) {
  haveUserStepLast = true;
  userStepLast = func;
}

void DataBlock::EnrollUserStepFirst(StepFunc func) {
  haveUserStepFirst = true;
  userStepFirst = func;
}

Web Proxy Viewer  |  New URL  |  Original Page