SpECTRE  v2025.03.17
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
domain::CoordinateMaps::FocallyLiftedMapHelpers Namespace Reference

Holds helper functions for use with domain::CoordinateMaps::FocallyLiftedMap. More...

Functions

template<typename T >
void scale_factor (const gsl::not_null< tt::remove_cvref_wrap_t< T > * > &result, const std::array< T, 3 > &src_point, const std::array< double, 3 > &proj_center, const std::array< double, 3 > &sphere_center, double radius, bool src_is_between_proj_and_target)
 Finds how long to extend a line segment to have it intersect a point on a 2-sphere. More...
 
std::optional< double > try_scale_factor (const std::array< double, 3 > &src_point, const std::array< double, 3 > &proj_center, const std::array< double, 3 > &sphere_center, double radius, bool pick_larger_root, bool pick_root_greater_than_one, bool solve_for_root_minus_one=true)
 
template<typename T >
void d_scale_factor_d_src_point (const gsl::not_null< std::array< tt::remove_cvref_wrap_t< T >, 3 > * > &result, const std::array< T, 3 > &intersection_point, const std::array< double, 3 > &proj_center, const std::array< double, 3 > &sphere_center, const T &lambda)
 

Detailed Description

Holds helper functions for use with domain::CoordinateMaps::FocallyLiftedMap.

Function Documentation

◆ d_scale_factor_d_src_point()

template<typename T >
void domain::CoordinateMaps::FocallyLiftedMapHelpers::d_scale_factor_d_src_point ( const gsl::not_null< std::array< tt::remove_cvref_wrap_t< T >, 3 > * > &  result,
const std::array< T, 3 > &  intersection_point,
const std::array< double, 3 > &  proj_center,
const std::array< double, 3 > &  sphere_center,
const T &  lambda 
)

Computes λ/x0i, where λ is the quantity returned by scale_factor and x_0 is src_point in the scale_factor function.

The formula (see FocallyLiftedMap) is

λx0j=λ2Cjx1j|x1iPi|2+(x1iPi)(PiCi).

Note that it takes intersection_point and not src_point as a parameter.

In the arguments to the function below, intersection_point is x1, proj_center is Pi, sphere_center is Ci, and radius is R.

◆ scale_factor()

template<typename T >
void domain::CoordinateMaps::FocallyLiftedMapHelpers::scale_factor ( const gsl::not_null< tt::remove_cvref_wrap_t< T > * > &  result,
const std::array< T, 3 > &  src_point,
const std::array< double, 3 > &  proj_center,
const std::array< double, 3 > &  sphere_center,
double  radius,
bool  src_is_between_proj_and_target 
)

Finds how long to extend a line segment to have it intersect a point on a 2-sphere.

Details

Consider a 2-sphere with center Ci and radius R, and and let Pi and x0i be two arbitrary 3D points.

Consider the line passing through Pi and x0i. If this line intersects the sphere at a point x1i, then we can write

x1i=Pi+(x0iPi)λ,

where λ is a scale factor.

scale_factor computes and returns λ.

Even more detail:

To solve for λ, we note that x1i is on the surface of the sphere, so

|x1iCi|2=R2,

(where |Ai|2 means δijAiAj),

or equivalently

|PiCi+(x0iPi)λ|2=R2.

This is a quadratic equation for λ and it generally has more than one real root. It takes the usual form aλ2+bλ+c=0, with

a=|x0iPi|2,b=2(x0iPi)(PjCj)δij,c=|PiCi|2R2,

So how do we choose between multiple roots? Some of the maps that use scale_factor assume that for all points, x0i is between Pi and x1i. Those maps should set the parameter src_is_between_proj_and_target to true. Other maps assume that for all points, xi is always between x0i and Pi. Those maps should set the parameter src_is_between_proj_and_target to false.

Warning
If we ever add maps where src_is_between_proj_and_target can change from point to point, the logic of scale_factor needs to be changed.

In the arguments to the function below, src_point is x0i, proj_center is Pi, sphere_center is Ci, and radius is R.

◆ try_scale_factor()

std::optional< double > domain::CoordinateMaps::FocallyLiftedMapHelpers::try_scale_factor ( const std::array< double, 3 > &  src_point,
const std::array< double, 3 > &  proj_center,
const std::array< double, 3 > &  sphere_center,
double  radius,
bool  pick_larger_root,
bool  pick_root_greater_than_one,
bool  solve_for_root_minus_one = true 
)

Solves a problem of the same form as scale_factor, but is used only by the inverse function to compute λ~ and λ¯. try_scale_factor is used in two contexts:

try_scale_factor is used to determine λ¯ given xi. λ¯ is defined by

x1i=Pi+(xiPi)λ¯.

try_scale_factor is used by the lambda_tilde functions of some of the InnerMap classes (namely those InnerMap classes where x0i is a spherical surface) to solve for λ~ given xi. λ~ is defined by

x0i=Pi+(xiPi)λ~.

In both of these contexts, the input parameter src_point is xi, a point that is supposed to be in the range of the FocallyLiftedMap. Because the inverse function can be and is called for an arbitrary xi that might not be in the range of the FocallyLiftedMap, try_scale_factor returns a std::optional, with a default-constructed std::optional if the roots it finds are not as expected (i.e. if the inverse map was called for a point not in the range of the map).

Because try_scale_factor can be called in different situations, it has additional boolean arguments pick_larger_root and pick_root_greater_than_one that allow the caller to choose which root to return.

Furthermore, to reduce roundoff errors near λ~=1, the default behavior is to solve the quadratic equation for λ~1 (and then add 1 to the solution). If instead one wants to solve the quadratic equation directly for λ~ so as to obtain slightly different roundoff behavior, then one should specify the argument solve_for_root_minus_one to be false.

try_scale_factor is not templated on type because it is used only by the inverse function, which works only on doubles.