Skip to content

IEEEST Stabilizer Improvements/Corrections - #460

Open
lukelowry wants to merge 6 commits into
developfrom
lukel/ieeest-dev
Open

IEEEST Stabilizer Improvements/Corrections#460
lukelowry wants to merge 6 commits into
developfrom
lukel/ieeest-dev

Conversation

@lukelowry

@lukelowry lukelowry commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Description

Fixes and cleans up the IEEEST stabilizer implementation and documentation.

This updates the older initial implementation style so that reduced-order notch filters and zero denominator time constants are handled consistently

Proposed changes

  • Replace the branchy/safe-inverse notch logic with a fixed DAE form using differential tags.
  • Initialize IEEEST from the attached input signal instead of forcing all states to zero.
  • Document the implemented equations, initialization, derived parameters, and unsupported compatibility parameters.
  • Tests for initialization, residuals, invalid wiring, invalid notch parameters, zero time constants, and Jacobian consistency.

Checklist

  • All tests pass for the focused PhasorDynamics coverage.
  • Code compiles cleanly with flags -Wall -Wpedantic -Wconversion -Wextra.
  • The new code follows GridKit™ style guidelines.
  • There are unit tests for the new code.
  • The new code is documented.
  • The feature branch is rebased with respect to the target branch.

Changelog changes N/A

Further comments

This is cleanup/correction work for the existing IEEEST model, not a new model

@lukelowry
lukelowry marked this pull request as ready for review June 22, 2026 18:43
@lukelowry

Copy link
Copy Markdown
Collaborator Author

@pelesh this fix is also ready to be merged I forgot to make a PR for this one.

@pelesh pelesh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic governing changing differential into algebraic equations and vice versa does not seem to be sustainable. This requires more offline discussion.

Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
@lukelowry
lukelowry force-pushed the lukel/ieeest-dev branch 2 times, most recently from 8bbbad6 to 090289b Compare June 26, 2026 11:02
@lukelowry

Copy link
Copy Markdown
Collaborator Author

I have rebased and adjusted the formulation to align with #463 .

@nkoukpaizan nkoukpaizan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few comments here. Perhaps worth discussing at our next meeting.

Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread tests/UnitTests/PhasorDynamics/StabilizerIeeestTests.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp
using Variable = typename ModelDataT::MonitorableVariables;
monitor_->set(Variable::vss, [this]
{ return y_[11]; });
auto index = [](IeeestInternalVariables variable)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen this pattern a few times. Consider defining once if it is really needed. I would argue it's less readable.

Comment thread tests/UnitTests/PhasorDynamics/runStabilizerIeeestTests.cpp
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/Ieeest.hpp
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp
Comment thread tests/UnitTests/PhasorDynamics/StabilizerIeeestTests.hpp Outdated
@lukelowry

Copy link
Copy Markdown
Collaborator Author

Testing Ground for template parameters <Order N>

@lukelowry lukelowry added this to the WECC Completion milestone Jul 2, 2026
@lukelowry

Copy link
Copy Markdown
Collaborator Author

general implementation of the template parameter done

@nkoukpaizan nkoukpaizan added enhancement New feature or request cleanup labels Jul 10, 2026
@lukelowry
lukelowry force-pushed the lukel/ieeest-dev branch 4 times, most recently from d0dc95a to d2be200 Compare July 17, 2026 21:58
@lukelowry

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan what are your thoughts on my template implementation?

@nkoukpaizan

Copy link
Copy Markdown
Collaborator

@nkoukpaizan what are your thoughts on my template implementation?

The model implementation is cleaner with the order as a template parameter. However, the order remains a runtime selection based on floating point comparisons, which is what I wanted to avoid.

@lukelowry

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan we could possibly require the order to be passed as a parameter of IEEEST model, would that resolve your concern?

"Order" is not usually directly exposed as a model parameter and so would require some knowledge of how IEEEST works to pass valid parameters.

Can you give an example where the runtime comparison is bad/fails? I might be able to resolve both our concerns if I understand better.

@nkoukpaizan

Copy link
Copy Markdown
Collaborator

@nkoukpaizan we could possibly require the order to be passed as a parameter of IEEEST model, would that resolve your concern?

"Order" is not usually directly exposed as a model parameter and so would require some knowledge of how IEEEST works to pass valid parameters.

Can you give an example where the runtime comparison is bad/fails? I might be able to resolve both our concerns if I understand better.

Yes, exposing the order as a parameter to the model is what I had in mind. Understood that that's not the domain practice. That's why as was asking whether this is possible as a question.

