Skip to content

Problem Generators

Kengo TOMIDA edited this page May 28, 2016 · 37 revisions

Problem Generator File

When configuring the code, a problem generator must be specified using the --prob option. A list of available problem generators is given in the help message of the configuration script (use -h option).

Problem generators stored in src/pgen contain problem-specific functions and variables. This includes:

  • Initial conditions
  • User-defined boundary conditions
  • User-defined physical source terms
  • User-defined Mesh spacing functions
  • User-defined mesh refinement criteria
  • User-defined analysis functions
  • etc...

It will probably be necessary to read the Programmer Guide in order to understand the data structures and Mesh in Athena++ well enough to write a new problem generator. The existing files in the /src/prob directory can be used as starting templates. In this section, we briefly explain the structure of problem generators.

The following interfaces (+ any functions you need) can be defined in a problem generator file:

  • void Mesh::InitUserMeshData(ParameterInput *pin)
  • void Mesh::UserWorkAfterLoop(void)
  • void MeshBlock::InitUserMeshBlockData(ParameterInput *pin)
  • void MeshBlock::ProblemGenerator(ParameterInput *pin)
  • void MeshBlock::UserWorkInLoop(void)

These functions are optional (although practically ProblemGenerator must be always defined). When these functions are not defined, default ones that do nothing are used.

Mesh::InitUserMeshData

This function is called at the beginning of a simulation (both the first run and restarting) for allocating and initializing global variables shared with all the MeshBlocks, and for enrolling user-defined functions. The following functions can be enrolled here:

Also, the user-defined data field in the Mesh class can be declared and allocated in this function. This features enables users to store any data that are automatically saved and loaded when the code is restarted. See below for details.

Mesh::UserWorkAfterLoop

This function is called at the end of the simulation for cleaning up the resources allocated in InitUserMeshData.

Users do not need to delete the user-defined data arrays allocated in InitUserMeshData using Allocate(Real/Int)UserMeshBlockDataField as they are automatically deleted.

MeshBlock::InitUserMeshBlockData

This is similar to Mesh::InitUserMeshData, and is called at the beginning of a simulation (both the first run and restarting) for allocating and initializing local variables belonging to each MeshBlock. This is mainly intended for User MeshBlock Data. This function is not for initializing the simulation setup, which should be done in MeshBlock::ProblemGenerator.

MeshBlock::ProblemGenerator

This function sets the initial condition for the problem. For hydrodynamics, the cell-centered conservative variables (phydro->u) must be set here. The face-centered magnetic fields (pfield->bx1f, bx2f, and bx3f) also must be set for MHD.

For details, see the Programmer Guide and sample files in the src/pgen directory.

MeshBlock::UserWorkInLoop

This function is called at the end of every timestep (note: it is not called at the half timestep). A user can do analysis in this function. This is intended only for analysis, and not for manipulating the data. In such a case, one should use a user-defined source term function and/or the boundary conditions.

Reading Parameters from the Input File

Users can read parameters from the input file in Mesh::InitUserMeshProperties(ParameterInput *pin) and MeshBlock::ProblemGenerator(ParameterInput *pin). For this purpose, the following functions are provided:

  • int ParameterInput::GetInteger(std::string block, std::string name)
  • Real ParameterInput::GetReal(std::string block, std::string name)
  • std::string GetString(std::string block, std::string name)
  • int ParameterInput::GetOrAddInteger(std::string block, std::string name, int value)
  • Real ParameterInput::GetOrAddReal(std::string block, std::string name, Real value)
  • std::string ParameterInput::GetOrAddString(std::string block, std::string name, std::string value)

The first three functions return a parameter with name in <block>. These functions fail when that parameter is not defined in the input file. The latter three functions are similar but with a default value. For example, in order to read a plasma beta parameter named "beta" in the <problem> block,

Real beta = pin->GetReal("problem", "beta");

And if you want to set a default value if no value is specified in the input file,

Real beta = pin->GetReal("problem", "beta", 1000.0);

For details, again, see the Programmer Guide and sample files in the src/pgen directory.

User-defined Data Field

While any variables can be defined in the problem generator file, they are not saved or transferred when the simulation is restarted. Athena++ provides interfaces for users to allocate variables that can be automatically saved and loaded when the simulation is restarted. The data can be arrays of any shape, and can be Real or integer. The data field can be stored in Mesh and MeshBlock. User Mesh Data can be used to store the data shared among nodes (i.e. global, common data), while User MeshBlock Data are accessible only within a MeshBlock.

In order to use this feature, first declare the number of the data field:

  • void Mesh::AllocateRealUserMeshDataField(int n)
  • void Mesh::AllocateIntUserMeshDataField(int n)
  • void MeshBlock::AllocateRealUserMeshBlockDataField(int n)
  • void MeshBlock::AllocateIntUserMeshBlockDataField(int n)

Then, allocate the data arrays such as

  • AthenaArray Mesh::iusermeshdata[i]
  • AthenaArray Mesh::rusermeshdata[i]
  • AthenaArray MeshBlock::iusermeshblockdata[i]
  • AthenaArray MeshBlock::rusermeshblockdata[i]

These functions should be called in Mesh::InitUserMeshData or MeshBlock::InitUserMeshBlockData. For example, in order to allocate two Real arrays, one is just one variable and the other is a 16x16 2D array, in Mesh, write the following code:

void Mesh::InitUserMeshData(ParameterInput *pin)
{
  AllocateRealUserMeshDataField(2);
  rusermeshdata[0].NewAthenaArray(1);
  rusermeshdata[1].NewAthenaArray(16,16);
  for(int j=0; j<16; j++) {
    for(int i=0; i<16; i++) {
      // initialization
      rusermeshdata[1](j,i)=0.0; 
    }
  }
  return;
}

Then these data can be used from other functions that can see the Mesh class. These data are automatically saved and loaded when the simulation is restarted. However, note that only the data on the master node (rank=0) is written in the restarting file, and it is users' responsibility to maintain consistency between nodes.

Similarly, in order to allocate a 3D integer array in MeshBlocks, write like:

void MeshBlock::InitUserMeshBlockData(ParameterInput *pin)
{
  AllocateIntUserMeshBlockDataField(1);
  iusermeshblockdata[0].NewAthenaArray(16,16,16);
  for(int k=0; k<16; k++)
    for(int j=0; j<16; j++) {
      for(int i=0; i<16; i++) {
        // initialization
        iusermeshdata[1](k,j,i)=0; 
      }
    }
  }
  return;
}

Note that the data fields allocated using this feature are automatically cleaned up at the end of the simulation, so users do not need to delete them.

Clone this wiki locally