/*
* @(#)AclfParserHelper.java
*
* Copyright (C) 2009 www.interpss.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* @Author Mike Zhou
* @Version 1.0
* @Date 04/11/2009
*
* Revision History
* ================
*
*/
package org.ieee.odm.model.aclf;
import static org.ieee.odm.ODMObjectFactory.OdmObjFactory;
import java.util.Hashtable;
import java.util.List;
import javax.xml.bind.JAXBElement;
import org.ieee.odm.common.ODMLogger;
import org.ieee.odm.model.AbstractModelParser;
import org.ieee.odm.model.IODMModelParser;
import org.ieee.odm.model.base.BaseDataSetter;
import org.ieee.odm.model.base.BaseJaxbHelper;
import org.ieee.odm.schema.ActivePowerUnitType;
import org.ieee.odm.schema.ApparentPowerUnitType;
import org.ieee.odm.schema.BusGenDataXmlType;
import org.ieee.odm.schema.BusLoadDataXmlType;
import org.ieee.odm.schema.BusShuntYDataXmlType;
import org.ieee.odm.schema.BusXmlType;
import org.ieee.odm.schema.FlowInterfaceRecXmlType;
import org.ieee.odm.schema.InterchangeXmlType;
import org.ieee.odm.schema.LFGenCodeEnumType;
import org.ieee.odm.schema.LFLoadCodeEnumType;
import org.ieee.odm.schema.LineBranchXmlType;
import org.ieee.odm.schema.LoadflowBusXmlType;
import org.ieee.odm.schema.LoadflowGenDataXmlType;
import org.ieee.odm.schema.LoadflowLoadDataXmlType;
import org.ieee.odm.schema.LoadflowNetXmlType;
import org.ieee.odm.schema.LoadflowShuntYDataXmlType;
import org.ieee.odm.schema.PSXfrBranchXmlType;
import org.ieee.odm.schema.ReactivePowerUnitType;
import org.ieee.odm.schema.SwitchedShuntXmlType;
import org.ieee.odm.schema.StaticVarCompensatorXmlType;
import org.ieee.odm.schema.TielineXmlType;
import org.ieee.odm.schema.VoltageUnitType;
import org.ieee.odm.schema.XformerZTableXmlType;
import org.ieee.odm.schema.XfrBranchXmlType;
import org.ieee.odm.schema.YUnitType;
/**
* Aclf model parser help functions
*
* @author mzhou
*
*/
public class AclfParserHelper extends BaseJaxbHelper {
/**
* create a Contribution shuntY object under the busRec
*
* @param busRec
*/
public static LoadflowShuntYDataXmlType createContriShuntY(LoadflowBusXmlType busRec) {
BusShuntYDataXmlType shuntYData = busRec.getShuntYData();
if (shuntYData == null) {
shuntYData = OdmObjFactory.createBusShuntYDataXmlType();
busRec.setShuntYData(shuntYData);
shuntYData.setEquivY(OdmObjFactory.createYXmlType());
}
LoadflowShuntYDataXmlType contribShuntY = OdmObjFactory.createLoadflowShuntYDataXmlType();
shuntYData.getContributeShuntY().add(contribShuntY);
return contribShuntY;
}
public static LoadflowLoadDataXmlType getDefaultLoad(BusLoadDataXmlType loadData) {
if (loadData.getContributeLoad().size() == 0)
loadData.getContributeLoad().add(OdmObjFactory.createContributeLoad(
OdmObjFactory.createLoadflowLoadDataXmlType()));
return loadData.getContributeLoad().get(0).getValue();
}
/**
* create a Contribution Load object under the busRec
*
* @param busRec
*/
public static LoadflowLoadDataXmlType createContriLoad(LoadflowBusXmlType busRec) {
BusLoadDataXmlType loadData = busRec.getLoadData();
/* this should never happen
if (loadData == null) {
loadData = OdmObjFactory.createBusLoadDataXmlType();
busRec.setLoadData(loadData);
LoadflowLoadDataXmlType load = OdmObjFactory.createLoadflowLoadDataXmlType();
loadData.getContributeLoad().add(OdmObjFactory.createContributeLoad(load));
}
*/
LoadflowLoadDataXmlType contribLoad = OdmObjFactory.createLoadflowLoadDataXmlType();
loadData.getContributeLoad().add(OdmObjFactory.createContributeLoad(contribLoad));
return contribLoad;
}
public static LoadflowGenDataXmlType getDefaultGen(BusGenDataXmlType genData) {
if (genData.getContributeGen().size() == 0)
genData.getContributeGen().add(OdmObjFactory.createContributeGen(
OdmObjFactory.createLoadflowGenDataXmlType()));
return genData.getContributeGen().get(0).getValue();
}
/**
* create a Contribution Generator object under the busRec
*
* @param busRec
*/
public static LoadflowGenDataXmlType createContriGen(LoadflowBusXmlType busRec) {
BusGenDataXmlType genData = busRec.getGenData();
/* this should never happen
if (genData == null) {
genData = OdmObjFactory.createBusGenDataXmlType();
busRec.setGenData(genData);
LoadflowGenDataXmlType gen = OdmObjFactory.createLoadflowGenDataXmlType();
genData.getContributeGen().add(OdmObjFactory.createContributeGen(gen));
}
*/
// some model does not need ContributeGenList
LoadflowGenDataXmlType contribGen = OdmObjFactory.createLoadflowGenDataXmlType();
genData.getContributeGen().add(OdmObjFactory.createContributeGen(contribGen));
return contribGen;
}
/**
* create bus EquivData info after the contributing records are defined
*
* @param parser
* @return
*/
@Deprecated
public static boolean createBusEquivData(IODMModelParser parser) {
createBusEquivGenData(parser);
createBusEquivLoadData(parser);
createBusEquivShuntYData(parser);
return true;
}
/**
* consolidate bus genContributionList to the equiv gen
*
*/
@SuppressWarnings("unchecked") public static boolean createBusEquivGenData(IODMModelParser parser ) {
LoadflowNetXmlType baseCaseNet = ((AbstractModelParser<LoadflowNetXmlType>) parser).getNet();
for (JAXBElement<? extends BusXmlType> bus : baseCaseNet.getBusList().getBus()) {
LoadflowBusXmlType busRec = (LoadflowBusXmlType)bus.getValue();
BusGenDataXmlType genData = busRec.getGenData();
LoadflowGenDataXmlType defaultGen = getDefaultGen(genData);
if (genData != null) {
if ( genData.getContributeGen().size() > 0) {
LoadflowGenDataXmlType equivGen = getDefaultGen(genData);
double pgen = 0.0, qgen = 0.0, qmax = 0.0, qmin = 0.0, pmax = 0.0, pmin = 0.0, vSpec = 0.0;
VoltageUnitType vSpecUnit = VoltageUnitType.PU;
String remoteBusId = null;
boolean offLine = true;
for ( JAXBElement<? extends LoadflowGenDataXmlType> elem : genData.getContributeGen()) {
LoadflowGenDataXmlType gen = elem.getValue();
if (!gen.isOffLine()) {
offLine = false;
if (remoteBusId == null) {
if (gen.getRemoteVoltageControlBus() != null) {
remoteBusId = BaseJaxbHelper.getRecId(gen.getRemoteVoltageControlBus());
}
}
else if (!remoteBusId.equals(BaseJaxbHelper.getRecId(gen.getRemoteVoltageControlBus()))) {
ODMLogger.getLogger().severe("Inconsistant remote control bus id, " + remoteBusId +
", " + BaseJaxbHelper.getRecId(gen.getRemoteVoltageControlBus()));
return false;
}
pgen += gen.getPower().getRe();
qgen += gen.getPower().getIm();
if(gen.getQLimit() != null) {
qmax += gen.getQLimit().getMax();
qmin += gen.getQLimit().getMin();
}
if(gen.getPLimit() != null) {
pmax += gen.getPLimit().getMax();
pmin += gen.getPLimit().getMin();
}
if (gen.getDesiredVoltage() != null) {
if (vSpec == 0.0) {
vSpec = gen.getDesiredVoltage().getValue();
vSpecUnit = gen.getDesiredVoltage().getUnit();
}
else if (vSpec != gen.getDesiredVoltage().getValue()) {
ODMLogger.getLogger().severe("Inconsistant gen desired voltage, " +
BaseJaxbHelper.getRecId(gen.getRemoteVoltageControlBus()));
return false;
}
}
}
}
if (offLine && genData.getCode() != LFGenCodeEnumType.SWING)
// generator on a swing bus might turned off
genData.setCode(LFGenCodeEnumType.OFF);
else if (genData.getCode() == LFGenCodeEnumType.PV) {
equivGen.setPower(BaseDataSetter.createPowerValue(pgen, qgen, ApparentPowerUnitType.MVA));
if (qmax != 0.0 || qmin != 0.0) {
equivGen.setQLimit(BaseDataSetter.createReactivePowerLimit(qmax, qmin, ReactivePowerUnitType.MVAR));
if (vSpec != 0.0) {
equivGen.setDesiredVoltage(BaseDataSetter.createVoltageValue(vSpec, vSpecUnit));
}
}
else {
// this is the case when the generator is turn-off
genData.setCode(LFGenCodeEnumType.PQ);
}
}
else { // PQ bus
equivGen.setPower(BaseDataSetter.createPowerValue(pgen, qgen, ApparentPowerUnitType.MVA));
if (pmax != 0.0 || pmin != 0.0) {
equivGen.setPLimit(BaseDataSetter.createActivePowerLimit(pmax, pmin, ActivePowerUnitType.MW));
}
}
if (remoteBusId != null && !remoteBusId.equals(busRec.getId()) &&
genData.getCode() == LFGenCodeEnumType.PV){
// Remote Q Bus control, we need to change this bus to a GPQ bus so that its Q could be adjusted
defaultGen.setRemoteVoltageControlBus(
((AbstractModelParser<LoadflowNetXmlType>) parser).createBusRef(remoteBusId));
}
}
else {
genData.setCode(LFGenCodeEnumType.NONE_GEN);
if (defaultGen.getPower() != null)
defaultGen.setPower(null);
if (defaultGen.getVoltageLimit() != null)
defaultGen.setVoltageLimit(null);
}
}
}
return true;
}
/**
* consolidate bus loadContributionList to the load
*
*/
@SuppressWarnings("unchecked") public static boolean createBusEquivLoadData(IODMModelParser parser) {
LoadflowNetXmlType baseCaseNet = ((AbstractModelParser<LoadflowNetXmlType>) parser).getNet();
for (JAXBElement<? extends BusXmlType> bus : baseCaseNet.getBusList().getBus()) {
LoadflowBusXmlType busRec = (LoadflowBusXmlType)bus.getValue();
BusLoadDataXmlType loadData = busRec.getLoadData();
LoadflowLoadDataXmlType defaultLoad = getDefaultLoad(loadData);
if (loadData != null) {
if ( loadData.getContributeLoad().size() > 0) {
double cp_p=0.0, cp_q=0.0, ci_p=0.0, ci_q=0.0, cz_p=0.0, cz_q=0.0;
for ( JAXBElement<? extends LoadflowLoadDataXmlType> loadXml : loadData.getContributeLoad()) {
LoadflowLoadDataXmlType load = loadXml.getValue();
if (!load.isOffLine()) {
if (load.getConstPLoad() != null) {
cp_p += load.getConstPLoad().getRe();
cp_q += load.getConstPLoad().getIm();
}
if (load.getConstILoad() != null) {
ci_p += load.getConstILoad().getRe();
ci_q += load.getConstILoad().getIm();
}
if (load.getConstZLoad() != null) {
cz_p += load.getConstZLoad().getRe();
cz_q += load.getConstZLoad().getIm();
}
}
}
if ((cp_p != 0.0 || cp_q != 0.0) && (ci_p==0.0 && ci_q ==0.0 && cz_p==0.0 && cz_q ==0.0) ) {
defaultLoad.setCode(LFLoadCodeEnumType.CONST_P);
defaultLoad.setConstPLoad(BaseDataSetter.createPowerValue(cp_p, cp_q, ApparentPowerUnitType.MVA));
}
else if ((ci_p != 0.0 || ci_q != 0.0) && (cp_p==0.0 && cp_q ==0.0 && cz_p==0.0 && cz_q ==0.0) ) {
defaultLoad.setCode(LFLoadCodeEnumType.CONST_I);
defaultLoad.setConstILoad(BaseDataSetter.createPowerValue(ci_p, ci_q, ApparentPowerUnitType.MVA));
}
else if ((cz_p != 0.0 || cz_q != 0.0) && (ci_p==0.0 && ci_q ==0.0 && cp_p==0.0 && cp_q ==0.0) ) {
defaultLoad.setCode(LFLoadCodeEnumType.CONST_Z);
defaultLoad.setConstZLoad(BaseDataSetter.createPowerValue(cz_p, cz_q, ApparentPowerUnitType.MVA));
}
else if ((cp_p != 0.0 || cp_q != 0.0 || ci_p!= 0.0 || ci_q != 0.0 || cz_p != 0.0 || cz_q !=0.0)) {
defaultLoad.setCode(LFLoadCodeEnumType.FUNCTION_LOAD);
defaultLoad.setConstPLoad(BaseDataSetter.createPowerValue(cp_p, cp_q, ApparentPowerUnitType.MVA));
defaultLoad.setConstILoad(BaseDataSetter.createPowerValue(ci_p, ci_q, ApparentPowerUnitType.MVA));
defaultLoad.setConstZLoad(BaseDataSetter.createPowerValue(cz_p, cz_q, ApparentPowerUnitType.MVA));
}
else {
defaultLoad.setCode(LFLoadCodeEnumType.NONE_LOAD);
}
}
else
defaultLoad.setCode(LFLoadCodeEnumType.NONE_LOAD);
}
}
return true;
}
/**
* consolidate bus loadContributionList to the load
*
*/
@SuppressWarnings("unchecked") public static boolean createBusEquivShuntYData(IODMModelParser parser) {
LoadflowNetXmlType baseCaseNet = ((AbstractModelParser<LoadflowNetXmlType>) parser).getNet();
for (JAXBElement<? extends BusXmlType> bus : baseCaseNet.getBusList().getBus()) {
LoadflowBusXmlType busRec = (LoadflowBusXmlType)bus.getValue();
BusShuntYDataXmlType shuntYData = busRec.getShuntYData();
if (shuntYData != null) {
if ( shuntYData.getContributeShuntY().size() > 0) {
//LoadflowShuntYDataXmlType equivY = shuntYData.getEquivY();
double g=0.0, b=0.0;
for ( LoadflowShuntYDataXmlType y : shuntYData.getContributeShuntY()) {
if (!y.isOffLine()) {
if (y.getY() != null) {
g += y.getY().getRe();
b += y.getY().getIm();
}
}
}
if (g != 0.0 || b != 0.0) {
shuntYData.setEquivY(BaseDataSetter.createYValue(g, b, YUnitType.PU));
}
}
}
}
return true;
}
/**
* create a SVC object under the bus object
*
* @param bus
*/
public static StaticVarCompensatorXmlType createSVC(LoadflowBusXmlType bus) {
StaticVarCompensatorXmlType svc = OdmObjFactory.createStaticVarCompensatorXmlType();
bus.setSvc(svc);
return svc;
}
/**
* create a ShuntCompensatorXmlType object under the bus object
*
* @param bus
*/
public static SwitchedShuntXmlType createShuntCompensator(LoadflowBusXmlType bus) {
//if (bus.getShuntCompensatorData().getShuntCompensatorList() == null) {
// bus.getShuntCompensatorData().setShuntCompensatorList(odmObjFactory.createShuntCompensatorDataXmlTypeShuntCompensatorList());
//}
SwitchedShuntXmlType compensator = OdmObjFactory.createSwitchedShuntXmlType();
bus.setSwitchedShunt(compensator);
return compensator;
}
/**
* get Xfr Z correction table item by item number
*
* @param number
* @param xfrZTable
* @return
*/
public static XformerZTableXmlType.XformerZTableItem getXfrZTableItem(int number, XformerZTableXmlType xfrZTable) {
for (XformerZTableXmlType.XformerZTableItem item : xfrZTable.getXformerZTableItem()) {
if (item.getNumber() == number)
return item;
}
return null;
}
}