This is the source code for class that reads TMY (Typical Meteorological Year) files.
This is just to take a look at before you download -- if you want to download it, then download all the solar classes here: Solar Tools Source
'Solar Analysis Tools - 'Copyright (C) 2005 Gary Reysa (gary@BuildItSolar.com)
' This program is free software; you can redistribute it and/or modify it ' under the terms of the GNU General Public License as published by the Free ' Software Foundation; either version 2 of the License, or (at your option) ' any later version.
' This program is distributed in the hope that it will be useful and encourage ' further development of solar tools, 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.
' TMY class ' This class reads a TMY (Typical Meterlogal Year) weather files, and provides ' various methods to access the weather data ' ' TMY weather files for many cities are available here: ' http://rredc.nrel.gov/solar/old_data/nsrdb/tmy2/ ' ' This class is primarely intended to extract weather data from a TMY ' for the purpose of driving a simulation that requires weather data. ' ' !!IMPORTANT NOTE!! that the TMY data is in SI units, but this class converts them to ' English units as it reads them. ' When you ask for TMY data from this class it will come out in English units! <-------- ' See notes for each field below.
' TODO: ' Look at fixing up missing data ' Should read the file header, and offer these fields as properties (e.g. city, ...) ' Think about converting to an arraylist of TMYstruc
Imports System Imports System.IO Imports System.Math
'TMY structure -- holds the data fields for one record from a TMY file -- there is one record ' for each hour of the year. ' Note: the units listed below are what is stored in array, many are converted from metric ' as read from the TMY files to English before storing in array wx Public Structure TMYstruc Dim Year As Short 'p 2 - 3 Year that data came from 69 to 90ish Dim Month As Single 'p 4 - 5 Month Dim Day As Short 'p 6 - 7 Day Dim Hour As Short 'p 8 - 9 Hour Dim Ihorzext As Single 'p 10-13 Extraterrestrial Horz Rad (BTU/hr-ft^2) Dim Idnext As Single 'p 14-17 Extraterrestrial Direct Normal Rad (BTU/hr-ft^2) Dim Ihorzglo As Single 'p 18-21 Global Horz Rad (direct + diffuse) (BTU/hr-ft^2) Dim Idn As Single 'p 24-27 Direct Normal Radiation (BTU/hr-ft^2) Dim Ihorzdif As Single 'p 30-33 Diffuse rad on horz surface (BTU/hr-ft^2) Dim ILhorzglo As Single 'p 36-39 Total Illuminance on horz surf in (lux) Dim ILdn As Single 'p 42-45 Direct normal illuminance in (lux) Dim ILhorzdif As Single 'p 48-51 Diffuse illuminance on horz surf (lux) Dim SkyCov As Short 'p 60-65 Amount of sky dome covered in tenths Dim Tdb As Single 'p 68-71 Tempeerature - dry buld (deg F) Dim Tdp As Single 'p 74-77 Temperature - dew pointbuld deg F Dim RH As Short 'p 80-82 Relative Humidity (0 to 100) Dim Patm As Single 'p 85-88 Atmospheric pressure (lb/in^2) Dim WindDir As Short 'p 91-93 Wind Direction (0 to 360) calm is a zero Dim WindSpd As Single 'p 96-98 Wind speed in tenths of (MPH) Dim Viz As Single 'p 101-104 Visibility in tenths of miles Dim Ceil As Single 'p 107-111 Ceiling in ft (-1 indicates ulimited ceiling) Dim WxNow As String 'p 114-123 Present weather in a 10 diget code Dim Precip As Single 'p 124-126 Water precip in hour (inches ) -- see Note 1 Dim SnowDep As Single 'p 134-136 Snow depth in (inches) (for day or for hour?) Dim LastSnow As Short 'p 139-140 Days since last snowfall
' keep these data sizes as small as possilbe there will be 365*24 = 8760 of them at 94 bytes each = 806k
' Note 1: Precipitable water does not mean actual rain in last hour -- it has something to do ' with how much water is in the air? End Structure
Public Class TMYcls Private mTMYHeaderString As String
' wx array of TMY strucs holds a full year of TMY data -- one TMYstruc for each hour of year ' index zero holds nothing -- index one holds first record ' index for hour 1 of day 10 is 10*24 + 1 = 241 -- ' hour 1 goes from midnight to 1am, 2 from 1am to 2am ... 24 from 11pm to 12midnight
Private wx(365 * 24 + 1) As TMYstruc
Private aDate As Date
'Returns a TMYstruc for the hour index passed Public Function TMYrec(ByVal ix As Integer) As TMYstruc If (ix >= 1) And (ix <= 365 * 24) Then Return wx(ix) Else Return Nothing End If End Function
' !!!! fix this -- want month 1 to jan (not month 0 is jan) -- this may be ok ' want day 1 of month to be day one, not day zero is day 1
' returns TMYstruc for the Month, Day Of Month, and Hour passed Public Function TMYrecForDate(ByVal Month As Short, ByVal DayOfMonth As Short, ByVal Hr As Short) As TMYstruc aDate = DateSerial(2001, Month, DayOfMonth) Dim DOY As Integer = aDate.DayOfYear() If DOY > 365 Then DOY = 365 If DOY < 1 Then DOY = 1 Return TMYrec((DOY - 1) * 24 + Hr) End Function
Public Function TMYrecIndexForDate(ByVal Month As Short, ByVal DayOfMonth As Short, ByVal Hr As Short) As Integer aDate = DateSerial(2001, Month, DayOfMonth) Dim DOY As Integer = aDate.DayOfYear() If DOY > 365 Then DOY = 365 If DOY < 1 Then DOY = 1 Return (DOY - 1) * 24 + Hr End Function
Public Function TMYHeader() As String Return mTMYHeaderString End Function
' Fix Missing Data -- replace missing data with reasonable interpolations Public Sub FixMissingData()
' to be added End Sub
' Opens the passed TMY data file, and reads the data into array wx of TMY structures ' Returns true if successful, otherwise returns false Public Function ReadTMYFile(ByVal FN As String) As Boolean
Dim sr As StreamReader ' Create an instance of StreamReader to read from a file. Try sr = New StreamReader(FN) Catch ex As Exception Console.WriteLine("TMYcls:ReadTMYFile: can't open TMY file: " & FN) Return False End Try Dim s As String ' Read and display the lines from the file until the end ' of the file is reached.
' read the header line mTMYHeaderString = sr.ReadLine()
Dim ix As Integer = 0 ' don't use the zeroth entry in wx array wx(ix) = Nothing ix += 1
Do s = sr.ReadLine() 'Console.WriteLine(s) If (s Is Nothing) Then Else wx(ix).Year = s.Substring(1, 2) 'p 2 - 3 Year that data came from 69 to 90ish wx(ix).Year = wx(ix).Year + 1900 wx(ix).Month = s.Substring(3, 2) 'p 4 - 5 Month wx(ix).Day = s.Substring(5, 2) 'p 6 - 7 Day wx(ix).Hour = s.Substring(7, 2) 'p 8 - 9 Hour wx(ix).Ihorzext = s.Substring(9, 4) 'p 10-13 Extraterrestrial Horz Rad wx(ix).Ihorzext = wx(ix).Ihorzext * 0.317 ' convert to BTU/hr-ft^2 wx(ix).Idnext = s.Substring(13, 4) 'p 14-17 Extraterrestrial Direct Normal Rad wx(ix).Idnext = wx(ix).Idnext * 0.317 ' convert to BTU/hr-ft^2 wx(ix).Ihorzglo = s.Substring(17, 4) 'p 18-21 Global Horz Rad (direct + diffuse) w/m^2 wx(ix).Ihorzglo = wx(ix).Ihorzglo * 0.317 ' convert to BTU/hr-ft^2 wx(ix).Idn = s.Substring(23, 4) 'p 24-27 Direct Normal Rad w/m^2 wx(ix).Idn = wx(ix).Idn * 0.317 ' convert to BTU... wx(ix).Ihorzdif = s.Substring(29, 4) 'p 30-33 Diffuse rad on horz surface w/m^2 wx(ix).Ihorzdif = wx(ix).Ihorzdif * 0.317 ' convert to BTU... wx(ix).ILhorzglo = s.Substring(35, 4) 'p 36-39 Total Illuminance on horz surf in lux/100 wx(ix).ILhorzglo = wx(ix).ILhorzglo * 100 ' convert to lux wx(ix).ILdn = s.Substring(41, 4) 'p 42-45 Direct normal illuminance in lux/100 wx(ix).ILdn = wx(ix).ILdn * 100.0 ' conver to lux wx(ix).ILhorzdif = s.Substring(47, 4) 'p 48-51 Diffuse illuminance on horz surf in lux/100 wx(ix).ILhorzdif = wx(ix).ILhorzdif * 100 ' convert to lux wx(ix).SkyCov = s.Substring(59, 2) 'p 60-65 Amount of sky dome covered in tenths wx(ix).Tdb = s.Substring(67, 4) 'p 68-71 Tempeerature - dry buld deg C wx(ix).Tdb = (wx(ix).Tdb / 10.0) * 1.8 + 32 ' remove 10 multiplier and convert from deg C to deg F wx(ix).Tdp = s.Substring(73, 4) 'p 74-77 Temperature - dew pointbuld deg C wx(ix).Tdp = (wx(ix).Tdp / 10.0) * 1.8 + 32 ' convert to deg F wx(ix).RH = s.Substring(79, 3) 'p 80-82 Relative Humidity (0 to 100) wx(ix).Patm = s.Substring(84, 4) 'p 85-88 Atmospheric pressure millibars wx(ix).Patm = wx(ix).Patm * 0.0145 ' convert from millibar to lb/in^2
wx(ix).WindDir = s.Substring(90, 3) 'p 91-93 Wind Direction (0 to 360) calm is a zero wx(ix).WindSpd = s.Substring(95, 3) 'p 96-98 Wind speed in tenths of M/Sec (0 to 400) 400 = 40.0 m/sec wx(ix).WindSpd = (wx(ix).WindSpd / 10.0) * 2.237 ' remove multiplier of 10 and convert to MPH wx(ix).Viz = s.Substring(100, 4) 'p 101-104 Visibility in tenths of km (eg 1609 = 160.9 km/hr) wx(ix).Viz = (wx(ix).Viz / 10.0) * 0.6214 'remove multiplier, and convert to mi wx(ix).Ceil = s.Substring(106, 5) 'p 107-111 Ceiling in meters (0 to 30450) If (wx(ix).Ceil = 77777) Then : wx(ix).Ceil = -1 Else : wx(ix).Ceil = wx(ix).Ceil / 3.281 End If 'convert from meter to feet wx(ix).WxNow = s.Substring(113, 10) 'p 114-123 Present weather in a 10 diget code wx(ix).Precip = s.Substring(123, 3) 'p 124-126 Water precip in hour mm wx(ix).Precip = wx(ix).Precip / 25.4 ' convert from mm to inches wx(ix).SnowDep = s.Substring(133, 3) 'p 134-136 Snow depth in cm (for day or for hour?) wx(ix).SnowDep = wx(ix).SnowDep / 2.54 ' convert from cm to inches wx(ix).LastSnow = s.Substring(138, 2) 'p 139-140 Days since l= s.SubString(t snowfall If (wx(ix).LastSnow = 99) Then wx(ix).LastSnow = -1 'Console.WriteLine("wx: year {0} Month {1} Day {2}", wx(ix).Year, wx(ix).Month, wx(ix).Day) 'Console.WriteLine("wx: Idn {0} Ceil {1} LastSnw {2}", wx(ix).Idn, wx(ix).Ceil, wx(ix).LastSnow) ix = ix + 1 End If Loop Until s Is Nothing
sr.Close() Return True End Function
Public Sub WxAtIx(ByVal ix As Integer) Console.WriteLine("Wx({0})", ix) Console.WriteLine("Year {0,7} ", wx(ix).Year) ' = s.Substring(1, 2) 'p 2 - 3 Year that data came from 69 to 90ish Console.WriteLine("Month {0,7} ", wx(ix).Month) ' = s.Substring(3, 2) 'p 4 - 5 Month Console.WriteLine("Day {0,7} ", wx(ix).Day) ' = s.Substring(5, 2) 'p 6 - 7 Day Console.WriteLine("Hour {0,10:F2} ", wx(ix).Hour) ' = s.Substring(7, 2) 'p 8 - 9 Hour Console.WriteLine("Ihorzext {0,10:F2} ", wx(ix).Ihorzext) ' = s.Substring(9, 4) 'p 10-13 Extraterrestrial Horz Rad Console.WriteLine("Idnext {0,10:F2} ", wx(ix).Idnext) ' = s.Substring(13, 4) 'p 14-17 Extraterrestrial Direct Normal Rad Console.WriteLine("Ihorzglo {0,10:F2} ", wx(ix).Ihorzglo) ' = s.Substring(17, 4) 'p 18-21 Global Horz Rad (direct + diffuse) w/m^2 Console.WriteLine("Idn {0,10:F2} ", wx(ix).Idn) ' = s.Substring(23, 4) 'p 24-27 Direct Normal Rad w/m^2 Console.WriteLine("Ihorzdif {0,10:F2} ", wx(ix).Ihorzdif) ' = s.Substring(29, 4) 'p 30-33 Diffuse rad on horz surface w/m^2 Console.WriteLine("ILhorzglo {0,7} ", wx(ix).ILhorzglo) ' = s.Substring(35, 4) 'p 36-39 Total Illuminance on horz surf in Klux (0 to 130) Console.WriteLine("ILdn {0,7} ", wx(ix).ILdn) ' = s.Substring(41, 4) 'p 42-45 Direct normal illuminance in Klux Console.WriteLine("ILhorzdif {0,7} ", wx(ix).ILhorzdif) ' = s.Substring(47, 4) 'p 48-51 Diffuse illuminance on horz surf Console.WriteLine("SkiCov {0,10:F2} ", wx(ix).SkyCov) ' = s.Substring(59, 2) 'p 60-65 Amount of sky dome covered in tenths Console.WriteLine("Tdb {0,10:F2} ", wx(ix).Tdb) ' = s.Substring(67, 4) 'p 68-71 Tempeerature - dry buld deg C Console.WriteLine("Tdp {0,10:F2} ", wx(ix).Tdp) ' = s.Substring(73, 4) 'p 74-77 Temperature - dew pointbuld deg C Console.WriteLine("RH {0,7} ", wx(ix).RH) ' = s.Substring(79, 3) 'p 80-82 Relative Humidity (0 to 100) Console.WriteLine("Patm {0,10:F2} ", wx(ix).Patm) ' = s.Substring(84, 4) 'p 85-88 Atmospheric pressure millibars Console.WriteLine("WindDir {0,7} ", wx(ix).WindDir) ' = s.Substring(90, 3) 'p 91-93 Wind Direction (0 to 360) calm is a zero Console.WriteLine("WindSpd {0,10:F2} ", wx(ix).WindSpd) ' = s.Substring(95, 3) 'p 96-98 Wind speed in tenths of M/Sec (0 to 400) 400 = 40.0 m/sec Console.WriteLine("Viz {0,10:F2} ", wx(ix).Viz) ' = s.Substring(100, 4) 'p 101-104 Visibility in tenths of km (eg 1609 = 160.9 km/hr) Console.WriteLine("Ceil {0,7} ", Round(wx(ix).Ceil)) ' = s.Substring(106, 5) 'p 107-111 Ceiling in meters (0 to 30450) Console.WriteLine("WxNow {0,10:F2} ", wx(ix).WxNow) ' = s.Substring(113, 10) 'p 114-123 Present weather in a 10 diget code Console.WriteLine("Precip {0,10:F2} ", wx(ix).Precip) ' = s.Substring(123, 3) 'p 124-126 Water precip in hour mm Console.WriteLine("SnowDep {0,10:F2} ", wx(ix).SnowDep) ' = s.Substring(133, 3) 'p 134-136 Snow depth in cm (for day or for hour?) Console.WriteLine("LastSnow {0,7} ", wx(ix).LastSnow) ' = s.Substring(138, 2) 'p 139-140 Days since l= s.SubString(t snowfall End Sub
End Class