Services#

Services are helper variables outside the DAE variable list. They are most often used for storing intermediate constants but can be used for special operations to work around restrictions in the symbolic framework.

Background#

Services are v-providers, meaning each service has an attribute v for storing service values. Unlike variables, services do not participate in the DAE system directly but provide computed values that variables and equations can use.

The base class of services is andes.core.service.BaseService.

Service Types#

BaseService([name, tex_name, unit, info, vtype])

Base class for Service.

OperationService([name, tex_name, info])

Base class for a type of Service which performs specific operations.

ConstService([v_str, v_numeric, vtype, ...])

A type of Service that stays constant once initialized.

VarService([v_str, v_numeric, vtype, name, ...])

Variable service that gets updated in each step/iteration before computing the residual equations.

ExtService(model, src, indexer[, attr, ...])

Service constants whose value is from an external model or group.

PostInitService([v_str, v_numeric, vtype, ...])

Constant service that gets stored once after init.

NumReduce(u, ref, fun[, name, tex_name, ...])

A helper Service type which reduces a linearly stored 2-D ExtParam into 1-D Service.

NumRepeat(u, ref, **kwargs)

A helper Service type which repeats a v-provider's value based on the shape from a BackRef

IdxRepeat(u, ref, **kwargs)

Helper class to repeat IdxParam.

BackRef(**kwargs)

A special type of reference collector.

RefFlatten(ref, **kwargs)

A service type for flattening andes.core.service.BackRef into a 1-D list.

EventFlag(u[, vtype, name, tex_name, info])

Service to flag events when the input value changes.

VarHold(u, hold[, vtype, name, tex_name, info])

Service for holding the input when the hold signal is on.

ExtendedEvent(u[, t_ext, trig, enable, ...])

Service for indicating an event for an extended, predefined period of time following the event disappearance.

DataSelect(optional, fallback[, name, ...])

Class for selecting values for optional DataParam or NumParam.

NumSelect(optional, fallback, name, ...)

Class for selecting values for optional NumParam.

DeviceFinder(u, link, idx_name, default_model)

Service for finding idx of devices which are linked to the given devices.

FlagCondition(u, func[, flag, name, ...])

Class for flagging values based on a condition function.

FlagValue(u, value[, flag, name, tex_name, ...])

Class for flagging values that equal to the given value.

FlagGreaterThan(u[, value, flag, equal, ...])

Service for flagging parameters > or >= the given value element-wise.

FlagLessThan(u[, value, flag, equal, name, ...])

Service for flagging parameters < or <= the given value element-wise.

InitChecker(u[, lower, upper, equal, ...])

Class for checking init values against known typical values.

Replace(old_val, flt, new_val[, name, ...])

Replace parameters with new values if the function returns True

ApplyFunc(u, func[, name, tex_name, info, cache])

Class for applying a numerical function on a parameter..

Class

Description

ConstService

Internal service for constant values

VarService

Variable service updated at each iteration before equations

ExtService

External service for retrieving values from value providers

PostInitService

Constant service evaluated after TDS initialization

NumReduce

Reduce linear 2-D arrays into 1-D arrays

NumRepeat

Repeat a 1-D array to linear 2-D arrays

IdxRepeat

Repeat a 1-D list to linear 2-D list

EventFlag

Flag changes in inputs as an event

VarHold

Hold input value when a hold signal is active

ExtendedEvent

Extend an event signal for a given period of time

DataSelect

Select optional str data if provided or use the fallback

NumSelect

Select optional numerical data if provided

DeviceFinder

Find or create devices linked to the given devices

BackRef

Collect idx-es for backward references

RefFlatten

Convert BackRef list of lists into a 1-D list

InitChecker

Check initial values against typical values

FlagValue

Flag values that equal the given value

Replace

Replace values that return True for the given lambda func

Internal Constants#

The most commonly used service is ConstService. It stores an array of constants whose value is evaluated from a provided symbolic string. Constants are only evaluated once in the model initialization phase, ahead of variable initialization. ConstService is handy for calculating intermediate constants from parameters.

For example, a turbine governor has a NumParam R for the droop. ConstService allows calculating the inverse of the droop (the gain) and using it in equations:

self.R = NumParam()
self.G = ConstService(v_str='u/R')

where u is the online status parameter. The model can then use G in subsequent variable or equation strings.

