Add files via upload

This commit is contained in:
mathur04
2024-07-04 13:15:37 +02:00
committed by GitHub
parent 9faebead7e
commit e1ed417974
7 changed files with 763 additions and 0 deletions

View File

@ -0,0 +1,107 @@
#include <iostream>
#include <vector>
#include <cmath>
#include <complex>
#include <algorithm>
#include <string>
#include <cassert>
#include <functional>
// Forward declarations
struct ScanData {
struct CscanData {
std::string WaveType;
double Cl;
double Cs;
std::vector<double> X;
double ProbeDiameter;
double Frequency;
double Bandwidth;
std::string DefectType;
double Diameter;
double Tilt;
} CscanData;
std::vector<double> timeScale;
std::vector<std::vector<double>> AscanValues;
};
std::tuple<std::vector<std::vector<std::complex<double>>>,
std::vector<std::vector<std::complex<double>>>,
std::vector<std::vector<std::complex<double>>>,
std::vector<std::complex<double>>,
std::vector<std::complex<double>>>
GenerateModelFilter(const ScanData& scanData,
bool pad = true,
double ep = 0.03,
std::string TrFreqSp = "gaussian",
int Rx = 1,
double T1 = 0) {
// Verify scanData parameter
assert(scanData.CscanData.WaveType != "" && "scanData invalid structure");
// Verify input parameters
assert(Rx > 0 && "Rx must be positive");
assert(T1 >= 0 && "Excitation pulse width must be positive");
// Get scan data information
double c = (scanData.CscanData.WaveType == "L") ? scanData.CscanData.Cl : scanData.CscanData.Cs;
double ERMv = c / 2;
double scanX = scanData.CscanData.X[0] * 1e-3;
double deltaScanX = (scanData.CscanData.X[1] - scanData.CscanData.X[0]) * 1e-3 / Rx;
double deltaT = (scanData.timeScale[1] - scanData.timeScale[0]) * 1e-6;
// Get acquisition matrix sizes
int nt0 = scanData.AscanValues.size();
int nu0 = (scanData.AscanValues[0].size() - 1) * Rx + 1;
// Zero-padding
int nt = pad ? std::pow(2, std::ceil(std::log2(nt0)) + 1) : nt0;
int nu = pad ? 2 * nu0 : nu0;
// Calculate matched filters
auto [C1, Hed] = pCalcMatchedFilter(nt, deltaT, nu, deltaScanX,
scanData.CscanData.ProbeDiameter * 1e-3,
scanData.CscanData.Frequency * 1e6,
scanData.CscanData.Bandwidth * 1e6,
ERMv, TrFreqSp, T1);
// Calculate flaw response
auto SA = pCalcScatteringAmplitude(nt, deltaT, c,
scanData.CscanData.DefectType,
scanData.CscanData.Diameter * 1e-3 / 2,
scanData.CscanData.Tilt);
// Build Model and Filter
std::vector<std::vector<std::complex<double>>> Model(nt, std::vector<std::complex<double>>(nu));
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
Model[i][j] = C1[i][j] * std::conj(Hed[i] * SA[i]);
}
}
std::vector<std::vector<std::complex<double>>> Filter(nt, std::vector<std::complex<double>>(nu));
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
std::complex<double> AA = std::conj(C1[i][j]) / (C1[i][j] * std::conj(C1[i][j]) + ep);
Filter[i][j] = AA * std::conj(Hed[i]);
}
}
return std::make_tuple(Model, Filter, C1, Hed, SA);
}
// Protected function to calculate match filter response
std::tuple<std::vector<std::vector<std::complex<double>>>, std::vector<std::complex<double>>>
pCalcMatchedFilter(int nt, double dt, int nx, double dx, double d, double fc, double BW, double ERMv,
const std::string& TrFreqSp, double T1) {
// Implementation details omitted for brevity
// This function would return C1 and Hed
}
// Protected function to calculate scattering amplitude response
std::vector<std::complex<double>> pCalcScatteringAmplitude(int nt, double dt, double c,
const std::string& flaw, double b, double ang) {
// Implementation details omitted for brevity
// This function would return SA
}

