Skip to content

Commit 88c0d03

Browse files
committed
Interpolate velocity history for radiation convolution
1 parent 0a58e4a commit 88c0d03

2 files changed

Lines changed: 89 additions & 97 deletions

File tree

include/hydroc/hydro_forces.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,10 +246,10 @@ class TestHydro {
246246
std::vector<double> cb_minus_cg_;
247247
double rirf_timestep_;
248248
Eigen::VectorXd rirf_time_vector; // Assumed consistent for each body
249-
int offset_rirf; // For managing the circular nature of velocity history in convolution
250249

251250
// Properties for velocity history management and time tracking
252-
std::vector<double> velocity_history_;
251+
std::vector<std::vector<std::vector<double>>> velocity_history_;
252+
std::vector<double> time_history_;
253253
double prev_time;
254254

255255
// Added mass related properties

src/hydro_forces.cpp

Lines changed: 87 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
#include <chrono/physics/ChLoad.h>
1515
#include <unsupported/Eigen/Splines>
1616

17+
#include <Eigen/Dense>
1718
#include <algorithm>
1819
#include <cmath>
20+
#include <fstream>
21+
#include <iostream>
1922
#include <memory>
2023
#include <numeric> // std::accumulate
2124
#include <random>
22-
#include <vector>
23-
#include <Eigen/Dense>
24-
#include <fstream>
25-
#include <iostream>
2625
#include <stdexcept>
26+
#include <vector>
2727

2828
const int kDofPerBody = 6;
2929
const int kDofLinOrRot = 3;
@@ -96,7 +96,7 @@ ForceFunc6d::ForceFunc6d() : forces_{{this, 0}, {this, 1}, {this, 2}, {this, 3},
9696

9797
ForceFunc6d::ForceFunc6d(std::shared_ptr<ChBody> object, TestHydro* user_all_forces) : ForceFunc6d() {
9898
body_ = object;
99-
std::string temp = body_->GetNameString(); // remove "body" from "bodyN", convert N to int, get body num
99+
std::string temp = body_->GetNameString(); // remove "body" from "bodyN", convert N to int, get body num
100100
b_num_ = stoi(temp.erase(0, 4)); // 1 indexed TODO: fix b_num starting here to be 0 indexed
101101
all_hydro_forces_ = user_all_forces; // TODO switch to smart pointers? does this use = ?
102102
if (all_hydro_forces_ == NULL) {
@@ -166,9 +166,7 @@ TestHydro::TestHydro(std::vector<std::shared_ptr<ChBody>> user_bodies,
166166
: bodies_(user_bodies),
167167
num_bodies_(bodies_.size()),
168168
file_info_(H5FileInfo(h5_file_name, num_bodies_).ReadH5Data()) {
169-
170-
prev_time = -1;
171-
offset_rirf = 0;
169+
prev_time = -1;
172170

173171
// Set up time vector
174172
rirf_time_vector = file_info_.GetRIRFTimeVector();
@@ -178,7 +176,11 @@ TestHydro::TestHydro(std::vector<std::shared_ptr<ChBody>> user_bodies,
178176
int total_dofs = kDofPerBody * num_bodies_;
179177

180178
// Initialize vectors
181-
velocity_history_.assign(file_info_.GetRIRFDims(2) * total_dofs, 0.0);
179+
time_history_.clear();
180+
velocity_history_.clear();
181+
for (int b = 0; b < num_bodies_; ++b) {
182+
velocity_history_.push_back(std::vector<std::vector<double>>(0));
183+
}
182184
force_hydrostatic_.assign(total_dofs, 0.0);
183185
force_radiation_damping_.assign(total_dofs, 0.0);
184186
total_force_.assign(total_dofs, 0.0);
@@ -238,48 +240,12 @@ void TestHydro::AddWaves(std::shared_ptr<WaveBase> waves) {
238240
user_waves_->Initialize();
239241
}
240242

241-
double TestHydro::GetVelHistoryVal(int step, int c) const {
242-
if (step < 0 || step >= file_info_.GetRIRFDims(2) || c < 0 || c >= num_bodies_ * kDofPerBody) {
243-
std::cout << "wrong vel history index " << std::endl;
244-
return 0;
245-
}
246-
247-
int index = c % kDofPerBody;
248-
int b = c / kDofPerBody; // 0 indexed
249-
int calculated_index = index + (kDofPerBody * b) + (kDofPerBody * num_bodies_ * step);
250-
251-
if (calculated_index >= num_bodies_ * kDofPerBody * file_info_.GetRIRFDims(2) || calculated_index < 0) {
252-
std::cout << "bad vel history math" << std::endl;
253-
return 0;
254-
}
255-
256-
return velocity_history_[calculated_index];
257-
}
258-
259-
double TestHydro::SetVelHistory(double val, int step, int b_num, int index) {
260-
if (step < 0 || step >= file_info_.GetRIRFDims(2) || b_num < 1 || b_num > num_bodies_ || index < 0 ||
261-
index >= kDofPerBody) {
262-
std::cout << "bad set vel history indexing" << std::endl;
263-
return 0;
264-
}
265-
266-
int calculated_index = index + (kDofPerBody * (b_num - 1)) + (kDofPerBody * num_bodies_ * step);
267-
268-
if (calculated_index < 0 || calculated_index >= num_bodies_ * kDofPerBody * file_info_.GetRIRFDims(2)) {
269-
std::cout << "bad set vel history math" << std::endl;
270-
return 0;
271-
}
272-
273-
velocity_history_[calculated_index] = val;
274-
return val;
275-
}
276-
277243
std::vector<double> TestHydro::ComputeForceHydrostatics() {
278244
assert(num_bodies_ > 0);
279245

280-
const double rho = file_info_.GetRhoVal();
281-
const auto g_acc = bodies_[0]->GetSystem()->Get_G_acc(); // assuming all bodies in same system
282-
const double gg = g_acc.Length();
246+
const double rho = file_info_.GetRhoVal();
247+
const auto g_acc = bodies_[0]->GetSystem()->Get_G_acc(); // assuming all bodies in same system
248+
const double gg = g_acc.Length();
283249

284250
for (int b = 0; b < num_bodies_; b++) {
285251
std::shared_ptr<chrono::ChBody> body = bodies_[b];
@@ -294,7 +260,7 @@ std::vector<double> TestHydro::ComputeForceHydrostatics() {
294260

295261
chrono::ChVectorN<double, kDofPerBody> body_displacement;
296262
for (int ii = 0; ii < kDofLinOrRot; ii++) {
297-
body_displacement[ii] = body_position[ii] - body_equilibrium[ii];
263+
body_displacement[ii] = body_position[ii] - body_equilibrium[ii];
298264
body_displacement[ii + kDofLinOrRot] = body_rotation[ii] - body_equilibrium[ii + kDofLinOrRot];
299265
}
300266

@@ -328,69 +294,95 @@ std::vector<double> TestHydro::ComputeForceRadiationDampingConv() {
328294
const int numRows = kDofPerBody * num_bodies_;
329295
const int numCols = kDofPerBody * num_bodies_;
330296

331-
// "Shift" everything left 1
332-
offset_rirf--; // Starts as 0 before timestep change
333-
334-
// Keep offset close to 0, avoids small chance of overflow errors in long simulations
335-
if (offset_rirf < -1 * size) {
336-
offset_rirf += size;
337-
}
338-
339297
assert(numRows * size > 0 && numCols > 0);
340298

341-
std::vector<double> timeseries(numRows * numCols * size, 0.0);
342299
std::vector<double> tmp_s(numRows * size, 0.0);
343300

344-
// Helper function for timeseries indexing
345-
auto TimeseriesIndex = [&](int row, int col, int step) { return (row * numCols * size) + (col * size) + step; };
346-
347301
// Helper function for tmp_s indexing
348302
auto TmpSIndex = [&](int row, int step) { return (row * size) + step; };
349303

350-
// Helper function for circular indexing
351-
auto CircularIndex = [&](int value) { return ((value % size) + size) % size; };
304+
// time history
305+
auto t_sim = bodies_[0]->GetChTime();
306+
auto t_min = t_sim - rirf_timestep_ * size;
307+
time_history_.insert(time_history_.begin(), t_sim);
308+
309+
// velocity history
310+
for (int b = 0; b < num_bodies_; b++) {
311+
auto& body = bodies_[b];
312+
auto& velocity_history_body = velocity_history_[b];
352313

353-
// Set last entry as velocity
354-
for (int i = 0; i < 3; i++) {
355-
for (int b = 1; b <= num_bodies_; b++) {
356-
int vi = CircularIndex(size + offset_rirf);
357-
SetVelHistory(bodies_[b - 1]->GetPos_dt()[i], vi, b, i);
358-
SetVelHistory(bodies_[b - 1]->GetWvel_par()[i], vi, b, i + 3);
314+
auto vel = body->GetPos_dt();
315+
auto wvel = body->GetWvel_par();
316+
std::vector<double> vel_vec = {vel[0], vel[1], vel[2], wvel[0], wvel[1], wvel[2]};
317+
velocity_history_body.insert(velocity_history_body.begin(), vel_vec);
318+
}
319+
320+
// remove unnecessary history
321+
if (time_history_.size() > 1) {
322+
while (time_history_[time_history_.size() - 2] < t_min) {
323+
time_history_.pop_back();
324+
for (int b = 0; b < num_bodies_; b++) {
325+
auto& velocity_history_body = velocity_history_[b];
326+
velocity_history_body.pop_back();
327+
}
359328
}
360329
}
361330

362-
if (convTrapz_) {
363-
for (int row = 0; row < numRows; row++) {
364-
for (int st = 0; st < size; st++) {
365-
int vi = CircularIndex(st + offset_rirf);
366-
tmp_s[TmpSIndex(row, st)] = 0;
367-
for (int col = 0; col < numCols; col++) {
368-
timeseries[TimeseriesIndex(row, col, st)] = GetRIRFval(row, col, st) * GetVelHistoryVal(vi, col);
369-
tmp_s[TmpSIndex(row, st)] += timeseries[TimeseriesIndex(row, col, st)];
331+
if (convTrapz_ && time_history_.size() > 1) {
332+
int idx_history = 0;
333+
334+
// iterate over RIRF steps
335+
for (int step = 0; step < size; step++) {
336+
auto t_rirf = t_sim - rirf_timestep_ * step;
337+
while (time_history_[idx_history + 1] > t_rirf && idx_history < time_history_.size() - 1) {
338+
idx_history += 1;
339+
}
340+
if (idx_history >= time_history_.size() - 1) {
341+
break;
342+
}
343+
344+
// iterate over bodies
345+
for (int idx_body = 0; idx_body < num_bodies_; idx_body++) {
346+
auto& velocity_history_body = velocity_history_[idx_body];
347+
348+
// interpolate velocity at t_rirf from recorded velocity history
349+
// time values
350+
auto t1 = time_history_[idx_history + 1];
351+
auto t2 = time_history_[idx_history];
352+
if (t_rirf < t1 || t_rirf > t2) {
353+
throw std::runtime_error("Radiation convolution: wrong interpolation: " + std::to_string(t_rirf) +
354+
" not between " + std::to_string(t1) + " and " + std::to_string(t2) + ".");
355+
}
356+
// weights
357+
auto w1 = (t2 - t_rirf) / (t2 - t1);
358+
auto w2 = 1.0 - w1;
359+
// velocity values
360+
auto vel1 = velocity_history_body[idx_history + 1];
361+
auto vel2 = velocity_history_body[idx_history];
362+
363+
for (int dof = 0; dof < kDofPerBody; dof++) {
364+
// get column index
365+
int col = dof + idx_body * kDofPerBody;
366+
// get weighted velocity for DOF
367+
auto vel_weighted = w1 * vel1[dof] + w2 * vel2[dof];
368+
369+
// iterate over rows
370+
for (int row = 0; row < numRows; row++) {
371+
tmp_s[TmpSIndex(row, step)] += GetRIRFval(row, col, step) * vel_weighted;
372+
}
370373
}
371-
if (st > 0) {
374+
}
375+
376+
if (step > 0) {
377+
// cummulate values for current step on all rows
378+
for (int row = 0; row < numRows; row++) {
372379
// Integrate tmp_s
373-
force_radiation_damping_[row] += (tmp_s[TmpSIndex(row, st - 1)] + tmp_s[TmpSIndex(row, st)]) / 2.0 *
374-
(rirf_time_vector[st] - rirf_time_vector[st - 1]);
380+
force_radiation_damping_[row] += (tmp_s[TmpSIndex(row, step - 1)] + tmp_s[TmpSIndex(row, step)]) /
381+
2.0 * (rirf_time_vector[step] - rirf_time_vector[step - 1]);
375382
}
376383
}
377384
}
378385
}
379-
//else {
380-
// // Convolution integral assuming fixed dt
381-
// for (int row = 0; row < numRows; row++) {
382-
// double sumVelHistoryAndRIRF = 0.0;
383-
// for (int col = 0; col < numCols; col++) {
384-
// for (int st = 0; st < size; st++) {
385-
// int vi = CircularIndex(st + offset_rirf);
386-
// timeseries[TimeseriesIndex(row, col, st)] = GetRIRFval(row, col, st) * GetVelHistoryVal(vi, col);
387-
// sumVelHistoryAndRIRF += timeseries[TimeseriesIndex(row, col, st)];
388-
// }
389-
// }
390-
// force_radiation_damping_[row] -= sumVelHistoryAndRIRF * rirf_timestep;
391-
// }
392-
//}
393-
394386
return force_radiation_damping_;
395387
}
396388

0 commit comments

Comments
 (0)