/*
* @(#)BPADynamicRecord.java
*
* Copyright (C) 2006-2008 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 Stephen Hau
* @Version 1.0
* @Date 02/11/2008
*
* Revision History
* ================
*
*/
package org.ieee.odm.adapter.bpa.dynamic;
import static org.ieee.odm.ODMObjectFactory.OdmObjFactory;
import java.text.NumberFormat;
import javax.xml.bind.JAXBElement;
import org.ieee.odm.adapter.bpa.lf.BPABusRecord;
import org.ieee.odm.common.ODMException;
import org.ieee.odm.common.ODMLogger;
import org.ieee.odm.model.base.ODMModelStringUtil;
import org.ieee.odm.model.dstab.DStabDataSetter;
import org.ieee.odm.model.dstab.DStabModelParser;
import org.ieee.odm.model.dstab.DStabParserHelper;
import org.ieee.odm.schema.BusXmlType;
import org.ieee.odm.schema.ClassicMachineXmlType;
import org.ieee.odm.schema.DStabBusXmlType;
import org.ieee.odm.schema.DStabGenDataXmlType;
import org.ieee.odm.schema.DStabLoadDataXmlType;
import org.ieee.odm.schema.Eq11Ed11MachineXmlType;
import org.ieee.odm.schema.Eq1Ed1MachineXmlType;
import org.ieee.odm.schema.LineDStabXmlType;
import org.ieee.odm.schema.LoadflowGenDataXmlType;
import org.ieee.odm.schema.MutualZeroZXmlType;
import org.ieee.odm.schema.NetworkXmlType;
import org.ieee.odm.schema.ShortCircuitLoadDataXmlType;
import org.ieee.odm.schema.TransformerZeroSeqXmlType;
import org.ieee.odm.schema.VoltageUnitType;
import org.ieee.odm.schema.XfrDStabXmlType;
import org.ieee.odm.schema.XfrZeroSeqConnectLocationEnumType;
import org.ieee.odm.schema.YUnitType;
import org.ieee.odm.schema.ZUnitType;
public class BPADynamicSequenceRecord {
public static void processSequenceData(String str, DStabModelParser parser) throws ODMException {
final String strAry[]=getSequenceDataFields(str);
if(strAry[0].equals("XO")){
final String fromId = BPABusRecord.getBusId(strAry[1]);
final String toId = BPABusRecord.getBusId(strAry[3]);
//TODO Change 1->0;
String cirId="1";
if(!strAry[6].equals("")){
cirId=strAry[6];
}
XfrDStabXmlType xfr=null;
// BusRefRecordXmlType fromBusRef=null;
// BusRefRecordXmlType toBusRef=null;
/*
* BPA Branch data does NOT have a strict requirement of the sequence fromId and toId,
* it seems that an exchange of them is also supported, namely,"fromId-to-toId" and "toId-to-fromId" are the same in BPA.
* The following processing is to consider this kind of special case.
*/
if(parser.getBranch(fromId, toId, cirId)!=null){
xfr =parser.getDStabXfr(fromId, toId, cirId);
// fromBusRef=parser.createBusRef(fromId);
// toBusRef=parser.createBusRef(toId);
}
else if (parser.getBranch(toId, fromId, cirId)!=null){
xfr =parser.getDStabXfr(toId, fromId, cirId);
// fromBusRef=parser.createBusRef(toId);
// toBusRef=parser.createBusRef(fromId);
}
else throw new ODMException("Branch not found in the DStabNet, id: " + fromId + "-" + toId + "(" + cirId + ")");
// xfr.setFromBus(fromBusRef);
// xfr.setToBus(toBusRef);
TransformerZeroSeqXmlType xfrZeroSeq =new TransformerZeroSeqXmlType();
int location= new Integer(strAry[5]).intValue();
if(location==1){
xfrZeroSeq.setConectionLocation(XfrZeroSeqConnectLocationEnumType.AT_BUS_1);
}else if(location==2){
xfrZeroSeq.setConectionLocation(XfrZeroSeqConnectLocationEnumType.AT_BUS_2);
}else {
xfrZeroSeq.setConectionLocation(XfrZeroSeqConnectLocationEnumType.BETWEEN_BUS_1_N_BUS_2);
}
xfr.setXfrZeroSeq(xfrZeroSeq);
//Z0
double x0=ODMModelStringUtil.getDouble(strAry[7], 0.0);
double r0=ODMModelStringUtil.getDouble(strAry[8], 0.0);
if(!strAry[7].contains(".")){
x0=x0/10000;
}
if(!strAry[8].contains(".")){
r0=r0/10000;
}
xfr.setZ0(DStabDataSetter.createZValue(r0, x0, ZUnitType.PU));
}
else if(strAry[0].equals("XR")){
final String busId = BPABusRecord.getBusId(strAry[1]);
DStabBusXmlType bus = parser.getDStabBus(busId);
double busBase = ODMModelStringUtil.getDouble(strAry[2], 0.0);
bus.setBaseVoltage(DStabDataSetter.createVoltageValue(busBase, VoltageUnitType.KV));
double r0 = ODMModelStringUtil.getDouble(strAry[3], 0.0);
double x0 = ODMModelStringUtil.getDouble(strAry[4], 0.0);
if(!strAry[3].contains(".")){
r0=r0/10000;
}
if(!strAry[4].contains(".")){
x0=x0/10000;
}
double factor = r0*r0+x0*x0;
//ScSimpleBusXmlType.ScShuntLoadData scsld =odmObjFactory.createScSimpleBusXmlTypeScShuntLoadData();
DStabLoadDataXmlType load = DStabParserHelper.getDefaultLoad(bus.getLoadData());
load.setShuntLoadZeroY(DStabDataSetter.createYValue(r0/factor, -x0/factor, YUnitType.PU));
//bus.setScShuntLoadData(scsld);
}
else if(strAry[0].equals("LO")){
final String fromId = BPABusRecord.getBusId(strAry[1]);
final String toId = BPABusRecord.getBusId(strAry[3]);
//TODO Change 1->0, since id=1 already exists in one of some parallel branches,while info for the other one is missing
// also such change is consistent with Load Flow positive sequence processing
String cirId="1";
if(!strAry[6].equals("")){
cirId=strAry[6];
}
LineDStabXmlType line =null;
// BusRefRecordXmlType fromBusRef=null;
// BusRefRecordXmlType toBusRef=null;
/*
* BPA Branch data does NOT have a strict requirement of sequence of fromId and toId,
* it seems that an exchange of them is also supported.
* The following processing is to consider this kind of special case.
*/
if(parser.getBranch(fromId, toId, cirId)!=null){
line =parser.getDStabLine(fromId, toId, cirId);
// fromBusRef=parser.createBusRef(fromId);
// toBusRef=parser.createBusRef(toId);
}
else if (parser.getBranch(toId, fromId, cirId)!=null){
line =parser.getDStabLine(toId, fromId, cirId);
// fromBusRef=parser.createBusRef(toId);
// toBusRef=parser.createBusRef(fromId);
}
else throw new ODMException("Branch not found in the DStabNet, id: " + fromId + "-" + toId + "(" + cirId + ")");
//parser.getDStabLine(fromId, toId, cirId);
//TODO can't set the rated voltage of frombus and tobus .When we get the branch,these info have been included?
// line.setFromBus(fromBusRef);
// line.setToBus(toBusRef);
//Z0
double r0=ODMModelStringUtil.getDouble(strAry[7], 0.0);
double x0=ODMModelStringUtil.getDouble(strAry[8], 0.0);
if(!strAry[7].contains(".")){
r0=r0/10000;
}
if(!strAry[8].contains(".")){
x0=x0/10000;
}
line.setZ0(DStabDataSetter.createZValue(r0, x0, ZUnitType.PU));
//Y1
double g1=ODMModelStringUtil.getDouble(strAry[9], 0.0);
double b1=ODMModelStringUtil.getDouble(strAry[10], 0.0);
if(!strAry[9].contains(".")){
g1=g1/10000;
}
if(!strAry[10].contains(".")){
b1=b1/10000;
}
line.setY0ShuntFromSide(DStabDataSetter.createYValue(g1, b1, YUnitType.PU));
//Y2
double g2=ODMModelStringUtil.getDouble(strAry[11], 0.0);
double b2=ODMModelStringUtil.getDouble(strAry[12], 0.0);
if(!strAry[11].contains(".")){
g2=g2/10000;
}
if(!strAry[12].contains(".")){
b2=b2/10000;
}
line.setY0ShuntToSide(DStabDataSetter.createYValue(g2, b2, YUnitType.PU));
}
else if(strAry[0].equals("LM")){
final String line1fId = BPABusRecord.getBusId(strAry[1]);
final String line1tId = BPABusRecord.getBusId(strAry[3]);
String line1cirId="1";
if(!strAry[5].equals("")){
line1cirId=strAry[5];
}
LineDStabXmlType line1 = parser.getDStabLine(line1fId, line1tId, line1cirId);
final String line2fId = BPABusRecord.getBusId(strAry[6]);
final String line2tId = BPABusRecord.getBusId(strAry[8]);
String line2cirId="1";
if(!strAry[10].equals("")){
line2cirId=strAry[10];
}
LineDStabXmlType line2 = parser.getDStabLine(line2fId, line2tId, line2cirId);
double rm=ODMModelStringUtil.getDouble(strAry[11], 0.0);
double xm=ODMModelStringUtil.getDouble(strAry[12], 0.0);
if(!strAry[11].contains(".")){
rm=rm/10000;
}
if(!strAry[12].contains(".")){
xm=xm/10000;
}
MutualZeroZXmlType mutualZ0 =OdmObjFactory.createMutualZeroZXmlType();
mutualZ0.setZM(DStabDataSetter.createZValue(rm, xm, ZUnitType.PU));
line1.getLineMutualZeroZ().add(mutualZ0);
line2.getLineMutualZeroZ().add(mutualZ0);
}
}
public static void processNegativeData( DStabModelParser parser) throws ODMException{
NetworkXmlType.BusList busList=parser.getDStabNet().getBusList();
int size=busList.getBus().size();
for(int i=0;i<size;i++){
BusXmlType Bus = busList.getBus().get(i).getValue();
if(!(Bus instanceof DStabBusXmlType)){
i--;
size--;
}
DStabBusXmlType bus=parser.getDStabBus(Bus.getId());
// for( JAXBElement<? extends BusXmlType> busXml:parser.getDStabNet().getBusList().getBus()){
// DStabBusXmlType bus=parser.getDStabBus(busXml.getValue().getId());
// negative sequence generator data
if(bus.getGenData().getContributeGen()!=null){
for(JAXBElement<? extends LoadflowGenDataXmlType> gen : bus.getGenData().getContributeGen()){
DStabGenDataXmlType dynGen = (DStabGenDataXmlType)gen.getValue();
//for(DynamicGeneratorXmlType dynGen:odmObjFactory.createDStabBusXmlTypeDynamicGenList().getDynamicGen()){
double xd1=0.0;
double x2=0.0;
double tq01=0.0;
if(dynGen.getMachineModel().getValue().getClass().toString().equals("class org.ieee.odm.schema.Eq11Ed11MachineXmlType")){
Eq11Ed11MachineXmlType subGen=(Eq11Ed11MachineXmlType)dynGen.getMachineModel().getValue();
xd1=subGen.getXd1();
tq01=subGen.getTq01().getValue();
}else if(dynGen.getMachineModel().getValue().getClass().toString().equals("class org.ieee.odm.schema.Eq1Ed1MachineXmlType")){
Eq1Ed1MachineXmlType tranGen=(Eq1Ed1MachineXmlType)dynGen.getMachineModel().getValue();
xd1=tranGen.getXd1();
tq01=tranGen.getTq01().getValue();
}else if(dynGen.getMachineModel().getValue().getClass().toString().equals("class org.ieee.odm.schema.ClassicMachineXmlType")){
ClassicMachineXmlType claGen=(ClassicMachineXmlType)dynGen.getMachineModel().getValue();
xd1=claGen.getXd1();
tq01=0.0; //TODO Why the tq01 in classic model is equal to 0.0?
}
//TODO b= X��d/X��d , b can be set in the CASE card,the default value is 0.65 .
//so how can we get the b value from the CASE card?
//non-salient pole machine
if(tq01!=0.0){
x2=1.22*0.65*xd1;
}
//salient pole generator
else{
x2=0.65*xd1;
}
//4 decimal places specified
NumberFormat ddf1= NumberFormat.getInstance();
ddf1.setMaximumFractionDigits(4);
x2= new Double(ddf1.format(x2)).doubleValue();
//TODO How to set the negative sequence impedance to associate to generator?
//How about the case that several generators is in parallel on the bus?
//ScGenDataXmlType scgd = odmObjFactory.createScGenDataXmlType();
//scgd.setNegativeZ(DStabDataSetter.createZValue(0.0, x2, ZUnitType.PU));
// TODO bus.getScGenData().add(scgd);
//odmObjFactory.createSequenceBusDataXmlTypeGenData().setNegativeZ(DStabDataSetter.createZValue(0.0, x2, ZUnitType.PU));
}
}
//negative sequence load data
if(bus.getLoadData()!=null){
DStabLoadDataXmlType load = DStabParserHelper.getDefaultLoad(bus.getLoadData());
if(load!=null){
//TODO ���ォ���ɸ����ɵ�Ч�ɶԵ�֧·�����迹�����ڵ㱾��IJ����ӵ�֧·�ĸ�������أ�
//hard coded values
//ScSimpleBusXmlType.ScShuntLoadData scsld = odmObjFactory.createScSimpleBusXmlTypeScShuntLoadData();
load.setShuntLoadNegativeY(DStabDataSetter.createYValue(0.19, 0.36, YUnitType.PU));
//bus.setScShuntLoadData(scsld);
}
}
}
}
/*
for(GeneratorXmlType gen:tranSimu.getDynamicDataList().getBusDynDataList()
.getGeneratorDataList().getGeneratorArray()){
double xd1=0.0;
double x2=0.0;
double tq01=0.0;
if(gen.getGeneratorType().equals(GeneratorXmlType.GeneratorType.SUBTRANS_MODEL)){
SubTransientMachineXmlType subGen=
gen.getGeneratorModel().getSubTransientModel();
xd1=subGen.getXd1();
tq01=subGen.getTq01().getValue();
}else if(gen.getGeneratorType().equals(GeneratorXmlType.GeneratorType.TRANSIENT_MODEL)){
TransientMachineXmlType tranGen=
gen.getGeneratorModel().addNewTransModel();
xd1=tranGen.getXd1();
tq01=tranGen.getTq01().getValue();
}else if(gen.getGeneratorType().equals(GeneratorXmlType.GeneratorType.CLASSICAL_MODEL)){
ClassicMachineXmlType claGen=
gen.getGeneratorModel().getClassicalModel();
xd1=claGen.getXd1();
tq01=0.0;;
}
//non-salient pole machine
if(tq01!=0.0){
x2=1.22*0.65*xd1;
}
//salient pole generator
else{
x2=0.65*xd1;
}
NegativeSequenceDataListXmlType.GeneratorNegativeList.GeneratorNegative xfrNeg=
XBeanTranStabSimuHelper.addNewGenNeg(tranSimu);
String busId=gen.getLocatedBus().getName();
String genId="";
if(gen.getGenId()!=null){
genId=gen.getGenId().getName();
xfrNeg.addNewMacId().setName(genId);
}
xfrNeg.addNewBusId().setName(busId);
xfrNeg.setZXNeg(x2);
}
for( LoadCharacteristicXmlType load: tranSimu.getDynamicDataList().
getBusDynDataList().getLoadCharacteristicDataList().getLoadArray() ){
NegativeSequenceDataListXmlType.ShuntLoadNegativeList.ShuntLoadNegative loadNeg=
XBeanTranStabSimuHelper.addNewShuntLoadNeg(tranSimu);
if(load.getLocation().equals(LoadCharacteristicXmlType.Location.AT_AREA)){
loadNeg.setLoadLocation(NegativeSequenceDataListXmlType.ShuntLoadNegativeList.
ShuntLoadNegative.LoadLocation.AT_AREA);
}else if(load.getLocation().equals(LoadCharacteristicXmlType.Location.AT_BUS)){
loadNeg.setLoadLocation(NegativeSequenceDataListXmlType.ShuntLoadNegativeList.
ShuntLoadNegative.LoadLocation.AT_BUS);
}else {
loadNeg.setLoadLocation(NegativeSequenceDataListXmlType.ShuntLoadNegativeList.
ShuntLoadNegative.LoadLocation.AT_ZONE);
}
loadNeg.addNewLocationId().setName(load.getLocationId().getName());
// TODO: hard coded values
loadNeg.setRNeg(0.19);
loadNeg.setXNeg(0.36);
}
*/
private static String[] getSequenceDataFields(String str){
final String[] strAry= new String[13];
// line type
strAry[0] = ODMModelStringUtil.getStringReturnEmptyString(str,1, 2).trim();
//----to process the Chinese characters in the fromBus name, if any.
String temp=ODMModelStringUtil.getStringReturnEmptyString(str,5, 12).trim();
int chnCharNum1=ODMModelStringUtil.getChineseCharNum(temp);
//from bus name
strAry[1] = ODMModelStringUtil.getStringReturnEmptyString(str,5, 12-chnCharNum1).trim();
//---to process the Chinese characters in the toBus name, if any.
temp=ODMModelStringUtil.getStringReturnEmptyString(str,19-chnCharNum1, 26-chnCharNum1).trim();
int chnCharNum2=ODMModelStringUtil.getChineseCharNum(temp);
//to bus name
strAry[3] = ODMModelStringUtil.getStringReturnEmptyString(str,19-chnCharNum1, 26-chnCharNum1-chnCharNum2).trim();
//LM card have 4 buses
if(str.substring(0, 2).startsWith("LM")){
//----to process the Chinese characters in the fromBus name 0f line2, if any.
temp=ODMModelStringUtil.getStringReturnEmptyString(str,36-chnCharNum1-chnCharNum2, 43-chnCharNum1-chnCharNum2).trim();
int chnCharNum3=ODMModelStringUtil.getChineseCharNum(temp);
//from bus name
strAry[6] = ODMModelStringUtil.getStringReturnEmptyString(str,36-chnCharNum1-chnCharNum2, 43-chnCharNum1-chnCharNum2-chnCharNum3).trim();
//---to process the Chinese characters in the toBus name of line2, if any.
temp=ODMModelStringUtil.getStringReturnEmptyString(str,50-chnCharNum1-chnCharNum2-chnCharNum3, 57-chnCharNum1-chnCharNum2-chnCharNum3).trim();
int chnCharNum4=ODMModelStringUtil.getChineseCharNum(temp);
//to bus name
strAry[8] = ODMModelStringUtil.getStringReturnEmptyString(str,50-chnCharNum1-chnCharNum2-chnCharNum3, 57-chnCharNum1-chnCharNum2-chnCharNum3-chnCharNum4).trim();
}
//--- replace all the Chinese Characters, since they are not used in the following processing.
if(chnCharNum1>0||chnCharNum2>0)str=ODMModelStringUtil.replaceChineseChar(str);
try{
if(str.substring(0, 2).startsWith("XO")){
//strAry[0]=ModelStringUtil.getStringReturnEmptyString(str,1, 2).trim();
//bus1
//strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,5, 12).trim();
//bus1 Voltage
strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str,13, 16).trim();
//bus2
//strAry[3]=ModelStringUtil.getStringReturnEmptyString(str,19, 26).trim();
//bus2 Voltage
strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str,27, 30).trim();
//zrLocation
strAry[5]=ODMModelStringUtil.getStringReturnEmptyString(str,32, 32).trim();
//par
strAry[6]=ODMModelStringUtil.getStringReturnEmptyString(str,34, 34).trim();
//X0
strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str,38, 44).trim();
//R0
strAry[8]=ODMModelStringUtil.getStringReturnEmptyString(str,45, 51).trim();
}else if(str.substring(0, 2).startsWith("XR")){
//strAry[0]=ModelStringUtil.getStringReturnEmptyString(str,1, 2).trim();
//bus1
//strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,5, 12).trim();
//bus1 Voltage
strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str,13, 16).trim();
//R0
strAry[3]=ODMModelStringUtil.getStringReturnEmptyString(str,22, 28).trim();
//X0
strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str,29, 35).trim();
}else if(str.substring(0, 2).startsWith("LO")){
//strAry[0]=ModelStringUtil.getStringReturnEmptyString(str,1, 2).trim();
//bus1
//strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,5, 12).trim();
//bus1 Voltage
strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str,13, 16).trim();
//bus2
//strAry[3]=ModelStringUtil.getStringReturnEmptyString(str,19, 26).trim();
//bus2 Voltage
strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str,27, 30).trim();
//par
strAry[6]=ODMModelStringUtil.getStringReturnEmptyString(str,33, 33).trim();
//R0
strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str,36, 42).trim();
//X0
strAry[8]=ODMModelStringUtil.getStringReturnEmptyString(str,43, 49).trim();
//G1
strAry[9]=ODMModelStringUtil.getStringReturnEmptyString(str,50, 56).trim();
//B1
strAry[10]=ODMModelStringUtil.getStringReturnEmptyString(str,57, 63).trim();
//G2
strAry[11]=ODMModelStringUtil.getStringReturnEmptyString(str,64, 70).trim();
//B2
strAry[12]=ODMModelStringUtil.getStringReturnEmptyString(str,71, 77).trim();
}else if(str.substring(0, 2).startsWith("LM")){
//strAry[0]=ModelStringUtil.getStringReturnEmptyString(str,1, 2).trim();
//busI line 1
//strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,5, 12).trim();
//busI Voltage
strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str,13, 16).trim();
//busJ line 1
//strAry[3]=ModelStringUtil.getStringReturnEmptyString(str,19, 26).trim();
//busJ Voltage
strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str,27, 30).trim();
//par1
strAry[5]=ODMModelStringUtil.getStringReturnEmptyString(str,33, 33).trim();
//busK line2
//strAry[6]=ModelStringUtil.getStringReturnEmptyString(str,36, 43).trim();
//busK voltage
strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str,44, 47).trim();
//busL line2
//strAry[8]=ModelStringUtil.getStringReturnEmptyString(str,50, 57).trim();
//busL voltage
strAry[9]=ODMModelStringUtil.getStringReturnEmptyString(str,58, 61).trim();
//par2
strAry[10]=ODMModelStringUtil.getStringReturnEmptyString(str,64, 64).trim();
//Rm
strAry[11]=ODMModelStringUtil.getStringReturnEmptyString(str,67, 73).trim();
//Xm
strAry[12]=ODMModelStringUtil.getStringReturnEmptyString(str,74, 80).trim();
}
}catch(Exception e){
ODMLogger.getLogger().severe(e.toString());
}
return strAry;
}
}