/*
* @(#)UCTEXfrAdjustDataMapper.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.ucte.mapper;
import static org.ieee.odm.ODMObjectFactory.OdmObjFactory;
import org.ieee.odm.adapter.ucte.UCTE_DEFAdapter;
import org.ieee.odm.adapter.ucte.parser.UCTEXfrAdjustDataParser;
import org.ieee.odm.common.ODMModelContansts;
import org.ieee.odm.common.ODMException;
import org.ieee.odm.model.aclf.AclfModelParser;
import org.ieee.odm.model.base.BaseDataSetter;
import org.ieee.odm.model.base.BaseJaxbHelper;
import org.ieee.odm.model.base.ODMModelStringUtil;
import org.ieee.odm.schema.ActivePowerUnitType;
import org.ieee.odm.schema.AdjustmentModeEnumType;
import org.ieee.odm.schema.AngleAdjustmentXmlType;
import org.ieee.odm.schema.AngleUnitType;
import org.ieee.odm.schema.FactorUnitType;
import org.ieee.odm.schema.PSXfrBranchXmlType;
import org.ieee.odm.schema.TapAdjustBusLocationEnumType;
import org.ieee.odm.schema.TapAdjustmentEnumType;
import org.ieee.odm.schema.TapAdjustmentXmlType;
import org.ieee.odm.schema.VoltageAdjustmentDataXmlType;
import org.ieee.odm.schema.VoltageUnitType;
import org.ieee.odm.schema.XfrBranchXmlType;
public class UCTEXfrAdjustDataMapper extends BaseUCTEDataMapper {
public UCTEXfrAdjustDataMapper() {
this.dataParser = new UCTEXfrAdjustDataParser();
}
public void mapInputLine(final String str, AclfModelParser parser) throws ODMException {
this.dataParser.parseFields(str);
String fromNodeId = this.dataParser.getString("fromNodeId"),
toNodeId = this.dataParser.getString("toNodeId"),
orderCode = this.dataParser.getString("orderCode"),
type = this.dataParser.getString("type", "SYMM");
double dUPhase = this.dataParser.getDouble("dUPhase", 0.0),
uKvPhase = this.dataParser.getDouble("uKvPhase", 0.0);
int nPhase = this.dataParser.getInt("nPhase", 0),
n1Phase = this.dataParser.getInt("n1Phase", 0);
double dUAngle = this.dataParser.getDouble("dUAngle", 0.0),
thetaDegAngle = this.dataParser.getDouble("thetaDegAngle", 0.0),
pMwAngle = this.dataParser.getDouble("pMwAngle", 0.0);
int nAngle = this.dataParser.getInt("nAngle", 0),
n1Angle = this.dataParser.getInt("n1Angle", 0);
if (dUPhase > 0.0 && dUAngle > 0.0) {
throw new ODMException("Error: both phase regulation and angle regulation data are presented");
}
XfrBranchXmlType xfrBranch = parser.getXfrBranch(fromNodeId, toNodeId, orderCode);
if (xfrBranch == null) {
throw new ODMException("Error: branch cannot be found, line: " + str);
}
if (dUPhase > 0.0) {
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "dUPhase", new Double(dUPhase).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "nPhase", new Double(nPhase).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "n1Phase", new Double(n1Phase).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "uKvPhase", new Double(uKvPhase).toString());
double ratioFactor = xfrBranch.getToTurnRatio().getValue();
double x = 1.0 / (1.0 + n1Phase*dUPhase*0.01);
// UCTE model at to side x : 1.0, InterPSS model 1.0:turnRatio
xfrBranch.setToTurnRatio(BaseDataSetter.createTurnRatioPU(ratioFactor/x));
if (uKvPhase > 0.0) {
TapAdjustmentXmlType tapAdj = OdmObjFactory.createTapAdjustmentXmlType();
xfrBranch.setTapAdjustment(tapAdj);
tapAdj.setAdjustmentType(TapAdjustmentEnumType.VOLTAGE);
// tap control of voltage at to node side
// 2 - Variable tap for voltage control (TCUL, LTC)
double maxTap = ratioFactor*(nPhase*dUPhase),
minTap = ratioFactor*(-nPhase*dUPhase);
tapAdj.setTapLimit(BaseDataSetter.createTapLimit(maxTap, minTap));
tapAdj.getTapLimit().setUnit(FactorUnitType.PERCENT);
tapAdj.setTapAdjStepSize(dUPhase);
tapAdj.setTapAdjOnFromSide(false);
VoltageAdjustmentDataXmlType vAdjData = OdmObjFactory.createVoltageAdjustmentDataXmlType();
tapAdj.setVoltageAdjData(vAdjData);
vAdjData.setMode(AdjustmentModeEnumType.VALUE_ADJUSTMENT);
vAdjData.setDesiredValue(uKvPhase);
vAdjData.setDesiredVoltageUnit(VoltageUnitType.KV);
vAdjData.setAdjVoltageBus(parser.createBusRef(toNodeId));
vAdjData.setAdjBusLocation(TapAdjustBusLocationEnumType.TO_BUS);
}
}
else if (dUAngle > 0.0) {
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "dUAngle", new Double(dUAngle).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "thetaDegAngle", new Double(thetaDegAngle).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "nAngle", new Double(nAngle).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "n1Angle", new Double(n1Angle).toString());
if (dUPhase != 0.0)
BaseJaxbHelper.addNVPair(xfrBranch, "pMwAngle", new Double(pMwAngle).toString());
double ratioFactor = xfrBranch.getToTurnRatio().getValue();
double ang = 0.0, angMax = 0.0, angMin = 0.0, x = 1.0;
double a = n1Angle*dUAngle*0.01,
aMax = nAngle*dUAngle*0.01,
aMin = -nAngle*dUAngle*0.01;
if (type.equals(UCTE_DEFAdapter.PsXfrType_ASYM)) {
if (thetaDegAngle == 90.0) {
ang = Math.atan(a);
angMax = Math.atan(aMax);
angMin = Math.atan(aMin);
x = 1.0 / Math.sqrt(1.0 + a*a);
}
else {
double theta = thetaDegAngle * ODMModelContansts.Deg2Rad,
asin = a*Math.sin(theta),
acos = 1.0 + a*Math.cos(theta),
asinMax = aMax*Math.sin(theta),
acosMax = 1.0 + aMax*Math.cos(theta),
asinMin = aMin*Math.sin(theta),
acosMin = 1.0 + aMin*Math.cos(theta);
ang = Math.atan(asin/acos);
angMax = Math.atan(asinMax/acosMax);
angMin = Math.atan(asinMin/acosMin);
x = 1.0 / Math.sqrt(asin*asin + acos*acos);
}
}
else { // default type is SYMM
ang = 2.0 * Math.atan(a/2.0);
angMax = 2.0 * Math.atan(aMax/2.0);
angMin = 2.0 * Math.atan(aMin/2.0);
}
PSXfrBranchXmlType psXfrBranch = (PSXfrBranchXmlType)ODMModelStringUtil.casting(
xfrBranch, "XfrBranchXmlType", "PSXfrBranchXmlType", parser.getEncoding());
psXfrBranch.setToAngle(BaseDataSetter.createAngleValue(-ang*ODMModelContansts.Rad2Deg, AngleUnitType.DEG));
psXfrBranch.setToTurnRatio(BaseDataSetter.createTurnRatioPU(ratioFactor/x));
if (pMwAngle != 0.0) {
AngleAdjustmentXmlType angAdj = OdmObjFactory.createAngleAdjustmentXmlType();
psXfrBranch.setAngleAdjustment(angAdj);
angAdj.setMode(AdjustmentModeEnumType.VALUE_ADJUSTMENT);
angAdj.setDesiredValue(pMwAngle);
angAdj.setDesiredActivePowerUnit(ActivePowerUnitType.MW);
angAdj.setAngleLimit(BaseDataSetter.createAngleLimit(angMax, angMin, AngleUnitType.DEG));
angAdj.setAngleAdjOnFromSide(false);
// this part if not specified in the UCTE spec. We assume it is measured on to side
angAdj.setDesiredMeasuredOnFromSide(false);
}
}
}
}