radial_extension.cpp algorithm cmath limits utility serif/geometry/deformation/radial_extension.hpp serif/geometry/deformation/detail/action_storage.hpp serif serif::geometry serif::geometry::deformation #include<algorithm> #include<cmath> #include<limits> #include<utility> #include"serif/geometry/deformation/radial_extension.hpp" #include"serif/geometry/deformation/detail/action_storage.hpp" namespaceserif::geometry::deformation { RadialExtension::RadialExtension(std::shared_ptr<constRadialInterpolation>interpolation,std::vector<double>radial_weights) :m_interpolation(std::move(interpolation)),m_radial_weights(std::move(radial_weights)) { } DeformationStatusRadialExtension::apply(std::span<constdouble>surface_displacement,std::span<double>volume_displacement,Workspace)const { constDeformationStatusstatus=detail::validate_action_arguments(volume_displacement,output_size(),{{surface_displacement,input_size()}}); if(!status) { returnstatus; } std::fill(volume_displacement.begin(),volume_displacement.end(),0.0); conststd::size_tcount=m_radial_weights.size(); constRadialInterpolationData&reference=m_interpolation->data(); for(std::size_tnode=0;node<count;++node) { if(m_radial_weights[node]==0.0) { continue; } for(std::size_tcomponent=0;component<3;++component) { doublevalue=0.0; for(intentry=reference.row_offsets[node];entry<reference.row_offsets[node+1];++entry) { value+=reference.interpolation_weights[entry]*surface_displacement[3*reference.surface_columns[entry]+component]; } volume_displacement[node+component*count]=m_radial_weights[node]*value; } } returnvalidate_deformation_values(volume_displacement,output_size()); } DeformationStatusRadialExtension::apply_transpose(std::span<constdouble>volume_force,std::span<double>surface_force,Workspace)const { constDeformationStatusstatus=detail::validate_action_arguments(surface_force,input_size(),{{volume_force,output_size()}}); if(!status) { returnstatus; } std::fill(surface_force.begin(),surface_force.end(),0.0); conststd::size_tcount=m_radial_weights.size(); constRadialInterpolationData&reference=m_interpolation->data(); for(std::size_tnode=0;node<count;++node) { if(m_radial_weights[node]==0.0) { continue; } for(intentry=reference.row_offsets[node];entry<reference.row_offsets[node+1];++entry) { for(std::size_tcomponent=0;component<3;++component) { surface_force[3*reference.surface_columns[entry]+component]+=m_radial_weights[node]*reference.interpolation_weights[entry]*volume_force[node+component*count]; } } } returnvalidate_deformation_values(surface_force,input_size()); } std::expected<RadialExtension,DeformationFailure>make_radial_extension(std::shared_ptr<constRadialInterpolation>interpolation,PowerLawRadialExtensioninterior,FixedInfinityRadialExtension) { if(!interpolation||!std::isfinite(interior.radial_power)||interior.radial_power<1.0) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::invalid_configuration,.message="Radialextensionrequiresinterpolationdataandafinitestellarpowerofatleastone."}); } constRadialInterpolationData&reference=interpolation->data(); conststd::size_tcount=interpolation->scalar_dof_count(); RadialExtensionresult(std::move(interpolation),std::vector<double>(count,0.0)); for(std::size_tnode=0;node<count;++node) { constdoubleradius=reference.logical_radii[node]; if(reference.stellar_support[node]) { result.m_radial_weights[node]=std::pow(radius/reference.stellar_radius,interior.radial_power); } elseif(reference.vacuum_support[node]) { result.m_radial_weights[node]=(reference.infinity_radius-radius)/(reference.infinity_radius-reference.stellar_radius); } if(!std::isfinite(result.m_radial_weights[node])) { returnstd::unexpected(DeformationFailure{.reason=DeformationFailureReason::non_finite,.message="Aradialextensionweightisnon-finite."}); } //Compilationomitsinterpolationatthefixedcenterusingthissameroundoffthreshold. constdoublecenter_tolerance=64.0*std::numeric_limits<double>::epsilon()*reference.infinity_radius; if(radius<=center_tolerance&&reference.stellar_support[node]) { result.m_radial_weights[node]=0.0; } } returnresult; } }//namespaceserif::geometry::deformation