Skip to content

Commit

Permalink
Create a JacobianInverse operator
Browse files Browse the repository at this point in the history
Create an `InverseJacobianMatrix` operator. This operator removes the need for the remaining inheritance of jacobian. Closes #410 .

See merge request gysela-developpers/gyselalibxx!782

--------------------------------------------
  • Loading branch information
EmilyBourne committed Nov 25, 2024
1 parent dffd882 commit b6800fa
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 350 deletions.
10 changes: 5 additions & 5 deletions src/geometryRTheta/advection_field/advection_field_rp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class AdvectionFieldFinder
* The parameter @f$ \varepsilon @f$ for the linearization of the
* electric field.
*/
AdvectionFieldFinder(Mapping const& mapping, double const epsilon = 1e-12)
explicit AdvectionFieldFinder(Mapping const& mapping, double const epsilon = 1e-12)
: m_mapping(mapping)
, m_polar_spline_evaluator(ddc::NullExtrapolationRule())
, m_spline_evaluator {ddc::NullExtrapolationRule(), ddc::NullExtrapolationRule(), ddc::PeriodicExtrapolationRule<Theta>(), ddc::PeriodicExtrapolationRule<Theta>()}
Expand Down Expand Up @@ -245,6 +245,8 @@ class AdvectionFieldFinder
get_const_field(coords),
get_const_field(electrostatic_potential_coef));

InverseJacobianMatrix<Mapping, CoordRTheta> inv_jacobian_matrix(m_mapping);

