36 const double domain_start = geom_locations.front();
37 const double domain_end = geom_locations.back();
38 if (domain_end == domain_start) {
39 throw std::invalid_argument(
40 "Invalid geometric locations: domain start and end points are equal."
45 std::vector<double> mapped_locations(geom_locations.size());
46 const auto domain_span = domain_end - domain_start;
47 std::ranges::transform(
48 geom_locations, std::begin(mapped_locations),
49 [domain_start, domain_span](
auto geom_location) {
50 return 2. * (geom_location - domain_start) / domain_span - 1.;
53 return mapped_locations;
66 std::span<const double> input_points, std::span<const double> output_points
69 const auto num_input_points = input_points.size();
70 const auto num_output_points = output_points.size();
73 std::vector<double> weights(num_output_points, 0.);
76 auto shape_functions = std::vector<std::vector<double>>(
77 num_output_points, std::vector<double>(num_input_points, 0.)
79 for (
auto input_point : std::views::iota(0U, num_input_points)) {
81 for (
auto output_point : std::views::iota(0U, num_output_points)) {
82 shape_functions[output_point][input_point] = weights[output_point];
86 return shape_functions;
99 std::span<const double> input_points, std::span<const double> output_points
102 const auto num_input_points = input_points.size();
103 const auto num_output_points = output_points.size();
106 std::vector<double> weights(num_output_points, 0.);
109 auto derivative_functions = std::vector<std::vector<double>>(
110 num_output_points, std::vector<double>(num_input_points, 0.)
112 for (
auto input_point : std::views::iota(0U, num_input_points)) {
114 for (
auto output_point : std::views::iota(0U, num_output_points)) {
115 derivative_functions[output_point][input_point] = weights[output_point];
119 return derivative_functions;
135 size_t p, std::span<
const std::vector<double>> shape_functions,
136 std::span<
const std::array<double, 3>> points_to_fit
138 if (shape_functions.size() != p) {
139 throw std::invalid_argument(
"shape_functions rows do not match order p.");
141 const size_t n = shape_functions[0].size();
142 if (std::any_of(shape_functions.begin(), shape_functions.end(), [n](
const auto& row) {
143 return row.size() != n;
145 throw std::invalid_argument(
"Inconsistent number of columns in shape_functions.");
149 const auto A = Kokkos::View<double**, Kokkos::LayoutLeft, Kokkos::HostSpace>(
"A", p, p);
151 A(p - 1, p - 1) = 1.;
152 for (
auto j : std::views::iota(0U, p)) {
153 for (
auto i : std::views::iota(1U, p - 1U)) {
154 A(i, j) = std::transform_reduce(
155 std::begin(shape_functions[i]), std::end(shape_functions[i]),
156 std::begin(shape_functions[j]), 0., std::plus<>(), std::multiplies<>()
162 const auto B = Kokkos::View<double* [3], Kokkos::LayoutLeft, Kokkos::HostSpace>(
"B", p);
163 for (
auto dim : std::views::iota(0U, 3U)) {
164 B(0, dim) = points_to_fit[0][dim];
165 B(p - 1, dim) = points_to_fit[n - 1][dim];
167 for (
auto i : std::views::iota(1U, p - 1U)) {
168 for (
auto k : std::views::iota(0U, n)) {
169 for (
auto dim : std::views::iota(0U, 3U)) {
170 B(i, dim) += shape_functions[i][k] * points_to_fit[k][dim];
176#ifdef Kynema_ENABLE_MKL
177 using index_type = MKL_INT;
179 using index_type = int;
182 Kokkos::View<index_type*, Kokkos::LayoutLeft, Kokkos::HostSpace>(
"IPIV", B.extent(0));
183 const auto rows =
static_cast<index_type
>(p);
185 lapack::LAPACKE_dgesv(LAPACK_COL_MAJOR, rows, 3, A.data(), rows, IPIV.data(), B.data(), rows);
187 auto result = std::vector<std::array<double, 3>>(B.extent(0));
189 for (
auto i : std::views::iota(0U, result.size())) {
190 for (
auto j : std::views::iota(0U, result.front().size())) {
191 result[i][j] = B(i, j);
std::vector< double > MapGeometricLocations(std::span< const double > geom_locations)
Maps input geometric locations -> normalized domain using linear mapping.
Definition least_squares_fit.hpp:34
void LagrangePolynomialInterpWeights(double x, std::span< const double > xs, std::vector< double > &weights)
Computes weights for Lagrange polynomial interpolation.
Definition interpolation.hpp:69
void LagrangePolynomialDerivWeights(double x, std::span< const double > xs, std::vector< double > &weights)
Computes weights for Lagrange polynomial derivative interpolation.
Definition interpolation.hpp:97
std::vector< std::array< double, 3 > > PerformLeastSquaresFitting(size_t p, std::span< const std::vector< double > > shape_functions, std::span< const std::array< double, 3 > > points_to_fit)
Performs least squares fitting to determine interpolation coefficients.
Definition least_squares_fit.hpp:134
std::vector< std::vector< double > > ComputeShapeFunctionValues(std::span< const double > input_points, std::span< const double > output_points)
Computes shape function matrices ϕg relating points ξb to ξg At least two input points are required a...
Definition least_squares_fit.hpp:65
std::vector< std::vector< double > > ComputeShapeFunctionDerivatives(std::span< const double > input_points, std::span< const double > output_points)
Computes shape function derivatives dϕg relating points ξb to ξg At least two input points are requir...
Definition least_squares_fit.hpp:98