Program Listing for File gravity.cpp
↰ Return to documentation for file (gravity/gravity.cpp
)
// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************
#include <string>
#include "gravity.hpp"
#include "dataBlock.hpp"
#include "input.hpp"
void Gravity::Init(Input &input, DataBlock *datain) {
this->data = datain;
data->haveGravity = true;
// Gravitational potential
int nPotential = input.CheckEntry("Gravity","potential");
if(nPotential >=0) {
this->havePotential = true;
for(int i = 0 ; i < nPotential ; i++) {
std::string potentialString = input.Get<std::string>("Gravity","potential",i);
if(potentialString.compare("userdef") == 0) {
this->haveUserDefPotential = true;
} else if (potentialString.compare("central") == 0) {
this->haveCentralMassPotential = true;
this->centralMass = input.GetOrSet<real>("Gravity","Mcentral",0, 1.0);
} else if (potentialString.compare("selfgravity") == 0) {
this->haveSelfGravityPotential = true;
} else {
IDEFIX_ERROR("Unknown type of gravitational potential in idefix.ini. ");
}
}
}
// Body Force
if(input.CheckEntry("Gravity","bodyForce")>=0) {
std::string potentialString = input.Get<std::string>("Gravity","bodyForce",0);
if(potentialString.compare("userdef") == 0) {
this->haveBodyForce = true;
} else {
IDEFIX_ERROR("Unknown type of body force in idefix.ini. "
"Only userdef is implemented");
}
}
// Allocate required arrays
if(havePotential && !haveInitialisedPotential) {
phiP = IdefixArray3D<real>("Gravity_PhiP",
data->np_tot[KDIR], data->np_tot[JDIR], data->np_tot[IDIR]);
haveInitialisedPotential = true;
}
if(haveBodyForce && !haveInitialisedBodyForce) {
bodyForceVector = IdefixArray4D<real>("Gravity_bodyForce", COMPONENTS,
data->np_tot[KDIR], data->np_tot[JDIR], data->np_tot[IDIR]);
haveInitialisedBodyForce = true;
}
}
void Gravity::ShowConfig() {
if(data->haveGravity) {
idfx::cout << "Gravity: ENABLED." << std::endl;
if(haveUserDefPotential) {
idfx::cout << "Gravity: User-defined gravitational potential ENABLED." << std::endl;
if(!gravPotentialFunc) {
IDEFIX_ERROR("No user-defined gravitational potential has been enrolled.");
}
}
if(haveCentralMassPotential) {
idfx::cout << "Gravity: central mass gravitational potential ENABLED with M="
<< this->centralMass << std::endl;
}
if(haveSelfGravityPotential) {
idfx::cout << "Gravity: self-gravity ENABLED." << std::endl;
}
if(haveBodyForce) {
idfx::cout << "Gravity: user-defined body force ENABLED." << std::endl;
if(!bodyForceFunc) {
IDEFIX_ERROR("No user-defined body force has been enrolled.");
}
}
}
}
// This function compute the gravitational field, using both body force and potential
void Gravity::ComputeGravity() {
idfx::pushRegion("Gravity::ComputeGravity");
if(havePotential) {
if(haveUserDefPotential) {
if(gravPotentialFunc == nullptr) {
IDEFIX_ERROR("Gravitational potential is enabled, "
"but no user-defined potential has been enrolled.");
}
idfx::pushRegion("Gravity::user-defined:gravPotentialFunc");
gravPotentialFunc(*data, data->t, data->x[IDIR], data->x[JDIR], data->x[KDIR], phiP);
idfx::popRegion();
} else {
ResetPotential();
}
if(haveCentralMassPotential) {
AddCentralMassPotential();
}
if(havePlanetsPotential) {
IDEFIX_ERROR("Planet potential not implemented. Ask GWF.");
}
if(haveSelfGravityPotential) {
IDEFIX_ERROR("Self gravity potential not implemented. Ask JM.");
}
}
if(haveBodyForce) {
// When bodyforce is enabled, it has to be a userdefined function, enrolled previously
if(bodyForceFunc == nullptr) {
IDEFIX_ERROR("Gravitational potential is enabled, "
"but no user-defined potential has been enrolled.");
}
idfx::pushRegion("Gravity: user-defined:bodyForceFunc");
bodyForceFunc(*data, data->t, bodyForceVector);
idfx::popRegion();
}
idfx::popRegion();
}
void Gravity::EnrollPotential(GravPotentialFunc myFunc) {
if(!this->haveUserDefPotential) {
IDEFIX_WARNING("In order to enroll your gravitational potential, "
"you need to enable it first in the .ini file "
"with the potential entry in [Gravity].");
}
this->gravPotentialFunc = myFunc;
}
void Gravity::EnrollBodyForce(BodyForceFunc myFunc) {
if(!this->haveBodyForce) {
IDEFIX_WARNING("In order to enroll your body force, "
"you need to enable it first in the .ini file "
"with the bodyForce entry in [Gravity].");
}
this->bodyForceFunc = myFunc;
}
// Fill the gravitational potential with zeros
void Gravity::ResetPotential() {
idfx::pushRegion("Gravity::ResetPotential");
IdefixArray3D<real> phiP = this->phiP;
idefix_for("Gravity::ResetPotential",
0, data->np_tot[KDIR],
0, data->np_tot[JDIR],
0, data->np_tot[IDIR],
KOKKOS_LAMBDA(int k, int j, int i) {
phiP(k,j,i) = ZERO_F;
});
idfx::popRegion();
}
void Gravity::AddCentralMassPotential() {
idfx::pushRegion("Gravity::AddCentralMassPotential");
IdefixArray1D<real> x1 = data->x[IDIR];
IdefixArray1D<real> x2 = data->x[JDIR];
IdefixArray1D<real> x3 = data->x[KDIR];
IdefixArray3D<real> phiP = this->phiP;
real mass = this->centralMass;
#if GEOMETRY == CARTESIAN
IDEFIX_ERROR("Central mass potential is not defined in cartesian geometry");
#endif
idefix_for("Gravity::AddCentralMassPotential",
0, data->np_tot[KDIR],
0, data->np_tot[JDIR],
0, data->np_tot[IDIR],
KOKKOS_LAMBDA(int k, int j, int i) {
real r;
#if GEOMETRY == POLAR
r = D_EXPAND( x1(i)*x1(i), , + x3(k)*x3(k));
r = sqrt(r);
#elif GEOMETRY == CYLINDRICAL
r = D_EXPAND( x1(i)*x1(i), + x2(j)*x2(j) , );
r = sqrt(r);
#elif GEOMETRY == SPHERICAL
r = x1(i);
#else
r = ONE_F; // Make sure this one is initialized
#endif
phiP(k,j,i) += -mass/r;
});
idfx::popRegion();
}