class andes.core.service.ConstService(v_str: str | None = None, v_numeric: Callable | None = None, vtype: type | None = None, name: str | None = None, tex_name: str | None = None, info: str | None = None, unit: str | None = None)[source]

A type of Service that stays constant once initialized.

ConstService are usually constants calculated from parameters. They are only evaluated once in the initialization phase before variables are initialized. Therefore, uninitialized variables must not be used in v_str`.

ConstService are evaluated in sequence after getting external variables and parameters and before initializing internal variables.

Parameters:
namestr

Name of the ConstService

v_strstr

An equation string to calculate the variable value.

v_numericCallable, optional

A callable which returns the value of the ConstService

v_type: type, optional, default to float

Type of element in the value array in float or complex

Attributes:
varray-like or a scalar

ConstService value

_v_t0np.ndarray or None

v at t=0, saved by snapshot_init(). Used by restore_init() to reset v to the post-init baseline.

VarService#

Updated at each iteration before equation evaluation. Use for intermediate values that depend on the current state of variables.

class andes.core.service.VarService(v_str: str | None = None, v_numeric: Callable | None = None, vtype: type | None = None, name: str | None = None, tex_name: str | None = None, info: str | None = None, unit: str | None = None, sequential: bool | None = True)[source]

Variable service that gets updated in each step/iteration before computing the residual equations. As a results, variable values from the k-th step are used to compute a VarService that will be used to compute the residual for the (k+1)-th step.

This class is useful when one has non-differentiable algebraic equations, which make use of abs(), re and im. Instead of creating Algeb, one can put the equation in VarService, which will be updated before solving algebraic equations.

Parameters:
sequentialbool, optional, default to True

True if this VarService depends on previously defined VarService and should be evaluated in sequence. False if this VarService only uses known variables.

Warning

VarService is intended for non-differentiable expressions (e.g., Abs(), re(), im()) that cannot appear in algebraic equations. If the expression is differentiable, an Algeb variable should be used instead.

During model initialization, VarService is evaluated before any variable v_str assignment is computed. If the expression references algebraic or state variables, those variables will still hold their default (typically zero) values, resulting in an incorrect initial VarService value. Variables whose v_str depends on this VarService will consequently be initialized from an erroneous starting point. At runtime, this effect is self-correcting because VarService is re-evaluated every iteration with updated variable values. However, the incorrect initial value can cause convergence difficulties or incorrect limiter flag settings during the first few iterations.

VarService is not solved simultaneously with algebraic equations, meaning that a one-step delay exists between the algebraic variables and the VarService value.

Examples

In ESST3A model, the voltage and current sensors (vd + jvq), (Id + jIq) estimate the sensed VE using equation

\[VE = | K_{PC}*(v_d + 1j v_q) + 1j (K_I + K_{PC}*X_L)*(I_d + 1j I_q)|\]

One can use VarService to implement this equation

self.VE = VarService(
    tex_name='V_E', info='VE', v_str='Abs(KPC*(vd + 1j*vq) + 1j*(KI +
    KPC*XL)*(Id + 1j*Iq))', )

PostInitService#

Evaluated after TDS initialization, when variable values have been determined.

class andes.core.service.PostInitService(v_str: str | None = None, v_numeric: Callable | None = None, vtype: type | None = None, name: str | None = None, tex_name: str | None = None, info: str | None = None, unit: str | None = None)[source]

Constant service that gets stored once after init.

This service is useful when one need to store initialization values stored in variables.

Examples

In ESST3A model, the vf variable is initialized followed by other variables. One can store the initial vf into vf0 so that equation vf - vf0 = 0 will hold.

self.vref0 = PostInitService(info='Initial reference voltage input',
                             tex_name='V_{ref0}', v_str='vref', )

Since all ConstService are evaluated before equation evaluation, without using PostInitService, one will need to create lots of ConstService to store values in the initialization path towards vf0, in order to correctly initialize vf.

External Constants#

Service constants whose value is retrieved from an external model or group. Using ExtService is similar to using external variables. The values of ExtService will be retrieved once during the initialization phase before ConstService evaluation.

For example, a synchronous generator needs to retrieve the p and q values from static generators for initialization. In the __init__() of a synchronous generator model, one can define:

self.p0 = ExtService(src='p',
                     model='StaticGen',
                     indexer=self.gen,
                     tex_name='P_0')
class andes.core.service.ExtService(model: str, src: str, indexer: BaseParam | BaseService, attr: str = 'v', allow_none: bool = False, default=0, name: str = None, tex_name: str = None, vtype=None, info: str = None)[source]

Service constants whose value is from an external model or group.

Parameters:
srcstr

Variable or parameter name in the source model or group

modelstr

A model name or a group name

indexerIdxParam or BaseParam

An "Indexer" instance whose v field contains the idx of devices in the model or group.

Examples

A synchronous generator needs to retrieve the p and q values from static generators for initialization. ExtService is used for this purpose.

In a synchronous generator, one can define the following to retrieve StaticGen.p as p0:

class GENCLSModel(Model):
    def __init__(...):
        ...
        self.p0 = ExtService(src='p',
                             model='StaticGen',
                             indexer=self.gen,
                             tex_name='P_0')

Shape Manipulators#

This section is for advanced model developers.

All generated equations operate on 1-dimensional arrays and can use algebraic calculations only. In some cases, one model would use BackRef to retrieve 2-dimensional indices and use such indices to retrieve variable addresses. The retrieved addresses usually have a different length than the referencing model and cannot be used directly for calculation.

Shape manipulator services can be used in such cases:

  • NumReduce reduces a linearly stored 2-D ExtParam into 1-D Service

  • NumRepeat repeats a 1-D value into linearly stored 2-D value based on the shape from a BackRef

class andes.core.service.BackRef(**kwargs)[source]

A special type of reference collector.

BackRef is used for collecting device indices of other models referencing the parent model of the BackRef. The v``field will be a list of lists, each containing the `idx of other models referencing each device of the parent model.