Floating point values are stored with limited precision. We'd have to guarantee that the value returned by the parser is bit-for-bit equal to zero. That may be the case for nlohmann-json, but considering #227 and the possibility of using a different parser, that's not guaranteed.

@lukelowry

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan i see the issue now thank you, that was very clarifying. After reflecting on my past experience and discussing with others at TAMU, I think deriving the order from the parameters alone is not intuitive or safe, either.

As discussed, we should add an integer parameter to the IEEEST model, "order" and use that for the StabilizerFactory (rename to IeeestFactory). Then, our parameter validation can gate for zero division relevant to each static order (e.g. $A_2 + A_3&gt;0$). Additionally the model json may then contain some coefficients that are only used at a certain "order", which would be a feature IMO since you can retain information needed for higher order but choose to operate at smaller order.

I will make this change then we can reasess.

@lukelowry

Copy link
Copy Markdown
Collaborator Author

Since IEEEST is already not in Hessenberg form, I am temporarily closing this in favor of #520, which is a significantly cleaner implicit representation of the model. The 'minimum time constant' approach is unfortunately making validation quite difficult. Tracked in #463

I am justifying this decision because IEEEST can simply be removed from a case if it becomes a blocker for Hessenberg, but right now validation is more urgent. We can reopen after v0.2 is released

@lukelowry lukelowry closed this Aug 4, 2026
@pelesh pelesh reopened this Aug 6, 2026
@lukelowry

Copy link
Copy Markdown
Collaborator Author

Rebasing ASAP

@pelesh

pelesh commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

I suggest to proceed like this:

  • Define model order as an integer parameter.
  • Use switch statement in initialization and residual functions to select correct equations with the order parameter as the switch.

I would avoid templates for now. I don't think we should use hacks as in #520.

@lukelowry

Copy link
Copy Markdown
Collaborator Author

@pelesh please see most recent version of this branch, where I use a switch. How does this look?

@lukelowry

Copy link
Copy Markdown
Collaborator Author

Confirmed working in validation of three cases against PowerWorld. See #461

@lukelowry
lukelowry marked this pull request as ready for review August 8, 2026 19:08
@lukelowry
lukelowry force-pushed the lukel/ieeest-dev branch 2 times, most recently from e9ebe94 to d81ab35 Compare August 8, 2026 23:07

@pelesh pelesh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better!!

A few things to fix quickly before more thorough review.

Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp

@nkoukpaizan nkoukpaizan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments on the current state of the PR.

I'll defer to @pelesh if the switch really is what we want to go with.

Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/Ieeest.hpp Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/IeeestImpl.hpp Outdated
Comment on lines +300 to +302
switch (order_)
{
case 0:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure having the switch inside the residual evaluation is better than other alternatives we've explored. I suspect that is the motivation for the new -mllvm -simplifycfg-sink-common=false flag.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I had to add that flag for Enzyme to construct correctly. I will wait for @pelesh to chime in

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is not going to work as implemented (I rushed to celebration too early). You need a separate residual for each order and separate Jacobian for each residual. Jacobian derivatives are evaluated at compile time, so they have to have residual equations available at compile time.

The switch statement can be used to select residual function of the right order and its matching Jacobian but they need to be implemented separately. The rest of model infrastructure could be reused, I think.

Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/README.md Outdated
Comment thread GridKit/Model/PhasorDynamics/Stabilizer/IEEEST/README.md
Comment thread tests/UnitTests/PhasorDynamics/StabilizerIeeestTests.hpp
Comment thread tests/UnitTests/PhasorDynamics/StabilizerIeeestTests.hpp Outdated
@lukelowry

Copy link
Copy Markdown
Collaborator Author

@nkoukpaizan thank you for the timely review. pending @pelesh and @abirchfield now

@lukelowry
lukelowry requested a review from pelesh August 11, 2026 18:57

@pelesh pelesh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current implementation does not build on my machine. Enzyme seems to be trying to get derivatives for all runtime combinations and eventually runs out of memory.

The issue we are dealing here is not the modeling of a device but rather trying to fit five different mathematical model in one component. The documentation in README is misleading in that regard.

I suggest implement stabilizer for only one order as a temporary solution.

@lukelowry

Copy link
Copy Markdown
Collaborator Author

I would rather do the other branch we had for IEEEST #520 than do a single-order implementation as a temporary solution then, because that is much cleaner its just not in Hessenberg form. I can't validate the cases in #461 without variable order IEEEST

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cleanup enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants