barotropic_density.hpp cmath optional string_view utility serif/dimensions/type_alias.hpp serif/discretization/blocks/fields.hpp serif/eos/evaluation.hpp serif/eos/exceptions.hpp serif/eos/relations/relations.hpp serif/equations/companion.hpp serif/equations/contributions.hpp serif/equations/point.hpp serif/equations/rigid_rotation.hpp serif/utils/error/errors.hpp src/compile_time_checks/serif/model/barotropic_density.cpp src/compile_time_checks/serif/model/density_primal.cpp src/compile_time_checks/serif/model/execution_validation.cpp src/compile_time_checks/serif/model/normalization.cpp src/compile_time_checks/serif/model/validation.cpp src/compile_time_checks/serif/operators/coordinate_identity_meanfield.cpp src/compile_time_checks/serif/operators/plan.cpp src/include/serif/backend/mfem/serialize/top.hpp src/include/serif/equations/equations.hpp serif::equations::BarotropicDensityBalance serif serif::equations #pragmaonce #include<cmath> #include<optional> #include<string_view> #include<utility> #include"serif/dimensions/type_alias.hpp" #include"serif/discretization/blocks/fields.hpp" #include"serif/eos/evaluation.hpp" #include"serif/eos/exceptions.hpp" #include"serif/eos/relations/relations.hpp" #include"serif/equations/companion.hpp" #include"serif/equations/contributions.hpp" #include"serif/equations/point.hpp" #include"serif/equations/rigid_rotation.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::equations{ template<eos::models::EOSModelEOS> requireseos::models::EOSSupportingRelation<EOS,eos::relations::PressurePotentialFromDensity>&& eos::models::EOSSupportingRelation<EOS,eos::relations::DensityFromPressure>&& eos::models::EOSSupportingPartialDerivative<EOS,eos::relations::PressureFromDensity,dimensions::MassDensity> classBarotropicDensityBalancefinal:publicContribution<discretization::forms::Operand<discretization::blocks::density::mass>>{ public: usingDensity=discretization::blocks::density::mass; usingPotential=discretization::blocks::gravity::potential; usingSurfaceLevel=discretization::blocks::barotropic_constant::mass_normalization; usingAngularVelocity=discretization::blocks::rotation::angular_velocity; usingOperands=utils::types::TypeList<discretization::forms::Operand<Density>, discretization::forms::Operand<Potential>,discretization::forms::Operand<SurfaceLevel>, discretization::forms::Operand<AngularVelocity>>; usingResidualQuantity=dimensions::BarotropicPressurePotential; usingIsobaricSurfaceField=Density; staticconstexprstd::string_viewname="barotropicdensitybalance"; explicitBarotropicDensityBalance( EOSequation_of_state, constdimensions::PressureValuesurface_pressure=dimensions::PressureValue{0.0}, constRigidRotation::Vector&axis={0.0,0.0,1.0}, constRigidRotation::Vector&center={}, std::optional<PointMassCompanion>companion=std::nullopt ): m_eos(std::move(equation_of_state)), m_surface_pressure(surface_pressure), m_rotation(RigidRotation::unit_rotation(axis,center)), m_companion(companion){ usingnamespaceutils::errors; serif_ensure<SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT,eos::EOSEvaluationError>( std::isfinite(surface_pressure.value())&&surface_pressure.value()>=0.0, "Barotropicdensitybalancerequiresfinitenonnegativesurfacepressure;received{}.",surface_pressure.value()); constautosurface_density=eos::evaluate<dimensions::MassDensity>(m_eos,surface_pressure); serif_ensure<SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT,eos::EOSEvaluationError>( std::isfinite(surface_density.value())&&surface_density.value()>=0.0, "TheEOSreturnedsurfacedensity{}atpressure{};chooseavalidnonnegativebarotropicbranch.", surface_density.value(),surface_pressure.value()); m_surface_pressure_potential=eos::evaluate<dimensions::BarotropicPressurePotential>(m_eos,surface_density).value(); serif_ensure<SERiFErrorCode::EOS_NONFINITE_RESULT,eos::EOSEvaluationError>( std::isfinite(m_surface_pressure_potential), "TheEOSpressurepotentialisnotfiniteatsurfacedensity{};chooseasurfacepressurewithafiniteprimitive.", surface_density.value()); } [[nodiscard]]PointLinearization<Operands>evaluate(constEquationPoint<Operands>&point)const{ usingnamespaceutils::errors; constdoubledensity=point.fields.templateget<Density>(); serif_ensure<SERiFErrorCode::EOS_INVALID_THERMODYNAMIC_INPUT,eos::EOSEvaluationError>( std::isfinite(density)&&density>0.0, "Barotropicdensitybalancerequirespositivefiniteinteriordensity;received{}.Imposethevacuumtraceseparately.",density); constdimensions::DensityValuestate{density}; constdoublepressure_potential=eos::evaluate<dimensions::BarotropicPressurePotential>(m_eos,state).value(); constdoubledensity_derivative=eos::partial_derivative<dimensions::Pressure, dimensions::MassDensity>(m_eos,state).value()/density; serif_ensure<SERiFErrorCode::EOS_NONFINITE_RESULT,eos::EOSEvaluationError>( std::isfinite(pressure_potential)&&std::isfinite(density_derivative), "TheEOSpressurepotentialorP_rho/rhoisnotfiniteatinteriordensity{};useavalidbarotropicstate.",density); constdoubleomega=point.fields.templateget<AngularVelocity>(); constdoublecentrifugal_potential=m_rotation.centrifugal_potential(point.position); PointLinearization<Operands>result; result.residual=pressure_potential-m_surface_pressure_potential+point.fields.templateget<Potential>()-omega*omega*centrifugal_potential-point.fields.templateget<SurfaceLevel>(); result.field_derivatives.templateget<Density>()=density_derivative; result.field_derivatives.templateget<Potential>()=1.0; result.field_derivatives.templateget<SurfaceLevel>()=-1.0; result.field_derivatives.templateget<AngularVelocity>()=-2.0*omega*centrifugal_potential; result.position_derivative=m_rotation.centrifugal_potential_gradient(point.position); for(double&component:result.position_derivative){ component*=-omega*omega; } if(m_companion){ result.residual+=m_companion->potential(point.position); constautogradient=m_companion->potential_gradient(point.position); for(intaxis=0;axis<3;++axis){result.position_derivative[axis]+=gradient[axis];} } returnresult; } template<typenameOperand> [[nodiscard]]staticintadditional_order(Operand,constintposition_order){ returnDensity::FunctionalSpace::order+position_order; } [[nodiscard]]constEOS&equation_of_state()constnoexcept{returnm_eos;} [[nodiscard]]dimensions::PressureValuesurface_pressure()constnoexcept{returnm_surface_pressure;} [[nodiscard]]constRigidRotation&rotation()constnoexcept{returnm_rotation;} [[nodiscard]]conststd::optional<PointMassCompanion>&companion()constnoexcept{returnm_companion;} private: EOSm_eos; dimensions::PressureValuem_surface_pressure; RigidRotationm_rotation; std::optional<PointMassCompanion>m_companion; doublem_surface_pressure_potential; }; }