Skip to content

Phasor Dynamics examples do not re-solve for consistent initial conditions after discrete events, such as bus faults #226

@alexander-novo

Description

@alexander-novo

Overview

As an example, consider the PhasorDynamics/TenGen example, which uses bus faults as discrete events during the simulation. After (de)activating the bus fault, the simulation is re-initialized:

fault.setStatus(1);
ida.initializeSimulation(1.0, false);
nout = static_cast<int>(std::round((1.1 - 1.0) / dt));
ida.runSimulation(1.1, nout, output_cb);

But a value of false is passed to to initializeSimulation for the parameter findConsistent, which is used to determine if IDACalcIC() should be called:

if (findConsistent)
{
int initType = IDA_Y_INIT;
if (tag_)
initType = IDA_YA_YDP_INIT;
retval = IDACalcIC(solver_, initType, 0.1);
checkOutput(retval, "IDACalcIC");
copyVec(yy_, model_->y());
copyVec(yp_, model_->yp());
}

The documentation for IDACalcIC() says

IDACalcIC() calculates corrected initial conditions for the DAE system for certain index-one problems including a class of systems of semi-implicit form (see §5.2.2 and [26]). It uses a Newton iteration combined with a linesearch algorithm. Calling IDACalcIC() is optional. It is only necessary when the initial conditions do not satisfy the given system. Thus if y0 and yp0 are known to satisfy $F(t_0, y_0, \dot{y}_0) = 0$, then a call to IDACalcIC() is generally not necessary.

In general, we don't know that the condition $F(t_0, y_0, \dot{y}_0) = 0$ is satisfied, and by experimentation we can verify that it isn't in this particular example. This indicates that a call to IDACalcIC() should still be necessary.

The documentation also says

A call to the function IDACalcIC() must be preceded by successful calls to IDACreate() and IDAInit() (or IDAReInit()), and by a successful call to the linear system solver specification function. The call to IDACalcIC() should precede the call(s) to IDASolve() for the given problem.

This seems to imply to me that a call to IDAReInit() (which is being done in initializeSimulation()) is not enough to verify that initial conditions are consistent and that we must still call IDACalcIC() (@Steven-Roberts can you confirm?)

Background

I've known about this for some time - in our Matlab models which are being compared to solutions generated by GridKit, the values after discrete events would always differ drastically, and step size controllers of certain Matlab integrators were not able to meet requested tolerances when we would not re-solve for consistent initial conditions (not all integrators are as tolerant as BDF turns out haha). When I discussed it with @reid-g, he mentioned that this was expected behavior - power systems engineers would not want algebraics to change discretely when re-solving for consistent initial conditions. But when I let @abirchfield and Carol know in our meeting about fixed vs adaptive integrators, they were surprised to learn about this behavior.

Fixes

If this behavior is intentional, it (and the reasoning behind it) needs to be documented somewhere since multiple people now have been surprised by it. Also maybe we should have a discussion with @abirchfield and Carol verifying that's what we want.

Otherwise, it would be best to fix these examples by changing the value false to true. Also, it would be interesting to see if this API could be changed so that true is the default - it doesn't happen often in our simulations, I think, that the simulation needs to be re-initialized and most of those times the initial conditions should be made consistent. The extra (potentially unneeded) computation should be overshadowed by the rest of the simulation.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationexamples

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions