Understanding generic hydrodynamical setups of disk-planet systems in Athena++
The biggest problem I have had is to develop a better understanding of frames of reference in which the equations are needed to be implemented in the code, say for example, in the MeshBlock::ProblemGenerator. The basic structure of a file looks like as follows
// Define initial conditions
void MeshBlock::ProblemGenerator(ParameterInput *pin) {
// The idea now is to set the initial conditions at each grid-point
// in the simulation domain. Initial conditions refer to the initial
// density and momentum of the constituent fluids that make up the disk
// In case of disk-planet interactions, the "planet" itself is not part of
// initial conditions (even if it is assumed to start exerting its
// gravitational influence at t=0), but rather in a separate source
// function.
// Assume the program has been configured for spherical coordinates.
for (int k = ks; k <= ke; ++k) {
// Notice the order of loops, the first index is `x3`, or in the case
// of spherical coordinates, φ.
Real x3 = pcoord->x3v(k); // φ
// Also note the special variables offered by the `MeshBlock` class
// in the form of `ks`, `ke`, `js`.. etc, providing the start and
// end indices for us to loop over. Later when setting boundary conditions
// we will see how handy they are when ghost cells also
// get involved.
for (int j = js; j <= je; ++j) {
Real x2 = pcoord->x2v(j); // θ
for (int i = is; i <= ie; ++i) {
Real x3 = pcoord->x1v(i); // r
// Now goes the logic to set the conditions. Again,
// one must set the initial density and momentum at least.
// Depending on the EOS, energy and pressure also need to be
// set. One important thing to note is often in these problems
// we assume locally isothermal or vertically isothermal EOS.
// This needs to be set by the user explicitly as the
// `--eos=isothermal` configuration option while compiling the code
// is only applicable to globally isothermal EOS.
// A simple way to understand this is through sound speed.
// Globally isothermal implies `c_s` is constant everywhere.
// Vertically isothermal implies `c_s` has some dependence in
// radial direction.
}
}
}
}
Understanding the planetary potential
Most model papers define gravity exerted by the planet by specifying its potential
In the code, we have the 3 variables for each direction, depending on the choice of our coordinate system. For simplicity, let us work in spherical coordinates.
Before we substitute
This reduces the potential
Now, let’s start by writing
Similarly, the indirect term,
The third term has no dependence on
// In the function `PlanetaryGravity` in disk_planet_spherical.cpp and solar_system.cpp
// this d
distance_square(i) = SQR(x_dis(i)) + SQR(y_dis(i)) + SQR(z_dis(i));
// this is R - R_p cos (Δ)
R_dis(i) = R_arr(i) - rad_planet[p] * std::cos(phi_arr(i) - phi_planet_move); //
// this is GM_p / (\tilde{d^3}) (assuming `PlanetaryGravityOrder == 2`)
gravity(i) = (planet_gm / std::pow(distance_square(i) + SQR(rad_soft[p]), 1.5));
// this is the indirect term
indirect_acc_R(i) = planet_gm * std::cos(phi_arr(i) - phi_planet_move) / SQR(rad_planet[p]);Similarly, one can derive expressions for
Implementing the Bae+25’s potential
Bae+25 defines their potential as
when
We can now now compare the terms on how to modify the code. Essentially we need to make the following replacement:
which translated to following in the code
Real d = std::sqrt(distance_square(i));
Real epsilon = rad_soft[p];
if (d <= epsilon) {
Real x = d / epsilon;
gravity(i) = planet_gm * (4.0 - 3.0 * x) / (epsilon * epsilon * epsilon);
} else {
// No softening
gravity(i) = planet_gm / (d * d * d);
}