Loading src/lib.rs +15 −13 Original line number Diff line number Diff line Loading @@ -9,8 +9,8 @@ struct ReservoirData { initial_storage: f64, max_release: f64, min_release: f64, inflow: Vec<f64>, release: Vec<f64>, catchment_inflow: Vec<f64>, target_release: Vec<f64>, } #[derive(FromPyObject)] Loading @@ -29,19 +29,20 @@ struct ReservoirResults { storage: Vec<f64>, release: Vec<f64>, spill: Vec<f64>, inflow: Vec<f64>, release_target: Vec<f64>, catchment_inflow: Vec<f64>, total_inflow: Vec<f64>, target_release: Vec<f64>, } fn simulate_timestep( reservoir: &ReservoirData, inflow: f64, release_target: f64, target_release: f64, previous_storage: f64, ) -> ReservoirState { let available_water = previous_storage + inflow; let release = release_target let release = target_release .max(reservoir.min_release) .min(reservoir.max_release) .min(available_water); Loading Loading @@ -70,7 +71,7 @@ fn simulate_cascade( // Get first reservoir's data to determine simulation length let first_reservoir = cascade_data.reservoirs.values().next() .ok_or_else(|| PyValueError::new_err("No reservoirs provided"))?; let n = first_reservoir.inflow.len(); let n = first_reservoir.catchment_inflow.len(); let mut results = HashMap::new(); let reservoir_names: Vec<&String> = cascade_data.reservoirs.keys().collect(); Loading @@ -83,8 +84,9 @@ fn simulate_cascade( storage, release: vec![0.0; n], spill: vec![0.0; n], inflow: vec![0.0; n], release_target: reservoir.release.clone(), catchment_inflow: reservoir.catchment_inflow.clone(), total_inflow: vec![0.0; n], target_release: reservoir.target_release.clone(), }); } Loading @@ -97,11 +99,11 @@ fn simulate_cascade( // Calculate inflow: use input inflow for first reservoir, // otherwise use outflow from previous reservoir let current_inflow = if i == 0 { reservoir.inflow[t] reservoir.catchment_inflow[t] } else { let prev_name = &reservoir_names[i-1]; let prev_results = &results[*prev_name]; prev_results.release[t] + prev_results.spill[t] reservoir.catchment_inflow[t] + prev_results.release[t] + prev_results.spill[t] }; // Get previous storage for this reservoir Loading @@ -116,7 +118,7 @@ fn simulate_cascade( let state = simulate_timestep( reservoir, current_inflow, reservoir.release[t], reservoir.target_release[t], previous_storage, ); Loading @@ -124,7 +126,7 @@ fn simulate_cascade( current_results.storage[t] = state.storage; current_results.release[t] = state.release; current_results.spill[t] = state.spill; current_results.inflow[t] = current_inflow; current_results.total_inflow[t] = current_inflow; } } Loading Loading
src/lib.rs +15 −13 Original line number Diff line number Diff line Loading @@ -9,8 +9,8 @@ struct ReservoirData { initial_storage: f64, max_release: f64, min_release: f64, inflow: Vec<f64>, release: Vec<f64>, catchment_inflow: Vec<f64>, target_release: Vec<f64>, } #[derive(FromPyObject)] Loading @@ -29,19 +29,20 @@ struct ReservoirResults { storage: Vec<f64>, release: Vec<f64>, spill: Vec<f64>, inflow: Vec<f64>, release_target: Vec<f64>, catchment_inflow: Vec<f64>, total_inflow: Vec<f64>, target_release: Vec<f64>, } fn simulate_timestep( reservoir: &ReservoirData, inflow: f64, release_target: f64, target_release: f64, previous_storage: f64, ) -> ReservoirState { let available_water = previous_storage + inflow; let release = release_target let release = target_release .max(reservoir.min_release) .min(reservoir.max_release) .min(available_water); Loading Loading @@ -70,7 +71,7 @@ fn simulate_cascade( // Get first reservoir's data to determine simulation length let first_reservoir = cascade_data.reservoirs.values().next() .ok_or_else(|| PyValueError::new_err("No reservoirs provided"))?; let n = first_reservoir.inflow.len(); let n = first_reservoir.catchment_inflow.len(); let mut results = HashMap::new(); let reservoir_names: Vec<&String> = cascade_data.reservoirs.keys().collect(); Loading @@ -83,8 +84,9 @@ fn simulate_cascade( storage, release: vec![0.0; n], spill: vec![0.0; n], inflow: vec![0.0; n], release_target: reservoir.release.clone(), catchment_inflow: reservoir.catchment_inflow.clone(), total_inflow: vec![0.0; n], target_release: reservoir.target_release.clone(), }); } Loading @@ -97,11 +99,11 @@ fn simulate_cascade( // Calculate inflow: use input inflow for first reservoir, // otherwise use outflow from previous reservoir let current_inflow = if i == 0 { reservoir.inflow[t] reservoir.catchment_inflow[t] } else { let prev_name = &reservoir_names[i-1]; let prev_results = &results[*prev_name]; prev_results.release[t] + prev_results.spill[t] reservoir.catchment_inflow[t] + prev_results.release[t] + prev_results.spill[t] }; // Get previous storage for this reservoir Loading @@ -116,7 +118,7 @@ fn simulate_cascade( let state = simulate_timestep( reservoir, current_inflow, reservoir.release[t], reservoir.target_release[t], previous_storage, ); Loading @@ -124,7 +126,7 @@ fn simulate_cascade( current_results.storage[t] = state.storage; current_results.release[t] = state.release; current_results.spill[t] = state.spill; current_results.inflow[t] = current_inflow; current_results.total_inflow[t] = current_inflow; } } Loading