/* * @(#)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 java.util.ArrayList; import java.util.Hashtable; import java.util.List; 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.ApparentPowerUnitType; import org.ieee.odm.schema.ClassicMachineXmlType; import org.ieee.odm.schema.DStabBusXmlType; import org.ieee.odm.schema.DStabGenDataXmlType; import org.ieee.odm.schema.DStabNetXmlType; import org.ieee.odm.schema.Eq11Ed11MachineXmlType; import org.ieee.odm.schema.Eq11MachineXmlType; import org.ieee.odm.schema.Eq1Ed1MachineXmlType; import org.ieee.odm.schema.Eq1MachineXmlType; import org.ieee.odm.schema.EquiMachineXmlType; import org.ieee.odm.schema.VoltageUnitType; public class BPADynamicGeneratorRecord { private static List<String> subTransBusIdList=new ArrayList<String>(); private static Hashtable<String,Double>SubTransientData =new Hashtable<String,Double>(); public static void processGeneratorData(String str, DStabModelParser parser) throws ODMException { final String strAry[]=getGeneratorDataFields(str); DStabNetXmlType net = parser.getDStabNet(); if (str.substring(0,2).trim().equals("MC")){ String busId = BPABusRecord.getBusId(strAry[1]); DStabBusXmlType bus = parser.getDStabBus(busId); //DStabGenDataXmlType dynGen = (DStabGenDataXmlType)bus.getGenData().getEquivGen().getValue(); DStabGenDataXmlType dynGen = DStabParserHelper.getDefaultGen(bus.getGenData()); ClassicMachineXmlType mach = DStabParserHelper.createClassicMachine(dynGen); double ratedVoltage=ODMModelStringUtil.getDouble(strAry[2], 0.0); dynGen.setRatedMachVoltage(DStabDataSetter.createVoltageValue(ratedVoltage, VoltageUnitType.KV)); String dynGenId="1"; if(!strAry[3].equals("")){ dynGenId=strAry[3]; } dynGen.setId(dynGenId); double Emws=ODMModelStringUtil.getDouble(strAry[4], 0.0); double MvaBase=ODMModelStringUtil.getDouble(strAry[7], net.getBasePower().getValue()); // infinite bus if(Emws==999999){ mach.setH(999999); }else{ double h=0.0; if(Emws!=0.0){ h=Emws/MvaBase; NumberFormat ddf1= NumberFormat.getInstance(); ddf1.setMaximumFractionDigits(4); h= new Double(ddf1.format(h)).doubleValue(); mach.setH(h); } } double pContri=ODMModelStringUtil.getDouble(strAry[5], 100.0);//% in InterPSS double qContri=ODMModelStringUtil.getDouble(strAry[6], 100.0); dynGen.setPContributionPercent(pContri); dynGen.setQContributionPercent(qContri); dynGen.setMvaBase(DStabDataSetter.createApparentPower(MvaBase, ApparentPowerUnitType.MVA)); double xd1=ODMModelStringUtil.getDouble(strAry[9], 0.0); if(!strAry[9].contains(".")){ xd1=xd1/10000; } mach.setXd1(xd1); double D=ODMModelStringUtil.getDouble(strAry[18], 0.0);// Recommended value is 2 if(!strAry[18].contains(".")){ D=D/10000; } mach.setD(D*2);//DIPSS=DBPA*2 } /* * M record is only to store the sub-transient info, * this, together with MF/MG record,represents a full machine model considering damper. */ else if(str.substring(0, 2).trim().equals("M")){ String busId = BPABusRecord.getBusId(strAry[1]); subTransBusIdList.add(busId); double xd11=ODMModelStringUtil.getDouble(strAry[8], 0.0); if(!strAry[8].contains(".")){ xd11=xd11/10000; } SubTransientData.put("xd11", xd11); double xq11=ODMModelStringUtil.getDouble(strAry[9], 0.0); if(!strAry[9].contains(".")){ xq11=xq11/10000; } SubTransientData.put("xq11", xq11); double td011=ODMModelStringUtil.getDouble(strAry[10], 0.0); if(!strAry[10].contains(".")){ td011=td011/10000; } SubTransientData.put("td011", td011); double tq011=ODMModelStringUtil.getDouble(strAry[11], 0.0); if(!strAry[11].contains(".")){ tq011=tq011/10000; } SubTransientData.put("tq011", tq011); } /* * only MF record(there is no M record prior to MF record) * represents a transient type machine model(Eq1Ed1) * while M and MF records together represent sub-transient; */ else if(str.substring(0, 2).trim().equals("MF")){ String busId = BPABusRecord.getBusId(strAry[1]); DStabBusXmlType bus = parser.getDStabBus(busId); String dynGenId="1"; if(!strAry[3].equals("")){ dynGenId=strAry[3]; } //DStabGenDataXmlType dynGen = (DStabGenDataXmlType)bus.getGenData().getEquivGen().getValue(); DStabGenDataXmlType dynGen = DStabParserHelper.getDefaultGen(bus.getGenData()); dynGen.setId(dynGenId); double ratedVoltage=ODMModelStringUtil.getDouble(strAry[2], 0.0); dynGen.setRatedMachVoltage(DStabDataSetter.createVoltageValue(ratedVoltage, VoltageUnitType.KV)); Eq1MachineXmlType mach=null; boolean isEq1Ed1=true; boolean isSalient=false; double tq01=ODMModelStringUtil.getDouble(strAry[14], 0.0); if(tq01<1E-5){// Tq01==0.0 isEq1Ed1=false; isSalient=true; mach=DStabParserHelper.createEq1Machine(dynGen); } else mach=DStabParserHelper.createEq1Ed1Machine(dynGen); if(isSubTransientModel(busId)){ if(isSalient) mach = DStabParserHelper.createEq11Machine(dynGen); else mach=DStabParserHelper.createEq11Ed11Machine(dynGen); // set the subTransient data saved before in the hashtable to machine. setSubTransientData(mach); } double pContri=ODMModelStringUtil.getDouble(strAry[5], 100.0);//% in InterPSS double qContri=ODMModelStringUtil.getDouble(strAry[6], 100.0); dynGen.setPContributionPercent(pContri); dynGen.setQContributionPercent(qContri); double MvaBase=ODMModelStringUtil.getDouble(strAry[7], net.getBasePower().getValue()); dynGen.setMvaBase(DStabDataSetter.createApparentPower(MvaBase, ApparentPowerUnitType.MVA)); //TODO Mike, this is the baseMVA for the per unit system in BPA, I don't think this is the same as the rated power of a machine. // sometimes, these two are set differently, such as the baseMVA would be chosen equal to system baseMVA . double Emws=ODMModelStringUtil.getDouble(strAry[4], 0.0); double h=0.0; if(Emws!=0.0){ h=Emws/MvaBase; NumberFormat ddf1= NumberFormat.getInstance(); ddf1.setMaximumFractionDigits(4); h= new Double(ddf1.format(h)).doubleValue(); mach.setH(h); } double ra=ODMModelStringUtil.getDouble(strAry[8], 0.0); if(!strAry[8].contains(".")){ ra=ra/10000; } mach.setRa(ra); double xd1=ODMModelStringUtil.getDouble(strAry[9], 0.0); if(!strAry[9].contains(".")){ xd1=xd1/10000; } mach.setXd1(xd1); double xq1=ODMModelStringUtil.getDouble(strAry[10], 0.0); if(!strAry[10].contains(".")){ xq1=xq1/10000; } if(isEq1Ed1){ ((Eq1Ed1MachineXmlType)mach).setXq1(xq1); } double xd=ODMModelStringUtil.getDouble(strAry[11], 0.0); if(!strAry[11].contains(".")){ xd=xd/10000; } mach.setXd(xd); double xq=ODMModelStringUtil.getDouble(strAry[12], 0.0); if(!strAry[12].contains(".")){ xq=xq/10000; } mach.setXq(xq); double td01=ODMModelStringUtil.getDouble(strAry[13], 0.0); if(!strAry[13].contains(".")){ td01=td01/100; } mach.setTd01(DStabDataSetter.createTimeConstSec(td01)); if(!strAry[14].contains(".")){ tq01=tq01/100; } if(isEq1Ed1) ((Eq1Ed1MachineXmlType)mach).setTq01(DStabDataSetter.createTimeConstSec(tq01)); double xl=ODMModelStringUtil.getDouble(strAry[15], 0.0); if(!strAry[15].contains(".")){ xl=xl/10000; } if(xl<1E-6) xl=0.95*xd1;// set a default value, also a BPA approach. mach.setXl(xl); Eq1MachineXmlType.SeFmt1 seFmt1 = DStabParserHelper.createMachineSeFmt1(); double SE1=ODMModelStringUtil.getDouble(strAry[16], 0.0); if(!strAry[16].contains(".")){ SE1=SE1/10000; } double SE2=ODMModelStringUtil.getDouble(strAry[17], 0.0); if(!strAry[17].contains(".")){ SE2=SE2/1000; } // if SE1 or SE2 not defined, use the default value if (SE1 > 0.0 && SE2 > 0.0) { seFmt1.setSe100(SE1*100);//SE1% in InterPSS. seFmt1.setSe120(SE2*100); seFmt1.setSliner(0.8); } mach.setSeFmt1(seFmt1); double D=ODMModelStringUtil.getDouble(strAry[18], 0.0); if(!strAry[18].contains(".")){ D=D/100; } mach.setD(D*2);//DIPSS=DBPA*2 } else if(str.substring(0, 2).trim().equals("LN")){ String busId1=""; if(!strAry[1].equals("")){ busId1 = BPABusRecord.getBusId(strAry[1]); } double Vol1=ODMModelStringUtil.getDouble(strAry[2], 0.0); if(!busId1.equals("")&&Vol1!=0.0){ DStabBusXmlType bus1 = parser.getDStabBus(busId1); //DStabGenDataXmlType dynGen = (DStabGenDataXmlType)bus1.getGenData().getEquivGen().getValue(); DStabGenDataXmlType dynGen = DStabParserHelper.getDefaultGen(bus1.getGenData()); dynGen.setRatedMachVoltage(DStabDataSetter.createVoltageValue(Vol1, VoltageUnitType.KV)); EquiMachineXmlType mach = DStabParserHelper.createEquiMachine(dynGen); EquiMachineXmlType.EquivGen equGen =OdmObjFactory.createEquiMachineXmlTypeEquivGen(); if(bus1.getGenData()!=null){ double pGen=dynGen.getPower().getRe(); equGen.setEquiPgen(pGen);//TODO why only pGen, for equivalence, qGen should be included equGen.setPGenUnit(ApparentPowerUnitType.MVA); mach.setEquivGen(equGen); }else{ equGen.setDCLineBus(true); mach.setEquivGen(equGen); } } // String busId2=""; // if(!strAry[3].equals("")){ // busId2=BusRecord.getBusId(strAry[3]); // } // double Vol2=ModelStringUtil.getDouble(strAry[4], 0.0); // // String busId3=""; // if(!strAry[5].equals("")){ // busId3=BusRecord.getBusId(strAry[5]); // } // double Vol3=ModelStringUtil.getDouble(strAry[6], 0.0); // // String busId4=""; // if(!strAry[7].equals("")){ // busId4=BusRecord.getBusId(strAry[7]); // } // double Vol4=ModelStringUtil.getDouble(strAry[8], 0.0); // // String busId5=""; // if(!strAry[9].equals("")){ // busId5=BusRecord.getBusId(strAry[9]); // } // double Vol5=ModelStringUtil.getDouble(strAry[10], 0.0); } } private static String[] getGeneratorDataFields ( final String str) { final String[] strAry = new String[19]; try{ if(str.substring(0, 2).trim().equals("M")){ strAry[0]=ODMModelStringUtil.getStringReturnEmptyString(str,1, 2).trim(); //to process the Chinese characters first, if any. int chineseCharNum=ODMModelStringUtil.getChineseCharNum(str.substring(3,10).trim()); //Columns 6-13 busName strAry[1] = ODMModelStringUtil.getStringReturnEmptyString(str,4, 11-chineseCharNum).trim(); String str2=chineseCharNum==0?str:ODMModelStringUtil.replaceChineseChar(str); //strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,4, 11).trim(); strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str2,12, 15).trim(); strAry[3]=ODMModelStringUtil.getStringReturnEmptyString(str2,16, 16).trim(); strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str2,17, 21).trim(); strAry[5]=ODMModelStringUtil.getStringReturnEmptyString(str2,23, 25).trim(); strAry[6]=ODMModelStringUtil.getStringReturnEmptyString(str2,31, 32).trim(); strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str2,34, 36).trim(); strAry[8]=ODMModelStringUtil.getStringReturnEmptyString(str2,38, 42).trim(); strAry[9]=ODMModelStringUtil.getStringReturnEmptyString(str2,43, 47).trim(); strAry[10]=ODMModelStringUtil.getStringReturnEmptyString(str2,48, 51).trim(); strAry[11]=ODMModelStringUtil.getStringReturnEmptyString(str2,52, 55).trim(); } else if(str.substring(0, 2).trim().equals("MC")||str.substring(0, 2).trim().equals("MF")){ strAry[0]=ODMModelStringUtil.getStringReturnEmptyString(str,1, 2).trim(); //to process the Chinese characters first, if any. int chineseCharNum=ODMModelStringUtil.getChineseCharNum(str.substring(3,10).trim());; //Columns 6-13 busName strAry[1] = ODMModelStringUtil.getStringReturnEmptyString(str,4, 11-chineseCharNum).trim(); String str2=chineseCharNum==0?str:ODMModelStringUtil.replaceChineseChar(str); //strAry[1]=ModelStringUtil.getStringReturnEmptyString(str2,4, 11).trim(); strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str2,12, 15).trim(); strAry[3]=ODMModelStringUtil.getStringReturnEmptyString(str2,16, 16).trim(); strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str2,17, 22).trim(); strAry[5]=ODMModelStringUtil.getStringReturnEmptyString(str2,23, 25).trim(); strAry[6]=ODMModelStringUtil.getStringReturnEmptyString(str2,26, 28).trim(); strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str2,29, 32).trim(); strAry[8]=ODMModelStringUtil.getStringReturnEmptyString(str2,33, 36).trim(); strAry[9]=ODMModelStringUtil.getStringReturnEmptyString(str2,37, 41).trim(); strAry[10]=ODMModelStringUtil.getStringReturnEmptyString(str2,42, 46).trim(); strAry[11]=ODMModelStringUtil.getStringReturnEmptyString(str2,47, 51).trim(); strAry[12]=ODMModelStringUtil.getStringReturnEmptyString(str2,52, 56).trim(); strAry[13]=ODMModelStringUtil.getStringReturnEmptyString(str2,57, 60).trim(); strAry[14]=ODMModelStringUtil.getStringReturnEmptyString(str2,61, 63).trim(); strAry[15]=ODMModelStringUtil.getStringReturnEmptyString(str2,64, 68).trim(); strAry[16]=ODMModelStringUtil.getStringReturnEmptyString(str2,69, 73).trim(); strAry[17]=ODMModelStringUtil.getStringReturnEmptyString(str2,74, 77).trim(); strAry[18]=ODMModelStringUtil.getStringReturnEmptyString(str2,78, 80).trim(); } else if(str.substring(0, 2).trim().equals("LN")){ strAry[0]=ODMModelStringUtil.getStringReturnEmptyString(str,1, 2).trim(); //to process the Chinese characters first, if any. int chineseCharNum=ODMModelStringUtil.getChineseCharNum(str); //Columns 6-13 busName strAry[1] = ODMModelStringUtil.getStringReturnEmptyString(str,4, 11-chineseCharNum).trim(); String str2=chineseCharNum==0?str:ODMModelStringUtil.replaceChineseChar(str); //strAry[1]=ModelStringUtil.getStringReturnEmptyString(str,4, 11).trim(); strAry[2]=ODMModelStringUtil.getStringReturnEmptyString(str,12, 15).trim(); strAry[3]=ODMModelStringUtil.getStringReturnEmptyString(str,19, 26).trim(); strAry[4]=ODMModelStringUtil.getStringReturnEmptyString(str,27, 30).trim(); strAry[5]=ODMModelStringUtil.getStringReturnEmptyString(str,34, 41).trim(); strAry[6]=ODMModelStringUtil.getStringReturnEmptyString(str,42, 45).trim(); strAry[7]=ODMModelStringUtil.getStringReturnEmptyString(str,49, 56).trim(); strAry[8]=ODMModelStringUtil.getStringReturnEmptyString(str,57, 60).trim(); strAry[9]=ODMModelStringUtil.getStringReturnEmptyString(str,64, 71).trim(); strAry[10]=ODMModelStringUtil.getStringReturnEmptyString(str,72, 75).trim(); } }catch(Exception e){ ODMLogger.getLogger().severe(e.toString()); } return strAry; } private static boolean isSubTransientModel(String busId){ return subTransBusIdList.contains(busId); } private static void setSubTransientData(Eq1MachineXmlType mach){ if(mach instanceof Eq11MachineXmlType){ ((Eq11MachineXmlType)mach).setXd11(SubTransientData.get("xd11")); ((Eq11MachineXmlType)mach).setTd011(DStabDataSetter.createTimeConstSec(SubTransientData.get("td011"))); ((Eq11MachineXmlType)mach).setXq11(SubTransientData.get("xq11")); ((Eq11MachineXmlType)mach).setTq011(DStabDataSetter.createTimeConstSec(SubTransientData.get("tq011"))); } else if(mach instanceof Eq11Ed11MachineXmlType){ ((Eq11Ed11MachineXmlType)mach).setXd11(SubTransientData.get("xd11")); ((Eq11Ed11MachineXmlType)mach).setTd011(DStabDataSetter.createTimeConstSec(SubTransientData.get("td011"))); ((Eq11Ed11MachineXmlType)mach).setXq11(SubTransientData.get("xq11")); ((Eq11Ed11MachineXmlType)mach).setTq011(DStabDataSetter.createTimeConstSec(SubTransientData.get("tq011"))); } } }