124
UTSR/ModS2.cpp Normal file
View File

@ -0,0 +1,124 @@
#include <vector>
#include <complex>
#include <cmath>
#include <algorithm>
#include <cassert>
#include <fftw3.h>
std::vector<std::vector<double>> ModS2(const std::vector<std::vector<double>>& image, double dt, double du, double ERMv, double tau0, const std::vector<std::vector<double>>& ModTransd, int R_x = 1) {
// Check R_x argument
R_x = std::max(1, R_x);
assert(R_x > 0 && "R_x must be positive");
// Zero-padding
int nt0 = image.size();
int nu0 = image[0].size();
int nt = ModTransd.size();
int nu = ModTransd[0].size();
if (nt < nt0) {
nt = std::pow(2, std::ceil(std::log2(nt0)) + 1);
}
if (nu < nu0) {
nu = 2 * nu0;
}
// Data and image grids
std::vector<std::vector<double>> f(nt, std::vector<double>(nu));
std::vector<std::vector<double>> ku(nt, std::vector<double>(nu));
std::vector<std::vector<double>> fkz(nt, std::vector<double>(nu));
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
f[i][j] = (i - nt/2) / (dt * nt);
ku[i][j] = (j - nu/2) / (du * nu);
fkz[i][j] = ERMv * std::copysign(1.0, f[i][j]) * std::sqrt(std::pow(ku[i][j], 2) + std::pow(f[i][j] / ERMv, 2));
}
}
// Converting image to frequency domain
fftw_complex *in, *out;
fftw_plan p;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nt * nu);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * nt * nu);
for (int i = 0; i < nt0; ++i) {
for (int j = 0; j < nu0; ++j) {
in[i*nu + j][0] = image[i][j];
in[i*nu + j][1] = 0;
}
}
p = fftw_plan_dft_2d(nt, nu, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p);
std::vector<std::vector<std::complex<double>>> ftimage(nt, std::vector<std::complex<double>>(nu));
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
ftimage[i][j] = std::complex<double>(out[i*nu + j][0], out[i*nu + j][1]);
}
}
// Generates data spectrum (by adjoint of linear interpolation)
// Note: linterpAdj function is not provided, so it's omitted here
std::vector<std::vector<std::complex<double>>> ftdata = ftimage; // Placeholder
if (tau0 != 0) {
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
ftdata[i][j] *= std::exp(std::complex<double>(0, 2 * M_PI * (fkz[i][j] - f[i][j]) * tau0));
}
}
}
// Inserts transducer model (if exists)
if (!ModTransd.empty()) {
int rowShift = (nt - ModTransd.size()) / 2;
int colShift = (nu - ModTransd[0].size()) / 2;
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
int ii = (i + rowShift) % nt;
int jj = (j + colShift) % nu;
if (ii < ModTransd.size() && jj < ModTransd[0].size()) {
ftdata[i][j] *= ModTransd[ii][jj];
} else {
ftdata[i][j] = 0;
}
}
}
}
// Converting data to time domain
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
in[i*nu + j][0] = ftdata[i][j].real();
in[i*nu + j][1] = ftdata[i][j].imag();
}
}
p = fftw_plan_dft_2d(nt, nu, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_execute(p);
std::vector<std::vector<double>> data(nt0, std::vector<double>(nu0));
for (int i = 0; i < nt0; ++i) {
for (int j = 0; j < nu0; ++j) {
data[i][j] = out[i*nu + j][0] / (nt * nu);
}
}
// Applies sub-sampling
if (R_x > 1) {
for (int i = 0; i < nt0; ++i) {
for (int j = 0; j < nu0; j += R_x) {
data[i][j/R_x] = data[i][j] * R_x;
}
}
data[0].resize(nu0/R_x);
}
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
return data;
}

89
UTSR/ModS2T.cpp Normal file
View File