BackRef can be passed as indexer for params and vars, or shape for NumReduce and NumRepeat. See examples for illustration.

See also

andes.core.service.NumReduce

A more complete example using BackRef to build the COI model

Examples

A Bus device has an IdxParam of area, storing the idx of area to which the bus device belongs. In Bus.__init__(), one has

self.area = IdxParam(model='Area')

Suppose Bus has the following data

idx

area

Vn

1

1

110

2

2

220

3

1

345

4

1

500

The Area model wants to collect the indices of Bus devices which points to the corresponding Area device. In Area.__init__, one defines

self.Bus = BackRef()

where the member attribute name Bus needs to match exactly model name that Area wants to collect idx for. Similarly, one can define self.ACNode = BackRef() to collect devices in the ACNode group that references Area.

The collection of idx happens in andes.system.System._collect_ref_param(). It has to be noted that the specific Area entry must exist to collect model idx-dx referencing it. For example, if Area has the following data

idx 1

Then, only Bus 1, 3, and 4 will be collected into self.Bus.v, namely, self.Bus.v == [ [1, 3, 4] ].

If Area has data

idx 1 2

Then, self.Bus.v will end up with [ [1, 3, 4], [2] ].

class andes.core.service.NumReduce(u, ref: BackRef, fun: Callable, name=None, tex_name=None, info=None, cache=True)[source]

A helper Service type which reduces a linearly stored 2-D ExtParam into 1-D Service.

NumReduce works with ExtParam whose v field is a list of lists. A reduce function which takes an array-like and returns a scalar need to be supplied. NumReduce calls the reduce function on each of the lists and return all the scalars in an array.

Parameters:
uExtParam

Input ExtParam whose v contains linearly stored 2-dimensional values

refBackRef

The BackRef whose 2-dimensional shapes are used for indexing

funCallable

The callable for converting a 1-D array-like to a scalar

Examples

Suppose one wants to calculate the mean value of the Vn in one Area. In the Area class, one defines

class AreaModel(...):
    def __init__(...):
        ...
        # backward reference from `Bus`
        self.Bus = BackRef()

        # collect the Vn in an 1-D array
        self.Vn = ExtParam(model='Bus',
                           src='Vn',
                           indexer=self.Bus)

        self.Vn_mean = NumReduce(u=self.Vn,
                                 fun=np.mean,
                                 ref=self.Bus)

Suppose we define two areas, 1 and 2, the Bus data looks like

idx

area

Vn

1

1

110

2

2

220

3

1

345

4

1

500

Then, self.Bus.v is a list of two lists [ [1, 3, 4], [2] ]. self.Vn.v will be retrieved and linearly stored as [110, 345, 500, 220]. Based on the shape from self.Bus, numpy.mean() will be called on [110, 345, 500] and [220] respectively. Thus, self.Vn_mean.v will become [318.33, 220].

