Skip to content

Commit e89cabb

Browse files
committed
remove dead comparison helpers and document TestHydro as HydroSystem adapter
Remove dead internal helpers EvaluateHydroSystem() and CompareWithHydroSystem() from TestHydro. Update header and implementation comments in hydro_forces to reflect the new architecture: TestHydro is a thin adapter over HydroSystem/ChronoHydroCoupler, and the Create*Component helpers are the single sources of truth for component configuration. Legacy ComputeForce* methods and compare_mode_ are retained for API compatibility and clearly marked as legacy.
1 parent 73ca6bd commit e89cabb

2 files changed

Lines changed: 65 additions & 113 deletions

File tree

include/hydroc/hydro_forces.h

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,29 @@
77
* @brief Header file of TestHydro main class and helper classes
88
* ComponentFunc and ForceFunc6d.
99
*
10-
* OVERVIEW:
11-
* This header defines the public interface for hydrodynamic force computation
12-
* in multibody marine systems. It provides Chrono-compatible force callbacks
13-
* that integrate hydrostatics, radiation damping, and wave excitation.
10+
* ARCHITECTURE:
11+
* TestHydro is a thin adapter over HydroSystem + ChronoHydroCoupler.
12+
* Force computation is handled internally by HydroSystem, which owns:
13+
* - HydrostaticsComponent (restoring forces + buoyancy)
14+
* - RadiationComponent (RIRF convolution, owns velocity history)
15+
* - ExcitationComponent (wave forcing)
16+
*
17+
* The sign convention is: total = hydrostatics - radiation + waves.
18+
* (RadiationComponent applies the negative sign internally since damping
19+
* opposes motion.)
1420
*
1521
* MAIN RESPONSIBILITIES:
16-
* - TestHydro: Main orchestrator class for all hydrodynamic force components
22+
* - TestHydro: Façade over HydroSystem; provides Chrono force callbacks
1723
* - ForceFunc6d: Wraps 6-DOF force/torque callbacks for Chrono bodies
1824
* - ComponentFunc: Per-DOF force function for Chrono's ChForce system
1925
*
26+
* COMPONENT CONSTRUCTION:
27+
* Force components are constructed via factory methods:
28+
* - CreateHydrostaticsComponent()
29+
* - CreateRadiationComponent()
30+
* - CreateExcitationComponent()
31+
* These are the single source of truth for component configuration.
32+
*
2033
* INTERACTIONS:
2134
* - Used by setup_hydro_from_yaml to create and configure TestHydro instances
2235
* - Called by Chrono during simulation via ChForce callbacks
@@ -27,21 +40,9 @@
2740
* - Bodies are 1-indexed in CoordinateFuncForBody (legacy, from ForceFunc6d)
2841
* - All bodies share same H5 file (multibody data in single file)
2942
* - 6 DOF per body (surge, sway, heave, roll, pitch, yaw)
30-
* - Forces computed once per time step and cached
31-
*
32-
* KNOWN LIMITATIONS:
33-
* - Monolithic design: all physics components mixed in TestHydro
34-
* - Tight coupling to Chrono types (hard to test in isolation)
35-
* - Body indexing inconsistency (1-indexed vs 0-indexed)
36-
* - No per-body enable/disable of force components
37-
*
38-
* FUTURE REFACTORING:
39-
* This class will be replaced by HydroSystem + ChronoHydroCoupler.
40-
* TestHydro will become a thin legacy adapter for API stability.
43+
* - Forces computed once per time step and cached via prev_time check
4144
*********************************************************************/
4245