// > computation of the electric field
ddc::for_each(grid, [&](IdxRTheta const irp) {
double const r = ddc::coordinate(ddc::select<GridR>(irp));
Expand All @@ -253,8 +255,7 @@ class AdvectionFieldFinder
if (r > m_epsilon) {
CoordRTheta const coord_rp(r, th);

Matrix_2x2 inv_J; // Inverse Jacobian matrix
m_mapping.inv_jacobian_matrix(coord_rp, inv_J);
Matrix_2x2 inv_J = inv_jacobian_matrix(coord_rp);

// Gradiant of phi in the physical index range (Cartesian index range)
double const deriv_x_phi
Expand Down Expand Up @@ -304,8 +305,7 @@ class AdvectionFieldFinder
// --- Value at r = m_epsilon:
CoordRTheta const coord_rp_epsilon(m_epsilon, th);

Matrix_2x2 inv_J_eps; // Jacobian matrix
m_mapping.inv_jacobian_matrix(coord_rp_epsilon, inv_J_eps);
Matrix_2x2 inv_J_eps = inv_jacobian_matrix(coord_rp_epsilon);

double const deriv_r_phi_epsilon = evaluator.deriv_dim_1(
coord_rp_epsilon,
Expand Down
12 changes: 6 additions & 6 deletions tests/geometryRTheta/polar_poisson/test_cases.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ class CurvilinearSolution : public PoissonSolution<CurvilinearToCartesian>
template <class CurvilinearToCartesian>
class CartesianSolution : public PoissonSolution<CurvilinearToCartesian>
{
private:
InverseJacobianMatrix<CurvilinearToCartesian, Coord<R, Theta>> m_inverse_jacobian;

public:
/**
* @brief Instantiate a CartesianSolution.
Expand All @@ -126,6 +129,7 @@ class CartesianSolution : public PoissonSolution<CurvilinearToCartesian>
*/
explicit CartesianSolution(CurvilinearToCartesian const& coordinate_converter)
: PoissonSolution<CurvilinearToCartesian>(coordinate_converter)
, m_inverse_jacobian(coordinate_converter)
{
}

Expand Down Expand Up @@ -156,9 +160,7 @@ class CartesianSolution : public PoissonSolution<CurvilinearToCartesian>
const double y = ddc::get<Y>(cart_coord);

const double r = ddc::get<R>(coord);
const double dx_r
= PoissonSolution<CurvilinearToCartesian>::m_coordinate_converter.inv_jacobian_11(
coord);
const double dx_r = m_inverse_jacobian.inv_jacobian_11(coord);

const double C = 1e-4 * ipow(2., 12);
return C * std::sin(2 * M_PI * y)
Expand All @@ -182,9 +184,7 @@ class CartesianSolution : public PoissonSolution<CurvilinearToCartesian>
const double y = ddc::get<Y>(cart_coord);

const double r = ddc::get<R>(coord);
const double dy_r
= PoissonSolution<CurvilinearToCartesian>::m_coordinate_converter.inv_jacobian_12(
coord);
const double dy_r = m_inverse_jacobian.inv_jacobian_12(coord);

const double C = 1e-4 * ipow(2., 12);
return C * std::cos(2 * M_PI * x)
Expand Down
20 changes: 14 additions & 6 deletions vendor/sll/include/sll/mapping/cartesian_to_pseudo_cartesian.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

#include <sll/view.hpp>

#include "inverse_jacobian_matrix.hpp"
#include "mapping_tools.hpp"

/**
* @brief A class describing a mapping from a Cartesian domain to a pseudo-Cartesian.
* This operation is carried out using 2 curvilinear to Cartesian mappings.
Expand Down Expand Up @@ -48,6 +51,11 @@ class CartesianToPseudoCartesian
using Theta = typename MappingToCartesian::curvilinear_tag_theta;
using CoordRTheta = ddc::Coordinate<R, Theta>;

static_assert(is_2d_mapping_v<MappingToCartesian>);
static_assert(is_2d_mapping_v<MappingToPseudoCartesian>);
static_assert(has_2d_jacobian_v<MappingToCartesian, CoordRTheta>);
static_assert(has_2d_jacobian_v<MappingToPseudoCartesian, CoordRTheta>);

private:
MappingToCartesian m_mapping_to_cartesian;
MappingToPseudoCartesian m_mapping_to_pseudo_cartesian;
Expand Down Expand Up @@ -91,13 +99,14 @@ class CartesianToPseudoCartesian

Matrix_2x2 inv_jacobian_from_cartesian;
Matrix_2x2 jacobian_from_pseudo_cartesian;
InverseJacobianMatrix inv_jacobian_cartesian(m_mapping_to_cartesian);
if (r < m_epsilon) {
Matrix_2x2 J_0;
m_mapping_to_cartesian.to_pseudo_cartesian_jacobian_center_matrix(J_0);

CoordRTheta coord_eps(m_epsilon, ddc::get<Theta>(coord_rtheta));

m_mapping_to_cartesian.inv_jacobian_matrix(coord_eps, inv_jacobian_from_cartesian);
inv_jacobian_from_cartesian = inv_jacobian_cartesian(coord_eps);
m_mapping_to_pseudo_cartesian
.jacobian_matrix(coord_eps, jacobian_from_pseudo_cartesian);
Matrix_2x2 J_eps = mat_mul(jacobian_from_pseudo_cartesian, inv_jacobian_from_cartesian);
Expand All @@ -107,7 +116,7 @@ class CartesianToPseudoCartesian
J[1][0] = (1 - r / m_epsilon) * J_0[1][0] + r / m_epsilon * J_eps[1][0];
J[1][1] = (1 - r / m_epsilon) * J_0[1][1] + r / m_epsilon * J_eps[1][1];
} else {
m_mapping_to_cartesian.inv_jacobian_matrix(coord_rtheta, inv_jacobian_from_cartesian);
inv_jacobian_from_cartesian = inv_jacobian_cartesian(coord_rtheta);
m_mapping_to_pseudo_cartesian
.jacobian_matrix(coord_rtheta, jacobian_from_pseudo_cartesian);
J = mat_mul(jacobian_from_pseudo_cartesian, inv_jacobian_from_cartesian);
Expand Down Expand Up @@ -198,6 +207,7 @@ class CartesianToPseudoCartesian

Matrix_2x2 jacobian_from_cartesian;
Matrix_2x2 inv_jacobian_from_pseudo_cartesian;
InverseJacobianMatrix inv_jacobian_pseudo_cartesian(m_mapping_to_pseudo_cartesian);
if (r < m_epsilon) {
Matrix_2x2 J_0;
m_mapping_to_cartesian.to_pseudo_cartesian_jacobian_center_matrix(J_0);
Expand All @@ -206,8 +216,7 @@ class CartesianToPseudoCartesian
CoordRTheta coord_eps(m_epsilon, ddc::get<Theta>(coord_rtheta));

m_mapping_to_cartesian.jacobian_matrix(coord_eps, jacobian_from_cartesian);
m_mapping_to_pseudo_cartesian
.inv_jacobian_matrix(coord_eps, inv_jacobian_from_pseudo_cartesian);
inv_jacobian_from_pseudo_cartesian = inv_jacobian_pseudo_cartesian(coord_eps);
Matrix_2x2 J_eps = mat_mul(inv_jacobian_from_pseudo_cartesian, jacobian_from_cartesian);

J[0][0] = (1 - r / m_epsilon) * J_0_inv[0][0] + r / m_epsilon * J_eps[0][0];
Expand All @@ -216,8 +225,7 @@ class CartesianToPseudoCartesian
J[1][1] = (1 - r / m_epsilon) * J_0_inv[1][1] + r / m_epsilon * J_eps[1][1];
} else {
m_mapping_to_cartesian.jacobian_matrix(coord_rtheta, jacobian_from_cartesian);
m_mapping_to_pseudo_cartesian
.inv_jacobian_matrix(coord_rtheta, inv_jacobian_from_pseudo_cartesian);
inv_jacobian_from_pseudo_cartesian = inv_jacobian_pseudo_cartesian(coord_rtheta);
J = mat_mul(jacobian_from_cartesian, inv_jacobian_from_pseudo_cartesian);
}
}
Expand Down
28 changes: 21 additions & 7 deletions vendor/sll/include/sll/mapping/discrete_to_cartesian.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

#include <ddc/ddc.hpp>

#include <sll/math_tools.hpp>
#include <sll/view.hpp>

#include "coordinate_converter.hpp"
#include "curvilinear2d_to_cartesian.hpp"
#include "jacobian.hpp"
#include "mapping_tools.hpp"
#include "pseudo_cartesian_compatible_mapping.hpp"

Expand All @@ -35,7 +35,6 @@ template <
class MemorySpace = typename SplineEvaluator::memory_space>
class DiscreteToCartesian
: public CoordinateConverter<ddc::Coordinate<R, Theta>, ddc::Coordinate<X, Y>>
, public NonAnalyticalJacobian<ddc::Coordinate<R, Theta>>
, public PseudoCartesianCompatibleMapping
, public Curvilinear2DToCartesian<X, Y, R, Theta>
{
Expand Down Expand Up @@ -166,7 +165,7 @@ class DiscreteToCartesian
*/
KOKKOS_FUNCTION void jacobian_matrix(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord,
Matrix_2x2& matrix) const final
Matrix_2x2& matrix) const
{
matrix[0][0]
= m_spline_evaluator.deriv_dim_1(coord, m_x_spline_representation.span_cview());
Expand Down Expand Up @@ -195,7 +194,7 @@ class DiscreteToCartesian
* @see SplineEvaluator2D
*/
KOKKOS_FUNCTION double jacobian_11(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const final
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const
{
return m_spline_evaluator.deriv_dim_1(coord, m_x_spline_representation.span_cview());
}
Expand All @@ -217,7 +216,7 @@ class DiscreteToCartesian
* @see SplineEvaluator2D
*/
KOKKOS_FUNCTION double jacobian_12(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const final
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const
{
return m_spline_evaluator.deriv_dim_2(coord, m_x_spline_representation.span_cview());
}
Expand All @@ -239,7 +238,7 @@ class DiscreteToCartesian
* @see SplineEvaluator2D
*/
KOKKOS_FUNCTION double jacobian_21(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const final
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const
{
return m_spline_evaluator.deriv_dim_1(coord, m_y_spline_representation.span_cview());
}
Expand All @@ -261,11 +260,26 @@ class DiscreteToCartesian
* @see SplineEvaluator2D
*/
KOKKOS_FUNCTION double jacobian_22(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const final
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const
{
return m_spline_evaluator.deriv_dim_2(coord, m_y_spline_representation.span_cview());
}

/**
* @brief Compute the Jacobian, the determinant of the Jacobian matrix of the mapping.
*
* @param[in] coord
* The coordinate where we evaluate the Jacobian.
*
* @return A double with the value of the determinant of the Jacobian matrix.
*/
KOKKOS_FUNCTION double jacobian(
ddc::Coordinate<curvilinear_tag_r, curvilinear_tag_theta> const& coord) const
{
Matrix_2x2 J;
jacobian_matrix(coord, J);
return determinant(J);
}


/**
Expand Down
148 changes: 148 additions & 0 deletions vendor/sll/include/sll/mapping/inverse_jacobian_matrix.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// SPDX-License-Identifier: MIT
#pragma once

#include <sll/view.hpp>

#include "mapping_tools.hpp"

/**
* A class to calculate the inverse of the Jacobian matrix.
* If specialised methods are available then these are used by the class.
* Otherwise the inverse is calculated from the Jacobian matrix.
*
* @tparam Mapping The mapping whose inverse we are interested in.
* @tparam PositionCoordinate The coordinate system in which the inverse should be calculated.
*/
template <class Mapping, class PositionCoordinate = typename Mapping::CoordArg>
class InverseJacobianMatrix
{
private:
Mapping m_mapping;

public:
/**
* @brief A constructor for the InverseJacobianMatrix.
* @param[in] mapping The mapping whose inverse we are interested in.
*/
KOKKOS_FUNCTION explicit InverseJacobianMatrix(Mapping const& mapping) : m_mapping(mapping) {}

/**
* @brief Compute full inverse Jacobian matrix.
*
* For some computations, we need the complete inverse Jacobian matrix or just the
* coefficients.
* The coefficients can be given indendently with the functions
* inv_jacobian_11, inv_jacobian_12, inv_jacobian_21 and inv_jacobian_22.
*
* @param[in] coord The coordinate where we evaluate the Jacobian matrix.
* @returns The inverse Jacobian matrix returned.
*
* @see inv_jacobian_11
* @see inv_jacobian_12
* @see inv_jacobian_21
* @see inv_jacobian_22
*/
KOKKOS_INLINE_FUNCTION Matrix_2x2 operator()(PositionCoordinate const& coord) const
{
Matrix_2x2 matrix;
if constexpr (has_2d_inv_jacobian_v<Mapping, PositionCoordinate>) {
m_mapping.inv_jacobian_matrix(coord, matrix);
} else {
static_assert(has_2d_jacobian_v<Mapping, PositionCoordinate>);
double jacob = m_mapping.jacobian(coord);
assert(fabs(jacob) > 1e-15);
matrix[0][0] = m_mapping.jacobian_22(coord) / jacob;
matrix[0][1] = -m_mapping.jacobian_12(coord) / jacob;
matrix[1][0] = -m_mapping.jacobian_21(coord) / jacob;
matrix[1][1] = m_mapping.jacobian_11(coord) / jacob;
}
return matrix;
}

/**
* @brief Compute the (1,1) coefficient of the inverse Jacobian matrix.
*
* Be careful because not all mappings are invertible, especially at the center point.
*
* @param[in] coord
* The coordinate where we evaluate the inverse Jacobian matrix.
*
* @return A double with the value of the (1,1) coefficient of the inverse Jacobian matrix.
*/
KOKKOS_INLINE_FUNCTION double inv_jacobian_11(PositionCoordinate const& coord) const
{
if constexpr (has_2d_inv_jacobian_v<Mapping, PositionCoordinate>) {
return m_mapping.inv_jacobian_11(coord);
} else {
static_assert(has_2d_jacobian_v<Mapping, PositionCoordinate>);
double jacob = m_mapping.jacobian(coord);
assert(fabs(jacob) > 1e-15);
return m_mapping.jacobian_22(coord) / jacob;
}
}

/**
* @brief Compute the (1,2) coefficient of the inverse Jacobian matrix.
*
* Be careful because not all mappings are invertible, especially at the center point.
*
* @param[in] coord
* The coordinate where we evaluate the inverse Jacobian matrix.
*
* @return A double with the value of the (1,2) coefficient of the inverse Jacobian matrix.
*/
KOKKOS_INLINE_FUNCTION double inv_jacobian_12(PositionCoordinate const& coord) const
{
if constexpr (has_2d_inv_jacobian_v<Mapping, PositionCoordinate>) {
return m_mapping.inv_jacobian_12(coord);
} else {
static_assert(has_2d_jacobian_v<Mapping, PositionCoordinate>);
double jacob = m_mapping.jacobian(coord);
assert(fabs(jacob) > 1e-15);
return -m_mapping.jacobian_12(coord) / jacob;
}
}
/**
* @brief Compute the (2,1) coefficient of the inverse Jacobian matrix.
*
* Be careful because not all mappings are invertible, especially at the center point.
*
* @param[in] coord
* The coordinate where we evaluate the inverse Jacobian matrix.
*
* @return A double with the value of the (2,1) coefficient of the inverse Jacobian matrix.
*/
KOKKOS_INLINE_FUNCTION double inv_jacobian_21(PositionCoordinate const& coord) const
{
if constexpr (has_2d_inv_jacobian_v<Mapping, PositionCoordinate>) {
return m_mapping.inv_jacobian_21(coord);
} else {
static_assert(has_2d_jacobian_v<Mapping, PositionCoordinate>);
double jacob = m_mapping.jacobian(coord);
assert(fabs(jacob) > 1e-15);
return -m_mapping.jacobian_21(coord) / jacob;
}
}

/**
* @brief Compute the (2,2) coefficient of the inverse Jacobian matrix.
*
* Be careful because not all mappings are invertible, especially at the center point.
*
* @param[in] coord
* The coordinate where we evaluate the inverse Jacobian matrix.
*
* @return A double with the value of the (2,2) coefficient of the inverse Jacobian matrix.
*/
KOKKOS_INLINE_FUNCTION double inv_jacobian_22(PositionCoordinate const& coord) const
{
if constexpr (has_2d_inv_jacobian_v<Mapping, PositionCoordinate>) {
return m_mapping.inv_jacobian_22(coord);
} else {
static_assert(has_2d_jacobian_v<Mapping, PositionCoordinate>);
double jacob = m_mapping.jacobian(coord);
assert(fabs(jacob) > 1e-15);
return m_mapping.jacobian_11(coord) / jacob;
}
}
};
Loading

0 comments on commit b6800fa

Please sign in to comment.