class andes.core.service.NumRepeat(u, ref, **kwargs)[source]

A helper Service type which repeats a v-provider's value based on the shape from a BackRef

Examples

NumRepeat was originally designed for computing the inertia-weighted average rotor speed (center of inertia speed). COI speed is computed with

\[\omega_{COI} = \frac{ \sum{M_i * \omega_i} } {\sum{M_i}}\]

The numerator can be calculated with a mix of BackRef, ExtParam and ExtState. The denominator needs to be calculated with NumReduce and Service Repeat. That is, use NumReduce to calculate the sum, and use NumRepeat to repeat the summed value for each device.

In the COI class, one would have

class COIModel(...):
    def __init__(...):
        ...
        self.SynGen = BackRef()
        self.SynGenIdx = RefFlatten(ref=self.SynGen)
        self.M = ExtParam(model='SynGen',
                          src='M',
                          indexer=self.SynGenIdx)

        self.wgen = ExtState(model='SynGen',
                             src='omega',
                             indexer=self.SynGenIdx)

        self.Mt = NumReduce(u=self.M,
                                 fun=np.sum,
                                 ref=self.SynGen)

        self.Mtr = NumRepeat(u=self.Mt,
                               ref=self.SynGen)

        self.pidx = IdxRepeat(u=self.idx,ref=self.SynGen)

Finally, one would define the center of inertia speed as

self.wcoi = Algeb(v_str='1', e_str='-wcoi')

self.wcoi_sub = ExtAlgeb(model='COI',
                         src='wcoi',
                         e_str='M * wgen / Mtr',
                         v_str='M / Mtr',
                         indexer=self.pidx,
                         )

It is very worth noting that the implementation uses a trick to separate the average weighted sum into n sub-equations, each calculating the \((M_i * \omega_i) / (\sum{M_i})\). Since all the variables are preserved in the sub-equation, the derivatives can be calculated correctly.

class andes.core.service.IdxRepeat(u, ref, **kwargs)[source]

Helper class to repeat IdxParam.

This class has the same functionality as andes.core.service.NumRepeat but only operates on IdxParam, DataParam or NumParam.

class andes.core.service.RefFlatten(ref, **kwargs)[source]

A service type for flattening andes.core.service.BackRef into a 1-D list.

Examples

This class is used when one wants to pass BackRef values as indexer.

andes.models.coi.COI collects referencing andes.models.group.SynGen with

self.SynGen = BackRef(info='SynGen idx lists', export=False)

After collecting BackRefs, self.SynGen.v will become a two-level list of indices, where the first level correspond to each COI and the second level correspond to generators of the COI.

Convert self.SynGen into 1-d as self.SynGenIdx, which can be passed as indexer for retrieving other parameters and variables

self.SynGenIdx = RefFlatten(ref=self.SynGen)

self.M = ExtParam(model='SynGen', src='M',
                  indexer=self.SynGenIdx, export=False,
                  )

Value Manipulation#

class andes.core.service.Replace(old_val, flt, new_val, name=None, tex_name=None, info=None, cache=True)[source]

Replace parameters with new values if the function returns True

class andes.core.service.ParamCalc(param1, param2, func, name=None, tex_name=None, info=None, cache=True)[source]

Parameter calculation service.

Useful to create parameters calculated instantly from existing ones.

class andes.core.service.ApplyFunc(u, func, name=None, tex_name=None, info=None, cache=True)[source]

Class for applying a numerical function on a parameter..

Parameters:
u

Input parameter

func

A condition function that returns True or False.

Warning

This class is not ready.

Idx and References#

class andes.core.service.DeviceFinder(u, link, idx_name: str, default_model: str, auto_find: bool | None = True, auto_add: bool | None = True, name: str | None = None, tex_name: str | None = None, info: str | None = None)[source]

Service for finding idx of devices which are linked to the given devices.

The auto_find parameter controls if the device idx should be automatically looked up. The auto_add parameter controls if the device will be automatically added. The two parameters are not exclusive. One can skip finding the device but automatically adding it.

If auto_find is True and the idx is None, DeviceFinder will look up for the device. If not found and auto_add is True, DevFinder will then automatically add the devices. The idx of the devices that are found or added will be stored to the DeviceFinder instance, so that DeviceFinder can be used like any IdxParam.

