Skip to content

Commit ec7f172

Browse files
committed
fix irregular waves & export of data to .h5 file
1 parent f9bc2de commit ec7f172

8 files changed

Lines changed: 87 additions & 40 deletions

File tree

include/hydroc/hydro_forces.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ class TestHydro {
218218
* @return 6N dimensional force for 6 DOF and N bodies in system (already Eigen type).
219219
*/
220220
Eigen::VectorXd ComputeForceWaves();
221+
// Expose the wave object (read-only) so callers can query inputs if needed
222+
std::shared_ptr<WaveBase> GetWave() const { return user_waves_; }
221223

222224
/**
223225
* @brief Fetches the RIRF value from the h5 file based on the provided indices.

include/hydroc/simulation_exporter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ class SimulationExporter {
133133
*/
134134
void Finalize();
135135

136+
/**
137+
* @brief Write irregular wave input arrays under /inputs/simulation/waves/irregular.
138+
*
139+
* All arrays are 1D and written with attributes documenting units.
140+
*/
141+
void WriteIrregularInputs(const std::vector<double>& frequencies_hz,
142+
const std::vector<double>& spectral_densities,
143+
const std::vector<double>& free_surface_time,
144+
const std::vector<double>& free_surface_eta);
145+
136146

137147

138148
// Runtime metadata (written into /meta/run at Finalize)

include/hydroc/wave_types.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,9 +297,14 @@ class IrregularWaves : public WaveBase {
297297
void Initialize() override {}
298298

299299
void CreateSpectrum();
300+
// Returns spectral density values S(f) (one per frequency bin)
300301
std::vector<double> GetSpectrum();
302+
// Returns precomputed free-surface elevation eta(t) samples
301303
std::vector<double> GetFreeSurfaceElevation();
302-
std::vector<double> GetEtaTimeData();
304+
// Returns time samples corresponding to eta(t)
305+
std::vector<double> GetFreeSurfaceTime() const;
306+
// Returns the frequency bins (Hz)
307+
std::vector<double> GetFrequenciesHz() const;
303308

304309
Eigen::VectorXd GetForceAtTime(double t) override;
305310

src/hydro_forces.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ TestHydro::TestHydro(std::vector<std::shared_ptr<ChBody>> user_bodies,
236236
// Set up hydro inputs
237237
user_waves_ = waves;
238238
AddWaves(user_waves_);
239+
240+
// If irregular waves are active, publish spectrum and free-surface inputs into HDF5 if an exporter is present.
241+
// The exporter is managed by the runner; here we only expose getters via the waves object.
239242
}
240243

241244
void TestHydro::AddWaves(std::shared_ptr<WaveBase> waves) {

src/hydrochrono_runner/run_hydrochrono_from_yaml.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "../hydro_yaml_parser.h"
66
#include <hydroc/hydro_forces.h>
77
#include <hydroc/simulation_exporter.h>
8+
#include <hydroc/wave_types.h>
89

910
#include <chrono_parsers/yaml/ChParserMbsYAML.h>
1011
#include <chrono/physics/ChSystem.h>
@@ -450,8 +451,10 @@ int RunHydroChronoFromYAML(int argc, char* argv[]) {
450451

451452
// Setup hydrodynamic forces
452453
hydroc::debug::LogDebug("Initializing TestHydro...");
453-
// Provide a neutral horizon (Chrono governs runtime via YAML/UI)
454-
test_hydro = SetupHydroFromYAML(hydro_data, bodies, loop_dt, /*time_end_hint*/ 0.0, 0.0);
454+
// Provide simulation horizon from YAML end_time (important for irregular waves spectrum)
455+
double sim_duration_hint = 0.0;
456+
TryFindYamlDouble(sim_file, "end_time", sim_duration_hint);
457+
test_hydro = SetupHydroFromYAML(hydro_data, bodies, loop_dt, sim_duration_hint, 0.0);
455458
hydroc::debug::LogDebug("Hydrodynamic forces initialized successfully");
456459

457460
// Inform location for diagnostics CSVs: write to hydro file directory
@@ -657,9 +660,23 @@ int RunHydroChronoFromYAML(int argc, char* argv[]) {
657660
exporter = std::make_unique<hydroc::SimulationExporter>(exp_opts);
658661

659662
// Write static info and model before stepping
660-
exporter->WriteSimulationInfo(system.get(), std::string(""), std::filesystem::path(model_file).filename().generic_string(), loop_dt, /*duration_seconds*/ 0.0);
663+
double duration_hint = 0.0; TryFindYamlDouble(sim_file, "end_time", duration_hint);
664+
exporter->WriteSimulationInfo(system.get(), std::string(""), std::filesystem::path(model_file).filename().generic_string(), loop_dt, duration_hint);
661665
exporter->WriteModel(system.get());
662666
exporter->BeginResults(system.get(), /*expected_steps*/ 0);
667+
668+
// If irregular waves are configured, persist spectrum and eta(t) inputs to HDF5
669+
if (test_hydro) {
670+
auto wave_ptr = test_hydro->GetWave();
671+
if (wave_ptr && wave_ptr->GetWaveMode() == WaveMode::irregular) {
672+
auto irreg = std::static_pointer_cast<IrregularWaves>(wave_ptr);
673+
std::vector<double> f = irreg->GetFrequenciesHz();
674+
std::vector<double> S = irreg->GetSpectrum();
675+
std::vector<double> tvec = irreg->GetFreeSurfaceTime();
676+
std::vector<double> eta = irreg->GetFreeSurfaceElevation();
677+
exporter->WriteIrregularInputs(f, S, tvec, eta);
678+
}
679+
}
663680
} catch (const std::exception& e) {
664681
hydroc::cli::LogWarning(std::string("HDF5 exporter disabled: ") + e.what());
665682
exporter.reset();

src/setup_hydro_from_yaml.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ std::shared_ptr<WaveBase> CreateWaveFromSettings(const WaveSettings& wave_settin
5656
params.ramp_duration_ = ramp_duration;
5757
params.wave_height_ = wave_settings.height;
5858
params.wave_period_ = wave_settings.period;
59-
params.seed_ = 1; // Default seed, could be made configurable
59+
// Use YAML-provided seed if available; fall back to a default deterministic seed
60+
params.seed_ = (wave_settings.seed > 0 ? wave_settings.seed : 1);
6061

6162
auto irregular_wave = std::make_shared<IrregularWaves>(params);
6263

src/simulation_exporter.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <hydroc/simulation_exporter.h>
77
#include <hydroc/h5_writer.h>
8+
#include <hydroc/wave_types.h>
89
#include <hydroc/version.h>
910
#include <hydroc/logging.h>
1011

@@ -81,6 +82,8 @@ struct SimulationExporter::Impl {
8182
H5Writer::Group g_results_model_tsdas;
8283
H5Writer::Group g_results_model_rsdas;
8384
H5Writer::Group g_results_model_joints;
85+
// irregular waves datasets (inputs)
86+
H5Writer::Group g_inputs_waves_irregular;
8487
// meta subtree
8588
H5Writer::Group g_meta;
8689

@@ -184,6 +187,7 @@ struct SimulationExporter::Impl {
184187
g_inputs_sim_time = writer.RequireGroup("/inputs/simulation/time");
185188
g_inputs_sim_env = writer.RequireGroup("/inputs/simulation/environment");
186189
g_inputs_sim_waves = writer.RequireGroup("/inputs/simulation/waves");
190+
g_inputs_waves_irregular = writer.RequireGroup("/inputs/simulation/waves/irregular");
187191
// results
188192
g_results = writer.RequireGroup("/results");
189193
g_results_model = writer.RequireGroup("/results/model");
@@ -347,6 +351,7 @@ void SimulationExporter::WriteSimulationInfo(chrono::ChSystem* system,
347351
g_waves.WriteAttribute("Hs", impl_->options.scenario_Hs);
348352
g_waves.WriteAttribute("Tp", impl_->options.scenario_Tp);
349353
if (impl_->options.scenario_seed >= 0) g_waves.WriteAttribute("seed", static_cast<double>(impl_->options.scenario_seed));
354+
// Group already reserved in ctor; datasets will be written later if available
350355
}
351356
}
352357

@@ -357,6 +362,36 @@ void SimulationExporter::WriteInitialConditions(chrono::ChSystem* ,
357362
double ) {
358363
// Deprecated in schema v0.3: handled in WriteSimulationInfo under inputs/simulation/*
359364
}
365+
void SimulationExporter::WriteIrregularInputs(const std::vector<double>& frequencies_hz,
366+
const std::vector<double>& spectral_densities,
367+
const std::vector<double>& free_surface_time,
368+
const std::vector<double>& free_surface_eta) {
369+
auto g = impl_->g_inputs_waves_irregular;
370+
// Write datasets if provided (skip empty vectors)
371+
if (!frequencies_hz.empty()) {
372+
std::array<hsize_t,1> d1 = {static_cast<hsize_t>(frequencies_hz.size())};
373+
g.WriteDataset("frequencies_hz", frequencies_hz, d1);
374+
g.WriteAttribute("frequencies_hz.units", std::string("Hz"));
375+
}
376+
if (!spectral_densities.empty()) {
377+
std::array<hsize_t,1> d1 = {static_cast<hsize_t>(spectral_densities.size())};
378+
g.WriteDataset("spectral_densities", spectral_densities, d1);
379+
g.WriteAttribute("spectral_densities.units", std::string("m^2/Hz"));
380+
g.WriteAttribute("spectral_densities.convention", std::string("JONSWAP (if gamma>1), else PM"));
381+
}
382+
if (!free_surface_time.empty()) {
383+
std::array<hsize_t,1> d1 = {static_cast<hsize_t>(free_surface_time.size())};
384+
g.WriteDataset("free_surface_time", free_surface_time, d1);
385+
g.WriteAttribute("free_surface_time.units", std::string("s"));
386+
}
387+
if (!free_surface_eta.empty()) {
388+
std::array<hsize_t,1> d1 = {static_cast<hsize_t>(free_surface_eta.size())};
389+
g.WriteDataset("free_surface_eta", free_surface_eta, d1);
390+
g.WriteAttribute("free_surface_eta.units", std::string("m"));
391+
g.WriteAttribute("free_surface_eta.location", std::string("x=0,y=0,z=0 (assumed)"));
392+
}
393+
}
394+
360395

361396
void SimulationExporter::WriteModel(chrono::ChSystem* system) {
362397
if (system == nullptr) {

src/wave_types.cpp

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,11 @@ std::vector<double> IrregularWaves::GetFreeSurfaceElevation() {
470470
return free_surface_elevation_sampled_;
471471
}
472472

473-
std::vector<double> IrregularWaves::GetEtaTimeData() {
474-
return time_data_;
473+
std::vector<double> IrregularWaves::GetFreeSurfaceTime() const { return free_surface_time_sampled_; }
474+
std::vector<double> IrregularWaves::GetFrequenciesHz() const {
475+
std::vector<double> out(spectrum_frequencies_.size());
476+
for (int i = 0; i < spectrum_frequencies_.size(); ++i) out[i] = spectrum_frequencies_[i];
477+
return out;
475478
}
476479

477480
void IrregularWaves::ReadEtaFromFile() {
@@ -669,22 +672,7 @@ void IrregularWaves::CreateSpectrum() {
669672
auto omegas = 2 * M_PI * spectrum_frequencies_;
670673
wavenumbers_ = ComputeWaveNumbers(omegas, water_depth_, g_);
671674

672-
// Open a file stream for writing
673-
std::ofstream outputFile("spectral_densities.txt");
674-
outputFile.precision(9);
675-
676-
// Check if the file stream is open
677-
if (outputFile.is_open()) {
678-
// Write the spectral densities and their corresponding frequencies to the file
679-
for (size_t i = 0; i < spectral_densities_.size(); ++i) {
680-
outputFile << spectrum_frequencies_[i] << " : " << spectral_densities_[i] << std::endl;
681-
}
682-
683-
// Close the file stream
684-
outputFile.close();
685-
} else {
686-
hydroc::cli::LogError("Unable to open file for writing.");
687-
}
675+
// Removed text file dump; this data will be written into HDF5 by the exporter when available.
688676
}
689677

690678
// TODO put spectrum functions in a new namespace (when we have more options?)
@@ -780,21 +768,7 @@ void IrregularWaves::CreateFreeSurfaceElevation() {
780768
}
781769
}
782770

783-
// Open a file stream for writing
784-
std::ofstream eta_output("eta.txt");
785-
eta_output.precision(9);
786-
787-
// Check if the file stream is open
788-
if (eta_output.is_open()) {
789-
// Write the spectral densities and their corresponding frequencies to the file
790-
for (size_t i = 0; i < free_surface_elevation_sampled_.size(); ++i) {
791-
eta_output << free_surface_time_sampled_[i] << " : " << free_surface_elevation_sampled_[i] << std::endl;
792-
}
793-
// Close the file stream
794-
eta_output.close();
795-
} else {
796-
hydroc::cli::LogError("Unable to open file for writing.");
797-
}
771+
// Removed text file dump; this data will be written into HDF5 by the exporter when available.
798772

799773
hydroc::debug::LogDebug("Finished precalculating free surface elevation.");
800774
}
@@ -836,9 +810,9 @@ double IrregularWaves::ExcitationConvolution(int body, int dof, double time) {
836810
// get free surface elevation
837811
double eta_val;
838812
if (t_tau == t1) {
839-
eta_val = free_surface_time_sampled_[idx];
813+
eta_val = free_surface_elevation_sampled_[idx];
840814
} else if (t_tau == t2) {
841-
eta_val = free_surface_time_sampled_[idx + 1];
815+
eta_val = free_surface_elevation_sampled_[idx + 1];
842816
} else if (t_tau > t1 && t_tau < t2) {
843817
// linearly interpolate free surface elevation between bounds
844818
auto eta1 = free_surface_elevation_sampled_[idx];

0 commit comments

Comments
 (0)