Peano
Loading...
Searching...
No Matches
LagrangeInterpolation.h
Go to the documentation of this file.
1// This file is part of the Peano project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
3#pragma once
4
6
7#include <map>
8
9namespace toolbox {
10 namespace curvi {
11 namespace Interpolation {
12 class Lagrange {
13 public:
14 static void interpolate3D(
15 const double position[3],
16 const Block& block,
17 std::vector<int> range_z,
18 std::vector<int> range_y,
19 std::vector<int> range_x,
20 double result[NCOORDS]
21 ) {
22 for (int k : range_z) {
23 double dz = range_z.back() - range_z.front();
24 double lagrange_z = uniformLagrangePolynomial(
25 (position[0] - range_z.front()) / dz,
26 k - range_z.front(),
27 range_z.back() - range_z.front() + 1
28 );
29 for (int j : range_y) {
30 double dy = range_y.back() - range_y.front();
31 double lagrange_y = uniformLagrangePolynomial(
32 (position[1] - range_y.front()) / dy,
33 j - range_y.front(),
34 range_y.back() - range_y.front() + 1
35 );
36 for (int i : range_x) {
37 double dx = range_x.back() - range_x.front();
38 double lagrange_x = uniformLagrangePolynomial(
39 (position[2] - range_x.front()) / dx,
40 i - range_x.front(),
41 range_x.back() - range_x.front() + 1
42 );
43
44 for (int d = 0; d < NCOORDS; d++) {
45 result[d] += lagrange_z * lagrange_y * lagrange_x
46 * block(d, Coordinate::Z, k, Coordinate::Y, j, Coordinate::X, i);
47 }
48 }
49 }
50 }
51 };
52
53 static void interpolate1D(
54 double position,
55 std::vector<double> nodes,
56 std::vector<double> values,
57 double result[NCOORDS]
58 ) {
59 // check if nodes and values fit:
60 if (nodes.size() != values.size() / NCOORDS) {
61 throw std::out_of_range("Values and nodes dont't fit in 1d lagrange interpolation");
62 }
63
64 std::fill_n(result, NCOORDS, 0);
65 std::vector<int> index_range = Index::getIndexRange(0, nodes.size());
66 for (int i : index_range) {
67 double lagrange = lagrangePolynomial(position, i, nodes);
68 idx2 idx(NCOORDS, nodes.size());
69 for (int d = 0; d < NCOORDS; d++) {
70 result[d] += lagrange * values[idx(d, i)];
71 }
72 }
73 };
74
75 static double lagrangePolynomial(double position, int i, std::vector<double> range) {
76 double nominator = 1;
77 double denominator = 1;
78 for (int j = 0; j < i; j++) {
79 nominator *= (position - range[j]);
80 denominator *= (range[i] - range[j]);
81 }
82
83 for (int j = i + 1; j < range.size(); j++) {
84 nominator *= (position - range[j]);
85 denominator *= (range[i] - range[j]);
86 }
87
88 return nominator / denominator;
89 }
90
91
92 static double uniformLagrangePolynomial(double position, int i, int range) {
93 double result = 1;
94 std::vector<double> uniform_mesh = getUniformMesh(range);
95
96 for (int j = 0; j < i; j++) {
97 result *= (position - uniform_mesh[j]);
98 }
99
100 for (int j = i + 1; j < range; j++) {
101 result *= (position - uniform_mesh[j]);
102 }
103
104 result /= getLagrangeDenominator(i, range);
105
106 return result;
107 };
108
109 private:
110 static std::vector<double> getUniformMesh(int range) {
111 // static std::map lagrangeDenominator;
112
113 /*used to hash results*/
114 /* static std::map<int,std::vector<double>> mesh_map; */
115 /* #pragma omp threadprivate(mesh_map) */
116 /* if( mesh_map.find(range) != mesh_map.end()){ */
117 /* return mesh_map[range]; */
118 /* } */
119 /**********************/
120
121 std::vector<double> uniform_mesh;
122
123 for (int i = 0; i < range; i++) {
124 uniform_mesh.push_back(i / double(range - 1));
125 }
126 // mesh_map[range] = uniform_mesh;
127 return uniform_mesh;
128 }
129
130 static double getLagrangeDenominator(int i, int range) {
131
132 /*used to hash results*/
133 /* typedef std::tuple<int,int> keytype; */
134 /* static std::map<keytype,double> denominator_map; */
135 /* #pragma omp threadprivate(denominator_map) */
136 /* keytype key(i,range); */
137
138 /* if( denominator_map.find(key) != denominator_map.end()){ */
139 /* return denominator_map[key]; */
140 /* } */
141 /**********************/
142
143 double denominator = 1;
144 std::vector<double> uniformMesh = getUniformMesh(range);
145 for (int j = 0; j < i; j++) {
146 denominator *= uniformMesh[i] - uniformMesh[j];
147 }
148
149 for (int j = i + 1; j < range; j++) {
150 denominator *= uniformMesh[i] - uniformMesh[j];
151 }
152
153 // denominator_map[key] = denominator;
154 return denominator;
155 }
156 };
157 } // namespace Interpolation
158 } // namespace curvi
159} // namespace toolbox
#define NCOORDS
Definition Coordinate.h:12
void Interpolation(double *result, tarch::la::Vector< Dimensions, int > *IndexForInter, double *raw, const double *coor, tarch::la::Vector< Dimensions, double > Offset, double volumeH, int patchSize)
static std::vector< int > getIndexRange(int start, int size)
Definition Index.h:13
static std::vector< double > getUniformMesh(int range)
static void interpolate3D(const double position[3], const Block &block, std::vector< int > range_z, std::vector< int > range_y, std::vector< int > range_x, double result[NCOORDS])
static double lagrangePolynomial(double position, int i, std::vector< double > range)
static void interpolate1D(double position, std::vector< double > nodes, std::vector< double > values, double result[NCOORDS])
static double uniformLagrangePolynomial(double position, int i, int range)
static double getLagrangeDenominator(int i, int range)