Adding new devices are called at the beginning of andes.system.System.setup().

Examples

The IEEEST stabilizer takes an optional parameter busf of the type IdxParam for specifying the connected bus frequency measurement device, which is needed for mode 6. To avoid reimplementing BusFreq within IEEEST, one can do

self.busfreq = DeviceFinder(self.busf,
                            link=self.buss, idx_name='bus',
                            default_model='BusFreq')

where self.busf is for the optional parameter for the idx of bus frequency estimation devices (e.g., BusFreq), self.buss is for the idx of buses that self.busf devices should measure, and idx_name is the name of the BusFreq parameter through which the indices of measured buses are given.

For each None or invalid values in self.busf, a BusFreq device will be created with its bus set to the corresponding value in self.buss. That is, BusFreq.[idx_name].v = [link].

At the end, the DeviceFinder instance will contain the list of BusFreq that are are connected to self.buss, respectively.

In the case of any valid value in self.busf, that is, the value is an existing BusFreq device, DeviceFinder will return it as is without checking if the BusFreq device actually measures the bus specified by self.buss. It allows to use the measurement at a different location, but the user have to perform the data consistency check.

Events#

class andes.core.service.EventFlag(u, vtype: type | None = None, name: str | None = None, tex_name=None, info=None)[source]

Service to flag events when the input value changes. The typical input is a v-provider with binary values.

Implemented by providing self.check(**kwargs) as v_numeric. EventFlag.v stores the values of the input variable in the most recent iteration/step.

After the evaluation of self.check(), self.v will be updated.

class andes.core.service.ExtendedEvent(u, t_ext: int | float | BaseParam | BaseService = 0.0, trig: str = 'rise', enable=True, v_disabled=0, extend_only=False, vtype: type | None = None, name: str | None = None, tex_name=None, info=None)[source]

Service for indicating an event for an extended, predefined period of time following the event disappearance.

The triggering of an event, whether the rise or fall edge, is specified through trig. For example, if trig = rise, the change of the input from 0 to 1 will be considered as an input, whereas the subsequent change back to 0 will be considered as the event end.

ExtendedEvent.v stores the flags whether the extended time has completed. Outputs will become 1 once the event starts and return to 0 when the extended time ends.

Parameters:
uv-provider

Triggering signal where the values are 0 or 1.

trigstr in ("rise", "fall")

Triggering edge for the beginning of an event. rise by default.

enablebool or v-provider

If disabled, the output will be v_disabled

extend_onlybool

Only output during the extended period, not the event period.

Warning

The performance of this class needs to be optimized.

class andes.core.service.VarHold(u, hold, vtype=None, name=None, tex_name=None, info=None)[source]

Service for holding the input when the hold signal is on.

Parameters:
holdv-provider, binary

Hold signal array with length equal to the input. For elements that are 1, the corresponding inputs are held until the hold signal returns to 0.

Flags#

class andes.core.service.FlagCondition(u, func, flag=1, name=None, tex_name=None, info=None, cache=True)[source]

Class for flagging values based on a condition function.

By default, values whose condition function output equal that equal to True/1 will be flagged as 1. 0 otherwise.

Parameters:
u

Input parameter

func

A condition function that returns True or False.

flag1 by default, only 0 or 1 is accepted.

The flag for the inputs whose condition output is True.

Warning

This class is not ready.

FlagCondition can only be applied to BaseParam with cache=True. Applying to Service will fail unless cache is False (at a performance cost).

class andes.core.service.FlagGreaterThan(u, value=0.0, flag=1, equal=False, name=None, tex_name=None, info=None, cache=True)[source]

Service for flagging parameters > or >= the given value element-wise.

Parameters that satisfy the comparison (u > or >= value) will flagged as flag (1 by default).

class andes.core.service.FlagLessThan(u, value=0.0, flag=1, equal=False, name=None, tex_name=None, info=None, cache=True)[source]

Service for flagging parameters < or <= the given value element-wise.

Parameters that satisfy the comparison (u < or <= value) will flagged as flag (1 by default).

class andes.core.service.FlagValue(u, value, flag=0, name=None, tex_name=None, info=None, cache=True)[source]

Class for flagging values that equal to the given value.

By default, values that equal to value will be flagged as 0. Non-matching values will be flagged as 1.

