WindGenData.java [tools/MetaModelTools/src/data/interpretors] Revision: cc41e45f67fa3e290531b41dca43638a993daf2e Date: Wed Oct 30 15:09:04 MDT 2019
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package data.interpretors;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author <a href="mailto:shaun.case@colostate.edu">Shaun Case</a>
*/
public class WindGenData {
public static final int MPS_THRESHOLD = 8;
public static final int MAX_YEARS = 100;
public static final int MAX_YEAR_AVERAGE_INDEX = MAX_YEARS;
private double[][][] dailyData = new double[MAX_YEARS][12][31]; //Daily Averages
private double[][] monthlyAverage = new double[MAX_YEARS + 1][12];
private double[] yearlyAverage = new double[MAX_YEARS + 1];
private double[][][] dailyEnergyData = new double[MAX_YEARS + 1][12][31]; //Daily Averages
private double[][] monthlyEnergyData = new double[MAX_YEARS + 1][12];
private double[] yearlyEnergyData = new double[MAX_YEARS + 1];
public static int[] monthDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
private String messages = "";
private boolean badWindData = false;
private String stationName = "";
private String period = "";
private int elevation = 0;
private Period windPeriod;
private int yearCount = 0;
public WindGenData(String windFileData) {
for (int year = 0; year < MAX_YEARS; year++) {
for (int month = 0; month < 12; month++) {
for (int day = 0; day < 31; day++) {
dailyData[year][month][day] = -1.0;
}
}
}
try {
readWindData(windFileData);
} catch (IOException ex) {
Logger.getLogger(WindGenData.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void readWindData(String windFileData) throws IOException {
BufferedReader windData;
windData = new BufferedReader(new StringReader(windFileData));
String windLine;
int count = 0;
int febCount = 0;
boolean foundData = false;
int lastYear = -1;
double yearTotal = 0;
double yearEnergyTotal = 0;
double monthEnergyTotal = 0;
int numDays = 0;
int numMonthDays = 0;
int lastMonth = -1;
double monthTotal = 0;
while ((windLine = windData.readLine()) != null) {
count++;
if (!foundData && windLine.startsWith("#")) {
if (windLine.contains("station:")) {
stationName = windLine.substring(windLine.indexOf("station: ") + 9);
} else {
if (windLine.contains("period: ")) {
period = windLine.substring(windLine.indexOf("period: ") + 8, windLine.indexOf("el:") - (windLine.indexOf("period: ") + 8));
String elString = windLine.substring(windLine.indexOf("el:") + 3);
elevation = Integer.parseInt(elString.replace("m", " ").trim());
} else {
if (windLine.contains("day mo year dir hr1")) {
if ((windLine = windData.readLine()) != null) {
if (windLine.contains("deg m/s m/s")) {
if ((windLine = windData.readLine()) != null) {
if (windLine.contains("# ----------------")) {
foundData = true;
} else {
messages += "\n#\nMissing comment underline line after deg m/s m/s... line";
badWindData = true;
break;
}
} else {
messages += "\n#\nMissing next line after deg m/s... line";
badWindData = true;
break;
}
}
} else {
messages += "\n#\nMissing next line after day mo year... line";
badWindData = true;
break;
}
}
}
}
continue;
} else {
if (foundData) {
String[] tokens = windLine.trim().split("\\s+");
if (tokens.length >= 28) {
int day, month, year;
double dayAverage = 0;
day = Integer.parseInt(tokens[0]) - 1;
month = Integer.parseInt(tokens[1]) - 1;
year = Integer.parseInt(tokens[2]) - 1;
if (month != lastMonth) {
if (lastMonth != -1) {
monthlyAverage[lastYear][lastMonth] = monthTotal / numMonthDays;
monthlyAverage[MAX_YEARS][lastMonth] += monthlyAverage[lastYear][lastMonth];
monthlyEnergyData[lastYear][lastMonth] = monthEnergyTotal;
}
monthTotal = 0;
numMonthDays = 0;
lastMonth = month;
monthEnergyTotal = 0;
}
if (year != lastYear) {
if (lastYear != -1) {
yearlyAverage[lastYear] = yearTotal / numDays;
yearlyAverage[MAX_YEARS] += yearlyAverage[lastYear];
yearlyEnergyData[lastYear] = yearEnergyTotal;
}
yearCount++;
yearTotal = 0;
numDays = 0;
lastYear = year;
yearEnergyTotal = 0;
}
if ((year <= period().getYears()) && (year < MAX_YEARS)) {
for (int i = 4; i < 28; i++) {
dayAverage += Double.parseDouble(tokens[i]);
}
dayAverage /= 24.0;
dailyData[year][month][day] = dayAverage;
//dailyData[MAX_YEAR_AVERAGE_INDEX][month][day] += dayAverage;
if (dayAverage > MPS_THRESHOLD) {
dailyEnergyData[year][month][day] = 0.6 * Math.pow(dayAverage - MPS_THRESHOLD, 2);
} else {
dailyEnergyData[year][month][day] = 0;
}
if ((month == 2) && (day == 29)) {
febCount++;
}
dailyEnergyData[MAX_YEARS][month][day] += dailyEnergyData[year][month][day];
yearEnergyTotal += dailyEnergyData[year][month][day];
monthEnergyTotal += dailyEnergyData[year][month][day];
monthTotal += dayAverage;
numMonthDays++;
yearTotal += dayAverage;
numDays++;
} else {
messages += "\n#\nWind file was longer than 100 years. Data clipped to 100 years.";
break;
}
} else {
messages += "\n#\nMissing hourly wind data on line " + count + "of the windgen data file. Expected 28 fields and found only " + tokens.length + " fields instead.";
badWindData = true;
break;
}
} else {
// Blank line?? Regardless ignore it for now...maybe generate an error if we discover that this cannot/shoud not happen in a .win file.
}
}
}
if (foundData && (yearCount > 0)) {
monthlyAverage[lastYear][lastMonth] = monthTotal / numMonthDays;
yearlyAverage[lastYear] = yearTotal / numDays;
monthlyEnergyData[lastYear][lastMonth] = monthEnergyTotal;
yearlyEnergyData[lastYear] = yearEnergyTotal;
yearCount++;
yearlyAverage[MAX_YEARS] /= yearCount;
yearlyEnergyData[MAX_YEARS] /= yearCount;
for (int i = 0; i < 12; i++) {
monthlyAverage[MAX_YEARS][i] /= yearCount;
monthlyEnergyData[MAX_YEARS][i] /= yearCount;
}
}
}
public int yearsSimulated() {
return period().getYears();
}
public int yearsInFile() {
return yearCount;
}
public int elevation() {
return elevation;
}
public double[][] monthlyAverages() {
return monthlyAverage;
}
public double monthlyAverage(int year, int month) {
if ((year < yearCount) && ((month >= 0) && (month < 12))) {
return monthlyAverage[year][month];
}
return Double.NaN;
}
public String stationName() {
return stationName;
}
public double yearlyAverage(int yearIndex) {
if ((yearIndex < yearCount) && (yearIndex >= 0)) {
return yearlyAverage[yearIndex];
}
return Double.NaN;
}
public double[] monthlyAverage(int yearIndex) {
if ((yearIndex < yearCount) && (yearIndex >= 0)) {
return monthlyAverage[yearIndex];
}
return null;
}
public double windEnergy(int month, int day, int period) {
double energyVal = 0;
if (period > 365) {
energyVal = Double.NaN;
} else {
int currentMonth = month;
int startDay = day;
int dayCount = 0;
while (dayCount < period) {
for (int tDay = startDay; tDay < monthDays[currentMonth]; tDay++) {
energyVal += (dailyEnergyData[MAX_YEARS][currentMonth][tDay] / yearCount);
dayCount++;
}
startDay = 0;
currentMonth++;
if ( currentMonth == 12){
currentMonth = 0;
}
}
}
return energyVal;
}
public double simulationAverage() {
return yearlyAverage[MAX_YEARS];
}
public double[] simulationMonthlyAverage() {
return monthlyAverage[MAX_YEARS];
}
public Period period() {
if (null == windPeriod) {
String periods[] = period.trim().split("-");
if (periods.length == 2) {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate startDate = LocalDate.parse(periods[0], df);
LocalDate endDate = LocalDate.parse(periods[1], df);
windPeriod = Period.between(startDate, endDate);
} else {
this.badWindData = true;
this.messages = "\n#\nPeriod string found in file is not properly formatted.";
}
}
return windPeriod;
}
public boolean badWindData() {
return badWindData;
}
public String windDataMessages() {
return messages;
}
}