@ -0,0 +1,89 @@
#include <vector>
#include <complex>
#include <cmath>
#include <algorithm>
#include <cassert>
#include <fftw3.h>
// Function declaration
std::vector<std::vector<double>> ModS2T(const std::vector<std::vector<double>>& data, double dt, double du, double ERMv, double tau0, const std::vector<std::vector<double>>& Filter, int R_x = 1) {
// Check R_x argument
R_x = std::max(1, R_x);
assert(R_x > 0 && "R_x must be positive");
std::vector<std::vector<double>> processedData = data;
// Applies linear interpolation (if necessary)
if (R_x > 1) {
// Implementation of linear interpolation
// Note: This part needs a more detailed implementation
}
// Zero-padding
int nt0 = processedData.size();
int nu0 = processedData[0].size();
int nt = std::max(static_cast<int>(std::pow(2, std::ceil(std::log2(nt0)) + 1)), static_cast<int>(Filter.size()));
int nu = std::max(2 * nu0, static_cast<int>(Filter[0].size()));
// Data and image grids
std::vector<std::vector<double>> f(nt, std::vector<double>(nu));
std::vector<std::vector<double>> ku(nt, std::vector<double>(nu));
std::vector<std::vector<double>> fkz(nt, std::vector<double>(nu));
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
f[i][j] = (i - nt/2) / (dt * nt);
ku[i][j] = (j - nu/2) / (du * nu);
fkz[i][j] = ERMv * std::copysign(1.0, f[i][j]) * std::sqrt(std::pow(ku[i][j], 2) + std::pow(f[i][j] / ERMv, 2));
}
}
// Converting data to frequency domain
std::vector<std::vector<std::complex<double>>> ftdata(nt, std::vector<std::complex<double>>(nu));
// Note: FFTW library should be used here for efficient FFT computation
if (tau0 != 0) {
for (int i = 0; i < nt; ++i) {
for (int j = 0; j < nu; ++j) {
ftdata[i][j] *= std::exp(std::complex<double>(0, -2 * M_PI * (fkz[i][j] - f[i][j]) * tau0));
}
}
}
// Applies filter (if it exists)
if (!Filter.empty()) {
// Implementation of filter application
// Note: This part needs a more detailed implementation
}
// Generating image spectrum (by linear interpolation)
std::vector<std::vector<std::complex<double>>> ftimage(nt, std::vector<std::complex<double>>(nu));
// Note: Linear interpolation should be implemented here
// Converting image to space domain
std::vector<std::vector<double>> image(nt0, std::vector<double>(nu0));
// Note: Inverse FFT should be applied here using FFTW library
for (int i = 0; i < nt0; ++i) {
for (int j = 0; j < nu0; ++j) {
image[i][j] *= R_x;
}
}
// Evaluates the gain
double enImage = 0, enData = 0;
for (const auto& row : image) {
for (double val : row) {
enImage += val * val;
}
}
for (const auto& row : data) {
for (double val : row) {
enData += val * val;
}
}
double gain = std::sqrt(enImage / enData);
return image;
}

67
UTSR/cossquare.cpp Normal file
View File

