Scripting Custom Run

InterPSS, though its GUI, provides standard menu items for you to run standard analysis, such as Loadflow, Short Circuit or Transient Stability analysis. InterPSS has also a very power and extensible power system simulation engine. You can extend it to do many other things, for example, repeatedly run Loadflow to find voltage stability limit for certain power transfer increase pattern. This custom analysis run scripting feature will allow you to write you own scripts to tell InterPSS how to run your case.

Custom Run Scripting

You can click the Run/Custom Run Scripts menu iteam or the Custom Run Scripts button to launch a custom run script editing dialog box.

You have the choice to use XML or Java as the scripting language. Future version will allow user to develop custom scripting language.

XML as scripting language

You can use an XML document to drive InterPSS run process. The document has to confirm InterPSS XML schema, discussed in InterPSS XML Document. For example, you can use an XML document to distribute multiple transient stability simulation cases to remote grid nodes for grid computing. You can find more details at InterPSS Grid Computing Solution user guide.

Java as Scripting Language

You need to implement the ISimuCaseRunner (JavaAPI) interface to perform a custom run. The following is a sample of a custom AC Loadflow implementation.

public class <classname> implements ISimuCaseRunner {

public boolean runCase(SimuContext simuCtx, IPSSMsgHub msg) {

// At this point, you have access to the network object containing all simulation data

AclfNetwork net = simuCtx.getAclfAdjNet();

LoadflowAlgorithm algo = CoreObjectFactory.createLoadflowAlgorithm(net);

algo.loadflow(msg);

return net.isLfConverged();

}

public void displayResult(SimuContext simuCtx) {

IOutputTextDialog dialog = UISpringAppContext.getOutputTextDialog("Loadflow Analysis Info");

dialog.display("Bla Bla ....");

}

}

You can edit your custom run scripts (Java Code). After completing, click the Run Button. The scripts (Java Code) will be compiled and executed. If there is any Java syntax error, you will get error messages, as follows:

Voltage Stability Analysis

Custom run scripting is a very power concept. You can use this feature to extend InterPSS in many ways. The following is an example to extend InterPSS to perform power transfer voltage stability limit analysis. The IEEE 14-Bus system is used as an example. We will gradually increase the power transfer from the generation area to the load area until loadflow diverge to find power transfer limit regarding voltage stability. Power transfer will be allocated in the following way:

    • Load Allocation : Bus10 (15%), Bus11 (25%), Bus12 (20%), Bus13 (20%), Bus14 (20%) while keeping power factor constant;
    • Generation Allocation : Bus2(40%), Bus3(40%), the rest to Bus1(Slack bus). For PQ bus, power factor is kept contant.

The following sample scripts is used to perform the analysis:

public class <classname> implements ISimuCaseRunner {

private MultiStudyCase mcase;

public boolean runCase(SimuContext simuCtx, IPSSMsgHub msg) {

mcase = createMultiStudyCase(simuCtx.getAclfAdjNet(), msg);

mcase.createBaseCase();

for (int i = 1; i <= 100; i++ ) { // running max 100 study cases

StudyCase studyCase = CoreObjectFactory.createStudyCase("StudyCase"+i, "Case"+i, i, mcase);

if (!mcase.runStudyCase(studyCase))

break; // when runStudyCase return false, indicating LF diverge, simulation will stop

}

return true;

}

public void displayResult(SimuContext simuCtx) {

String str = "";

for (StudyCase studyCase : mcase.getStudyCaseList()) {

str += "StudyCase: " + studyCase.getCaseNumber() + ", " + studyCase.getName() +

(((AclfNetworkResult)studyCase.getNetResult()).converged? " LF converged":" LF diverged") +

"," + studyCase.getDesc() + "\n";

for (BusResult r : studyCase.getBusResultList()) {

AclfBusResult result = (AclfBusResult)r;

str += result.toString() + "\n";

}

str += "\n";

}

// output simulation results to a popup dialog

IOutputTextDialog dialog = UISpringAppContext.getOutputTextDialog("Power Transfer Analysis Info");

dialog.display(str);

}

private MultiStudyCase createMultiStudyCase(AclfAdjNetwork net, final IPSSMsgHub msg) {

MultiStudyCase mcase = CoreObjectFactory.createMultiStudyCase(net);

mcase.setCaseRunner(new AbstractAclfStudyCaseRunner() {

private StudyCase baseCase = null;

private AclfBusResult bus2Result, bus3Result, bus10Result, bus11Result, bus12Result, bus13Result, bus14Result;

public boolean generateCaseData(StudyCase studyCase) {

try {

if (baseCase == null) {

baseCase = studyCase.getParent().getStudyCase(Constants.BaseStudyCaseName);

bus2Result = (AclfBusResult)baseCase.getBusResult("0002");

bus3Result = (AclfBusResult)baseCase.getBusResult("0003");

bus10Result = (AclfBusResult)baseCase.getBusResult("0010");

bus11Result = (AclfBusResult)baseCase.getBusResult("0011");

bus12Result = (AclfBusResult)baseCase.getBusResult("0012");

bus13Result = (AclfBusResult)baseCase.getBusResult("0013");

bus14Result = (AclfBusResult)baseCase.getBusResult("0014");

}

double dP = studyCase.getCaseNumber()*0.1;

studyCase.setDesc(" Increase Power Transfer(pu) " + dP);

// increase generation

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus2Result, 0.4*dP);

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus3Result, 0.4*dP);

// increase load

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus10Result, 0.15*dP);

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus11Result, 0.25*dP);

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus12Result, 0.20*dP);

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus13Result, 0.20*dP);

