-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generalise `Quadrature` class to accept N dimensions. Add a helper function `quadrature_coeffs_nd` to return N-D coefficients from 1D functions defining the quadrature along each of the dimensions.
- Loading branch information
1 parent
2eb59aa
commit 27b6bb3
Showing
9 changed files
with
298 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,7 +118,7 @@ jobs: | |
git add . | ||
git config --global user.name "GitHub CI Documentation builder" | ||
git config --global user.email "[email protected]" | ||
git commit -m "Update docs" | ||
git commit -m "Update docs" || true | ||
git push | ||
shell: bash | ||
env: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Quadrature Methods | ||
|
||
Quadrature methods are methods for calculating the integral of a function from its value at a given set of points $p_1, ..., p_n$. | ||
These methods can be written as a scalar product of the value of the function at the points $f(p_1), ..., f(p_n)$, with the quadrature coefficients $q_1, ..., q_n$. | ||
|
||
This folder provides the class Quadrature which integrates a function from its values at the points defined by the discrete domain(s) on which the class is defined. | ||
The class should be initialised with the quadrature coefficients. | ||
|
||
Helper functions provide the quadrature coefficients obtained using different quadrature methods. | ||
The methods currently implemented are: | ||
- trapezoid_quadrature_coefficients() | ||
|
||
|
||
Additionally the function quadrature_coeffs_nd() helps define multi-dimensional quadrature methods from 1D methods. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// SPDX-License-Identifier: MIT | ||
/** | ||
* @file quadrature_coeffs_nd.hpp | ||
* File providing helper functions for defining multi-dimensional quadrature methods. | ||
*/ | ||
#pragma once | ||
|
||
|
||
/** | ||
* @brief Helper function which creates ND dimensions from N 1D quadrature coefficient functions. | ||
* | ||
* @param domain | ||
* The domain on which the coefficients will be defined. | ||
* @param func | ||
* The function which defines quadrature coefficients in the first dimension. | ||
* @param o_funcs | ||
* The functions which define quadrature coefficients in the subsequent dimensions. | ||
* | ||
* @returns The coefficients which define the quadrature method in ND. | ||
*/ | ||
template <class IDim, class... ODims> | ||
ddc::Chunk<double, ddc::DiscreteDomain<IDim, ODims...>> quadrature_coeffs_nd( | ||
ddc::DiscreteDomain<IDim, ODims...> const& domain, | ||
std::function<ddc::Chunk<double, ddc::DiscreteDomain<IDim>>(ddc::DiscreteDomain<IDim>)> | ||
func, | ||
std::function<ddc::Chunk<double, ddc::DiscreteDomain<ODims>>( | ||
ddc::DiscreteDomain<ODims>)>... o_funcs) | ||
{ | ||
// Get domains | ||
ddc::DiscreteDomain<IDim> const current_dim_domain = ddc::select<IDim>(domain); | ||
ddc::DiscreteDomain<ODims...> const other_dims_domain = ddc::select<ODims...>(domain); | ||
|
||
// Get coefficients in the first dimension | ||
ddc::Chunk<double, ddc::DiscreteDomain<IDim>> current_dim_coeffs = func(current_dim_domain); | ||
// Get coefficients over all other dimensions | ||
ddc::Chunk<double, ddc::DiscreteDomain<ODims...>> other_dim_coeffs | ||
= quadrature_coeffs_nd(other_dims_domain, o_funcs...); | ||
|
||
using DElemC = ddc::DiscreteElement<IDim>; | ||
using DElemO = ddc::DiscreteElement<ODims...>; | ||
|
||
// Calculate the combined coefficients over all dimensions | ||
ddc::Chunk<double, ddc::DiscreteDomain<IDim, ODims...>> coefficients(domain); | ||
|
||
ddc::for_each(current_dim_domain, [&](DElemC const idim) { | ||
ddc::for_each(other_dims_domain, [&](DElemO const odim) { | ||
coefficients(idim, odim) = current_dim_coeffs(idim) * other_dim_coeffs(odim); | ||
}); | ||
}); | ||
|
||
return coefficients; | ||
} | ||
|
||
/** | ||
* @brief Specialised 1D version of quadrature_coeffs_nd<IDim, ODims...>. | ||
* | ||
* @param domain | ||
* The domain on which the coefficients will be defined. | ||
* @param func | ||
* The function which defines quadrature coefficients. | ||
* | ||
* @returns The coefficients which define the quadrature method in 1D. | ||
*/ | ||
#include <ddc/ddc.hpp> | ||
template <class IDim> | ||
ddc::Chunk<double, ddc::DiscreteDomain<IDim>> quadrature_coeffs_nd( | ||
ddc::DiscreteDomain<IDim> const& domain, | ||
std::function<ddc::Chunk<double, ddc::DiscreteDomain<IDim>>(ddc::DiscreteDomain<IDim>)> | ||
func) | ||
{ | ||
return func(domain); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
#include <sll/bsplines_non_uniform.hpp> | ||
|
||
#include <gmock/gmock.h> | ||
#include <gtest/gtest.h> | ||
|
||
#include "geometry.hpp" | ||
#include "quadrature.hpp" | ||
#include "trapezoid_quadrature.hpp" | ||
|
||
TEST(QuadratureTest, ExactForConstantFunc) | ||
{ | ||
CoordX const x_min(0.0); | ||
CoordX const x_max(M_PI); | ||
IVectX const x_size(10); | ||
|
||
CoordY const y_min(0.0); | ||
CoordY const y_max(20.0); | ||
IVectY const y_size(10); | ||
|
||
// Creating mesh & supports | ||
ddc::init_discrete_space<BSplinesX>(x_min, x_max, x_size); | ||
ddc::init_discrete_space<BSplinesY>(y_min, y_max, y_size); | ||
|
||
ddc::init_discrete_space<IDimX>(SplineInterpPointsX::get_sampling()); | ||
ddc::init_discrete_space<IDimY>(SplineInterpPointsY::get_sampling()); | ||
|
||
IDomainX const gridx(SplineInterpPointsX::get_domain()); | ||
IDomainY const gridy(SplineInterpPointsY::get_domain()); | ||
|
||
IDomainXY const gridxy(gridx, gridy); | ||
|
||
Quadrature<IDimX, IDimY> const integrate(trapezoid_quadrature_coefficients(gridxy)); | ||
|
||
DFieldXY values(gridxy); | ||
|
||
ddc::for_each(gridxy, [&](ddc::DiscreteElement<IDimX, IDimY> const idx) { values(idx) = 1.0; }); | ||
double integral = integrate(values); | ||
double expected_val = (x_max - x_min) * (y_max - y_min); | ||
EXPECT_LE(abs(integral - expected_val), 1e-9); | ||
} | ||
|
||
template <std::size_t N> | ||
struct X | ||
{ | ||
static bool constexpr PERIODIC = false; | ||
}; | ||
|
||
template <std::size_t N> | ||
struct Y | ||
{ | ||
static bool constexpr PERIODIC = false; | ||
}; | ||
|
||
template <std::size_t N> | ||
double compute_error(int n_elems) | ||
{ | ||
using DimX = X<N>; | ||
using DimY = Y<N>; | ||
using BSplinesX = UniformBSplines<DimX, 3>; | ||
using BSplinesY = UniformBSplines<DimY, 3>; | ||
using GrevillePointsX | ||
= GrevilleInterpolationPoints<BSplinesX, BoundCond::GREVILLE, BoundCond::GREVILLE>; | ||
using GrevillePointsY | ||
= GrevilleInterpolationPoints<BSplinesY, BoundCond::GREVILLE, BoundCond::GREVILLE>; | ||
using IDimX = typename GrevillePointsX::interpolation_mesh_type; | ||
using IDimY = typename GrevillePointsY::interpolation_mesh_type; | ||
using IDomainX = ddc::DiscreteDomain<IDimX>; | ||
using IDomainY = ddc::DiscreteDomain<IDimY>; | ||
using IDomainXY = ddc::DiscreteDomain<IDimX, IDimY>; | ||
using DFieldXY = ddc::Chunk<double, IDomainXY>; | ||
|
||
ddc::Coordinate<DimX> const x_min(0.0); | ||
ddc::Coordinate<DimX> const x_max(M_PI); | ||
|
||
ddc::Coordinate<DimY> const y_min(0.0); | ||
ddc::Coordinate<DimY> const y_max(M_PI); | ||
|
||
ddc::init_discrete_space<BSplinesX>(x_min, x_max, n_elems); | ||
ddc::init_discrete_space<BSplinesY>(y_min, y_max, n_elems); | ||
|
||
ddc::init_discrete_space<IDimX>(GrevillePointsX::get_sampling()); | ||
ddc::init_discrete_space<IDimY>(GrevillePointsY::get_sampling()); | ||
IDomainX const gridx(GrevillePointsX::get_domain()); | ||
IDomainY const gridy(GrevillePointsY::get_domain()); | ||
IDomainXY const gridxy(gridx, gridy); | ||
|
||
Quadrature<IDimX, IDimY> const integrate(trapezoid_quadrature_coefficients(gridxy)); | ||
|
||
DFieldXY values(gridxy); | ||
|
||
ddc::for_each(gridxy, [&](ddc::DiscreteElement<IDimX, IDimY> const idx) { | ||
double const y_cos = cos(ddc::get<DimY>(ddc::coordinate(idx))); | ||
values(idx) = sin(ddc::get<DimX>(ddc::coordinate(idx))) * y_cos * y_cos; | ||
}); | ||
double integral = integrate(values); | ||
return std::abs(integral - M_PI); | ||
} | ||
|
||
template <std::size_t... Is> | ||
std::array<double, sizeof...(Is)> compute_errors(std::index_sequence<Is...>, int n_elems) | ||
{ | ||
return std::array<double, sizeof...(Is)> {compute_error<Is>(n_elems *= 2)...}; | ||
} | ||
|
||
TEST(QuadratureTest, UniformConverge) | ||
{ | ||
constexpr int NTESTS(4); | ||
|
||
std::array<double, NTESTS> error = compute_errors(std::make_index_sequence<NTESTS>(), 50); | ||
|
||
for (int i(1); i < NTESTS; ++i) { | ||
EXPECT_LE(error[i], error[i - 1]); | ||
double order = log(error[i - 1] / error[i]) / log(2.0); | ||
double order_error = abs(2 - order); | ||
EXPECT_LE(order_error, 1e-1); | ||
} | ||
} |