/*
* @(#)IeeeCDFBranchDataMapper.java
*
* Copyright (C) 2006 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 02/11/2008
*
* Revision History
* ================
*
*/
package org.ieee.odm.adapter.ieeecdf.mapper;
import static org.ieee.odm.ODMObjectFactory.OdmObjFactory;
import org.ieee.odm.adapter.ieeecdf.parser.IeeeCDFBranchDataParser;
import org.ieee.odm.common.ODMBranchDuplicationException;
import org.ieee.odm.common.ODMException;
import org.ieee.odm.model.IODMModelParser;
import org.ieee.odm.model.aclf.AclfDataSetter;
import org.ieee.odm.model.aclf.AclfModelParser;
import org.ieee.odm.model.base.BaseDataSetter;
import org.ieee.odm.schema.AdjustmentModeEnumType;
import org.ieee.odm.schema.AngleAdjustmentXmlType;
import org.ieee.odm.schema.AngleUnitType;
import org.ieee.odm.schema.ApparentPowerUnitType;
import org.ieee.odm.schema.BranchXmlType;
import org.ieee.odm.schema.BusXmlType;
import org.ieee.odm.schema.LimitXmlType;
import org.ieee.odm.schema.LineBranchXmlType;
import org.ieee.odm.schema.MvarFlowAdjustmentDataXmlType;
import org.ieee.odm.schema.PSXfrBranchXmlType;
import org.ieee.odm.schema.TapAdjustBusLocationEnumType;
import org.ieee.odm.schema.TapAdjustmentXmlType;
import org.ieee.odm.schema.VoltageAdjustmentDataXmlType;
import org.ieee.odm.schema.XfrBranchXmlType;
import org.ieee.odm.schema.YUnitType;
import org.ieee.odm.schema.ZUnitType;
/**
* IEEE CDF line record ODM mapper
*
* @author mzhou
*
*/
public class IeeeCDFBranchDataMapper extends AbstractIeeeCDFDataMapper {
/**
* constructor
*/
public IeeeCDFBranchDataMapper() {
this.dataParser = new IeeeCDFBranchDataParser();
}
@Override public void mapInputLine(final String str, AclfModelParser parser) throws ODMException, ODMBranchDuplicationException {
// parse the input data line
dataParser.parseFields(str);
// Columns 1- 4 Tap bus number [I] *
// For transformers or phase shifters, the side of the model the non-unity tap is on.
// Columns 6- 9 Z bus number [I] *
// For transformers and phase shifters, the side of the model the device impedance is on.
// Columns 11-12 Load flow area [I]
// Columns 13-15 Loss zone [I]
// Column 17 Circuit [I] * (Use 1 for single lines)
// Column 19 Type [I] *
// 0 - Transmission line
// 1 - Fixed tap
// 2 - Variable tap for voltage control (TCUL, LTC)
// 3 - Variable tap (turns ratio) for MVAR control
// 4 - Variable phase angle for MW control (phase shifter)
final String fid = IODMModelParser.BusIdPreFix + dataParser.getString("FromNum");
final String tid = IODMModelParser.BusIdPreFix + dataParser.getString("ToNum");
String cirId = dataParser.getString("CirId");
if(cirId.equals(""))cirId="1";//if empty,set cirId to 1 by default
int branchType = dataParser.getInt("Type", 0);
// create branch xml record
BranchXmlType branch = (BranchXmlType) (branchType == 0?
parser.createLineBranch(fid, tid, cirId) :
((branchType == 1 || branchType == 2 || branchType == 3)?
parser.createXfrBranch(fid, tid, cirId) : parser.createPSXfrBranch(fid, tid, cirId)));
branch.setAreaNumber(dataParser.getInt("Area", 0));
branch.setZoneNumber(dataParser.getInt("Zone", 0));
//branch.setId(ODMModelStringUtil.formBranchId(fid, tid, cirId));
// Columns 20-29 Branch resistance R, per unit [F] *
// Columns 30-40 Branch reactance X, per unit [F] * No zero impedance lines
// Columns 41-50 Line charging B, per unit [F] * (total line charging, +B), Xfr B is negative
final double rpu = dataParser.getDouble("R");
final double xpu = dataParser.getDouble("X");
final double bpu = dataParser.getDouble("B");
if (branchType == 0) {
LineBranchXmlType line = (LineBranchXmlType)branch;
AclfDataSetter.setLineData(line, rpu, xpu, ZUnitType.PU, 0.0, bpu, YUnitType.PU);
}
// assume ratio and angle are defined at to side
// Columns 77-82 Transformer final turns ratio [F]
// Columns 84-90 Transformer (phase shifter) final angle [F]
final double ratio = dataParser.getDouble("TurnRatio");
final double angle = dataParser.getDouble("ShiftAngle");
if (branchType > 0) {
if (angle == 0.0) { // regular Xfr branch
XfrBranchXmlType xfrBranch = (XfrBranchXmlType)branch;
AclfDataSetter.createXformerData(xfrBranch,
rpu, xpu, ZUnitType.PU, ratio, 1.0,
0.0, bpu, YUnitType.PU);
BusXmlType fromBusRec = parser.getBus(fid);
BusXmlType toBusRec = parser.getBus(tid);
if (fromBusRec != null && toBusRec != null) {
AclfDataSetter.setXfrRatingData(xfrBranch,
fromBusRec.getBaseVoltage().getValue(),
toBusRec.getBaseVoltage().getValue(),
fromBusRec.getBaseVoltage().getUnit());
}
else {
throw new ODMException("Error: fromBusRecord and/or toBusRecord cannot be found, fromId, toId: " + fid + ", " + tid);
}
} else { // psXfr branch
PSXfrBranchXmlType psXfrBranch = (PSXfrBranchXmlType)branch;
AclfDataSetter.createPhaseShiftXfrData(psXfrBranch, rpu, xpu, ZUnitType.PU,
ratio, 1.0, angle, 0.0, AngleUnitType.DEG,
0.0, bpu, YUnitType.PU);
BusXmlType fromBusRec = parser.getBus(fid);
BusXmlType toBusRec = parser.getBus(tid);
if (fromBusRec != null && toBusRec != null) {
AclfDataSetter.setXfrRatingData(psXfrBranch,
fromBusRec.getBaseVoltage().getValue(),
toBusRec.getBaseVoltage().getValue(),
fromBusRec.getBaseVoltage().getUnit());
}
else {
throw new ODMException("Error: fromBusRecord and/or toBusRecord cannot be found, fromId, toId: " + fid + ", " + tid);
}
}
}
// Columns 51-55 Line MVA rating No 1 [I] Left justify!
// Columns 57-61 Line MVA rating No 2 [I] Left justify!
// Columns 63-67 Line MVA rating No 3 [I] Left justify!
double rating1Mvar = dataParser.getDouble("MvaRating1", 0.0),
rating2Mvar = dataParser.getDouble("MvaRating2", 0.0),
rating3Mvar = dataParser.getDouble("MvaRating3", 0.0);
branch.setRatingLimit(OdmObjFactory.createBranchRatingLimitXmlType());
AclfDataSetter.setBranchRatingLimitData(branch.getRatingLimit(),
rating1Mvar, rating2Mvar, rating3Mvar, ApparentPowerUnitType.MVA);
/*
* map PsXfr/Xfr control/adjustment info
*/
String controlBusId = "";
int controlSide = 0;
double stepSize = 0.0, maxTapAng = 0.0, minTapAng = 0.0, maxVoltPQ = 0.0, minVoltPQ = 0.0;
if (branchType > 1) {
// Columns 69-72 Control bus number
controlBusId = IODMModelParser.BusIdPreFix + dataParser.getString("CntlBusNum");
// Column 74 Side [I]
// 0 - Controlled bus is one of the terminals
// 1 - Controlled bus is near the tap side
// 2 - Controlled bus is near the impedance side (Z bus)
controlSide = dataParser.getInt("CntlBusSide", 0);
// Columns 106-111 Step size [F]
stepSize = dataParser.getDouble("TapStepSize");
// Columns 91-97 Minimum tap or phase shift [F]
// Columns 98-104 Maximum tap or phase shift [F]
minTapAng = dataParser.getDouble("MaxTapShiftAng");
maxTapAng = dataParser.getDouble("MinTapShiftAng");
// Columns 113-119 Minimum voltage, MVAR or MW limit [F]
// Columns 120-126 Maximum voltage, MVAR or MW limit [F]
minVoltPQ = dataParser.getDouble("MinVoltMvarMw");
maxVoltPQ = dataParser.getDouble("MaxVoltMvarMw");
}
if (branchType == 2 || branchType == 3) { // regular Xfr branch
XfrBranchXmlType xfrBranch = (XfrBranchXmlType)branch;
TapAdjustmentXmlType tapAdj = OdmObjFactory.createTapAdjustmentXmlType();
xfrBranch.setTapAdjustment(tapAdj);
tapAdj.setTapLimit(BaseDataSetter.createTapLimit(maxTapAng, minTapAng));
tapAdj.setTapAdjStepSize(stepSize);
tapAdj.setTapAdjOnFromSide(true);
if (branchType == 2) {
VoltageAdjustmentDataXmlType voltTapAdj = OdmObjFactory.createVoltageAdjustmentDataXmlType();
tapAdj.setVoltageAdjData(voltTapAdj);
voltTapAdj.setAdjVoltageBus(parser.createBusRef(controlBusId));
voltTapAdj.setAdjBusLocation(controlSide == 0 ? TapAdjustBusLocationEnumType.TERMINAL_BUS
: (controlSide == 1 ? TapAdjustBusLocationEnumType.NEAR_FROM_BUS
: TapAdjustBusLocationEnumType.NEAR_TO_BUS));
voltTapAdj.setMode(AdjustmentModeEnumType.RANGE_ADJUSTMENT);
if(voltTapAdj.getRange()==null)voltTapAdj.setRange(new LimitXmlType());
BaseDataSetter.setLimit(voltTapAdj.getRange(), maxVoltPQ, minVoltPQ);
} else if (branchType == 3) {
MvarFlowAdjustmentDataXmlType mvarTapAdj = OdmObjFactory.createMvarFlowAdjustmentDataXmlType();
tapAdj.setMvarFlowAdjData(mvarTapAdj);
if(mvarTapAdj.getRange()==null)mvarTapAdj.setRange(new LimitXmlType());
BaseDataSetter.setLimit(mvarTapAdj.getRange(), maxVoltPQ, minVoltPQ);
mvarTapAdj.setMode(AdjustmentModeEnumType.RANGE_ADJUSTMENT);
mvarTapAdj.setMvarMeasuredOnFormSide(true);
}
} else if (branchType == 4) { // PsXfr branch
PSXfrBranchXmlType psXfrBranch = (PSXfrBranchXmlType)branch;
AngleAdjustmentXmlType angAdj = OdmObjFactory.createAngleAdjustmentXmlType();
psXfrBranch.setAngleAdjustment(angAdj);
angAdj.setAngleLimit(OdmObjFactory.createAngleLimitXmlType());
BaseDataSetter.setLimit(angAdj.getAngleLimit(), maxTapAng, minTapAng);
if(angAdj.getRange()==null) angAdj.setRange(new LimitXmlType());
BaseDataSetter.setLimit(angAdj.getRange(), maxVoltPQ, minVoltPQ);
angAdj.setMode(AdjustmentModeEnumType.RANGE_ADJUSTMENT);
angAdj.setDesiredMeasuredOnFromSide(true);
}
}
}