AbstractAclfStudyCaseRunner.increaseBusLoadConstPF(bus14Result, 0.20*dP);

} catch (InterpssException e) {

msg.sendErrorMsg(e.toString());

return false;

}

return true;

}

});

return mcase;

}

After the simulation run, the results are displayed in a popup dialog box as follows:

At StudyCase33, the 33rd run, power transfer increased 3.3pu (330MW) from the base case. Voltage at Bus14 is quite low (0.6274pu). At StudyCase34, the 34th run, loadflow diverges, indicating voltage stability problem.

Voltage Profile Calculation

Very often, one may want to calculate multiple point voltage change profile as result of load change, for example during a day. The following is an example of calculating voltage profile for 24 load points.

public class <classname> implements ISimuCaseRunner {

private MultiStudyCase mcase;

public boolean runCase(SimuContext simuCtx, IPSSMsgHub msg) {

mcase = createMultiStudyCase(simuCtx.getAclfAdjNet(), msg);

mcase.createBaseCase();

for (int i = 1; i <= 24; i++ ) {

StudyCase studyCase = CoreObjectFactory.createStudyCase("StudyCase"+i, "Case"+i, i, mcase);

mcase.runStudyCase(studyCase);

}

return true;

}

public void displayResult(SimuContext simuCtx) {

String str = "";

for (StudyCase studyCase : mcase.getStudyCaseList()) {

str += "StudyCase: " + studyCase.getCaseNumber() + ", " + studyCase.getName() +

(((AclfNetworkResult)studyCase.getNetResult()).converged? " LF converged":" LF diverged") +

"," + studyCase.getDesc() + "\n";

for (BusResult r : studyCase.getBusResultList()) {

AclfBusResult result = (AclfBusResult)r;

str += result.toString() + "\n";

}

str += "\n";

}

IOutputTextDialog dialog = UISpringAppContext.getOutputTextDialog("Loadflow Analysis Info");

dialog.display(str);

}

private MultiStudyCase createMultiStudyCase(AclfAdjNetwork net, final IPSSMsgHub msg) {

MultiStudyCase mcase = CoreObjectFactory.createMultiStudyCase(net);

mcase.setCaseRunner(new AbstractAclfStudyCaseRunner() {

// Load profile 1

private double[] pFactorList_1 = {

0.3, 0.3, 0.3, 0.3, 1.0, 1.0,

1.0, 1.0, 1.0, 1.0, 1.0, 1.0,

1.0, 1.0, 1.4, 1.3, 1.3, 1.0,

1.0, 1.0, 0.2, 0.2, 0.2, 0.1};

private double[] qFactorList_1 = {

0.2, 0.2, 0.2, 0.2, 0.3, 1.0,

1.0, 1.0, 1.0, 1.0, 1.0, 1.0,

1.0, 1.0, 1.0, 1.2, 1.2, 1.2,

1.0, 1.0, 1.0, 0.1, 0.1, 0.1};

// Load profile 2

private double[] pFactorList_2 = {

0.3, 0.3, 0.3, 0.3, 1.0, 1.0,

1.0, 1.0, 1.0, 1.0, 0.9, 0.8,

1.0, 1.0, 1.1, 1.3, 1.3, 1.0,

1.0, 1.0, 0.2, 0.2, 0.2, 0.1};

private double[] qFactorList_2 = {

0.2, 0.2, 0.2, 0.2, 0.3, 1.0,

1.0, 1.0, 1.0, 1.0, 0.7, 0.6,

1.0, 1.0, 1.0, 1.2, 1.2, 1.2,

1.0, 1.0, 1.0, 0.1, 0.1, 0.1};

private StudyCase baseCase = null;

private AclfBusResult bus10Result, bus11Result, bus12Result, bus13Result, bus14Result;

public boolean generateCaseData(StudyCase studyCase) {

try {

if (baseCase == null) {

baseCase = studyCase.getParent().getStudyCase(Constants.BaseStudyCaseName);

bus10Result = (AclfBusResult)baseCase.getBusResult("0010");

bus11Result = (AclfBusResult)baseCase.getBusResult("0011");

bus12Result = (AclfBusResult)baseCase.getBusResult("0012");

bus13Result = (AclfBusResult)baseCase.getBusResult("0013");

bus14Result = (AclfBusResult)baseCase.getBusResult("0014");

}

int index = studyCase.getCaseNumber()-1;

// assume Bus10, Bus11 and Bus12 follows Load Profie-1

AbstractAclfStudyCaseRunner.increaseBusLoad(bus10Result, pFactorList_1[index], qFactorList_1[index]);

AbstractAclfStudyCaseRunner.increaseBusLoad(bus11Result, pFactorList_1[index], qFactorList_1[index]);

AbstractAclfStudyCaseRunner.increaseBusLoad(bus12Result, pFactorList_1[index], qFactorList_1[index]);

// assume Bus13, Bus14 follows Load Profie-2

AbstractAclfStudyCaseRunner.increaseBusLoad(bus13Result, pFactorList_2[index], qFactorList_2[index]);

AbstractAclfStudyCaseRunner.increaseBusLoad(bus14Result, pFactorList_2[index], qFactorList_2[index]);

} catch (InterpssException e) {

msg.sendErrorMsg(e.toString());

return false;

}

return true;

}

});

return mcase;

}

}