@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
// Function to check if input is a vector
bool isvector(double* f, int rows, int cols) {
return (rows == 1 || cols == 1);
}
// Function to check if input is a matrix
bool ismatrix(double* f, int rows, int cols) {
return (rows > 1 && cols > 1);
}
// Function to check if input is a scalar
bool isscalar(double* f, int rows, int cols) {
return (rows == 1 && cols == 1);
}
// Main function
double* cossquare(double* f, int rows, int cols, double fc, double BW) {
double f1 = fc - BW;
double f4 = fc + BW;
double* r = malloc(rows * cols * sizeof(double));
if (isvector(f, rows, cols)) {
int n = rows * cols;
for (int i = 0; i < n; i++) {
double ss = sin(M_PI * f[i] / (2 * fc));
bool ri1 = (fabs(f[i]) > fc) && (fabs(f[i]) <= f4);
bool ri2 = (fabs(f[i]) <= fc) && (fabs(f[i]) <= f4);
double ff1 = ri1 ? fabs(f[i]) : 0;
double ff2 = ri2 ? fabs(f[i]) : 0;
double r1 = ri1 ? pow(cos(M_PI * (fc - ff1) / (f4 - f1)), 2) : 0;
double r2 = ri2 ? ss * pow(cos(M_PI * (fc - ff2) / (f4 - f1)), 2) : 0;
r[i] = r1 + (f[i] >= 0 ? 1 : -1) * r2;
}
} else if (ismatrix(f, rows, cols)) {
for (int c = 0; c < cols; c++) {
for (int i = 0; i < rows; i++) {
double ss = sin(M_PI * f[i * cols + c] / (2 * fc));
bool ri1 = (fabs(f[i * cols + c]) > fc) && (fabs(f[i * cols + c]) <= f4);
bool ri2 = (fabs(f[i * cols + c]) <= fc) && (fabs(f[i * cols + c]) <= f4);
double ff1 = ri1 ? fabs(f[i * cols + c]) : 0;
double ff2 = ri2 ? fabs(f[i * cols + c]) : 0;
double r1 = ri1 ? pow(cos(M_PI * (fc - ff1) / (f4 - f1)), 2) : 0;
double r2 = ri2 ? ss * pow(cos(M_PI * (fc - ff2) / (f4 - f1)), 2) : 0;
r[i * cols + c] = r1 + (f[i * cols + c] >= 0 ? 1 : -1) * r2;
}
}
} else if (isscalar(f, rows, cols)) {
if ((fabs(f[0]) >= f1) && (fabs(f[0]) <= f4)) {
if (fabs(f[0]) > fc) {
r[0] = pow(cos(M_PI * (fc - fabs(f[0])) / (f4 - f1)), 2);
} else {
r[0] = sin(M_PI * f[0] / (2 * fc)) * pow(cos(M_PI * (fc - fabs(f[0])) / (f4 - f1)), 2);
}
} else {
r[0] = 0;
}
}
return r;
}

215
UTSR/datNDTread.cpp Normal file
View File

@ -0,0 +1,215 @@
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <limits>
#include <numeric>
namespace fs = std::filesystem;
struct ScanData {
struct CscanData {
int Rows;
int AscanPoints;
double TsGate;
double TendGate;
std::vector<double> X;
double Cl;
double Cs;
double Density;
double Frequency;
double Bandwidth;
char WaveType;
double BeamAngle;
double ProbeDiameter;
double MaxSdtRef;
double Y;
int Cols;
std::vector<std::vector<double>> CscanValues;
double Wavelength;
double Nearfield;
double NearfieldTime;
double ProbeEllipX;
double ProbeEllipY;
double TrueAngle;
double CalValue;
std::string DefectType;
double PosX;
double PosY;
double DepthCentre;
double Diameter;
double Height;
double Tilt;
double MaxSignal;
};
CscanData CscanData;
std::vector<std::vector<double>> AscanValues;
std::vector<double> timeScale;
};
ScanData datNDTread(const std::map<std::string, std::variant<double, std::string>>& args) {
ScanData scanData;
// Parse input arguments
double TsGate = std::get<double>(args.at("TsGate"));
double TendGate = std::get<double>(args.at("TendGate"));
double deltaT = std::get<double>(args.at("deltaT"));
double minX = std::get<double>(args.at("minX"));
double maxX = std::get<double>(args.at("maxX"));
double deltaX = std::get<double>(args.at("deltaX"));
double backDepth = std::get<double>(args.at("backDepth"));
double Density = std::get<double>(args.at("Density"));
double fc = std::get<double>(args.at("fc"));
double bw = std::get<double>(args.at("bw"));
char WaveType = std::get<std::string>(args.at("WaveType"))[0];
double BeamAngle = std::get<double>(args.at("BeamAngle"));
double d = std::get<double>(args.at("d"));
std::string baseFolder = std::get<std::string>(args.at("baseFolder"));
double gain = std::get<double>(args.at("gain"));
double A0 = std::get<double>(args.at("A0"));
double alpha = std::get<double>(args.at("alpha"));
// Get file list in base folder
std::vector<fs::path> files;
for (const auto& entry : fs::directory_iterator(baseFolder)) {
if (entry.path().extension() == ".dat") {
files.push_back(entry.path());
}
}
// Create AscanValues element
scanData.CscanData.Rows = files.size();
scanData.AscanValues.resize(scanData.CscanData.Rows);
// Import data as columns
std::vector<double> backWallIdx(files.size());
for (size_t i = 0; i < files.size(); ++i) {
std::string filename = files[i].filename().string();
int col;
sscanf(filename.c_str(), "pos%d.dat", &col);
col++;
std::vector<double> dat;
std::ifstream file(files[i]);
double value;
while (file >> value) {
dat.push_back(value);
}
size_t lenDat = dat.size();
auto idxm = std::min_element(dat.begin(), dat.begin() + lenDat / 3) - dat.begin();
auto limIdx = std::min_element(dat.begin() + 2 * lenDat / 3, dat.end()) - dat.begin();
auto idx2m = std::max_element(dat.begin() + 2 * lenDat / 3, dat.begin() + limIdx) - dat.begin();
backWallIdx[col - 1] = idx2m - idxm;
scanData.AscanValues[col - 1].resize(lenDat, 0);
std::copy(dat.begin() + idxm, dat.end(), scanData.AscanValues[col - 1].begin());
}
// Create timeScale element
scanData.CscanData.AscanPoints = scanData.AscanValues[0].size();
scanData.timeScale.resize(scanData.CscanData.AscanPoints);
std::iota(scanData.timeScale.begin(), scanData.timeScale.end(), 0);
std::transform(scanData.timeScale.begin(), scanData.timeScale.end(), scanData.timeScale.begin(),
[deltaT](double x) { return x * deltaT; });
// Define the time window for simulation
std::vector<double> t;
for (double time = TsGate; time <= TendGate; time += deltaT) {
t.push_back(time);
}
size_t nt = t.size();
size_t idxTsGate = std::lower_bound(t.begin(), t.end(), TsGate) - t.begin();
size_t idxTendGate = std::lower_bound(t.begin(), t.end(), TendGate) - t.begin();
// Update scanData with arguments values
scanData.CscanData.TsGate = TsGate;
scanData.CscanData.TendGate = TendGate;
scanData.CscanData.X.resize(scanData.CscanData.Rows);
std::iota(scanData.CscanData.X.begin(), scanData.CscanData.X.end(), 0);
std::transform(scanData.CscanData.X.begin(), scanData.CscanData.X.end(), scanData.CscanData.X.begin(),
[deltaX](double x) { return x * deltaX; });
std::vector<double> backWallIdxEnds = {backWallIdx.front(), backWallIdx.back()};
double Cl = backDepth * 2000 / std::accumulate(backWallIdxEnds.begin(), backWallIdxEnds.end(), 0.0,
[&](double sum, double idx) { return sum + scanData.timeScale[idx]; });
scanData.CscanData.Cl = Cl;
scanData.CscanData.Cs = 0;
scanData.CscanData.Density = Density;
scanData.CscanData.Frequency = fc;
scanData.CscanData.Bandwidth = bw;
scanData.CscanData.WaveType = WaveType;
scanData.CscanData.BeamAngle = BeamAngle;
scanData.CscanData.ProbeDiameter = d;
// Others elements
scanData.CscanData.MaxSdtRef = 0;
scanData.CscanData.Y = 0;
scanData.CscanData.Cols = 1;
scanData.CscanData.CscanValues.resize(scanData.CscanData.Rows, std::vector<double>(scanData.CscanData.Cols, 0));
double c = (WaveType == 'L' || WaveType == 'l') ? scanData.CscanData.Cl : scanData.CscanData.Cs;
scanData.CscanData.Wavelength = c / (scanData.CscanData.Frequency * 1000);
scanData.CscanData.Nearfield = std::pow(scanData.CscanData.ProbeDiameter / 2, 2) / scanData.CscanData.Wavelength;
scanData.CscanData.NearfieldTime = scanData.CscanData.Nearfield / (c / 2000);
scanData.CscanData.ProbeEllipX = 0;
scanData.CscanData.ProbeEllipY = 0;
scanData.CscanData.TrueAngle = scanData.CscanData.BeamAngle;
scanData.CscanData.CalValue = 0;
scanData.CscanData.DefectType = "empty";
scanData.CscanData.PosX = 0;
scanData.CscanData.PosY = 0;
scanData.CscanData.DepthCentre = 0;
scanData.CscanData.Diameter = 0;
scanData.CscanData.Height = 0;
scanData.CscanData.Tilt = 0;
// Adjust A-scan amplitude
if (std::isinf(gain)) {
double MaxSignal = 0;
for (const auto& ascan : scanData.AscanValues) {
MaxSignal = std::max(MaxSignal, *std::max_element(ascan.begin(), ascan.end(), [](double a, double b) { return std::abs(a) < std::abs(b); }));
}
for (auto& ascan : scanData.AscanValues) {
std::transform(ascan.begin(), ascan.end(), ascan.begin(), [MaxSignal](double x) { return x / MaxSignal; });
}
} else {
double gainFactor = std::pow(10, gain / 20);
for (auto& ascan : scanData.AscanValues) {
std::transform(ascan.begin(), ascan.end(), ascan.begin(), [gainFactor](double x) { return (0.5 / 2048 / gainFactor) * x; });
}
}
// Apply TGV
std::vector<double> zz(scanData.timeScale.size());
std::transform(scanData.timeScale.begin(), scanData.timeScale.end(), zz.begin(), [Cl](double t) { return t * Cl / 2000; });
std::vector<double> ffc(zz.size());
std::transform(zz.begin(), zz.end(), ffc.begin(), [A0, alpha](double z) { return std::max(1.0, (1 / A0) * std::exp(alpha * z)); });
for (auto& ascan : scanData.AscanValues) {
std::transform(ascan.begin(), ascan.end(), ffc.begin(), ascan.begin(), std::multiplies<double>());
}
// Calculate elements after the simulation session
scanData.CscanData.MaxSignal = 0;
for (const auto& ascan : scanData.AscanValues) {
scanData.CscanData.MaxSignal = std::max(scanData.CscanData.MaxSignal, *std::max_element(ascan.begin(), ascan.end(), [](double a, double b) { return std::abs(a) < std::abs(b); }));
}
for (size_t i = 0; i < scanData.CscanData.Rows; ++i) {
double maxAbs = *std::max_element(scanData.AscanValues[i].begin(), scanData.AscanValues[i].end(), [](double a, double b) { return std::abs(a) < std::abs(b); });
scanData.CscanData.CscanValues[i][0] = 10 * std::log10(maxAbs);
}
return scanData;
}

