MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
sbpcartesianinterpolation.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef SBPINTERPOLATION_H_
8#define SBPINTERPOLATION_H_
9
10#include <algorithm>
11#include <iomanip>
12
14#include "INCLUDE/maiatypes.h"
15#include "UTIL/tensor.h"
16#include "enums.h"
18
19namespace maia {
20namespace dg {
21
30namespace interpolation {
31
32
42inline void calcSBPNodes(const MInt noNodes, MFloat* nodes) {
43 TRACE();
44
45 ASSERT(noNodes > 0, "Number of nodes must be greater than zero!");
46
47 // Create equidistant nodes on [-1,1]
48 const MFloat dx = F2 / (noNodes - 1);
49 std::fill_n(&nodes[0], noNodes, F0);
50 for(MInt i = 0; i < noNodes; i++) {
51 nodes[i] = -F1 + i * dx;
52 }
53}
54
65inline void calcSBPWeights(const MInt noNodes, MFloatVector sbpP, MFloat* wInt) {
66 TRACE();
67
68 ASSERT(noNodes > 0, "Number of nodes must be greater than zero!");
69
70 const MInt lenP = sbpP.dim0();
71 const MFloat dx = F2 / (noNodes - 1);
72
73 // Create (diagonal) H Matrix as Vector from 'p' Vector
74 std::fill_n(&wInt[0], noNodes, dx);
75 for(MInt i = 0; i < lenP; i++) {
76 wInt[i] = sbpP(i) * dx;
77 wInt[noNodes - i - 1] = sbpP(i) * dx;
78 }
79}
80
90 const MInt noNodes = Q.dim(0);
91
92 MFloatMatrix B(noNodes, noNodes);
93 B.set(F0);
94 for(MInt i = 0; i < noNodes; i++) {
95 for(MInt j = 0; j < noNodes; j++) {
96 B(i, j) = Q(i, j) + Q(j, i);
97 }
98 }
99
100 MBool sbpProp = true;
101 if(!approx(B(0, 0), -F1, MFloatEps) || !approx(B(noNodes - 1, noNodes - 1), F1, MFloatEps)) {
102 sbpProp = false;
103 }
104
105 for(MInt i = 0; i < noNodes; i++) {
106 for(MInt j = 0; j < noNodes; j++) {
107 if(!approx(B(i, j), 0.0, MFloatEps) && i != j) {
108 sbpProp = false;
109 break;
110 }
111 if(!sbpProp) break;
112 }
113 }
114 std::cout << "SBP Propery " << sbpProp << std::endl;
115 return sbpProp;
116}
117
127inline void readCSV(std::string path, std::vector<std::vector<MFloat>>& data) {
128 std::ifstream stream(path);
129
130 MInt rank;
131 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
132
133 if(!rank) {
134 // Read data on rank 0
135 MInt l = 0;
136 while(stream) {
137 l++;
138 std::string s;
139 if(!getline(stream, s)) break;
140 if(s[0] != '#') {
141 std::istringstream ss(s);
142 std::vector<MFloat> record;
143 while(ss) {
144 std::string line;
145 if(!getline(ss, line, ',')) break;
146 record.push_back(std::stof(line));
147 }
148 data.push_back(record);
149 }
150 }
151
152 if(!stream.eof()) {
153 std::cerr << "Could not read file " << path << "\n";
154 std::__throw_invalid_argument("File not found.");
155 }
156
157 MInt dim0 = data.size();
158 MInt dim1 = data[0].size();
159
160 // transfer read data to sendBuffer
161 MFloatVector sendBuffer;
162 sendBuffer.resize(dim0 * dim1);
163 MInt it = 0;
164 for(auto& line : data) {
165 for(auto& coef : line) {
166 sendBuffer[it] = coef;
167 it++;
168 }
169 }
170
171 // Send data
172 MPI_Bcast(&dim0, 1, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dim0");
173 MPI_Bcast(&dim1, 1, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dim1");
174 MPI_Bcast(&sendBuffer[0], dim0 * dim1, MPI_DOUBLE, 0, MPI_COMM_WORLD, AT_, "sendBuffer");
175
176 } else {
177 // Receive data
178 MInt dim0;
179 MInt dim1;
180 MPI_Bcast(&dim0, 1, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dim0");
181 MPI_Bcast(&dim1, 1, MPI_INT, 0, MPI_COMM_WORLD, AT_, "dim1");
182
183 MFloatVector recvBuffer;
184 recvBuffer.resize(dim0 * dim1);
185 MPI_Bcast(&recvBuffer[0], dim0 * dim1, MPI_DOUBLE, 0, MPI_COMM_WORLD, AT_, "recvBuffer");
186
187 for(MInt i = 0; i < dim0; i++) {
188 std::vector<MFloat> line;
189 for(MInt j = 0; j < dim1; j++) {
190 line.push_back(recvBuffer(dim1 * i + j));
191 }
192 data.push_back(line);
193 }
194 }
195}
196
207inline void readDDRP(MFloat* nodesVector, MFloat* wIntVector, MFloat* dhatMatrix) {
208 std::string path = "./operatorsSBP/go4/DDRP307_N32/";
209 std::vector<std::vector<MFloat>> dData;
210 std::vector<std::vector<MFloat>> wData;
211 std::vector<std::vector<MFloat>> xData;
212
213 readCSV(path + "diff_matrix.csv", dData);
214 readCSV(path + "weights_int.csv", wData);
215 readCSV(path + "nodes.csv", xData);
216
217 const MInt nNodes = xData.size();
218
219 MFloatMatrix Dhat(&dhatMatrix[0], nNodes, nNodes);
220 MFloatVector wInt(&wIntVector[0], nNodes);
221 MFloatVector nodes(&nodesVector[0], nNodes);
222
223 // Copy the 2D Vector to the corresponding data structures
224 // Transpose and normalize differentiation matrix D
225 for(MInt i = 0; i < nNodes; i++) {
226 for(MInt j = 0; j < nNodes; j++) {
227 Dhat(i, j) = dData[j][i] * wData[j][0] / wData[i][0];
228 }
229 wInt(i) = wData[i][0];
230 nodes(i) = xData[i][0];
231 }
232}
233
246inline void calcDhatSBP(const MInt noNodes, MFloatVector sbpA, MFloatVector sbpQ, const MFloat* wInt,
247 MFloat* dhatMatrix) {
248 TRACE();
249
250 if(noNodes <= 0) {
251 TERM(-1);
252 }
253
254 MInt lenA = sbpA.dim0();
255 MInt lenQ = sbpQ.dim0();
256 MInt lenR = (1 + sqrt(1 + 8 * lenQ)) / 2;
257
258 // Create Q Matrix from 'q' and 'a' Vector
259 MFloatMatrix Q = MFloatMatrix(noNodes, noNodes);
260 Q.set(F0);
261
262 // Write upper rxr solver
263 Q(0, 0) = -0.5;
264 MInt k = 0;
265 for(MInt i = 0; i < lenR; i++) {
266 for(MInt j = i; j < lenR - 1; j++) {
267 Q(i, j + 1) = sbpQ(k);
268 Q(j + 1, i) = -sbpQ(k);
269 k++;
270 }
271 }
272
273 // Write interior points
274 for(MInt i = lenR; i < noNodes - lenR; i++) {
275 k = lenA - 1;
276 for(MInt j = i - lenA; j < i; j++) {
277 Q(i, j) = -sbpA(k);
278 k--;
279 }
280 k = 0;
281 for(MInt j = i + 1; j < i + lenA + 1; j++) {
282 Q(i, j) = sbpA(k);
283 k++;
284 }
285 }
286
287 // Write 'a' points around the upper rxr solver
288 for(MInt i = 0; i < lenA; i++) {
289 for(MInt j = i; j < lenA; j++) {
290 Q(lenR - i - 1, lenR - i + j) = sbpA(j);
291 }
292 }
293
294 // Mirror upper rxr solver onto lower half
295 for(MInt i = 0; i < lenR; i++) {
296 for(MInt j = 0; j < lenR + lenA; j++) {
297 Q(noNodes - i - 1, noNodes - j - 1) = -Q(i, j);
298 }
299 }
300
301 Q.transpose();
302
303 // checkSBPProp(Q);
304
305 MFloatMatrix Dhat(&dhatMatrix[0], noNodes, noNodes);
306 // Add normalization using integration weights
307 for(MInt i = 0; i < noNodes; i++) {
308 for(MInt j = 0; j < noNodes; j++) {
309 Dhat(i, j) = -Q(i, j) / wInt[i];
310 }
311 }
312}
313
326inline void readSbpOperator(MInt noNodes1D, MString opName, MFloatVector& sbpA, MFloatVector& sbpP,
327 MFloatVector& sbpQ) {
328 MString path = "./operatorsSBP/" + opName;
329 std::vector<std::vector<MFloat>> aData;
330 std::vector<std::vector<MFloat>> pData;
331 std::vector<std::vector<MFloat>> qData;
332
333 readCSV(path + "/a.csv", aData);
334 readCSV(path + "/p.csv", pData);
335 readCSV(path + "/q.csv", qData);
336
337 MInt lenA = aData.size();
338 MInt lenP = pData.size();
339 MInt lenR = lenP;
340 MInt lenQ = lenP * (lenP - 1) / 2;
341
342 ASSERT(noNodes1D >= 2 * lenR,
343 "Not enough nodes for the " + opName + " operator! " << noNodes1D << " set but " << 2 * lenR << " required.");
344
345 sbpA = MFloatVector(lenA);
346 MInt i = 0;
347 for(auto& a : aData) {
348 sbpA(i) = a[0];
349 i++;
350 }
351
352 sbpQ = MFloatVector(lenQ);
353 i = 0;
354 for(auto& q : qData) {
355 sbpQ(i) = q[0];
356 i++;
357 }
358
359 sbpP = MFloatVector(lenP);
360 i = 0;
361 for(auto& p : pData) {
362 sbpP(i) = p[0];
363 i++;
364 }
365}
366
381inline MBool getSBPOperator(const MInt noNodes1D, const MString opName, MFloatVector& sbpA, MFloatVector& sbpP,
382 MFloatVector& sbpQ) {
383 SBPOperator* op = nullptr;
384 MBool exists = false;
385
386 if(opName == "go4/s306") {
387 op = &s306;
388 exists = true;
389 } else {
390 return exists = false;
391 }
392
393 MInt lenA = op->a.size();
394 MInt lenP = op->p.size();
395 MInt lenR = lenP;
396 MInt lenQ = lenP * (lenP - 1) / 2;
397
398 ASSERT(noNodes1D >= 2 * lenR,
399 "Not enough nodes for the " + opName + " operator!" << noNodes1D << " set but " << 2 * lenR << " required.");
400
401 sbpA = MFloatVector(lenA);
402 MInt i = 0;
403 for(auto& a : op->a) {
404 sbpA(i) = a;
405 i++;
406 }
407
408 sbpQ = MFloatVector(lenQ);
409 i = 0;
410 for(auto& q : op->q) {
411 sbpQ(i) = q;
412 i++;
413 }
414
415 sbpP = MFloatVector(lenP);
416 i = 0;
417 for(auto& p : op->p) {
418 sbpP(i) = p;
419 i++;
420 }
421
422 return exists;
423}
424
438inline void findNodeIndicesAtPoint(const MFloat point, const MFloat* nodes, const MInt noNodes, MInt& idx1,
439 MInt& idx2) {
440 // TODO labels:DG Change to bisection/Catch collocating points
441 for(MInt i = 0; i < noNodes; i++) {
442 if(nodes[i] > point || approx(nodes[i], point, MFloatEps)) {
443 idx1 = i - 1;
444 idx2 = i;
445 break;
446 }
447 }
448 if(idx1 == -1) {
449 idx1++;
450 idx2++;
451 }
452}
453
467inline void calcLinearInterpolationBase(const MFloat x, const MInt noNodes, const MFloat* nodes,
468 MFloat* const polynomials) {
469 std::fill_n(&polynomials[0], noNodes, F0);
470
471 // Framing indices of point on grid
472 MInt idx[2] = {0, 0};
473 findNodeIndicesAtPoint(x, nodes, noNodes, idx[0], idx[1]);
474
475 const MFloat dx = 2.0 / (noNodes - 1);
476 polynomials[idx[0]] = fabs(nodes[idx[1]] - x) / dx;
477 polynomials[idx[1]] = fabs(nodes[idx[0]] - x) / dx;
478}
479
495template <class T, class U, class V>
496void calcLinearInterpolationMatrix(const MInt noNodesIn, const T nodesIn, const MInt noNodesOut, const U nodesOut,
497 V vandermonde) {
498 TRACE();
499
500 MFloatMatrix vdm(&vandermonde[0], noNodesOut, noNodesIn);
501
502 for(MInt k = 0; k < noNodesOut; k++) {
503 MBool rowHasMatch = false;
504 for(MInt j = 0; j < noNodesIn; j++) {
505 vdm(k, j) = F0;
506 if(approx(nodesOut[k], nodesIn[j], MFloatEps)) {
507 rowHasMatch = true;
508 vdm(k, j) = F1;
509 }
510 }
511
512 if(rowHasMatch == false) {
513 calcLinearInterpolationBase(nodesOut[k], noNodesIn, nodesIn, &vdm(k, 0));
514 }
515 }
516}
517
532inline void calcBilinearInterpolation(MFloat* point, const MFloat* nodes, const MInt noNodes, const MInt noVars,
533 const MFloat* u, MFloat* const out) {
534 // Framing indices of point on grid
535 // nDim x 2
536 MInt idx[2][2] = {{0, 0}, {0, 0}};
537 findNodeIndicesAtPoint(point[0], nodes, noNodes, idx[0][0], idx[0][1]);
538 findNodeIndicesAtPoint(point[1], nodes, noNodes, idx[1][0], idx[1][1]);
539
540 MFloatTensor U(const_cast<MFloat*>(u), noNodes, noNodes, 1, noVars);
541 const MFloat dx = 2.0 / (noNodes - 1);
542 const MFloat dx2 = pow(dx, 2);
543 // Not sure if necessary
544 std::fill_n(out, noVars, 0.0);
545
546 // aij is the corresponding weight to the value Uij
547 // aij is the fraction of the diagonally opposite subarea
548
549 for(MInt i = 0; i < 2; i++) {
550 for(MInt j = 0; j < 2; j++) {
551 const MFloat a = fabs((nodes[idx[0][1 - i]] - point[0]) * (nodes[idx[1][1 - j]] - point[1])) / dx2;
552 for(MInt v = 0; v < noVars; v++) {
553 out[v] += a * U(idx[0][i], idx[1][j], 0, v);
554 }
555 }
556 }
557}
558
572inline void calcTrilinearInterpolation(MFloat* point, const MFloat* nodes, const MInt noNodes, const MInt noVars,
573 const MFloat* u, MFloat* const out) {
574 // Framing indices of point on grid
575 // nDim x 2
576 MInt idx[3][2] = {{0, 0}, {0, 0}, {0, 0}};
577 findNodeIndicesAtPoint(point[0], nodes, noNodes, idx[0][0], idx[0][1]);
578 findNodeIndicesAtPoint(point[1], nodes, noNodes, idx[1][0], idx[1][1]);
579 findNodeIndicesAtPoint(point[2], nodes, noNodes, idx[2][0], idx[2][1]);
580
581 MFloatTensor U(const_cast<MFloat*>(u), noNodes, noNodes, noNodes, noVars);
582 const MFloat dx = 2.0 / (noNodes - 1);
583 const MFloat dx3 = pow(dx, 3);
584 // Not sure if necessary
585 std::fill_n(out, noVars, 0.0);
586
587 // aijk is the corresponding weight to the value Uijk
588 // aijk is the fraction of the diagonally opposite subvolume
589
590 for(MInt i = 0; i < 2; i++) {
591 for(MInt j = 0; j < 2; j++) {
592 for(MInt k = 0; k < 2; k++) {
593 const MFloat a = fabs((nodes[idx[0][1 - i]] - point[0]) * (nodes[idx[1][1 - j]] - point[1])
594 * (nodes[idx[2][1 - k]] - point[2]))
595 / dx3;
596
597 for(MInt v = 0; v < noVars; v++) {
598 out[v] += a * U(idx[0][i], idx[1][j], idx[2][k], v);
599 }
600 }
601 }
602 }
603}
604
605// ~jv Rework
606/*inline void calcBicubicSplineInterpolation(spline* spline, MFloat *point,
607 const MFloat* nodes, const MInt noNodes,
608 const MInt noVars, const MFloat* u,
609 MFloat* const out){
610
611 spline->set_boundary(spline->second_deriv,0,spline->second_deriv,0,false);
612 std::vector<MFloat> X(noNodes), Utmp(noNodes), Uinter1D(noNodes);
613 for (MInt i = 0; i < noNodes; ++i) {
614 X[i] = nodes[i];
615 }
616 MFloatTensor U(const_cast<MFloat*>(u),noNodes,noNodes,1,noVars);
617
618 for (MInt v = 0; v < noVars; ++v) {
619 auto debug = false;
620 if (v==2 && U(0,0,0,0)>1E30){
621 debug=true;
622 std::cout << "BICUBIC OUTPUT for p at " << point[0] << " " << point[1] << std::endl;}
623 Uinter1D.clear();
624 for (MInt i = 0; i < noNodes; ++i) {
625 Utmp.clear();
626 for (MInt j = 0; j < noNodes; ++j) {
627 Utmp.push_back(U(i,j,0,v));
628 }
629 if (debug){
630 std::cout << "TMP" << " " << point[1] << " " << X[i] << std::endl;
631 //for (auto en : X){std::cout << en << std::endl;}
632 //for (auto en : Utmp){std::cout << en << std::endl;}
633 for (MInt k = 0; k < noNodes; ++k) {
634 std::cout << X[k] << " : " << Utmp[k] << std::endl;
635 }}
636 //mTerm(1,AT_,"DEBUG");
637 spline->set_points(X,Utmp);
638 Uinter1D.push_back(spline->operator()(point[1]));
639 if(debug)std::cout << "TMP RES " << Uinter1D[i] << std::endl;
640 }
641 spline->set_points(X,Uinter1D);
642 out[v] = spline->operator()(point[0]);
643 if(debug){
644 std::cout << "END " << point[0] << std::endl;
645 for (MInt k = 0; k < noNodes; ++k) {
646 std::cout << X[k] << " : " << Uinter1D[k] << std::endl;
647 }
648 std::cout << "END RES " << out[v] << std::endl;}
649 //if (out[v] <= -0.004){mTerm(1,AT_,"DEBUG TERM");}
650 }
651
652 //calcBilinearInterpolation(point,nodes,noNodes,noVars,u,out);
653}
654*/
655
656} // namespace interpolation
657} // namespace dg
658} // namespace maia
659
660#endif /* SBPINTERPOLATION_H_ */
void transpose()
Transposes the first two dimensions (i.e. acting as if the tensor is a matrix).
Definition: tensor.h:306
size_type dim0() const
Return the size of dimension 0.
Definition: tensor.h:366
void set(const T &value)
Initializes tensor to constant value.
Definition: tensor.h:271
size_type dim(size_type d) const
Return the size of dimension d.
Definition: tensor.h:349
size_type resize(size_type n0, size_type n1=1, size_type n2=1, size_type n3=1, size_type n4=1)
Deletes the old data structure and creates a new one with the requested dimensions.
Definition: tensor.h:230
MBool approx(const T &, const U &, const T)
Definition: functions.h:272
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
void readCSV(std::string path, std::vector< std::vector< MFloat > > &data)
Reads .csv-file on rank 0 and broadcasts it to all ranks.
void findNodeIndicesAtPoint(const MFloat point, const MFloat *nodes, const MInt noNodes, MInt &idx1, MInt &idx2)
Finds the neighboring indices to point in one dimension.
void readSbpOperator(MInt noNodes1D, MString opName, MFloatVector &sbpA, MFloatVector &sbpP, MFloatVector &sbpQ)
Reads all coefficient files to contruct SBP operator.
void calcTrilinearInterpolation(MFloat *point, const MFloat *nodes, const MInt noNodes, const MInt noVars, const MFloat *u, MFloat *const out)
Calculates trilinear interpolation at given point (3D)
MBool checkSBPProp(const MFloatMatrix &Q)
Helper function for checking the SBP property of a given operator.
void calcLinearInterpolationBase(const MFloat x, const MInt noNodes, const MFloat *nodes, MFloat *const polynomials)
Calculates linear interpolation base for point (1D).
void calcSBPNodes(const MInt noNodes, MFloat *nodes)
Generates an equidistant node distribution.
void readDDRP(MFloat *nodesVector, MFloat *wIntVector, MFloat *dhatMatrix)
Reads DDRP operator and nodal distribution from file.
void calcLinearInterpolationMatrix(const MInt noNodesIn, const T nodesIn, const MInt noNodesOut, const U nodesOut, V vandermonde)
Calculates the linear interpolation matrix (Vandermonde) to interpolate from one set of nodes to anot...
void calcDhatSBP(const MInt noNodes, MFloatVector sbpA, MFloatVector sbpQ, const MFloat *wInt, MFloat *dhatMatrix)
Calculates SBP operator from coefficients.
void calcSBPWeights(const MInt noNodes, MFloatVector sbpP, MFloat *wInt)
Calulates the diagonal weight matrix (H) entries.
void calcBilinearInterpolation(MFloat *point, const MFloat *nodes, const MInt noNodes, const MInt noVars, const MFloat *u, MFloat *const out)
Calculates bilinear interpolation at given point (2D)
MBool getSBPOperator(const MInt noNodes1D, const MString opName, MFloatVector &sbpA, MFloatVector &sbpP, MFloatVector &sbpQ)
Gets SBP Coefficients from corresponding header if existent.
Namespace for auxiliary functions/classes.
std::vector< MFloat > a
std::vector< MFloat > p
std::vector< MFloat > q
Definition: contexttypes.h:19
maia::tensor::Tensor< MFloat > MFloatMatrix
Definition: tensor.h:1098
maia::tensor::Tensor< MFloat > MFloatVector
Definition: tensor.h:1095