Skip to content

Commit

Permalink
Merge pull request #180 from NREL/f3/ninterp-methods
Browse files Browse the repository at this point in the history
Convenience methods for ninterp
  • Loading branch information
calbaker authored Jan 16, 2025
2 parents e3729f7 + dafc457 commit 781119a
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 6 deletions.
96 changes: 90 additions & 6 deletions fastsim-core/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,57 @@ impl Min for &[f64] {
}
impl Min for Vec<f64> {
fn min(&self) -> anyhow::Result<f64> {
Ok(self.iter().fold(f64::INFINITY, |acc, curr| acc.min(*curr)))
self.as_slice().min()
}
}
impl Min for Vec<&f64> {
impl Min for &[&f64] {
fn min(&self) -> anyhow::Result<f64> {
Ok(self.iter().fold(f64::INFINITY, |acc, curr| acc.min(**curr)))
}
}
impl Min for Vec<&f64> {
fn min(&self) -> anyhow::Result<f64> {
self.as_slice().min()
}
}
impl Min for &[Vec<f64>] {
fn min(&self) -> anyhow::Result<f64> {
self.iter()
.map(|v| v.min())
.try_fold(f64::INFINITY, |acc, x| Ok(acc.min(x?)))
}
}
impl Min for Vec<Vec<f64>> {
fn min(&self) -> anyhow::Result<f64> {
self.as_slice().min()
}
}
impl Min for &[Vec<Vec<f64>>] {
fn min(&self) -> anyhow::Result<f64> {
self.iter()
.map(|v| v.min())
.try_fold(f64::INFINITY, |acc, x| Ok(acc.min(x?)))
}
}
impl Min for Vec<Vec<Vec<f64>>> {
fn min(&self) -> anyhow::Result<f64> {
self.as_slice().min()
}
}
impl Min for Interpolator {
fn min(&self) -> anyhow::Result<f64> {
match self {
Interpolator::Interp0D(value) => Ok(*value),
Interpolator::Interp1D(interp) => interp.f_x().min(),
Interpolator::Interp2D(interp) => interp.f_xy().min(),
Interpolator::Interp3D(interp) => interp.f_xyz().min(),
Interpolator::InterpND(interp) => Ok(interp
.values()
.iter()
.fold(f64::INFINITY, |acc, x| acc.min(*x))),
}
}
}

pub trait Max {
fn max(&self) -> anyhow::Result<f64>;
Expand All @@ -52,18 +95,59 @@ impl Max for &[f64] {
}
impl Max for Vec<f64> {
fn max(&self) -> anyhow::Result<f64> {
Ok(self
.iter()
.fold(f64::NEG_INFINITY, |acc, curr| acc.max(*curr)))
self.as_slice().max()
}
}
impl Max for Vec<&f64> {
impl Max for &[&f64] {
fn max(&self) -> anyhow::Result<f64> {
Ok(self
.iter()
.fold(f64::NEG_INFINITY, |acc, curr| acc.max(**curr)))
}
}
impl Max for Vec<&f64> {
fn max(&self) -> anyhow::Result<f64> {
self.as_slice().max()
}
}
impl Max for &[Vec<f64>] {
fn max(&self) -> anyhow::Result<f64> {
self.iter()
.map(|v| v.max())
.try_fold(f64::NEG_INFINITY, |acc, x| Ok(acc.max(x?)))
}
}
impl Max for Vec<Vec<f64>> {
fn max(&self) -> anyhow::Result<f64> {
self.as_slice().max()
}
}
impl Max for &[Vec<Vec<f64>>] {
fn max(&self) -> anyhow::Result<f64> {
self.iter()
.map(|v| v.max())
.try_fold(f64::NEG_INFINITY, |acc, x| Ok(acc.max(x?)))
}
}
impl Max for Vec<Vec<Vec<f64>>> {
fn max(&self) -> anyhow::Result<f64> {
self.as_slice().max()
}
}
impl Max for Interpolator {
fn max(&self) -> anyhow::Result<f64> {
match self {
Interpolator::Interp0D(value) => Ok(*value),
Interpolator::Interp1D(interp) => interp.f_x().max(),
Interpolator::Interp2D(interp) => interp.f_xy().max(),
Interpolator::Interp3D(interp) => interp.f_xyz().max(),
Interpolator::InterpND(interp) => Ok(interp
.values()
.iter()
.fold(f64::NEG_INFINITY, |acc, x| acc.max(*x))),
}
}
}

pub trait Init {
/// Specialized code to execute upon initialization. For any struct with fields
Expand Down
107 changes: 107 additions & 0 deletions fastsim-core/src/utils/interp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
use crate::imports::*;

/// Methods for proportionally scaling interpolator function data
pub trait InterpolatorMethods {
fn set_min(&mut self, min: f64) -> anyhow::Result<()>;
fn set_max(&mut self, max: f64) -> anyhow::Result<()>;
fn set_range(&mut self, range: f64) -> anyhow::Result<()>;
}

impl InterpolatorMethods for Interpolator {
fn set_min(&mut self, min: f64) -> anyhow::Result<()> {
let old_min = self.min()?;
match self {
Interpolator::Interp0D(value) => Ok(*value = min),
Interpolator::Interp1D(interp) => {
todo!()
}
Interpolator::Interp2D(interp) => {
todo!()
}
Interpolator::Interp3D(interp) => {
todo!()
}
Interpolator::InterpND(interp) => {
todo!()
}
}
}

fn set_max(&mut self, max: f64) -> anyhow::Result<()> {
let old_max = self.max()?;
match self {
Interpolator::Interp0D(value) => Ok(*value = max),
Interpolator::Interp1D(interp) => {
Ok(interp.set_f_x(interp.f_x().iter().map(|x| x * max / old_max).collect())?)
}
Interpolator::Interp2D(interp) => Ok(interp.set_f_xy(
interp
.f_xy()
.iter()
.map(|v| v.iter().map(|x| x * max / old_max).collect())
.collect(),
)?),
Interpolator::Interp3D(interp) => Ok(interp.set_f_xyz(
interp
.f_xyz()
.iter()
.map(|v0| {
v0.iter()
.map(|v1| v1.iter().map(|x| x * max / old_max).collect())
.collect()
})
.collect(),
)?),
Interpolator::InterpND(interp) => {
Ok(interp.set_values(interp.values().map(|x| x * max / old_max))?)
}
}
}

fn set_range(&mut self, range: f64) -> anyhow::Result<()> {
let old_max = self.max()?;
let old_range = old_max - self.min()?;
ensure!(old_range != 0., "Cannot modify range when min == max");
match self {
Interpolator::Interp0D(_value) => unreachable!("The above `ensure` should trigger"),
Interpolator::Interp1D(interp) => Ok(interp.set_f_x(
interp
.f_x()
.iter()
.map(|x| old_max + (x - old_max) * range / old_range)
.collect(),
)?),
Interpolator::Interp2D(interp) => Ok(interp.set_f_xy(
interp
.f_xy()
.iter()
.map(|v| {
v.iter()
.map(|x| old_max + (x - old_max) * range / old_range)
.collect()
})
.collect(),
)?),
Interpolator::Interp3D(interp) => Ok(interp.set_f_xyz(
interp
.f_xyz()
.iter()
.map(|v0| {
v0.iter()
.map(|v1| {
v1.iter()
.map(|x| old_max + (x - old_max) * range / old_range)
.collect()
})
.collect()
})
.collect(),
)?),
Interpolator::InterpND(interp) => Ok(interp.set_values(
interp
.values()
.map(|x| old_max + (x - old_max) * range / old_range),
)?),
}
}
}
3 changes: 3 additions & 0 deletions fastsim-core/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use crate::imports::*;
use paste::paste;
use regex::Regex;

pub mod interp;
pub use interp::*;

impl Init for ninterp::Interpolator {}
impl SerdeAPI for ninterp::Interpolator {
const RESOURCE_PREFIX: &'static str = "interpolators";
Expand Down

0 comments on commit 781119a

Please sign in to comment.