-
Notifications
You must be signed in to change notification settings - Fork 4
SimParam interface
The SimParam and related classes can be found under: heavi.numeric:
heavi/
...
numeric.py
In order to facilitate custom simulation value handling heavi comes with a base class called SimValue. The class definition as of version 0.2.1 is as following:
class SimParam:
_eval_f = 1e9
@property
def value(self) -> float:
return self(self._eval_f)
def scalar(self) -> float:
"""Returns the scalar value of the parameter"""
return self(self._eval_f)
def initialize(self) -> None:
"""Initializes the parameter"""
pass
def __call__(self, f: np.ndarray) -> np.ndarray:
"""Returns the value of the parameter at a given frequency"""
return np.ones_like(f) * self._value
def __repr__(self) -> str:
"""Returns a string representation of the parameter"""
return f"SimParam({self._value})"
def negative(self) -> SimParam:
"""Returns the negative of the parameter"""
return Function(lambda f: -self(f))
def inverse(self) -> SimParam:
"""Returns the inverse of the parameter"""
return Function(lambda f: 1/self(f))Users can inherit from SimParam to implement custom behavior. The rest of this page will be dedicated to discussing what the default methods are and how to use them.
The value property is called by the interface to acquire a component value for example or parameter value when displaying and outputting things in the terminal. By default the value property will simply try to evaluate its value at 1Hz.
The scalar method is by default similar to the value property and might be omitted in later versions.
The initialize method is can be called on SimParam objects to tell the object to initialize or set its values/properties required to be able to evaluate itself. This method is used in the Random and Param class to set internal attributes for evaluation later on. For example, in the Random class, the initialize method will generate a new random value.
The __call__ dunder method is used to eventually generate a value given an array of frequency points and must therefor always return a frequency array. Be careful when implementing this method for scalar valued function to not return a float:
# RIGHT IMPLEMENTATION
def __call__(self, f: np.ndarray) -> np.ndarray:
return self.some_value * np.ones_like(f)
# WRONG IMPLEMENTATION
def __call__(self, f: np.ndarray) -> np.ndarray: # Does not return an array!
return self.some_valueImplement the repr method to instruct the class how to display itself in the terminal.
Implementing the negative method is very important for proper functioning of heavi. It may not necessarily be used but it will be used if properties are used to define impedances or admittances. For this reason, the SimParam class object must have a method to return a version of itself that returns the same value but negative. A safe implementation and the one chosen by default if you do not implement this method is:
def negative(self) -> SimParam:
return Function(lambda f: -self(f))The Function class is a version of the SimParam class that represents functions that are evaluates at each frequency.
The reason that SimParam doesn't default to this implementation always is to prevent unnecessary computational overhead when calling various nested functions in cases where this can be avoided. For example, the Scalar class representing just scalar values knows the scalar value so it can just return a new Scalar class object that has the negative scalar value etc.
The inverse method is the exact same as the negative method but instead it returns one divided by the SimParam instead of the negative. This is necessary because this is used when SimParam are used in defining the impedance values as everything is eventually mapped to admittance values.