SpECTRE  v2022.05.05
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.

## ◆ 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 $$\partial \lambda/\partial x_0^i$$, where $$\lambda$$ is the quantity returned by scale_factor and x_0 is src_point in the scale_factor function.

The formula (see FocallyLiftedMap) is

\begin{align*} \frac{\partial\lambda}{\partial x_0^j} &= \lambda^2 \frac{C_j - x_1^j}{|x_1^i - P^i|^2 + (x_1^i - P^i)(P_i - C_i)}. \end{align*}

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

In the arguments to the function below, intersection_point is $$x_1$$, proj_center is $$P^i$$, sphere_center is $$C^i$$, 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 $$C^i$$ and radius $$R$$, and and let $$P^i$$ and $$x_0^i$$ be two arbitrary 3D points.

Consider the line passing through $$P^i$$ and $$x_0^i$$. If this line intersects the sphere at a point $$x_1^i$$, then we can write

$x_1^i = P^i + (x_0^i-P^i) \lambda,$

where $$\lambda$$ is a scale factor.

scale_factor computes and returns $$\lambda$$.

### Even more detail:

To solve for $$\lambda$$, we note that $$x_1^i$$ is on the surface of the sphere, so

$|x_1^i-C^i|^2 = R^2,$

(where $$|A^i|^2$$ means $$\delta_{ij} A^i A^j$$),

or equivalently

$| P^i-C^i + (x_0^i-P^i)\lambda |^2 = R^2.$

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

\begin{align*} a &= |x_0^i-P^i|^2,\\ b &= 2(x_0^i-P^i)(P^j-C^j)\delta_{ij},\\ c &= |P^i-C^i|^2 - R^2, \end{align*}

So how do we choose between multiple roots? Some of the maps that use scale_factor assume that for all points, $$x_0^i$$ is between $$P^i$$ and $$x_1^i$$. Those maps should set the parameter src_is_between_proj_and_target to true. Other maps assume that for all points, $$x^i$$ is always between $$x_0^i$$ and $$P^i$$. 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 $$x_0^i$$, proj_center is $$P^i$$, sphere_center is $$C^i$$, 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 $$\tilde{\lambda}$$ and $$\bar{\lambda}$$. try_scale_factor is used in two contexts:

try_scale_factor is used to determine $$\bar{\lambda}$$ given $$x^i$$. $$\bar{\lambda}$$ is defined by

\begin{align*} x_1^i = P^i + (x^i - P^i) \bar{\lambda}.\end{align*}

try_scale_factor is used by the lambda_tilde functions of some of the InnerMap classes (namely those InnerMap classes where $$x_0^i$$ is a spherical surface) to solve for $$\tilde{\lambda}$$ given $$x^i$$. $$\tilde{\lambda}$$ is defined by

\begin{align*} x_0^i = P^i + (x^i - P^i) \tilde{\lambda}.\end{align*}

In both of these contexts, the input parameter src_point is $$x^i$$, 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 $$x^i$$ 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 $$\tilde{\lambda}=1$$, the default behavior is to solve the quadratic equation for $$\tilde{\lambda}-1$$ (and then add $$1$$ to the solution). If instead one wants to solve the quadratic equation directly for $$\tilde{\lambda}$$ 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.