polytrope.cpp serif/solver/seed/polytrope.hpp cmath numbers utility serif serif::solver serif::solver::seed #include"serif/solver/seed/polytrope.hpp" #include<cmath> #include<numbers> #include<utility> namespaceserif::solver::seed{ std::expected<RadialSeed,std::string>make_polytropic_seed( consteos::models::Polytrope&equation_of_state,dimensions::MassValuemass,PolytropeOptionsoptions){ constdoublen=equation_of_state.polytropic_index(); if(!std::isfinite(mass.value())||mass.value()<=0.0||!std::isfinite(options.gravitational_constant.value())||options.gravitational_constant.value()<=0.0){ returnstd::unexpected("Apolytropicseedrequiresapositivefinitetargetmassandgravitationalconstant."); } autosolution=utils::laneemden::solve(n,options.integration); if(!solution){ returnstd::unexpected(solution.error()); } if(!solution->surface){ returnstd::unexpected("Afinite-radiusstellarseedrequiresaLane-Emdenfirstzero;chooseafinite-radiusindexandsufficientintegrationextent."); } if(!options.central_density){ if(std::abs(n-3.0)<1.0e-12){ returnstd::unexpected("Ann=3polytrope'smassisindependentofcentraldensity.Specifycentral_densitytochooseitsinitialradius."); } constautounit=utils::laneemden::scale_from_polytropic_constant(*solution,equation_of_state.polytropic_constant(), dimensions::DensityValue{1.0},options.gravitational_constant); if(!unit){ returnstd::unexpected(unit.error()); } constdoubledensity=std::exp((2.0*n/(3.0-n))*std::log(mass.value()/unit->mass.value())); options.central_density=dimensions::DensityValue{density}; } autoscales=utils::laneemden::scale_from_polytropic_constant(*solution,equation_of_state.polytropic_constant(), *options.central_density,options.gravitational_constant); if(!scales){ returnstd::unexpected(scales.error()); } //Anexplicitdensitydefinesaninitialguess,includingatn=3.Itsphysicalmass //neednotequalthemodel'starget;thatprescriptionbelongstotheequilibriumequations. //SimpsonintegrationoftheregulardimensionlessprofileestimatesIfortheinitialrigidrotation. constexprintintervals=2048; constdoublestep=solution->surface->xi/intervals; doubleintegral=0.0; for(intindex=1;index<intervals;++index){ constdoublexi=index*step; constautosample=utils::laneemden::evaluate(*solution,xi); if(!sample){ returnstd::unexpected(sample.error()); } constdoubleweight=index%2==0?2.0:4.0; integral+=weight*std::pow(sample->theta,n)*std::pow(xi,4); } constdoubleinertia=(8.0*std::numbers::pi/3.0)*scales->central_density.value()*std::pow(scales->radial_scale,5)*integral*step/3.0; if(!std::isfinite(inertia)||inertia<=0.0){ returnstd::unexpected("Thesphericalseed'smomentofinertiaisnotfiniteandpositive.Checkthephysicalscales."); } returnRadialSeed{.solution=std::move(*solution),.scales=*scales,.moment_of_inertia=inertia}; } }