hydrostatic_equilibrium.hpp algorithm cmath string_view serif/discretization/blocks/fields.hpp serif/equations/point.hpp serif/equations/rigid_rotation.hpp serif/utils/error/errors.hpp 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/equations/equations.hpp serif::equations::BarotropicHydrostaticEquilibrium serif serif::equations #pragmaonce #include<algorithm> #include<cmath> #include<string_view> #include"serif/discretization/blocks/fields.hpp" #include"serif/equations/point.hpp" #include"serif/equations/rigid_rotation.hpp" #include"serif/utils/error/errors.hpp" namespaceserif::equations{ //Sowehadapreviousversionofthiscodewhichhadroughly20klinesofbespokeoperatorsforeachequation //downthatrouteliemadnesseh? //Wehavetriedtomakethisproductionversionfarmoregeneric.HydrostaticEquilibriumhereisauseful //testcasesinceitsonthesimplerside(beingascalarvaluedthing) classBarotropicHydrostaticEquilibriumfinal{ public: usingTest=discretization::blocks::enthalpy::specific; usingResidualQuantity=dimensions::SpecificEnthalpy; usingPotential=discretization::blocks::gravity::potential; usingConstant=discretization::blocks::barotropic_constant::mass_normalization; usingAngularVelocity=discretization::blocks::rotation::angular_velocity; usingOperands=utils::types::TypeList< discretization::forms::Operand<Test>, discretization::forms::Operand<Potential>, discretization::forms::Operand<Constant>, discretization::forms::Operand<AngularVelocity> >; staticconstexprstd::string_viewname="hydrostaticequilibrium"; explicitBarotropicHydrostaticEquilibrium( constRigidRotation::Vector&axis={0.0,0.0,1.0}, constRigidRotation::Vector&center={} ): m_rotation(RigidRotation::unit_rotation(axis,center)){} [[nodiscard]]PointLinearization<Operands>evaluate(constEquationPoint<Operands>&point)const{ PointLinearization<Operands>result; constdoubleomega=point.fields.get<AngularVelocity>(); constdoubleomega_squared=omega*omega; //Belowthereissomelevelofmaybewierd(thoughnotawfulinthecontextofthelanguage)C++syntax.Weneedtogetaccesstothecorrect //fieldvaluesinatypesafemanner,theyaretuplessoweusethegetmethodwiththe //typeswealiasedatthetopofthisclass.Atotherpointsinthecodeyoumayseesomethinglike //point.fields.templateget<Test>()whichisabitmoreverbosebutisthesamething.Thetemplatekeywordisrequiredinthatcasebecause //therearecaseswherethereisanambiguitybetweenatemplateandacomparatoroperator(e.g.<)(Ithinkthisisthereason,franklyI'venever //reallysorteditout,Igenerallywritethe.templateversionandthemmyIDEtellsmethetemplateisnotneededsometimes...) //Hereiswhereweimplementtheresidual,thisisdirectlyfromthederivationabove result.residual=point.fields.templateget<Test>()+point.fields.get<Potential>()-omega_squared*m_rotation.centrifugal_potential(point.position)-point.fields.get<Constant>(); result.field_derivatives.get<Test>()=1.0; result.field_derivatives.get<Potential>()=1.0; result.field_derivatives.get<Constant>()=-1.0; result.field_derivatives.get<AngularVelocity>()=-2.0*omega*m_rotation.centrifugal_potential(point.position); result.position_derivative=m_rotation.centrifugal_potential_gradient(point.position); for(double&component:result.position_derivative){component*=-omega_squared;} returnresult; } template<typenameOperandT> [[nodiscard]]intadditional_order(OperandT,intposition_order)const{ ifconstexpr(discretization::blocks::HasFunctionalSpace<typename OperandT::term_type>){ returnstd::max(0,2*position_order-OperandT::term_type::FunctionalSpace::order); }else{ return2*position_order; } } private: RigidRotationm_rotation; }; }//namespaceserif::equations