Skip to main content

FopdtProcess

Struct FopdtProcess 

Source
pub struct FopdtProcess { /* private fields */ }
Expand description

A first-order-plus-dead-time process model, advanced one tick at a time.

Uses the exact analytical solution for a first-order lag driven by a piecewise-constant (zero-order-hold) input over each tick – pv_new = pv*decay + (1-decay)*(bias + gain*mv_effective), decay = exp(-tick_interval_s / time_constant_s) – rather than numerically integrating an ODE every tick, as Model/ProcessModelOPC.py’s scipy.integrate.odeint call does. This is not an approximation: it is the closed-form solution of tau * d(pv)/dt = -(pv - pv0) + gain*(mv - mv0) for an input held constant over [t, t+dt], which is exactly what “the controller wrote this MV and it stays there until the next write” means physically. Cross-checked numerically (in a disposable scratch script, not part of this repo) against the reference script’s own odeint-based integration across a range of gain/tau/dt combinations before relying on it – the two agree to within odeint’s own numerical tolerance (~1e-5).

Implementations§

Source§

impl FopdtProcess

Source

pub fn new( config: FopdtConfig, initial_pv: f32, initial_mv: f32, seed: u64, ) -> FopdtProcess

Builds a process starting at rest: initial_pv is assumed to already be the correct steady-state PV for initial_mv (i.e. nothing changes until a FopdtProcess::set_mv call moves the MV away from initial_mv). seed makes the noise sequence reproducible – the same config/seed/write sequence always produces the same PV sequence (on a given platform and rand version; see [rand::rngs::StdRng]’s own caveat that its algorithm is not a portability guarantee across those).

Source

pub fn pv(&self) -> f32

The current PV, as of the last FopdtProcess::step call (or initial_pv, if step has never been called).

Source

pub fn mv(&self) -> f32

The most recently recorded MV (see FopdtProcess::set_mv) – not delayed; this is what a real DCS’s own MV readback tag would report immediately. Only the PV’s response to it is delayed.

Source

pub fn set_mv(&mut self, mv: f32)

Records a new controller output, effective from the next FopdtProcess::step call onward (after passing through the dead-time delay line, if configured).

Source

pub fn step(&mut self) -> f32

Advances the process by one tick_interval_s, using whichever MV was most recently recorded via FopdtProcess::set_mv – delayed by dead_time_s, if configured – as the input, and returns the resulting PV (including noise, if configured).

Trait Implementations§

Source§

impl Debug for FopdtProcess

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more