feat(mean_field): added dimensions, discritization, and start of eos
The full rewrite of mean_field into something maintainable is progressing. dimensions is mostly done, discritization (domain, blocks, and fields) is done, and eos is progressing quickly
This commit is contained in:
32
src/include/serif/eos/evaluation.hpp
Normal file
32
src/include/serif/eos/evaluation.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "serif/eos/models/concepts.hpp"
|
||||
|
||||
namespace serif::eos {
|
||||
/*
|
||||
* I find the syntax that follows to be potentially confusing. Specifically the double use of noexcept. For those
|
||||
* unfamiliar a brief explanation follows.
|
||||
*
|
||||
* The first noexcept is used to mark if the overall function (evaluate) is noexcept. However, noexcept can take a boolean. noexcept(true)
|
||||
* tells the compiler that the function will not throw an exception (note if an exception is thrown in a noexcept function std::terminate will be called
|
||||
* and no try-catch block will catch the exception). This allows for the compiler to generate more efficient code. noexcept(false) tells
|
||||
* the compiler that the function may throw an exception (semantically it is equivalent to not including noexcept). The second noexcept
|
||||
* (e.g. noexcept(noexcept()) is used to determine what that boolean is. This is a confusing part of C++ syntax where the same
|
||||
* keyword has different semantic meanings depending on context. In this case the inner noexcept is used
|
||||
* to determine if the expression inside it is noexcept. That is to say if eos.evaluate(...) is noexcept for the particular
|
||||
* templates EOS argument then this function will be noexcept. If eos.evaluate(...) is not noexcept then this function will not be noexcept.
|
||||
*/
|
||||
template <dimensions::ThermodynamicQuantityType OutputQ, models::EOSModel EOS, dimensions::QuantityValueType... InputValues>
|
||||
requires models::EOSSupportingRelation<EOS, relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>>
|
||||
[[nodiscard]] constexpr dimensions::QuantityValue<OutputQ> evaluate(const EOS& eos, const InputValues... inputValues)
|
||||
noexcept(noexcept(eos.evaluate(relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>{}, inputValues...))) {
|
||||
return eos.evaluate(relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>{}, inputValues...);
|
||||
};
|
||||
|
||||
template <dimensions::ThermodynamicQuantityType OutputQ, dimensions::ThermodynamicQuantityType InputQ, models::EOSModel EOS, dimensions::QuantityValueType... InputValues>
|
||||
requires models::EOSSupportingPartialDerivative<EOS, relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>, InputQ>
|
||||
[[nodiscard]] constexpr dimensions::PartialDerivative<OutputQ, InputQ> partial_derivative(const EOS& eos, const InputValues... inputValues)
|
||||
noexcept(noexcept(eos.partialDerivative(relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>{}, dimensions::WithRespectTo<InputQ>{}, inputValues...))) {
|
||||
return eos.partial_derivative(relations::Relation<OutputQ, dimensions::QuantityOfT<InputValues>...>{}, dimensions::WithRespectTo<InputQ>{}, inputValues...);
|
||||
}
|
||||
|
||||
}
|
||||
32
src/include/serif/eos/exceptions.hpp
Normal file
32
src/include/serif/eos/exceptions.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace serif::eos {
|
||||
enum class EOSEvaluationErrorCode : uint8_t {
|
||||
unsupported_relation,
|
||||
unsupported_derivative,
|
||||
wrong_input_count,
|
||||
wrong_input_quantity,
|
||||
nonfinite_input,
|
||||
outside_domain,
|
||||
nonfinite_result,
|
||||
invalid_thermodynamic_input
|
||||
};
|
||||
|
||||
class EOSEvaluationError final : public std::domain_error {
|
||||
public:
|
||||
explicit EOSEvaluationError(
|
||||
const EOSEvaluationErrorCode code,
|
||||
std::string message ):
|
||||
std::domain_error(std::move(message)),
|
||||
m_code(code) {}
|
||||
|
||||
[[nodiscard]] EOSEvaluationErrorCode code() const noexcept {
|
||||
return m_code;
|
||||
}
|
||||
private:
|
||||
EOSEvaluationErrorCode m_code;
|
||||
};
|
||||
}
|
||||
28
src/include/serif/eos/models/concepts.hpp
Normal file
28
src/include/serif/eos/models/concepts.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "serif/eos/models/traits.hpp"
|
||||
|
||||
namespace serif::eos::models {
|
||||
template <typename EOSCandidate>
|
||||
concept EOSModel = is_equation_of_state_model_v<EOSCandidate>;
|
||||
|
||||
template <typename EOS, typename RelationT>
|
||||
concept EOSSupportingRelation = supports_relation_v<EOS, RelationT>;
|
||||
|
||||
template <typename EOS, typename RelationT, typename InputQuantity>
|
||||
concept EOSSupportingPartialDerivative = supports_partial_derivative_v<EOS, RelationT, InputQuantity>;
|
||||
|
||||
template <typename EOSCandidate>
|
||||
concept StructureSeedEOS = EOSModel<EOSCandidate> &&
|
||||
EOSSupportingRelation<EOSCandidate, relations::SpecificEnthalpyFromDensity>;
|
||||
|
||||
template <typename EOSCandidate>
|
||||
concept BarotropicClosureEOS = EOSModel<EOSCandidate> &&
|
||||
EOSSupportingRelation<EOSCandidate, relations::DensityFromSpecificEnthalpy> &&
|
||||
EOSSupportingPartialDerivative<EOSCandidate, relations::DensityFromSpecificEnthalpy, dimensions::SpecificEnthalpy>;
|
||||
|
||||
template <typename EOSCandidate>
|
||||
concept PressureForceEOS = EOSModel<EOSCandidate> &&
|
||||
EOSSupportingRelation<EOSCandidate, relations::PressureFromSpecificEnthalpy> &&
|
||||
EOSSupportingPartialDerivative<EOSCandidate, relations::PressureFromSpecificEnthalpy, dimensions::SpecificEnthalpy>;
|
||||
}
|
||||
67
src/include/serif/eos/models/polytropic.hpp
Normal file
67
src/include/serif/eos/models/polytropic.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include <format>
|
||||
#include "serif/eos/relations/relations.hpp"
|
||||
#include "serif/dimensions/type_alias.hpp"
|
||||
#include "serif/dimensions/partial.hpp"
|
||||
#include "serif/utils/misc/finite.hpp"
|
||||
|
||||
namespace serif::eos::models {
|
||||
struct PolytropeParameters final {
|
||||
double n;
|
||||
double K;
|
||||
};
|
||||
|
||||
class Polytrope final {
|
||||
public:
|
||||
/* The idea here (and with all EOS) is that we force the developer / implementer to enumerate all the thermodynamic relations
|
||||
* that the EOS supports explicitly. This is a small amount of boilerplate; however, it enables effectively a fully automatic
|
||||
* EOS compiler down the line. Much of the EOS system these classes depend on (relations, models, the system in evaluation) are all
|
||||
* there to allow for the compile-time checking of the EOS model and its relations and to allow the developer cross-section
|
||||
* of that to be limited to defining this relation catalog. Every EOS implemented should start (at the very top of the class
|
||||
* with a Relations alias in the public section of the class. Any EOS that does not have this will not compile.
|
||||
*/
|
||||
using Relations = relations::RelationCatalog<
|
||||
relations::PressureFromDensity,
|
||||
relations::PressureFromSpecificEnthalpy,
|
||||
relations::SpecificEnthalpyFromDensity,
|
||||
relations::SpecificEnthalpyFromPressure,
|
||||
relations::DensityFromSpecificEnthalpy
|
||||
>;
|
||||
|
||||
explicit Polytrope(const PolytropeParameters& parameters);
|
||||
explicit Polytrope(double n, double K);
|
||||
|
||||
[[nodiscard]] double polytropic_index() const noexcept;
|
||||
[[nodiscard]] double polytropic_constant() const noexcept;
|
||||
[[nodiscard]] double enthalpy_scale() const noexcept;
|
||||
|
||||
[[nodiscard]] dimensions::PressureValue evaluate(relations::PressureFromDensity, dimensions::DensityValue density) const;
|
||||
[[nodiscard]] dimensions::PressureValue evaluate(relations::PressureFromSpecificEnthalpy, dimensions::SpecificEnthalpyValue specific_enthalpy) const;
|
||||
[[nodiscard]] dimensions::SpecificEnthalpyValue evaluate(relations::SpecificEnthalpyFromDensity, dimensions::DensityValue density) const;
|
||||
[[nodiscard]] dimensions::SpecificEnthalpyValue evaluate(relations::SpecificEnthalpyFromPressure, dimensions::PressureValue pressure) const;
|
||||
[[nodiscard]] dimensions::DensityValue evaluate(relations::DensityFromSpecificEnthalpy, dimensions::SpecificEnthalpyValue specific_enthalpy) const;
|
||||
|
||||
[[nodiscard]] dimensions::PartialDerivative<dimensions::Density, dimensions::SpecificEnthalpy> partial_derivative(
|
||||
relations::DensityFromSpecificEnthalpy,
|
||||
dimensions::WithRespectTo<dimensions::SpecificEnthalpy>,
|
||||
dimensions::SpecificEnthalpyValue specific_enthalpy
|
||||
) const;
|
||||
|
||||
[[nodiscard]] dimensions::PartialDerivative<dimensions::Pressure, dimensions::SpecificEnthalpy> partial_derivative(
|
||||
relations::PressureFromSpecificEnthalpy,
|
||||
dimensions::WithRespectTo<dimensions::SpecificEnthalpy>,
|
||||
dimensions::SpecificEnthalpyValue specific_enthalpy
|
||||
) const;
|
||||
|
||||
[[nodiscard]] dimensions::PartialDerivative<dimensions::Pressure, dimensions::Density> partial_derivative(
|
||||
relations::PressureFromDensity,
|
||||
dimensions::WithRespectTo<dimensions::Density>,
|
||||
dimensions::DensityValue density
|
||||
) const;
|
||||
|
||||
private:
|
||||
double m_polytropic_index;
|
||||
double m_polytropic_constant;
|
||||
double m_enthalpy_scale;
|
||||
};
|
||||
}
|
||||
56
src/include/serif/eos/models/traits.hpp
Normal file
56
src/include/serif/eos/models/traits.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include "serif/dimensions/quantities.hpp"
|
||||
#include "serif/eos/relations/concepts.hpp"
|
||||
|
||||
namespace serif::eos::models {
|
||||
template <typename EOS, typename RelationT>
|
||||
struct ImplementsRelation_t : std::false_type{};
|
||||
|
||||
template <typename EOS, typename Output, typename... Inputs>\
|
||||
struct ImplementsRelation_t<EOS, relations::Relation<Output, Inputs...>> :
|
||||
std::bool_constant<
|
||||
requires(const std::remove_cvref_t<EOS> &eos, dimensions::QuantityValue<Inputs>... inputValues) {
|
||||
{
|
||||
eos.evaluate(relations::Relation<Output, Inputs...>{}, inputValues...)
|
||||
} -> std::same_as<dimensions::QuantityValue<Output>>;}>{}; // Read this as a requirement that when evaluating the templates EOS with the given relation and inputs the returned value is of the correct output type.
|
||||
|
||||
template <typename EOS, typename Catalog>
|
||||
struct ImplementsRelationCatalog_t : std::false_type {};
|
||||
|
||||
template <typename EOS, typename... Relations>
|
||||
struct ImplementsRelationCatalog_t<EOS, relations::RelationCatalog<Relations...>> :
|
||||
std::bool_constant<
|
||||
(ImplementsRelation_t<EOS, Relations>::value && ...)>{}; // Fold over all relations in a catalog and ensure the EOS implements all of them.
|
||||
|
||||
template <typename EOSCandidate, typename = void>
|
||||
struct IsEquationOfStateModel_t : std::false_type {};
|
||||
|
||||
template <typename EOSCandidate>
|
||||
struct IsEquationOfStateModel_t<EOSCandidate, std::void_t<typename std::remove_cvref_t<EOSCandidate>::Relations>> :
|
||||
std::bool_constant<
|
||||
relations::ValidRelationCatalog<typename std::remove_cvref_t<EOSCandidate>::Relations> && // First ensure the relation catalog is itself valid
|
||||
ImplementsRelationCatalog_t< // Then ensure that the EOSCandidate implements all relations in the catalog
|
||||
std::remove_cvref_t<EOSCandidate>,
|
||||
typename std::remove_cvref_t<EOSCandidate>::Relations>::value>{ };
|
||||
|
||||
template <typename EOS, typename RelationT, typename InputQuantity>
|
||||
struct ImplementsPartialDerivative_t : std::false_type {};
|
||||
|
||||
template <typename EOS, typename Output, typename... Inputs, typename InputQuantity>
|
||||
struct ImplementsPartialDerivative_t<EOS, relations::Relation<Output, Inputs...>, InputQuantity> :
|
||||
std::bool_constant<
|
||||
(std::same_as<InputQuantity, Inputs> || ...) &&
|
||||
requires (const std::remove_cvref_t<EOS> &eos, dimensions::QuantityValue<Inputs>... inputValues) {
|
||||
{eos.partialDerivative(relations::Relation<Output, Inputs...>{}, dimensions::WithRespectTo<InputQuantity>{}, inputValues...)} -> std::same_as<dimensions::PartialDerivative<Output, Inputs...>>;
|
||||
}>{};
|
||||
|
||||
template <typename EOSCandidate>
|
||||
inline constexpr bool is_equation_of_state_model_v = IsEquationOfStateModel_t<std::remove_cvref_t<EOSCandidate>>::value;
|
||||
|
||||
template <typename EOS, typename RelationT>
|
||||
inline constexpr bool supports_relation_v = is_equation_of_state_model_v<EOS> && ImplementsRelation_t<std::remove_cvref_t<EOS>, std::remove_cvref_t<RelationT>>::value;
|
||||
|
||||
template <typename EOS, typename RelationT, typename InputQuantity>
|
||||
inline constexpr bool supports_partial_derivative_v = is_equation_of_state_model_v<EOS> && ImplementsPartialDerivative_t<std::remove_cvref_t<EOS>, std::remove_cvref_t<RelationT>, InputQuantity>::value;
|
||||
}
|
||||
23
src/include/serif/eos/relations/catalog.hpp
Normal file
23
src/include/serif/eos/relations/catalog.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "serif/utils/misc/concepts/type_uniqueness.hpp"
|
||||
#include "serif/utils/misc/std_helper/variadic_cleaning.hpp"
|
||||
#include "serif/dimensions/quantities.hpp"
|
||||
|
||||
namespace serif::eos::relations {
|
||||
using utils::misc::std_helper::CountVariadicArguments;
|
||||
using utils::misc::concepts::AllTypesAreUnique;
|
||||
|
||||
template <typename Output, typename... Inputs>
|
||||
struct Relation final {
|
||||
using OutputQuantity = Output;
|
||||
using InputQuantities = dimensions::QuantityList<Inputs...>;
|
||||
|
||||
static constexpr std::size_t inputCount = CountVariadicArguments<Inputs...>();
|
||||
};
|
||||
|
||||
template <typename... Relations>
|
||||
struct RelationCatalog final {
|
||||
static constexpr std::size_t size = CountVariadicArguments<Relations...>();
|
||||
};
|
||||
}
|
||||
18
src/include/serif/eos/relations/concepts.hpp
Normal file
18
src/include/serif/eos/relations/concepts.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
#include "serif/eos/relations/traits.hpp"
|
||||
|
||||
|
||||
namespace serif::eos::relations {
|
||||
template <typename Catalog, typename RelationT>
|
||||
concept CatalogContainingRelation = relation_catalog_contains_relation_v<Catalog, RelationT>;
|
||||
|
||||
template <typename RelationT, typename Quantity>
|
||||
concept RelationContainingInput = relation_contains_input_v<RelationT, Quantity>;
|
||||
|
||||
template <typename RelationCandidate>
|
||||
concept ValidThermodynamicRelation = is_thermodynamic_relation_v<RelationCandidate>;
|
||||
|
||||
template <typename CandidateCatalog>
|
||||
concept ValidRelationCatalog = is_valid_relation_catalog_v<CandidateCatalog>;
|
||||
}
|
||||
|
||||
26
src/include/serif/eos/relations/relations.hpp
Normal file
26
src/include/serif/eos/relations/relations.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "serif/eos/relations/catalog.hpp"
|
||||
#include "serif/dimensions/dimensions.hpp"
|
||||
|
||||
namespace serif::eos::relations {
|
||||
using PressureFromDensity = Relation<
|
||||
dimensions::Pressure,
|
||||
dimensions::Density>;
|
||||
|
||||
using PressureFromSpecificEnthalpy = Relation<
|
||||
dimensions::Pressure,
|
||||
dimensions::SpecificEnthalpy>;
|
||||
|
||||
using SpecificEnthalpyFromDensity = Relation<
|
||||
dimensions::SpecificEnthalpy,
|
||||
dimensions::Density>;
|
||||
|
||||
using SpecificEnthalpyFromPressure = Relation<
|
||||
dimensions::SpecificEnthalpy,
|
||||
dimensions::Pressure>;
|
||||
|
||||
using DensityFromSpecificEnthalpy = Relation<
|
||||
dimensions::Density,
|
||||
dimensions::SpecificEnthalpy>;
|
||||
}
|
||||
54
src/include/serif/eos/relations/traits.hpp
Normal file
54
src/include/serif/eos/relations/traits.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "serif/eos/relations/catalog.hpp"
|
||||
|
||||
namespace serif::eos::relations {
|
||||
template <typename Catalog, typename RelationT>
|
||||
struct CatalogContainsRelation : std::false_type {};
|
||||
|
||||
template <typename... Relations, typename RelationT>
|
||||
struct CatalogContainsRelation<RelationCatalog<Relations...>, RelationT> :
|
||||
std::bool_constant<(std::same_as<RelationT, Relations> || ...)> {}; // Fold over all Relations and return true type if any of them match RelationT
|
||||
|
||||
template <typename RelationT, typename Quantity>
|
||||
struct RelationContainsInput : std::false_type {};
|
||||
|
||||
template <typename Output, typename... Inputs, typename Quantity>
|
||||
struct RelationContainsInput<Relation<Output, Inputs...>, Quantity> :
|
||||
std::bool_constant<(std::same_as<Quantity, Inputs> || ...)> {};
|
||||
|
||||
template <typename RelationCandidate>
|
||||
struct IsThermodynamicRelation : std::false_type {};
|
||||
|
||||
template <typename Output, typename... Inputs>
|
||||
struct IsThermodynamicRelation<Relation<Output, Inputs...>> :
|
||||
std::bool_constant<
|
||||
dimensions::ThermodynamicQuantityType<Output> && // Ensure the OutputQuantity is a valid thermodynamic quantity
|
||||
(dimensions::ThermodynamicQuantityType<Inputs> && ...) && // Fold over all InputQuantities to ensure they are valid thermodynamic quantities
|
||||
AllTypesAreUnique<Inputs...>> {}; // Ensure all InputQuantities are unique types
|
||||
|
||||
template <typename CandidateCatalog>
|
||||
struct IsValidRelationCatalog : std::false_type {};
|
||||
|
||||
template <typename... Relations>
|
||||
struct IsValidRelationCatalog<RelationCatalog<Relations...>> :
|
||||
std::bool_constant<
|
||||
(sizeof...(Relations) > 0) && // Ensure the catalog is not empty
|
||||
(IsThermodynamicRelation<Relations>::value && ...) && // Fold over all Relations and ensure they are all valid
|
||||
AllTypesAreUnique<Relations...>> {}; // Ensure all Relations are unique types (e.g. no duplicate relations)
|
||||
|
||||
template <typename Catalog, typename RelationT>
|
||||
inline constexpr bool relation_catalog_contains_relation_v = CatalogContainsRelation<std::remove_cv_t<Catalog>, std::remove_cv_t<RelationT>>::value;
|
||||
|
||||
template <typename RelationT, typename Quantity>
|
||||
inline constexpr bool relation_contains_input_v = RelationContainsInput<std::remove_cv_t<RelationT>, std::remove_cv_t<Quantity>>::value;
|
||||
|
||||
template <typename RelationCandidate>
|
||||
constexpr bool is_thermodynamic_relation_v = IsThermodynamicRelation<RelationCandidate>::value;
|
||||
|
||||
template <typename CatalogCandidate>
|
||||
constexpr bool is_valid_relation_catalog_v = IsValidRelationCatalog<CatalogCandidate>::value;
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user