-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make sure that DensityEnergyFromPressureTemperature works for all equations of state #449
Changes from 16 commits
4a210b5
50c08e7
acd9def
608a772
0bdead9
0a4b61a
f1d1fc4
c5f75a5
838b720
365dd65
376223f
9b083fa
c3182ff
1034b38
d6e80ee
5f79307
0e61f98
cc8db8f
58bc9c9
99aa6cd
1e72ff5
26dd8f5
be2f5b9
44e738b
fed072a
8cc2508
6dc8cae
bc5f10e
813e773
e0e587c
cf286de
2cdcc08
1d1873f
ceec265
8424efc
7d9c90a
ee5e374
38bba46
a74bd26
5f8e8e0
74ee377
9e4f844
1cd2f9d
6967e55
144b90b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,4 +36,4 @@ jobs: | |
.. | ||
make -j4 | ||
make install | ||
make test | ||
ctest --output-on-failure | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,4 +36,4 @@ jobs: | |
.. | ||
make -j4 | ||
make install | ||
make test | ||
ctest --output-on-failure |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,8 @@ | |
#include <ports-of-call/portability.hpp> | ||
#include <ports-of-call/portable_errors.hpp> | ||
#include <singularity-eos/base/constants.hpp> | ||
#include <singularity-eos/base/robust_utils.hpp> | ||
#include <singularity-eos/base/root-finding-1d/root_finding.hpp> | ||
#include <singularity-eos/base/variadic_utils.hpp> | ||
|
||
namespace singularity { | ||
|
@@ -836,6 +838,44 @@ class EosBase { | |
PORTABLE_ALWAYS_THROW_OR_ABORT(msg); | ||
} | ||
|
||
// JMM: This method is often going to be overloaded for special cases. | ||
template <typename Indexer_t = Real *> | ||
PORTABLE_INLINE_FUNCTION void | ||
DensityEnergyFromPressureTemperature(const Real press, const Real temp, | ||
Indexer_t &&lambda, Real &rho, Real &sie) const { | ||
Comment on lines
+859
to
+863
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This default implementation is usually not optimal but does seem to work if a given EOS doesn't need special cases. In general, though, an EOS should overload and implement its own. |
||
// TODO(JMM): A lot hardcoded in here... Hopefully relevent EOS's | ||
// overwrite. | ||
constexpr Real MAXFAC = 1e8; | ||
constexpr Real EPS = 10 * robust::EPS(); | ||
constexpr Real MINR_DEFAULT = 1e-4; | ||
jhp-lanl marked this conversation as resolved.
Show resolved
Hide resolved
|
||
constexpr Real DEFAULT_RHO_GUESS = 4; | ||
using RootFinding1D::findRoot; // more robust but slower. Better default. | ||
using RootFinding1D::Status; | ||
CRTP copy = *(static_cast<CRTP const *>(this)); | ||
auto PofRT = [&](const Real r) { | ||
return copy.PressureFromDensityTemperature(r, temp, lambda); | ||
}; | ||
// JMM: This can't be zero, in case MinimumDensity is zero | ||
Real rhomin = std::max(MINR_DEFAULT, copy.MinimumDensity()); | ||
Real rhomax = MAXFAC * rhomin; | ||
Real rhoguess = rho; // use input density | ||
if ((rhoguess < rhomin) || (rhoguess > rhomax)) { | ||
if ((rhomin < DEFAULT_RHO_GUESS) && (rhomax > DEFAULT_RHO_GUESS)) { | ||
rhoguess = DEFAULT_RHO_GUESS; | ||
} else { | ||
rhoguess = 0.5 * (rhomin + rhomax); | ||
} | ||
} | ||
auto status = findRoot(PofRT, press, rhoguess, rhomin, rhomax, EPS, EPS, rho); | ||
// JMM: This needs to not fail and instead return something sane | ||
if (status != Status::SUCCESS) { | ||
PORTABLE_WARN("DensityEnergyFromPressureTemperature failed to find root\n"); | ||
rho = rhoguess; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a function that may be passed data and I see it as similar to a PTE solve. Even if it fails out, something reasonable must be done. |
||
sie = copy.InternalEnergyFromDensityTemperature(rho, temp, lambda); | ||
return; | ||
} | ||
|
||
// Serialization | ||
/* | ||
The methodology here is there are *three* size methods all EOS's provide: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -125,6 +125,47 @@ class MGUsup : public EosBase<MGUsup> { | |
FillEos(Real &rho, Real &temp, Real &energy, Real &press, Real &cv, Real &bmod, | ||
const unsigned long output, | ||
Indexer_t &&lambda = static_cast<Real *>(nullptr)) const; | ||
|
||
PORTABLE_FORCEINLINE_FUNCTION | ||
Real MinimumDensity() const { return 10 * robust::EPS(); } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the reference isotherm scales as _rho0/rho, the EOS diverges at zero density. This bounds it at least to some degree. |
||
|
||
PORTABLE_FORCEINLINE_FUNCTION | ||
Real MaximumDensity() const { | ||
if (_s > 1) { | ||
return 0.99 * robust::ratio(_s * _rho0, _s - 1); | ||
} else { // for s <= 1, no maximum, but we need to pick something. | ||
return 1e3 * _rho0; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are the conditions where the reference isotherm is a positive temperature. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Honestly the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 I will add a comment to this effect. |
||
|
||
template <typename Indexer_t = Real *> | ||
PORTABLE_INLINE_FUNCTION void | ||
DensityEnergyFromPressureTemperature(const Real press, const Real temp, | ||
Yurlungur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Indexer_t &&lambda, Real &rho, Real &sie) const { | ||
using RootFinding1D::findRoot; | ||
using RootFinding1D::Status; | ||
// JMM: diverges for rho -> 0 | ||
// and for s > 1 and rho -> rho0 | ||
Real rhomin = MinimumDensity(); | ||
Real rhomax = MaximumDensity(); | ||
auto PofRT = [&](const Real r) { | ||
return PressureFromDensityTemperature(r, temp, lambda); | ||
}; | ||
Real rhoguess = rho; // use input density | ||
if ((rhoguess < rhomin) || (rhoguess > rhomax)) { | ||
rhoguess = 0.5 * (rhomin + rhomax); | ||
} | ||
// JMM: regula_falsi does not respect bounds | ||
auto status = findRoot(PofRT, press, rhoguess, rhomin, rhomax, robust::EPS(), | ||
robust::EPS(), rho); | ||
if (status != Status::SUCCESS) { | ||
PORTABLE_THROW_OR_ABORT( | ||
"DensityEnergyFromPressureTemperature failed to find root\n"); | ||
} | ||
sie = InternalEnergyFromDensityTemperature(rho, temp, lambda); | ||
return; | ||
} | ||
|
||
template <typename Indexer_t = Real *> | ||
PORTABLE_INLINE_FUNCTION void | ||
ValuesAtReferenceState(Real &rho, Real &temp, Real &sie, Real &press, Real &cv, | ||
|
@@ -148,11 +189,6 @@ class MGUsup : public EosBase<MGUsup> { | |
_AZbar.PrintParams(); | ||
printf("\n\n"); | ||
} | ||
// Density/Energy from P/T not unique, if used will give error | ||
template <typename Indexer_t> | ||
PORTABLE_INLINE_FUNCTION void | ||
DensityEnergyFromPressureTemperature(const Real press, const Real temp, | ||
Indexer_t &&lambda, Real &rho, Real &sie) const; | ||
inline void Finalize() {} | ||
static std::string EosType() { return std::string("MGUsup"); } | ||
static std::string EosPyType() { return EosType(); } | ||
|
@@ -200,6 +236,8 @@ PORTABLE_INLINE_FUNCTION Real MGUsup::HugTemperatureFromDensity(Real rho) const | |
Real eta = 1.0 - robust::ratio(_rho0, rho); | ||
Real f1 = 1.0 - _s * eta; | ||
if (f1 <= 0.0) { | ||
printf("f1, eta, rho, rho0, s = %.14e %.14e %.14e %.14e %.14e\n", f1, eta, rho, _rho0, | ||
_s); | ||
Yurlungur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
PORTABLE_ALWAYS_THROW_OR_ABORT("MGUsup model parameters s and rho0 together with rho " | ||
"give a negative argument for a logarithm."); | ||
} | ||
|
@@ -350,13 +388,6 @@ PORTABLE_INLINE_FUNCTION Real MGUsup::BulkModulusFromDensityInternalEnergy( | |
value = robust::ratio(_rho0, rho) * value; | ||
return value; | ||
} | ||
// AEM: Give error since function is not well defined | ||
template <typename Indexer_t> | ||
PORTABLE_INLINE_FUNCTION void MGUsup::DensityEnergyFromPressureTemperature( | ||
const Real press, const Real temp, Indexer_t &&lambda, Real &rho, Real &sie) const { | ||
EOS_ERROR("MGUsup::DensityEnergyFromPressureTemperature: " | ||
"Not implemented.\n"); | ||
} | ||
// AEM: We should add entropy and Gruneissen parameters here so that it is complete | ||
// If we add also alpha and BT, those should also be in here. | ||
template <typename Indexer_t> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -653,7 +653,25 @@ PORTABLE_INLINE_FUNCTION Real StellarCollapse::GruneisenParamFromDensityInternal | |
template <typename Indexer_t> | ||
PORTABLE_INLINE_FUNCTION void StellarCollapse::DensityEnergyFromPressureTemperature( | ||
const Real press, const Real temp, Indexer_t &&lambda, Real &rho, Real &sie) const { | ||
EOS_ERROR("StellarCollapse::DensityEnergyFromPRessureTemperature is a stub"); | ||
using RootFinding1D::regula_falsi; | ||
using RootFinding1D::Status; | ||
checkLambda_(lambda); | ||
Real lrguess = lRho_(rho); | ||
Real lT = lT_(temp); | ||
Real lP = P2lP_(press); | ||
Real Ye = lambda[Lambda::Ye]; | ||
|
||
if ((lrguess < lRhoMin_) || (lrguess > lRhoMax_)) { | ||
lrguess = lRho_(rhoNormal_); | ||
} | ||
auto lPofRT = [&](Real lR) { return lP_.interpToReal(Ye, lT, lR); }; | ||
auto status = regula_falsi(lPofRT, lP, lrguess, lRhoMin_, lRhoMax_, ROOT_THRESH, | ||
ROOT_THRESH, lrguess); | ||
Comment on lines
+669
to
+671
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the EOS is tabulated in logrho, use logrho for the root find. |
||
|
||
Real lE = lE_.interpToReal(Ye, lT, lrguess); | ||
rho = rho_(lrguess); | ||
sie = le2e_(lE); | ||
lambda[Lambda::lT] = lT; | ||
} | ||
|
||
template <typename Indexer_t> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,6 +131,10 @@ class Vinet : public EosBase<Vinet> { | |
ValuesAtReferenceState(Real &rho, Real &temp, Real &sie, Real &press, Real &cv, | ||
Real &bmod, Real &dpde, Real &dvdt, | ||
Indexer_t &&lambda = static_cast<Real *>(nullptr)) const; | ||
|
||
PORTABLE_FORCEINLINE_FUNCTION | ||
Real MinimumDensity() const { return std::cbrt(10 * robust::EPS()) * _rho0; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. EOS depends on |
||
|
||
// Generic functions provided by the base class. These contain e.g. the vector | ||
// overloads that use the scalar versions declared here | ||
SG_ADD_BASE_CLASS_USINGS(Vinet) | ||
|
@@ -152,11 +156,6 @@ class Vinet : public EosBase<Vinet> { | |
} | ||
printf("\n\n"); | ||
} | ||
// Density/Energy from P/T not unique, if used will give error | ||
template <typename Indexer_t = Real *> | ||
PORTABLE_INLINE_FUNCTION void | ||
DensityEnergyFromPressureTemperature(const Real press, const Real temp, | ||
Indexer_t &&lambda, Real &rho, Real &sie) const; | ||
Comment on lines
-155
to
-159
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use the default in the base class |
||
inline void Finalize() {} | ||
static std::string EosType() { return std::string("Vinet"); } | ||
static std::string EosPyType() { return EosType(); } | ||
|
@@ -375,13 +374,6 @@ PORTABLE_INLINE_FUNCTION Real Vinet::BulkModulusFromDensityInternalEnergy( | |
Vinet_F_DT_func(rho, temp, output); | ||
return output[7] * output[7] * rho; | ||
} | ||
// AEM: Give error since function is not well defined | ||
template <typename Indexer_t> | ||
PORTABLE_INLINE_FUNCTION void Vinet::DensityEnergyFromPressureTemperature( | ||
const Real press, const Real temp, Indexer_t &&lambda, Real &rho, Real &sie) const { | ||
EOS_ERROR("Vinet::DensityEnergyFromPressureTemperature: " | ||
"Not implemented.\n"); | ||
} | ||
// AEM: We should add entropy and Gruneissen parameters here so that it is complete | ||
// If we add also alpha and BT, those should also be in here. | ||
template <typename Indexer_t> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ | |
#include <memory> | ||
|
||
#include <ports-of-call/portability.hpp> | ||
#include <singularity-eos/base/robust_utils.hpp> | ||
|
||
inline std::string demangle(const char *name) { | ||
|
||
|
@@ -143,6 +144,34 @@ inline void compare_two_eoss(const E1 &test_e, const E2 &ref_e) { | |
return; | ||
} | ||
|
||
template <typename EOS, typename Indexer_t = Real *> | ||
PORTABLE_INLINE_FUNCTION bool | ||
CheckRhoSieFromPT(EOS eos, Real rho, Real T, | ||
Indexer_t &&lambda = static_cast<Real *>(nullptr)) { | ||
Comment on lines
+147
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Convenience function to let me test the functionality more easily |
||
const Real P = eos.PressureFromDensityTemperature(rho, T, lambda); | ||
const Real sie = eos.InternalEnergyFromDensityTemperature(rho, T, lambda); | ||
Real rtest, etest; | ||
eos.DensityEnergyFromPressureTemperature(P, T, lambda, rtest, etest); | ||
Real bmod = eos.BulkModulusFromDensityTemperature(rho, T, lambda); | ||
bool results_good = (isClose(rho, rtest, bmod * 1e-8) || isClose(rho, rtest, 1e-8)) && | ||
(isClose(sie, etest, bmod * 1e-8) || isClose(sie, etest, 1e-8)); | ||
if (!results_good) { | ||
Real P_test = eos.PressureFromDensityTemperature(rtest, T, lambda); | ||
Real residual = P_test - P; | ||
printf("RhoSie of PT failure!\n" | ||
"\trho_true = %.14e\n" | ||
"\tsie_true = %.14e\n" | ||
"\tP = %.14e\n" | ||
"\tT = %.14e\n" | ||
"\trho = %.14e\n" | ||
"\tsie = %.14e\n" | ||
"\tP_test = %.14e\n" | ||
"\tresidual = %.14e\n", | ||
rho, sie, P, T, rtest, etest, P_test, residual); | ||
} | ||
return results_good; | ||
} | ||
|
||
// Macro that checks for an exception or is a no-op depending on | ||
// whether or not a non-serial backend is supplied | ||
#ifdef PORTABILITY_STRATEGY_NONE | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd like to leave this permanently. You still get a summary out at the end, but here we can see what went wrong with a test. Useful for debugging, especially when the CI machine and your laptop disagree...