73
UTSR/linterp.cpp Normal file
View File

@ -0,0 +1,73 @@
#include <vector>
#include <algorithm>
#include <cmath>
std::vector<std::vector<double>> linterp(const std::vector<double>& X, const std::vector<std::vector<double>>& V, const std::vector<std::vector<double>>& Xq) {
// Ensure X is a column vector
std::vector<double> X_col = X;
// Ensure V is a column vector if it's a 1D vector
std::vector<std::vector<double>> V_col = V;
if (V.size() == 1) {
V_col = std::vector<std::vector<double>>(V[0].size(), std::vector<double>(1));
for (size_t i = 0; i < V[0].size(); ++i) {
V_col[i][0] = V[0][i];
}
}
// Ensure Xq is a column vector if it's a 1D vector
std::vector<std::vector<double>> Xq_col = Xq;
if (Xq.size() == 1) {
Xq_col = std::vector<std::vector<double>>(Xq[0].size(), std::vector<double>(1));
for (size_t i = 0; i < Xq[0].size(); ++i) {
Xq_col[i][0] = Xq[0][i];
}
}
// Allocate output variable space
std::vector<std::vector<double>> Vq(Xq_col.size(), std::vector<double>(Xq_col[0].size(), 0.0));
double dX = X_col[1] - X_col[0];
size_t N = V_col.size();
// Loop every Xq column
for (size_t col = 0; col < Xq_col[0].size(); ++col) {
// Calculate Xq shifts
std::vector<double> f;
std::vector<bool> fMask(Xq_col.size(), false);
for (size_t i = 0; i < Xq_col.size(); ++i) {
if (Xq_col[i][col] >= X_col[0] && Xq_col[i][col] <= X_col.back()) {
f.push_back((Xq_col[i][col] - X_col[0]) / dX);
fMask[i] = true;
}
}
// Calculate Xq index
std::vector<size_t> im(f.size());
for (size_t i = 0; i < f.size(); ++i) {
im[i] = static_cast<size_t>(std::floor(f[i]));
}
size_t im2Inval = std::count_if(im.begin(), im.end(), [N](size_t i) { return i + 2 > N; });
// Calculate interpolation factors
std::vector<double> fx(f.size()), gx(f.size());
for (size_t i = 0; i < f.size(); ++i) {
fx[i] = f[i] - im[i];
gx[i] = 1 - fx[i];
}
// Interpolate Vq values
size_t j = 0;
for (size_t i = 0; i < Xq_col.size(); ++i) {
if (fMask[i]) {
if (im2Inval > 0 && j >= f.size() - im2Inval) {
Vq[i][col] = gx[j] * V_col[im[j] + 1][col] + fx[j] * 0.0;
} else {
Vq[i][col] = gx[j] * V_col[im[j] + 1][col] + fx[j] * V_col[im[j] + 2][col];
}
++j;
}
}
}
return Vq;
}