Parameters:
u

Input parameter

value

Value to flag. Can be None, string, or a number.

flag0 by default, only 0 or 1 is accepted.

The flag for the matched ones

Warning

FlagNotNone can only be applied to BaseParam with cache=True. Applying to Service will fail unless cache is False (at a performance cost).

Data Select#

class andes.core.service.DataSelect(optional, fallback, name: str | None = None, tex_name: str | None = None, info: str | None = None)[source]

Class for selecting values for optional DataParam or NumParam.

This service is a v-provider that uses optional DataParam when available. Otherwise, use the fallback value.

DataParam will be tested for None, and NumParam will be tested with np.isnan().

Notes

An use case of DataSelect is remote bus. One can do

self.buss = DataSelect(option=self.busr, fallback=self.bus)

Then, pass self.buss instead of self.bus as indexer to retrieve voltages.

Another use case is to allow an optional turbine rating. One can do

self.Tn = NumParam(default=None)
self.Sg = ExtParam(...)
self.Sn = DataSelect(Tn, Sg)
class andes.core.service.NumSelect(optional, fallback, name: str | None = None, tex_name: str | None = None, info: str | None = None, ignore_cond: ~typing.Callable | None = functools.partial(<ufunc 'equal'>, 0))[source]

Class for selecting values for optional NumParam.

NumSelect works with internal and external parameters.

Any values equal to np.nan will always be ignored. If one needs to ignore values based on additional conditions, pass it through ignore_cond. For example, to ignore zero values, use ignore_cond = partial(np.equal, 0).

Examples

One use case is to allow an optional turbine rating. One can do

self.Tn = NumParam(default=None) self.Sg = ExtParam(...) self.Sn =
DataSelect(Tn, Sg)

Miscellaneous#

class andes.core.service.InitChecker(u, lower=None, upper=None, equal=None, not_equal=None, enable=True, error_out=False, **kwargs)[source]

Class for checking init values against known typical values.

Instances will be stored in Model.services_post and Model.services_icheck, which will be checked in Model.post_init_check() after initialization.

Parameters:
u

v-provider to be checked

lowerfloat, BaseParam, BaseVar, BaseService

lower bound

upperfloat, BaseParam, BaseVar, BaseService

upper bound

equalfloat, BaseParam, BaseVar, BaseService

values that the value from v_str should equal

not_equalfloat, BaseParam, BaseVar, BaseService

values that should not equal

enablebool

True to enable checking

Examples

Let's say generator excitation voltages are known to be in the range of 1.6 - 3.0 per unit. One can add the following instance to GENBase

self._vfc = InitChecker(u=self.vf,
                        info='vf range',
                        lower=1.8,
                        upper=3.0,
                        )

lower and upper can also take v-providers instead of float values.

One can also pass float values from Config to make it adjustable as in our implementation of GENBase._vfc.

class andes.core.service.CurrentSign(bus, bus1, bus2, name=None, tex_name=None, info=None)[source]

Service for computing the sign of the current flowing through a series device.

With a given line connecting bus1 and bus2, one can compute the current flow using (v1*exp(1j*a1) - v2*exp(1j*a2)) / (r + jx) whose value is the outflow on bus1.

CurrentSign can be used to compute the sign to be multiplied depending on the observing bus. For each value in bus, the sign will be +1 if it appears in bus1 or -1 otherwise.

bus1          bus2
 *------>>-----*
bus(+)        bus(-)
class andes.core.service.RandomService(func=<bound method RandomState.rand of RandomState(MT19937)>, **kwargs)[source]

A service type for generating random numbers.

Parameters:
namestr

Name

funcCallable

A callable for generating the random variable.

Warning

The value will be randomized every time it is accessed. Do not use it if the value needs to be stable for each simulation step.

class andes.core.service.SwBlock(*, init, ns, blocks, ext_sel=None, name=None, tex_name=None, info=None)[source]

Service type for switched shunt blocks.

Common Patterns#

Per-Unit Conversion#

self.Zbase = ConstService(v_str='Vn**2 / Sn')
self.R_pu = ConstService(v_str='R_ohm / Zbase')

Inverse Calculation#

self.R = NumParam()
self.gain = ConstService(v_str='u / R')

Conditional Value#

self.K = ConstService(v_str='K1 * (mode == 1) + K2 * (mode == 2)')

See Also#