43-
// TODO: clean up include statements
44-
4546
// Include hydro_types.h FIRST to ensure BodyForces and GeneralizedForce are available
4647
// before any other includes that might conflict (e.g., hydro_config_types.h)
4748
#include <hydroc/hydro_types.h>
@@ -252,29 +253,35 @@ class TestHydro {
252253
void AddWaves(std::shared_ptr<WaveBase> waves);
253254

254255
/**
255-
* @brief Computes the Hydrostatic stiffness force plus buoyancy force for a 6N dimensional system.
256+
* @brief Legacy API: Computes hydrostatic forces for a 6N dimensional system.
257+
*
258+
* NOTE: Retained for backward compatibility. The main force path now uses HydroSystem
259+
* (via CoordinateFuncForBody). This method is not called during normal simulation.
256260
*
257261
* @return 6N dimensional force for 6 DOF and N bodies in system.
258262
*/
259263
std::vector<double> ComputeForceHydrostatics();
260264

261265
/**
262-
* @brief Computes the Radiation Damping force with convolution history for a 6N dimensional system.
266+
* @brief Legacy API: Computes radiation damping forces for a 6N dimensional system.
263267
*
264-
* The discretization uses the time series of the the RIRF relative to the current step.
265-
* Linear interpolation is done on the velocity history if time_sim-time_rirf is between two values of the time
266-
* history. Trapezoidal integration is used to compute the force.
268+
* NOTE: Retained for backward compatibility. The main force path now uses HydroSystem
269+
* (via CoordinateFuncForBody). This method is not called during normal simulation.
267270
*
268-
* Time history is automatically added in this function (so it should only be called once per time step), and
269-
* history that is older than the maximum RIRF time value is automatically removed.
271+
* Returns positive damping magnitudes (legacy convention); the main path applies
272+
* the correct sign internally via RadiationComponent.
270273
*
271274
* @return 6N dimensional force for 6 DOF and N bodies in system.
272275
*/
273276
std::vector<double> ComputeForceRadiationDampingConv();
274277

275278
/**
276-
* @brief Computes the 6N dimensional force from any waves applied to the system.
277-
* @return 6N dimensional force for 6 DOF and N bodies in system (already Eigen type).
279+
* @brief Legacy API: Computes wave excitation forces for a 6N dimensional system.
280+
*
281+
* NOTE: Retained for backward compatibility. The main force path now uses HydroSystem
282+
* (via CoordinateFuncForBody). This method is not called during normal simulation.
283+
*
284+
* @return 6N dimensional force for 6 DOF and N bodies in system.
278285
*/
279286
Eigen::VectorXd ComputeForceWaves();
280287
// Expose the wave object (read-only) so callers can query inputs if needed
@@ -352,8 +359,8 @@ class TestHydro {
352359
// Hydrodynamics profiling accessors
353360
HydroProfileStats GetProfileStats() const { return profile_stats_; }
354361

355-
// Compare mode: when enabled, compares legacy force path vs HydroSystem path
356-
// and logs any discrepancies. Default is off.
362+
// Compare mode: legacy debugging feature, retained for API compatibility.
363+
// No longer affects behavior since the main path now uses HydroSystem exclusively.
357364
void SetCompareMode(bool enable) { compare_mode_ = enable; }
358365
bool GetCompareMode() const { return compare_mode_; }
359366

@@ -416,7 +423,7 @@ class TestHydro {
416423
std::unique_ptr<hydrochrono::hydro::HydroSystem> hydro_system_;
417424
std::unique_ptr<hydrochrono::hydro::ChronoHydroCoupler> chrono_coupler_;
418425

419-
// Compare mode flag: when true, compares legacy vs HydroSystem forces
426+
// Legacy compare mode flag: retained for API compatibility; no longer used.
420427
bool compare_mode_ = false;
421428

422429
// Convolution kernel preprocessing (optional)
@@ -451,15 +458,9 @@ class TestHydro {
451458
// Note: Each instance owns its own velocity history (they are independent).
452459
std::unique_ptr<hydrochrono::hydro::RadiationComponent> CreateRadiationComponent() const;
453460

454-
// Internal helpers for HydroSystem + ChronoHydroCoupler path
455-
// Constructs hydro_system_ and chrono_coupler_ once; subsequent calls are no-ops.
461+
// Internal helper: constructs hydro_system_ and chrono_coupler_ once.
462+
// Subsequent calls are no-ops. Called automatically by CoordinateFuncForBody().
456463
void EnsureHydroSystemAndCoupler();
457-
// Evaluate forces via HydroSystem (used by comparison harness)
458-
hydrochrono::hydro::BodyForces EvaluateHydroSystem(double time);
459-
460-
// Comparison harness: compares legacy forces vs HydroSystem forces and logs discrepancies.
461-
// Only called when compare_mode_ is true.
462-
void CompareWithHydroSystem(double time, int total_dofs);
463464
};
464465

465466
#endif

src/hydro_forces.cpp

Lines changed: 26 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,34 @@
44
* @brief Implementation of TestHydro main class and helper classes
55
* ComponentFunc and ForceFunc6d.
66
*
7-
* OVERVIEW:
8-
* This file implements the core hydrodynamic force computation for multibody
9-
* marine systems. It connects Chrono physics bodies to hydrodynamic components
10-
* (hydrostatics, radiation damping, wave excitation) and applies the
11-
* resulting forces during simulation.
7+
* ARCHITECTURE:
8+
* TestHydro is a thin adapter over HydroSystem + ChronoHydroCoupler.
9+
*
10+
* Force computation flow:
11+
* 1. Chrono calls CoordinateFuncForBody(body, dof) via ChForce callbacks.
12+
* 2. CoordinateFuncForBody detects new timesteps and calls chrono_coupler_->Evaluate().
13+
* 3. ChronoHydroCoupler extracts system state from Chrono bodies and invokes HydroSystem.
14+
* 4. HydroSystem evaluates all force components and returns BodyForces.
15+
* 5. Forces are flattened into the legacy total_force_ array for Chrono consumption.
16+
*
17+
* Sign convention: total = hydrostatics - radiation + waves
18+
* (RadiationComponent applies the negative sign internally since damping opposes motion.)
19+
*
20+
* COMPONENT CONSTRUCTION:
21+
* Force components are built via factory methods (single source of truth):
22+
* - CreateHydrostaticsComponent()
23+
* - CreateRadiationComponent()
24+
* - CreateExcitationComponent()
25+
*
26+
* LEGACY API:
27+
* The following methods are retained for backward compatibility but are NOT used
28+
* by the main force path (CoordinateFuncForBody):
29+
* - ComputeForceHydrostatics()
30+
* - ComputeForceRadiationDampingConv()
31+
* - ComputeForceWaves()
1232
*
1333
* MAIN RESPONSIBILITIES:
14-
* - TestHydro: Orchestrates all hydrodynamic force components for multiple bodies
34+
* - TestHydro: Façade over HydroSystem; provides Chrono force callbacks
1535
* - ForceFunc6d: Wraps Chrono ChForce/ChTorque callbacks for each body
1636
* - ComponentFunc: Provides per-DOF force values to Chrono's force system
1737
*
@@ -26,24 +46,11 @@
2646
* - Bodies are 1-indexed in ForceFunc6d interface (legacy)
2747
* - 6 DOF per body (surge, sway, heave, roll, pitch, yaw)
2848
* - Forces computed once per time step, cached via prev_time check
29-
* - RadiationComponent is the single source of truth for radiation history/forces
30-
*
31-
* KNOWN LIMITATIONS:
32-
* - Monolithic design: all force components mixed in one class
33-
* - Tight coupling to Chrono types (hard to test without Chrono)
34-
* - Body indexing inconsistency (1-indexed in some places, 0-indexed in others)
35-
* - No per-body enable/disable of radiation or excitation (system-wide only)
3649
*
3750
* DEBUG INSTRUMENTATION:
3851
* To enable debug output, compile with -DHYDROCHRONO_DEBUG.
39-
* This will print force components and timing info.
40-
* Baseline outputs to record:
41-
* - Total force vector per time step (total_force_)
42-
* - Individual components (hydrostatic, radiation, waves)
43-
* - RIRF kernel access patterns
4452
*********************************************************************/
4553

46-
// TODO minimize include statements, move all to header file hydro_forces.h?
4754
#include "hydroc/hydro_forces.h"
4855
#include <hydroc/chloadaddedmass.h>
4956
#include <hydroc/h5fileinfo.h>
@@ -547,59 +554,6 @@ void TestHydro::EnsureHydroSystemAndCoupler() {
547554
hydro_system_shared, bodies_);
548555
}
549556

550-
hydrochrono::hydro::BodyForces TestHydro::EvaluateHydroSystem(double time) {
551-
EnsureHydroSystemAndCoupler();
552-
return chrono_coupler_->Evaluate(time);
553-
}
554-
555-
void TestHydro::CompareWithHydroSystem(double time, int total_dofs) {
556-
// DEPRECATED: This method is no longer called from CoordinateFuncForBody().
557-
// The main force path now routes through HydroSystem, so there's nothing to compare.
558-
// This method is kept for potential external use but will likely be removed in a future cleanup.
559-
560-
// Evaluate forces via the persistent HydroSystem path
561-
hydrochrono::hydro::BodyForces new_forces = EvaluateHydroSystem(time);
562-
563-
// Flatten new_forces into legacy ordering: [body0_dof0, ..., body0_dof5, body1_dof0, ...]
564-
std::vector<double> new_total(total_dofs, 0.0);
565-
for (int body_idx = 0; body_idx < num_bodies_; ++body_idx) {
566-
const int offset = kDofPerBody * body_idx;
567-
for (int dof = 0; dof < kDofPerBody; ++dof) {
568-
new_total[offset + dof] = new_forces[body_idx][dof];
569-
}
570-
}
571-
572-
// Comparison tolerances
573-
const double abs_tol = 1e-6; // Absolute tolerance (N or N·m)
574-
const double rel_tol = 1e-4; // Relative tolerance (0.01%)
575-
576-
// Compare entry-by-entry
577-
int mismatch_count = 0;
578-
for (int idx = 0; idx < total_dofs; ++idx) {
579-
const double legacy_val = total_force_[idx];
580-
const double new_val = new_total[idx];
581-
const double diff = std::abs(legacy_val - new_val);
582-
const double max_abs = std::max(std::abs(legacy_val), std::abs(new_val));
583-
const double rel_diff = (max_abs > abs_tol) ? diff / max_abs : 0.0;
584-
585-
if (diff > abs_tol && rel_diff > rel_tol) {
586-
const int body_idx = idx / kDofPerBody;
587-
const int dof = idx % kDofPerBody;
588-
std::cout << "[COMPARE] Mismatch at t=" << time
589-
<< " body=" << body_idx << " dof=" << dof
590-
<< ": legacy=" << legacy_val
591-
<< " new=" << new_val
592-
<< " diff=" << diff
593-
<< " rel=" << rel_diff << std::endl;
594-
++mismatch_count;
595-
}
596-
}
597-
598-
if (mismatch_count == 0) {
599-
// Optionally log success at intervals (every 100 steps or so)
600-
// For now, silent when all forces match
601-
}
602-
}
603557

604558
// Legacy radiation convolution computation.
605559
// RadiationComponent is the single source of truth for radiation history and forces.
@@ -776,9 +730,6 @@ double TestHydro::CoordinateFuncForBody(int b, int dof_index) {
776730
}
777731
}
778732

779-
// Note: compare_mode_ is no longer used here because the main path IS HydroSystem now.
780-
// The legacy per-component path is preserved for external callers but not used by this method.
781-
782733
#ifdef HYDROCHRONO_DEBUG
783734
std::cout << "[HYDRO_DEBUG] CoordinateFuncForBody: body=" << b << ", dof=" << dof_index
784735
<< ", time=" << prev_time << ", force=" << total_force_[body_num_offset + dof_index] << std::endl;

0 commit comments

Comments
 (0)