Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions src/griddyn/Block.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ namespace blocks {
class RampLimiter;
} // namespace blocks

/** @brief class implementing basic control system block
the basic block class takes a single input X the output is then \f$K*(X+bias)\f$
optionally implementing limiters Omax and Omin the limiters have a reset level specified by
resetLevel once the object is initialized the determination of whether to use the ramps is fixed and
cannot be changed unless the object is reinitialized directly

the blocks take 1 or 2 inputs the first being the single input, if the differential input is set
then the second argument is the time derivative of the input
*/
/**
* @brief Common single-input/single-output base for dynamic control blocks.
*
* In its basic algebraic form GridBlock evaluates @f$y=K(u+b)@f$. Derived
* blocks select whether they own an algebraic or differential output/state,
* then override the residual, derivative, and analytic Jacobian as needed.
* The optional second input is @f$\dot u@f$ when `differential_input` is set.
*
* Inherited output limits apply a @ref blocks::ValueLimiter; inherited ramp
* limits apply a @ref blocks::RampLimiter to a differential output. Both use
* root-triggered engagement and `resetlevel` hysteresis. State layout and
* whether limits are active are fixed during dynamic initialization, so limit
* flags must be changed before reinitializing the block.
*/
class GridBlock: public GridSubModel {
public:
/** @brief flags common for all control blocks
Expand Down
1 change: 1 addition & 0 deletions src/griddyn/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ set(block_sources
blocks/DerivativeBlock.cpp
blocks/FunctionBlock.cpp
blocks/LutBlock.cpp
blocks/LeadLagBlock.cpp
blocks/TransferFunctionBlock.cpp
blocks/FilteredDerivativeBlock.cpp
blocks/BlockSequence.cpp
Expand Down
6 changes: 6 additions & 0 deletions src/griddyn/blocks/Block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ static const TypeFactory<GridBlock>
BLOCK_FACTORY("block", std::to_array<std::string_view>({"basic", "gain"}), "basic");
static const ChildTypeFactory<blocks::ControlBlock, GridBlock> CONTROL_BLOCK_FACTORY("block",
"control");
static const ChildTypeFactory<blocks::LeadLagBlock, GridBlock>
LEAD_LAG_BLOCK_FACTORY("block", std::to_array<std::string_view>({"leadlag", "lead_lag"}));
static const ChildTypeFactory<blocks::DeadbandBlock, GridBlock>
DEADBAND_BLOCK_FACTORY("block", std::to_array<std::string_view>({"deadband", "db"}));
static const ChildTypeFactory<blocks::DelayBlock, GridBlock>
Expand All @@ -40,6 +42,10 @@ static const ChildTypeFactory<blocks::FilteredDerivativeBlock, GridBlock>
FILTERED_DERIVATIVE_BLOCK_FACTORY(
"block",
std::to_array<std::string_view>({"fder", "filtered_deriv", "filtered_derivative"}));
static const ChildTypeFactory<blocks::TransferFunctionBlock, GridBlock>
TRANSFER_FUNCTION_BLOCK_FACTORY(
"block",
std::to_array<std::string_view>({"transfer_function", "transferfunction", "tf"}));

GridBlock::GridBlock(const std::string& objName): GridSubModel(objName)
{
Expand Down
17 changes: 13 additions & 4 deletions src/griddyn/blocks/BlockSequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@
#include <vector>

namespace griddyn::blocks {
/** @brief class implementing a sequence of blocks as a single block
A block is defined as a single input single output subModel. This object takes any number of blocks
in a sequence and processes them in the appropriate fashion.
*/
/**
* @brief Ordered serial composition of one or more GridBlock instances.
*
* For blocks @f$B_0,\ldots,B_n@f$, this composite evaluates
* @f$y=B_n(\ldots B_1(B_0(u+b))\ldots)@f$. It propagates output derivatives,
* residuals, analytic Jacobians, roots, and root triggers through the same
* ordering. States remain owned by the child blocks; this class only supplies
* the single-input/single-output composition and local-step scheduling.
*
* `differential_input` causes the first child to receive an input derivative.
* BlockSequence is a composite container, not an independently factory-loaded
* elementary block.
*/
class BlockSequence: public GridBlock {
public:
protected:
Expand Down
17 changes: 12 additions & 5 deletions src/griddyn/blocks/ControlBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,18 @@
#include <string>

namespace griddyn::blocks {
/** @brief class implementing a control block
block implementing \f$H(S)=\frac{K(1+T_2 s}{1+T_1 s}\f$
default is \f$T_2 =0\f$ for behavior equivalent to a delay block
if T1 is 0 it behaves like the basic block
*/
/**
* @brief Legacy first-order lead--lag GridBlock.
*
* This predates @ref LeadLagBlock and implements
* @f$H(s)=K(1+T_2s)/(1+T_1s)@f$. It owns an intermediate differential
* state and exposes an algebraic output. `t1` is the denominator time
* constant and `t2` is the numerator time constant; `t2=0` gives the
* first-order lag form. Inherited GridBlock gain, bias, and limiter settings
* apply. New controller code should prefer @ref LeadLagBlock, whose equation,
* initialization contract, and zero-order-hold stepping are documented and
* tested explicitly.
*/
class ControlBlock: public GridBlock {
public:
protected:
Expand Down
19 changes: 16 additions & 3 deletions src/griddyn/blocks/DeadbandBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@
#include <vector>

namespace griddyn::blocks {
/** @brief class implementing a deadband system
TOBE added
*/
/**
* @brief Stateful deadband, with optional continuous transition ramps.
*
* For biased input @f$x=u+b@f$, the normal deadband output is the configured
* `level` while @f$x\in[low,high]@f$ and is @f$x@f$ outside that interval.
* With the `shifted` flag, the outside branches are offset to meet `level`
* continuously at the bounds. `ramp`, `rampup`, and `rampdown` introduce
* linear transition regions instead. The exposed output is @f$K f(x)@f$ and
* inherited GridBlock limits may further clamp it.
*
* Root events transition among NORMAL, OUTSIDE, SHIFTED, and the two ramp
* states. `reset`, `resethigh`, and `resetlow` provide hysteresis; this is
* important for preventing event chatter near a boundary. `db`/`deadband`
* sets symmetric bounds around `level`; `high` and `low` set individual
* boundaries.
*/
class DeadbandBlock: public GridBlock {
public:
/** @brief flags for the deadband block*/
Expand Down
56 changes: 41 additions & 15 deletions src/griddyn/blocks/DelayBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,57 @@

#pragma once

/**
* @file DelayBlock.h
* @brief First-order lag (measurement or transport-delay approximation) block.
*/

#include "../Block.h"
#include <string>

namespace griddyn::blocks {
/** @brief class implementing a delay block
block implementing \f$H(S)=\frac{K}{1+T_1 s}\f$
if the time constant is very small it reverts to the basic block
*/
/**
* @brief First-order lag block.
*
* This block realizes the proper transfer function
* @f[
* H(s)=\frac{K}{1+T_1s}.
* @f]
* For input @f$u@f$, GridBlock bias @f$b@f$, and differential output state
* @f$y@f$, the DAE residual, derivative, and analytic Jacobian use
* @f[
* T_1\dot y=K(u+b)-y.
* @f]
* Thus it is the existing GridDyn first-order lag/transducer primitive; it
* does not include a lead numerator time constant. At an equilibrium,
* @f$y=K(u+b)@f$, so desired-output initialization back-solves this relation.
*
* Parameters `t1` and `t` set @f$T_1@f$; inherited `k`/`gain`, `bias`, and
* output-limit parameters retain their GridBlock meanings. A time constant
* below the GridDyn numerical-resolution threshold selects the historical
* simplified gain mode. The solver path continues to use the equation above;
* the separate @ref step path uses the legacy local integration routine and is
* therefore not an exact sampled-data discretization.
*/
class DelayBlock: public GridBlock {
public:
protected:
model_parameter mT1 = 0.1; //!< the time constant
model_parameter mT1 = 0.1; //!< Lag denominator time constant @f$T_1@f$.
public:
//!< default constructor
/** @brief Construct a unity-gain lag with @f$T_1=0.1@f$. */
explicit DelayBlock(const std::string& objName = "delayBlock_#");
/** alternate constructor to add in the time constant
@param[in] timeConstant the time constant
@param[in] objName the name of the block
*/
/**
* @brief Construct a unity-gain lag.
* @param[in] timeConstant Lag time constant @f$T_1@f$.
* @param[in] objName Name of the block.
*/
DelayBlock(double timeConstant, const std::string& objName = "delayBlock_#");
/** alternate constructor to add in the time constant
@param[in] timeConstant the time constant
@param[in] gainValue the block gain
@param[in] objName the name of the object
*/
/**
* @brief Construct a lag with explicit gain.
* @param[in] timeConstant Lag time constant @f$T_1@f$.
* @param[in] gainValue Steady-state gain @f$K@f$.
* @param[in] objName Name of the block.
*/
DelayBlock(double timeConstant, double gainValue, const std::string& objName = "delayBlock_#");
virtual CoreObject* clone(CoreObject* obj = nullptr) const override;

Expand Down
14 changes: 10 additions & 4 deletions src/griddyn/blocks/DerivativeBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@
#include <string>

namespace griddyn::blocks {
/** @brief class implementing a derivative
block implementing \f$H(S)=\frac{K s}{1+T_1 s}\f$
if the time constant is very small it reverts to the basic block
*/
/**
* @brief First-order filtered differentiator.
*
* The block realizes @f$H(s)=Ks/(1+T_1s)@f$ through a filtered input state
* @f$z@f$: @f$T_1\dot z=K(u+b)-z@f$ and exposed output @f$y=\dot z@f$.
* Thus its DC output is zero and a constant input initializes the derivative
* to zero. `t1` or `t` sets @f$T_1@f$; inherited `k`/`gain`, `bias`, and
* output limits retain their GridBlock meanings. The solver uses the
* analytic residual/Jacobian; local stepping uses the legacy integration path.
*/
class DerivativeBlock: public GridBlock {
protected:
model_parameter mT1 = 0.1; //!< delay time constant for the derivative filtering operation
Expand Down
14 changes: 10 additions & 4 deletions src/griddyn/blocks/FilteredDerivativeBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@
#include <string>

namespace griddyn::blocks {
/** @brief class implementing a derivative
block implementing \f$H(S)=\frac{K s}{1+T_1 s} \frac{1}{1+T_2 s}\f$

*/
/**
* @brief Two-stage filtered differentiator.
*
* This block realizes @f$H(s)=Ks/[(1+T_1s)(1+T_2s)]@f$. Its first state is
* the output of @f$T_1\dot z=K(u+b)-z@f$; the exposed output follows
* @f$T_2\dot y=\dot z-y@f$. Consequently a constant input has zero
* steady-state output. `t1` sets the pre-derivative filter and `t2` the
* output filter. Inherited output/ramp limits act on the exposed differential
* output and use normal GridBlock root handling.
*/
class FilteredDerivativeBlock: public GridBlock {
protected:
model_parameter mT1 = 0.1; //!< delay time constant for the derivative filtering operation
Expand Down
5 changes: 2 additions & 3 deletions src/griddyn/blocks/FunctionBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "FunctionBlock.h"

#include "core/CoreExceptions.h"
#include "core/CoreObjectTemplates.hpp"
#include "gmlc/utilities/stringOps.h"
#include "gmlc/utilities/vectorOps.hpp"
Expand Down Expand Up @@ -161,9 +162,7 @@ void FunctionBlock::setFunction(const std::string& functionName)
mBinaryFunctionPtr = binaryFunctionPtr;
opFlags.set(USES_CONSTANT_ARG);
} else {
mFunctionPtr = nullptr;
mDerivativeFunctionPtr = nullptr;
mBinaryFunctionPtr = nullptr;
throw InvalidParameterValue("unknown function block function: " + functionName);
}
}

Expand Down
14 changes: 11 additions & 3 deletions src/griddyn/blocks/FunctionBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,17 @@
#include <string>

namespace griddyn::blocks {
/** @brief class implementing a function operation on the input
a wide assortment of functions are available including trig, logs, and other common math
operations*/
/**
* @brief Algebraic wrapper around a supported unary or binary math function.
*
* Unary functions evaluate @f$y=K f(G(u+b))@f$. Binary functions evaluate
* @f$y=K f(G(u+b),a)@f$, where `arg` supplies the constant second argument.
* `function` and `func` select the function; an unknown name throws
* InvalidParameterValue rather than leaving a null callable. The analytic
* Jacobian is available for supported unary functions. Binary functions use
* the function interpreter's two-argument behavior and should be selected
* only when its derivative contract is suitable for the containing model.
*/
class FunctionBlock: public GridBlock {
public:
//!< flags for function block
Expand Down
13 changes: 10 additions & 3 deletions src/griddyn/blocks/IntegralBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@
#include <string>

namespace griddyn::blocks {
/** @brief class implementing an integral block
computes the integral of the input
*/
/**
* @brief Differential integrator with optional GridBlock limits.
*
* For output state @f$y@f$, the governing equation is
* @f$\dot y=K(u+b)@f$. `iv`/`initial_value` specifies the state used when
* no desired output is supplied; `t` is accepted as an inverse gain, setting
* @f$K=1/t@f$. Inherited value and ramp limits use GridBlock's root and
* anti-windup behavior. The local stepping path uses trapezoidal input
* integration.
*/
class IntegralBlock: public GridBlock {
public:
protected:
Expand Down
Loading