/*
* @(#)PSSEDynAdapter.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 Tony Huang
* @Version 1.0
* @Date 02/11/2013
*
* Revision History
* ================
*
*/
package org.ieee.odm.adapter.psse.impl;
import org.ieee.odm.adapter.psse.PSSEAdapter.PsseVersion;
import org.ieee.odm.adapter.psse.mapper.dynamic.DynamicModelLibHelper;
import org.ieee.odm.adapter.psse.mapper.dynamic.DynamicModelLibHelper.DynModelType;
import org.ieee.odm.adapter.psse.mapper.dynamic.PSSEDynExciterMapper;
import org.ieee.odm.adapter.psse.mapper.dynamic.PSSEDynGeneratorMapper;
import org.ieee.odm.adapter.psse.mapper.dynamic.PSSEDynTurGovMapper;
import org.ieee.odm.common.IFileReader;
import org.ieee.odm.common.ODMException;
import org.ieee.odm.model.IODMModelParser;
import org.ieee.odm.model.base.ODMModelStringUtil;
import org.ieee.odm.model.dstab.DStabModelParser;
import org.ieee.odm.schema.AnalysisCategoryEnumType;
import org.ieee.odm.schema.DStabNetXmlType;
public class PSSEDynAdapter extends PSSEAcscAdapter {
DynamicModelLibHelper dynLibHelper = new DynamicModelLibHelper();
PSSEDynGeneratorMapper generatorMapper =null;
PSSEDynExciterMapper exciterMapper =null;
PSSEDynTurGovMapper turGovMapper = null;
public PSSEDynAdapter(PsseVersion ver) {
super(ver);
generatorMapper = new PSSEDynGeneratorMapper(ver);
exciterMapper = new PSSEDynExciterMapper(ver);
turGovMapper = new PSSEDynTurGovMapper(ver);
}
/*
* parse the input dynamic model data
*/
public IODMModelParser parseDStabFile(final IFileReader din, String encoding) throws ODMException {
String lineStr = null;
String modelType = "";
int lineNo = 0;
try {
do {
lineStr = din.readLine();
if (lineStr != null) {
lineNo++;
if(skipInvalidLine(lineStr)){
System.out.println("Invalid line, line# "+lineNo+",:"+lineStr);
continue;
}
lineStr = lineStr.trim();
if(lineStr.length()>0){//only process when it is not a blank line
while(!isModelDataCompleted(lineStr)){
lineStr += din.readLine();
lineNo++;
}
//remove the "/" at the end of data definition
lineStr =lineStr.substring(0, lineStr.lastIndexOf("/"));
modelType = getModelType(lineStr);
DynModelType type = dynLibHelper.getModelType(modelType);
if(type!=null){
if(type==DynModelType.GENERATOR){
generatorMapper.procLineString(modelType, lineStr, (DStabModelParser) parser);
}
else if(dynLibHelper.getModelType(modelType)==DynModelType.EXCITER){
exciterMapper.procLineString(modelType, lineStr, (DStabModelParser)parser);
}
else if(dynLibHelper.getModelType(modelType)==DynModelType.TUR_GOV){
turGovMapper.procLineString(modelType, lineStr, (DStabModelParser)parser);
}
//save supported model data
dynLibHelper.saveSupportedModelData(lineStr);
}
else{
//System.out.println("model unsupported :"+lineStr);
//throw new Exception("The input dynamic model is not supported yet, Type #"+modelType);
dynLibHelper.procUnsupportedModel(modelType, lineStr);
}
}
}
}while(lineStr!=null);
} catch (Exception e) {
e.printStackTrace();
throw new ODMException("PSSE dynamic data input error, line # " + lineNo + ", " + e.toString());
}
System.out.println(dynLibHelper.getUnsupportdSVCRecs());
return parser;
}
@Override
public IODMModelParser parseInputFile(NetType type, IFileReader[] din,
String encoding) throws ODMException {
if(type !=NetType.DStabNet){
// initialize the parser first
throw new ODMException("input type is not Dstab NetType, please check ");
}
// the parser is supposed to be set at the PSSEDstabParser class, which call this method
if(parser == null){
parser = new DStabModelParser();
parser.getStudyCase().setAnalysisCategory(AnalysisCategoryEnumType.TRANSIENT_STABILITY);
}
DStabNetXmlType baseCaseNet = (DStabNetXmlType) parser.getNet();
/*
three files in the input array, i.e., power flow + sequence data + dynamic data file
Use the Acsc Parser to parse the first two files, namely, Aclf and Sequence data file.
*/
if(din.length==3){
// the second data file stores the sequence data
if(din[1]!=null){
baseCaseNet.setHasShortCircuitData(true);
}
super.parseInputFile(type, din, encoding);
//It is supposed that the third file defines the Dstab data.
this.parseDStabFile(din[2], encoding);
}
// only power flow and dynamic data included
else if(din.length==2){
super.parseInputFile(din[0], encoding);
this.parseDStabFile(din[1], encoding);
baseCaseNet.setHasLoadflowData(true);
baseCaseNet.setPositiveSeqDataOnly(true);
}
return parser;
}
/**
* Dynamic model Format:
* IBUS 'TYPE' ID DATALIST /
*
* @param lineStr
* @return
*/
private boolean isModelDataCompleted(String lineStr){
return lineStr.trim().lastIndexOf("/")>0;
}
/**
* Model type string is stored in the second entry.
* Exmaple:
* 1 'IEEET1' 1 0.06 20.0 0.2 1.172
*
* @param lineStr
* @return
*/
private String getModelType(String lineStr){
String[] strAry =lineStr.split("\\s+");
if(strAry.length>2)
return(ODMModelStringUtil.trimQuote(strAry[1]));
else
try {
throw new Exception("The input data is not correct model data"+lineStr);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private boolean skipInvalidLine(String lineStr){
if(lineStr.trim().length()==0.0){
return true;
}
//Check if the first line of multiInteger(String s) {
int busNum;
if(lineStr.trim().startsWith("//") || lineStr.trim().startsWith("/"))
return true;
// skip a line if it is not started with a bus Number, which is an integer,
try {
String[] strAry =lineStr.trim().split("\\s+");
busNum =Integer.parseInt(strAry[0].trim());
} catch(NumberFormatException e) {
//System.out.println("Error when processing line: \n"+ lineStr);
return true;
}
// only got here if we didn't return false
return false;
}
}