88
UTSR/linterpAdj.cpp Normal file
View File

@ -0,0 +1,88 @@
#include <vector>
#include <algorithm>
#include <cmath>
#include <numeric>
std::vector<std::vector<double>> linterpAdj(const std::vector<double>& X, const std::vector<std::vector<double>>& Xq, const std::vector<std::vector<double>>& Vq) {
// Ensure X is a column vector
std::vector<double> X_col = X;
// Ensure Vq is a column vector if it's a 1D vector
std::vector<std::vector<double>> Vq_col = Vq;
if (Vq.size() == 1) {
Vq_col = std::vector<std::vector<double>>(Vq[0].size(), std::vector<double>(1));
for (size_t i = 0; i < Vq[0].size(); ++i) {
Vq_col[i][0] = Vq[0][i];
}
}
// Ensure Xq is a column vector if it's a 1D vector
std::vector<std::vector<double>> Xq_col = Xq;
if (Xq.size() == 1) {
Xq_col = std::vector<std::vector<double>>(Xq[0].size(), std::vector<double>(1));
for (size_t i = 0; i < Xq[0].size(); ++i) {
Xq_col[i][0] = Xq[0][i];
}
}
// Allocate output variable space
std::vector<std::vector<double>> V(X_col.size(), std::vector<double>(Xq_col[0].size(), 0.0));
double dX = X_col[1] - X_col[0];
size_t N = V.size();
// Loop every Xq column
for (size_t col = 0; col < Xq_col[0].size(); ++col) {
// Calculate Xq shifts
std::vector<double> f;
std::vector<bool> fMask;
for (size_t i = 0; i < Xq_col.size(); ++i) {
double shift = (Xq_col[i][col] - X_col[0]) / dX;
if (Xq_col[i][col] >= X_col[0] && Xq_col[i][col] <= X_col.back()) {
f.push_back(shift);
fMask.push_back(true);
} else {
fMask.push_back(false);
}
}
// Calculate Xq index
std::vector<size_t> im(f.size());
for (size_t i = 0; i < f.size(); ++i) {
im[i] = static_cast<size_t>(std::floor(f[i]));
}
size_t im2Inval = std::count_if(im.begin(), im.end(), [N](size_t i) { return i + 2 > N; });
// Calculate interpolation factors
std::vector<double> fx(f.size()), gx(f.size());
for (size_t i = 0; i < f.size(); ++i) {
fx[i] = f[i] - im[i];
gx[i] = 1 - fx[i];
}
// Calculate adjoint interpolation
std::vector<double> VqM;
for (size_t i = 0; i < fMask.size(); ++i) {
if (fMask[i]) {
VqM.push_back(Vq_col[i][col]);
}
}
std::vector<double> pG(N, 0.0), pF(N, 0.0);
for (size_t i = 0; i < im.size(); ++i) {
pG[im[i] + 1] += gx[i] * VqM[i];
if (im[i] + 2 <= N) {
pF[im[i] + 2] += fx[i] * VqM[i];
}
}
pF.resize(N - im2Inval);
for (size_t i = 0; i < N; ++i) {
V[i][col] = pG[i] + (i < pF.size() ? pF[i] : 0.0);
}
}
return V;
}