perf(allocations): reduced overall allocations by 95%, increaseed jacobian applicatin by 2x
This commit uses global pre allocated work space to dramatically reduce memory usage and allocation time
This commit is contained in:
@@ -4,6 +4,7 @@ module;
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -14,6 +15,7 @@ export module mean_field:operators.prepared_angular_momentum;
|
||||
|
||||
export import :fem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :mapping.prepared_cache;
|
||||
export import :model.compiled_fixed_angular_momentum;
|
||||
export import :operators.context.gravity_field;
|
||||
|
||||
@@ -188,15 +190,13 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const PreparedAngularMomentumActionStatistics &GetActionStatistics() const noexcept;
|
||||
[[nodiscard]] const models::CompiledFixedAngularMomentum &GetCompiledConstraint() const noexcept;
|
||||
|
||||
private:
|
||||
struct QuadraturePointData final {
|
||||
mfem::IntegrationPoint integrationPoint;
|
||||
mfem::Vector densityShape;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
double density{0.0};
|
||||
double cylindricalRadiusSquared{0.0};
|
||||
};
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ElementPAData final {
|
||||
int elementId{-1};
|
||||
mfem::Array<int> densityDofs;
|
||||
@@ -205,9 +205,14 @@ export namespace mean_field::operators {
|
||||
mfem::DofTransformation *densityDofTransformation{nullptr};
|
||||
mfem::DofTransformation *displacementDofTransformation{nullptr};
|
||||
mfem::DofTransformation *compactificationDofTransformation{nullptr};
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
mfem::Vector baseDisplacement;
|
||||
mfem::Vector compactification;
|
||||
std::vector<QuadraturePointData> quadraturePoints;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
|
||||
mapping::VolumeMappingCache mappingContexts;
|
||||
mfem::Vector density;
|
||||
mfem::Vector quadratureWeights;
|
||||
mfem::Vector cylindricalRadiusSquared;
|
||||
};
|
||||
|
||||
void BuildStaticPlan();
|
||||
|
||||
@@ -2,6 +2,7 @@ module;
|
||||
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <vector>
|
||||
|
||||
@@ -97,6 +98,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const context::barotropic::BarotropicClosurePreparationStatistics &
|
||||
GetContextPreparationStatistics() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ConstructionData;
|
||||
|
||||
@@ -132,8 +139,11 @@ export namespace mean_field::operators {
|
||||
mfem::DofTransformation *enthalpyDofTransformation{nullptr};
|
||||
mfem::DofTransformation *displacementDofTransformation{nullptr};
|
||||
|
||||
mfem::DenseMatrix densityBasis;
|
||||
mfem::DenseMatrix enthalpyBasis;
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyBasis;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> displacementBasis;
|
||||
mfem::DenseMatrix inverseElementJacobians;
|
||||
|
||||
mfem::Vector weightedResidual;
|
||||
@@ -169,7 +179,6 @@ export namespace mean_field::operators {
|
||||
mutable mfem::Vector m_elementDisplacementVariation;
|
||||
mutable mfem::Vector m_quadratureDisplacementAction;
|
||||
mutable mfem::Vector m_elementDisplacementAction;
|
||||
mutable mfem::DenseMatrix m_referenceDShape;
|
||||
mutable mfem::DenseMatrix m_referenceDisplacementJacobian;
|
||||
|
||||
std::uint64_t m_preparationCount{0};
|
||||
|
||||
@@ -3,6 +3,7 @@ module;
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <mfem.hpp>
|
||||
@@ -14,6 +15,7 @@ export import :mapping.domain_mapper;
|
||||
export import :operators.context.gravity_field;
|
||||
export import :operators.kernels.gravity_displacement_force;
|
||||
export import :utils.blocks;
|
||||
import :fem.reference_tables;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
struct PreparedGravityDisplacementForceReport final {
|
||||
@@ -111,6 +113,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const context::gravity_field::GravityFieldLinearizationContext &
|
||||
GetGravityContext() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void VerifyPrepared() const;
|
||||
[[nodiscard]] std::expected<
|
||||
@@ -133,6 +141,10 @@ export namespace mean_field::operators {
|
||||
mfem::DofTransformation *gravityGradientDofTransformation{nullptr};
|
||||
mfem::DofTransformation *displacementDofTransformation{nullptr};
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> densityReferenceTable;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> displacementReferenceTable;
|
||||
std::shared_ptr<const fem::VectorReferenceTable> gravityReferenceTable;
|
||||
mfem::DenseMatrix meshPiolaJacobians;
|
||||
mfem::DenseMatrix mappingJacobians;
|
||||
mfem::DenseMatrix inverseMeshJacobians;
|
||||
mfem::DenseMatrix baseGravityReferenceValues;
|
||||
@@ -164,16 +176,17 @@ export namespace mean_field::operators {
|
||||
mutable mfem::Vector m_displacementShape;
|
||||
mutable mfem::Vector m_baseGravityReferenceValue;
|
||||
mutable mfem::Vector m_gravityVariationReferenceValue;
|
||||
mutable mfem::Vector m_gravityVariationReferenceCellValue;
|
||||
mutable mfem::Vector m_mappedBaseGravity;
|
||||
mutable mfem::Vector m_mappedGravityVariation;
|
||||
mutable mfem::Vector m_mappedGeometryVariation;
|
||||
mutable mfem::Vector m_forceValue;
|
||||
mutable mfem::DenseMatrix m_gravityGradientShape;
|
||||
mutable mfem::DenseMatrix m_referenceDisplacementDShape;
|
||||
mutable mfem::DenseMatrix m_referenceDisplacementJacobian;
|
||||
mutable mfem::DenseMatrix m_displacementJacobianVariation;
|
||||
mutable mfem::DenseMatrix m_mappingJacobian;
|
||||
mutable mfem::DenseMatrix m_inverseMeshJacobian;
|
||||
mutable mfem::DenseMatrix m_meshPiolaJacobian;
|
||||
|
||||
std::uint64_t m_residualPreparationCount{0};
|
||||
mutable std::uint64_t m_residualApplicationCount{0};
|
||||
|
||||
@@ -58,6 +58,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const field::FieldDofMap &GetPotentialMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.element_id, *data.integration_rule);
|
||||
}
|
||||
}
|
||||
|
||||
void MultTranspose(
|
||||
const mfem::Vector &potential,
|
||||
mfem::Vector &action
|
||||
@@ -80,6 +86,10 @@ export namespace mean_field::operators {
|
||||
const mfem::IntegrationRule *integration_rule{nullptr};
|
||||
|
||||
// Rows are quadrature points; columns are element DOFs.
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> density_reference;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> potential_reference;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> displacement_reference;
|
||||
// Non-VALUE map types retain their element-dependent physical basis.
|
||||
mfem::DenseMatrix density_basis;
|
||||
mfem::DenseMatrix potential_basis;
|
||||
mfem::DenseMatrix inverse_element_jacobians;
|
||||
@@ -87,6 +97,14 @@ export namespace mean_field::operators {
|
||||
// Contains quadrature weight, mesh Jacobian, mapped Jacobian,
|
||||
// and 4*pi*G.
|
||||
mfem::Vector quadrature_data;
|
||||
|
||||
[[nodiscard]] const mfem::DenseMatrix &GetDensityBasis() const {
|
||||
return density_reference ? density_reference->GetValues() : density_basis;
|
||||
}
|
||||
|
||||
[[nodiscard]] const mfem::DenseMatrix &GetPotentialBasis() const {
|
||||
return potential_reference ? potential_reference->GetValues() : potential_basis;
|
||||
}
|
||||
};
|
||||
|
||||
[[nodiscard]] GravitySourcePreparationResult TryPrepareImpl(
|
||||
@@ -119,7 +137,6 @@ export namespace mean_field::operators {
|
||||
mutable mfem::Vector m_element_displacement_variation;
|
||||
mutable mfem::Vector m_quadrature_variation_action;
|
||||
mutable mfem::Vector m_element_variation_action;
|
||||
mutable mfem::DenseMatrix m_reference_displacement_dshape;
|
||||
mutable mfem::DenseMatrix m_reference_displacement_jacobian;
|
||||
mfem::Vector m_displacement_true;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ export module mean_field:operators.prepared_hdiv_mass;
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
import :fem.reference_tables;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class HDivMassPreparationRejectionReason : std::uint8_t { invalid_mapping, non_finite_arithmetic };
|
||||
@@ -58,6 +59,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const field::FieldDofMap &GetFluxMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementVariationData &data : m_variationElements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
enum class PreparationMode : std::uint8_t { primal, linearization };
|
||||
|
||||
@@ -71,6 +78,10 @@ export namespace mean_field::operators {
|
||||
mfem::Vector baseDisplacement;
|
||||
mfem::Vector compactification;
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
std::shared_ptr<const fem::VectorReferenceTable> gravityReferenceTable;
|
||||
// Fixed computational-mesh Piola factor, separate from J_map.
|
||||
mfem::DenseMatrix meshPiolaJacobians;
|
||||
mfem::Vector referenceWeights;
|
||||
mfem::DenseMatrix frozenMappingData;
|
||||
};
|
||||
|
||||
@@ -112,7 +123,10 @@ export namespace mean_field::operators {
|
||||
mutable mfem::Vector m_elementDisplacementVariation;
|
||||
mutable mfem::Vector m_elementVariationAction;
|
||||
mutable mfem::Vector m_gravityGradientValue;
|
||||
mutable mfem::Vector m_gravityReferenceCellValue;
|
||||
mutable mfem::Vector m_referenceCellDual;
|
||||
mutable mfem::Vector m_massTensorVariationAction;
|
||||
mutable mfem::DenseMatrix m_meshPiolaJacobian;
|
||||
mutable mfem::DenseMatrix m_gravityGradientShape;
|
||||
mutable mfem::DenseMatrix m_massTensorVariation;
|
||||
std::uint64_t m_preparation_count{0};
|
||||
|
||||
@@ -4,6 +4,7 @@ module;
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
@@ -13,7 +14,9 @@ module;
|
||||
export module mean_field:operators.prepared_hydrostatic_equilibrium;
|
||||
|
||||
export import :fem;
|
||||
export import :fem.reference_tables;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :mapping.prepared_cache;
|
||||
export import :operators.context.hydrostatic_equilibrium;
|
||||
export import :physics.rigid_rotation;
|
||||
|
||||
@@ -216,6 +219,12 @@ export namespace mean_field::operators {
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ElementPAData {
|
||||
int elementId{-1};
|
||||
@@ -232,15 +241,23 @@ export namespace mean_field::operators {
|
||||
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
|
||||
// Rows are quadrature points and columns are element DOFs.
|
||||
mfem::DenseMatrix enthalpyBasis;
|
||||
mfem::DenseMatrix gravityPotentialBasis;
|
||||
// Immutable reference values and gradients are shared by FE/rule.
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyReferenceTable;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> gravityPotentialReferenceTable;
|
||||
|
||||
[[nodiscard]] const mfem::DenseMatrix &GetEnthalpyBasis() const {
|
||||
return enthalpyReferenceTable->GetValues();
|
||||
}
|
||||
|
||||
[[nodiscard]] const mfem::DenseMatrix &GetGravityPotentialBasis() const {
|
||||
return gravityPotentialReferenceTable->GetValues();
|
||||
}
|
||||
|
||||
// Rows are quadrature points and columns are physical components.
|
||||
mfem::DenseMatrix physicalPositions;
|
||||
|
||||
mfem::Vector quadratureWeights;
|
||||
std::vector<mapping::VolumeMappingContext> baseMappingContexts;
|
||||
mapping::VolumeMappingCache baseMappingContexts;
|
||||
|
||||
std::optional<mapping::ElementDisplacementData> baseDisplacementData;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ module;
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
@@ -11,6 +12,7 @@ export module mean_field:operators.prepared_mass_normalization;
|
||||
|
||||
export import :fem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :mapping.prepared_cache;
|
||||
export import :model.compiled_fixed_mass;
|
||||
export import :operators.context.gravity_field;
|
||||
export import :operators.prepared_constraint;
|
||||
@@ -187,14 +189,13 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const context::gravity_field::GravityFieldLinearizationContext &
|
||||
GetGravityContext() const noexcept;
|
||||
|
||||
private:
|
||||
struct QuadraturePointData final {
|
||||
mfem::IntegrationPoint integrationPoint;
|
||||
mfem::Vector densityShape;
|
||||
mapping::VolumeMappingContext mappingContext;
|
||||
double density{0.0};
|
||||
};
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ElementPAData final {
|
||||
int elementId{-1};
|
||||
|
||||
@@ -206,10 +207,15 @@ export namespace mean_field::operators {
|
||||
mfem::DofTransformation *displacementDofTransformation{nullptr};
|
||||
mfem::DofTransformation *compactificationDofTransformation{nullptr};
|
||||
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
|
||||
mfem::Vector baseDisplacement;
|
||||
mfem::Vector compactification;
|
||||
|
||||
std::vector<QuadraturePointData> quadraturePoints;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> densityBasis;
|
||||
mapping::VolumeMappingCache mappingContexts;
|
||||
mfem::Vector density;
|
||||
mfem::Vector quadratureWeights;
|
||||
};
|
||||
|
||||
void BuildStaticPlan();
|
||||
|
||||
@@ -4,6 +4,7 @@ module;
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -13,8 +14,10 @@ export module mean_field:operators.prepared_pressure_force;
|
||||
|
||||
export import :eos.polytrope;
|
||||
export import :fem;
|
||||
export import :fem.reference_tables;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :mapping.prepared_cache;
|
||||
export import :operators.context.pressure_force;
|
||||
export import :utils.blocks;
|
||||
|
||||
@@ -168,6 +171,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]]
|
||||
const fem::FEM &GetFEM() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ConstructionData;
|
||||
|
||||
@@ -196,10 +205,13 @@ export namespace mean_field::operators {
|
||||
|
||||
const mfem::IntegrationRule *integrationRule{nullptr};
|
||||
|
||||
/*
|
||||
* Rows are quadrature points and columns are enthalpy DOFs.
|
||||
*/
|
||||
mfem::DenseMatrix enthalpyBasis;
|
||||
// Immutable reference values and gradients are shared by FE/rule.
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> enthalpyReferenceTable;
|
||||
std::shared_ptr<const fem::ScalarReferenceTable> displacementReferenceTable;
|
||||
|
||||
[[nodiscard]] const mfem::DenseMatrix &GetEnthalpyBasis() const {
|
||||
return enthalpyReferenceTable->GetValues();
|
||||
}
|
||||
|
||||
/*
|
||||
* Each entry is:
|
||||
@@ -208,11 +220,9 @@ export namespace mean_field::operators {
|
||||
* x
|
||||
* physical dimension.
|
||||
*/
|
||||
std::vector<mfem::DenseMatrix> referenceTestGradients;
|
||||
|
||||
std::vector<mfem::DenseMatrix> physicalTestGradients;
|
||||
|
||||
std::vector<mapping::VolumeMappingContext> baseMappingContexts;
|
||||
mapping::VolumeMappingCache baseMappingContexts;
|
||||
|
||||
std::optional<mapping::ElementDisplacementData> baseDisplacementData;
|
||||
|
||||
|
||||
@@ -113,6 +113,12 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const context::rotational_displacement_force::RotationalDisplacementForceLinearizationContext &
|
||||
GetContext() const noexcept;
|
||||
|
||||
template <typename Visitor> void VisitMappedGeometryRules(Visitor &&visitor) const {
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
visitor(data.elementId, *data.integrationRule);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void VerifyPrepared() const;
|
||||
[[nodiscard]] std::expected<
|
||||
|
||||
@@ -269,6 +269,10 @@ export namespace mean_field::operators {
|
||||
[[nodiscard]] const deformation::PreparedDomainDeformationRuntime &GetDomainDeformation() const noexcept;
|
||||
[[nodiscard]] const mfem::Vector &GetSurfaceDeformationParameters() const;
|
||||
[[nodiscard]] const mfem::Vector &GetGeneratedVolumeDisplacement() const;
|
||||
void BuildVolumeDisplacementDirection(
|
||||
const mfem::Vector &surfaceDeformationDirection,
|
||||
mfem::Vector &volumeDisplacementDirection
|
||||
) const;
|
||||
[[nodiscard]] const mfem::Vector &GetFullMechanicalResidual() const;
|
||||
[[nodiscard]] const StellarEquilibriumDependencyStamp &GetGeneratedDisplacementDependency() const;
|
||||
|
||||
|
||||
@@ -2785,6 +2785,22 @@ export namespace mean_field::operators {
|
||||
return *m_physical;
|
||||
}
|
||||
|
||||
void BuildVolumeDisplacementDirection(
|
||||
const mfem::Vector &stateDirection,
|
||||
mfem::Vector &volumeDisplacementDirection
|
||||
) const {
|
||||
if (stateDirection.Size() != Width()) {
|
||||
throw std::invalid_argument(
|
||||
"The prepared stellar-equilibrium root received a state direction with the wrong size."
|
||||
);
|
||||
}
|
||||
const auto rootDirection = m_manifest.directionView(stateDirection);
|
||||
m_physical->BuildVolumeDisplacementDirection(
|
||||
rootDirection.block(utils::blocks::surface_deformation_field.parameters_term),
|
||||
volumeDisplacementDirection
|
||||
);
|
||||
}
|
||||
|
||||
template <models::ModelSpecification Specification>
|
||||
requires ModelType::template
|
||||
containsSpecification<Specification> [[nodiscard]] const auto &GetPreparedContribution() const noexcept {
|
||||
|
||||
@@ -298,6 +298,13 @@ export namespace mean_field::equilibrium {
|
||||
m_preparedOperator.Mult(direction, action);
|
||||
}
|
||||
|
||||
void BuildVolumeDisplacementDirection(
|
||||
const mfem::Vector &stateDirection,
|
||||
mfem::Vector &volumeDisplacementDirection
|
||||
) const {
|
||||
m_preparedOperator.BuildVolumeDisplacementDirection(stateDirection, volumeDisplacementDirection);
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] static CompiledSurfaceConstraintType CompileSurfaceConstraint(const ModelType &stellarModel) {
|
||||
return surface::compilePressureSurfaceConstraint<
|
||||
|
||||
Reference in New Issue
Block a user