/*
* @(#)UCTENodeDataParser.java
*
* Copyright (C) 2006-2013 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/2013
*
* Revision History
* ================
*
*/
package org.ieee.odm.adapter.ucte.parser;
import java.util.ArrayList;
import java.util.List;
import org.ieee.odm.adapter.AbstractDataFieldParser;
import org.ieee.odm.common.ODMException;
import org.ieee.odm.model.base.ODMModelStringUtil;
/**
* Class for processing UCTE node data line string
*
* @author mzhou
*
*/
public class UCTENodeDataParser extends AbstractDataFieldParser {
// custom base voltage is an extension to the UCTE std
private List<Double> customBaseVoltageList = new ArrayList<Double>();
public List<Double> getCustomBaseVoltageList() { return this.customBaseVoltageList; }
private boolean customBaseVoltage = false;
public void setCustomBaseVoltage(boolean b) { this.customBaseVoltage = b; }
@Override public String[] getMetadata() {
return new String[] {
// 0---------------1---------------2---------------3---------------4
"id", "name", "baseKv", "status", "nodeType",
// 5 6 7 8 9
"voltage", "pLoadMW", "qLoadMvar", "pGenMW", "qGenMvar",
// 10 11 12 13 14
"minGenMW", "maxGenMW", "minGenMVar", "maxGenMVar", "staticPrimaryControl",
// 15 16 17 18
"normalPowerPrimaryControl", "scMVA3P", "x_rRatio", "powerPlanType"
};
}
@Override public void parseFields(final String str) throws ODMException {
String id = ODMModelStringUtil.getString(str, 1, 8).trim().replace(' ', '_');
this.setValue(0, id);
String name = ODMModelStringUtil.getString(str, 10, 21).trim();
this.setValue(1, name);
double baseKv = 0.0;
if (!customBaseVoltage)
baseKv = getBaseVoltageKv(id);
String status = ODMModelStringUtil.getString(str, 23, 23); // 0 real, 1 equivalent
this.setValue(3, status);
String nodeType = ODMModelStringUtil.getString(str, 25, 25); // 0 PQ, 1 QAng, 2 PV, 3 Swing
this.setValue(4, nodeType);
double voltage = ODMModelStringUtil.getDouble(str, 27, 32);
if (customBaseVoltage) {
baseKv = findCustomBaseVoltage(voltage);
if (baseKv == 0.0) {
throw new ODMException("Custom base voltage lookup, cannot find proper value");
}
}
else {
if (voltage == 0.0)
voltage = baseKv;
}
this.setValue(2, new Double(baseKv).toString());
this.setValue(5, new Double(voltage).toString());
String pLoadMW = ODMModelStringUtil.getString(str, 34, 40);
this.setValue(6, pLoadMW);
String qLoadMvar = ODMModelStringUtil.getString(str, 42, 48);
this.setValue(7, qLoadMvar);
String pGenMW = ODMModelStringUtil.getString(str, 50, 56); // UCTE assumes out next as the positive direction
this.setValue(8, pGenMW);
String qGenMvar = ODMModelStringUtil.getString(str, 58, 64);
this.setValue(9, qGenMvar);
// optional fields
String minGenMW = ODMModelStringUtil.getString(str, 66, 72);
this.setValue(10, minGenMW);
String maxGenMW = ODMModelStringUtil.getString(str, 74, 80);
this.setValue(11, maxGenMW);
String minGenMVar = ODMModelStringUtil.getString(str, 82, 88);
this.setValue(12, minGenMVar);
String maxGenMVar = ODMModelStringUtil.getString(str, 90, 96);
this.setValue(13, maxGenMVar);
String staticPrimaryControl = ODMModelStringUtil.getString(str, 98, 102);
this.setValue(14, staticPrimaryControl);
String normalPowerPrimaryControl = ODMModelStringUtil.getString(str, 104, 110);
this.setValue(15, normalPowerPrimaryControl);
String scMVA3P = ODMModelStringUtil.getString(str, 112, 118);
this.setValue(16, scMVA3P);
String x_rRatio = ODMModelStringUtil.getString(str, 120, 126);
this.setValue(17, x_rRatio);
String powerPlanType = ODMModelStringUtil.getString(str, 128, 128);
this.setValue(18, powerPlanType);
}
public boolean processBaseVoltageRecord(String str) {
customBaseVoltageList.add(new Double(str));
return true;
}
private double getBaseVoltageKv(String nodeId) throws ODMException {
// According to the spec the node base voltage code is stored at the 7th char
int code = ODMModelStringUtil.getInt(nodeId, 7, 7);
return getBaseVoltageKv(code);
}
private double getBaseVoltageKv(int code) throws ODMException {
switch(code) {
case 0 : return 750.0;
case 1 : return 380.0;
case 2 : return 220.0;
case 3 : return 150.0;
case 4 : return 120.0;
case 5 : return 110.0;
case 6 : return 70.0;
case 7 : return 27.0;
case 8 : return 330.0;
case 9 : return 500.0;
default:
throw new ODMException("Wrong base voltage code, " + code);
}
}
private double findCustomBaseVoltage(double voltage) {
double baseKv = 0.0;
double e = 1.0e10;
for (Double bv : customBaseVoltageList) {
if (Math.abs(voltage - bv.doubleValue()) < e) {
baseKv = bv.doubleValue();
e = Math.abs(voltage - bv.doubleValue());
}
}
return baseKv;
}
}