Skip to content

Commit 2d23cd0

Browse files
Merge pull request #67 from symbiotic-engineering/update-notebook
capture excitation force/phase and fix type hints
2 parents 05d8643 + fa99d3c commit 2d23cd0

File tree

5 files changed

+302
-338
lines changed

5 files changed

+302
-338
lines changed

package/src/openflash/meem_engine.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,11 @@ def run_and_store_results(self, problem_index: int) -> Results:
587587

588588
full_added_mass_matrix = np.full((num_freqs, num_modes, num_modes), np.nan)
589589
full_damping_matrix = np.full((num_freqs, num_modes, num_modes), np.nan)
590+
# --- NEW: Initialize matrices for Excitation Force and Phase ---
591+
# Note: These are vectors (one value per mode per frequency), not NxN matrices like added mass
592+
full_excitation_force = np.full((num_freqs, num_modes), np.nan)
593+
full_excitation_phase = np.full((num_freqs, num_modes), np.nan)
594+
# ---------------------------------------------------------------
590595
all_potentials_batch_data = []
591596

592597
# 1. Create a SINGLE reusable Geometry/Problem Setup
@@ -684,6 +689,13 @@ def run_and_store_results(self, problem_index: int) -> Results:
684689
j_idx = j_idx_result[0]
685690
full_added_mass_matrix[freq_idx, j_idx, i_idx] = coeff_dict['real']
686691
full_damping_matrix[freq_idx, j_idx, i_idx] = coeff_dict['imag']
692+
# --- NEW: Capture Excitation Force & Phase ---
693+
# We only need to store this when i_idx (radiating mode) == j_idx (force mode)
694+
# or just capture it for the active mode.
695+
if i_idx == j_idx:
696+
full_excitation_force[freq_idx, j_idx] = coeff_dict.get('excitation_force', np.nan)
697+
full_excitation_phase[freq_idx, j_idx] = coeff_dict.get('excitation_phase', np.nan)
698+
# ---------------------------------------------
687699

688700
Cs = temp_engine.reformat_coeffs(X_i, NMK_list, len(NMK_list) - 1)
689701

@@ -710,10 +722,13 @@ def run_and_store_results(self, problem_index: int) -> Results:
710722
full_damping_matrix[freq_idx, :, i_idx] = np.nan
711723
continue
712724

725+
# --- UPDATED: Pass the new matrices to store_hydrodynamic_coefficients ---
713726
results.store_hydrodynamic_coefficients(
714727
frequencies=omegas_to_run,
715728
added_mass_matrix=full_added_mass_matrix,
716729
damping_matrix=full_damping_matrix,
730+
excitation_force=full_excitation_force, # <--- Add this
731+
excitation_phase=full_excitation_phase # <--- Add this
717732
)
718733

719734
if all_potentials_batch_data:

package/src/openflash/problem_cache.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# package/src/openflash/problem_cache.py
22
import numpy as np
3-
from typing import Callable, Dict, Any, Optional
3+
from typing import Callable, Dict, Any, Optional, List
44

55
from openflash.multi_equations import *
66

@@ -21,7 +21,7 @@ def __init__(self, problem):
2121
self.cached_m0: Optional[float] = None
2222
# -----------------------------------------------------------------
2323

24-
self.I_nm_vals: Optional[np.ndarray] = None
24+
self.I_nm_vals: Optional[List[np.ndarray]] = None
2525
self.named_closures: Dict[str, Any] = {}
2626

2727
def _set_A_template(self, A_template: np.ndarray):
@@ -50,7 +50,7 @@ def _set_precomputed_m_k_N_k(self, m_k_arr: np.ndarray, N_k_arr: np.ndarray, m0:
5050
self.cached_m0 = m0
5151
# ------------------------------------------------
5252

53-
def _set_I_nm_vals(self, I_nm_vals: np.ndarray):
53+
def _set_I_nm_vals(self, I_nm_vals: List[np.ndarray]):
5454
self.I_nm_vals = I_nm_vals
5555

5656
def _get_A_template(self) -> np.ndarray:

package/src/openflash/results.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Optional
12
import xarray as xr
23
import numpy as np
34
from openflash.geometry import Geometry
@@ -203,13 +204,9 @@ def store_all_potentials(self, all_potentials_batch: list[dict]):
203204

204205

205206
def store_hydrodynamic_coefficients(self, frequencies: np.ndarray,
206-
added_mass_matrix: np.ndarray, damping_matrix: np.ndarray):
207+
added_mass_matrix: np.ndarray, damping_matrix: np.ndarray, excitation_force: Optional[np.ndarray] = None, excitation_phase: Optional[np.ndarray] = None):
207208
"""
208-
Store hydrodynamic coefficients (added mass and damping).
209-
210-
:param frequencies: Array of frequency values.
211-
:param added_mass_matrix: 3D array (frequencies x modes x modes) of added mass coefficients.
212-
:param damping_matrix: 3D array (frequencies x modes x modes) of damping coefficients.
209+
Store hydrodynamic coefficients (added mass, damping, excitation).
213210
"""
214211
expected_shape = (len(frequencies), len(self.modes), len(self.modes))
215212

@@ -222,6 +219,18 @@ def store_hydrodynamic_coefficients(self, frequencies: np.ndarray,
222219

223220
self.dataset['added_mass'] = (('frequency', 'mode_i', 'mode_j'), added_mass_matrix)
224221
self.dataset['damping'] = (('frequency', 'mode_i', 'mode_j'), damping_matrix)
222+
223+
# --- NEW: Store Excitation Data ---
224+
if excitation_force is not None:
225+
# Shape is (frequency, mode_i) - Force on body i due to its own motion/wave
226+
# Note: For diffraction problem strictly, this might differ, but for radiation
227+
# we align it with mode_i.
228+
self.dataset['excitation_force'] = (('frequency', 'mode_i'), excitation_force)
229+
230+
if excitation_phase is not None:
231+
self.dataset['excitation_phase'] = (('frequency', 'mode_i'), excitation_phase)
232+
# ----------------------------------
233+
225234
print("Hydrodynamic coefficients stored in xarray dataset.")
226235

227236
def export_to_netcdf(self, file_path: str):

0 commit comments

Comments
 (0)