Using Custom Tracker Rotations
This mini-tutorial will show you how to import and use custom tracker rotation values from a file and use them to specify the tracker rotations when used in the energy calculation (and also in the visualisation).
Requirements
In order to use this functionality you need:
- To have followed the Importing Tracker Positions mini-tutorial and have imported your own trackers.
- A time-series data file - each date-time entry containing the rotation angle for each of the trackers in the site.
Tip
Please get in touch (send an email to solarfarmer@dnv.com) if you need assistance as this can be quite complex, especially if you're not familiar with C# scripting.
1. Add your trackers to a site layout
The first thing you should do is add individual trackers to a site layout from your data file.
Follow the Importing Tracker Positions mini-tutorial to do this.
Important
It is important that you add the trackers to the site layout using scripting rather than the usual layout tools as you need to give each tracker a unique ID (starting from 0) that are in the same order that the tracker rotations appear in your data file.
There is no way to set IDs of trackers through the UI (and it would be very time-consuming for a large number of trackers).
2. Read and use the tracker rotations
The trackers are now laid out on the site. The next thing is to read in the tracker rotation values and use these in a tracker position algorithm script (rather than using the default SolarFarmer tracking algorithm).
This example assumes that you have one or more CSV files containing the tracker rotation information with the following column headers:
Year,Month,Day,Hour,Minute,Second,Azimuth,Zenith,Tracker0,Tracker1,Tracker2,...
There should be a column for each of the trackers that you previously imported.
Important
The columns of the tracker rotations should be in the same order that the trackers appear in the original CSV file containing their locations. If not, the trackers will use the wrong rotation angles.
It is up to you to make sure the order (and count) is the same.
Each subsequent row contains a date/time and the rotation information for each of the trackers.
A few important points about the rotation data
- The rotation angles should be in degrees, and follow the convention of being negative in the mornings (pointing east)
and positive in the afternoons (pointing west).
- See Tracker Rotation Angle for more information.
- Please provide non-daylight savings time stamps (i.e., no summer-time values) for a non-leap year.
- If the data contains jumps for daylight-savings there will be duplicate time stamps (when the clocks go back) and missing values (when the clocks go forward), which will confuse things and prevent the calculation from working.
- The period between time stamps should be the same, with no gaps.
- They should include night-time values.
- The script will use all the rotation .csv files in the folder.
- This allows you to split the data into several smaller files, rather than one big file, to make working with the files a little easier (as they can get very large (> 1GB)).
- One big file is fine too.
- Make sure you don't have any extra .csv files in the folder that you don't want included, as these will get read-in too.
The UserLibs.TrackerShared.Utils.ReadAllTrackerRotationsFromFilesInFolder()
function reads the
tracker rotations from the file for you. If your data files differ from this format, please copy
the code and create your own script function to do this.
const string folderPathContainingTrackerRotationFiles = @"C:\Data\TrackerRotationsFolder\";
TrackerRotations trackerRotations = UserLibs.TrackerShared.Utils.ReadAllTrackerRotationsFromFilesInFolder(folderPathContainingTrackerRotationFiles);
The TrackerRotations class contains a list of tracker names and a list of timestamps for those trackers throughout the year.
You will use the script snippet above in the tracker position algorithm script that you create below.
a) Create a new tracker position algorithm script
In the drop-down in the top-left of the Script Editor, choose 'Tracker Position Algorithm Script Type' and press the button to add a new one of that type. (Here, 'tracker position' is used instead of 'tracker rotation', but they mean the same thing).
The new script should be filled with the following template script (for you to customise):
/// <summary>
/// TODO: Rename the class and describe here what it does.
/// </summary>
[DisplayName("<TODO: put display name here>")]
[Description("<TODO: put description here>")]
public class MyTrackerPositionAlgorithm : CustomDateTimeTrackerPositionAlgorithmBase
{
/// <summary>
/// Initialises this algorithm. Sets the tracker count and the time steps and
/// tracker rotations.
/// </summary>
/// <returns>
/// <c>true</c> if no errors occur during initialisation; otherwise <c>false</c>.
/// </returns>
public override bool Initialise()
{
// Put any initialisation code here (it is run once before the main calculation).
// Typically reading in the tracker rotations from a file.
// 1. Call SetTrackerCount() to set the tracker count.
// TODO: Set the tracker count with the real number of trackers
this.SetTrackerCount(0);
// 2. Then call AddTimeStep() multiple times to add a time step along with
// rotations for each tracker.
// TODO: Remove this line and call AddTimeStep multiple times with your own data
// - typically in a loop from the data read in from a file.
// There should be one rotation angle per tracker.
// Rotations are in degrees.
this.AddTimeStep(new DateTime(), new List<double> { 45.2, 48.9, 51.4 });
// 3. Return an appropriate value
// TODO: Return false if there are any errors (make sure to log the errors).
// Return true if all ok.
return true;
}
}
b) Set the display name, description and class name
- Add a summary comment to describe what the class does
- Set a display name in the
DisplayName
attribute (this will appear in the Tracker Specification screen to choose from) - Add a description in the
Description
attribute (appears as a tooltip for this script in the Tracker Specification screen) - Give the class a unique name
c) Fill in the Initialise() function
- Read tracker rotations in from a file
- Call
SetTrackerCount()
with the number of trackers - Add all the timesteps - call
this.AddTimeStep()
for each timestep. For each timestep there should be an entry (and in the same order) for each tracker in the array of tracker rotations you provide. - Return true if all ok.
Here is an example for you to copy and customise:
/// <summary>
/// Custom tracker rotation algorithm.
/// </summary>
[DisplayName("Demo custom tracker algorithm")]
[Description("A demo custom tracker algorithm")]
public class DemoCustomTrackerAlgorithm : CustomDateTimeTrackerPositionAlgorithmBase
{
/// <summary>
/// Initialises this algorithm.
/// </summary>
/// <returns>
/// <c>true</c> if no errors occur during initialisation; otherwise <c>false</c>.
/// </returns>
public override bool Initialise()
{
// 1. Read the tracker rotations in from files in a folder
const string folderPathContainingTrackerRotationFiles =
@"C:\Data\TrackerRotationsFolder\";
TrackerRotations trackerRotations = UserLibs.TrackerShared.Utils.ReadAllTrackerRotationsFromFilesInFolder(folderPathContainingTrackerRotationFiles);
// 2. Call SetTrackerCount() to set the tracker count.
this.SetTrackerCount(trackerRotations.TrackerNames.Length);
// 3. Then call AddTimeStep() multiple times to add a time step along with
// rotations for each tracker.
// There should be an entry (and in the same order) for each tracker in the
// float array of tracker rotations.
foreach (TrackerRotationsTimeStep timeStep in trackerRotations.TimeSteps)
{
this.AddTimeStep(timeStep.Time, timeStep.TrackerRotations);
}
// 4. Return an appropriate value
// (Return true if all ok).
return true;
}
}
The TrackerRotationsTimeStep class contains a timestamp and an array of tracker rotations (one for each tracker) for that timestamp.
d) Compile the custom script
- Press the 'Compile Script' button to compile your custom script to make sure it successfully compiles.
- Fix any errors before continuing.
e) Select the algorithm in the Tracker System Specification Task
- In the main SolarFarmer application window, go to the Tracker System Specification task (Trackers).
- In the 'Tracker Position Algorithm' section press on the 'Refresh from scripts' button.
- Open the dropdown and you should see your new custom algorithm listed. Select it.
f) Review the algorithm using the Review Trackers task.
- Go to the Review Trackers task
- Change the view to 3D and review the behaviour of your trackers using the custom algorithm.
Make sure that the data files containing the tracker rotations are present in the expected location (that you specified in the script) and that you set the date to be within the range in your time-series files.
g) Skip writing some of the output files for large sites.
- If you have chosen to save the time-series files when running the energy calculation (see Write Detailed Time-Series Files), some of the files (especially the module performance log file) can get extremely large for larger sites. To save memory and disk space it is recommended to skip writing some of these files.
- To do this:
- Create a new default script in your workbook
- Go to Skipping writing some of the output files to find a sample script for setting properties for the different file types.
- Paste the properties in the
Execute()
function, setting those that you want to skip totrue
, and those that you want to be generated tofalse
. - Run the script (you only have to run this once, as long as you save the workbook after running it).
- Save the workbook.
- This will prevent the file types you have chosen to be logged and generated when the calculation is run.
h) Run the Energy Calculation
Your custom tracker algorithm will be used for the trackers that use the tracker system specification that you chose the custom script.
Note
The file path of the folder containing the tracker rotation csv file(s) is saved in the script, in the workbook.
If you share the workbook with someone else, they will need the same folder available to them with the same path. Folders on network drives may work. If you use your C:\ drive other users will have to copy the same rotation files to the same folder path that you have specified.
Common Questions
What happens when I use different time periods for my custom tracker rotations and my solar resource data?
Running simulations using the default tracker rotation algorithm
Time stamps used in the simulation are defined by the time stamps of the records in the solar resource data (the selected solar resource in the 'Setup yield calculation' task).
The output time series time stamps match that of the selected solar resource.
Running simulations using custom tracker rotations
Time stamps used in the simulation are defined by the tracker rotation input time series.
The output time series time stamps match that of the tracker rotation time series.
If the time resolution of the selected solar resource data differs to the time resolution of the custom tracker rotations (or there is a time offset), the solar resource data is interpolated to generate matching solar resource data for the custom tracker rotation time stamps.
E.g., if your inputs are:
- hourly TMY solar resource data
- a 5-minute time period for custom tracker rotations
The simulation will be driven using the 5-minute time stamps from the custom trackers and interpolate the solar resource data appropriately for these 5-minute time stamps.
Note
We recommend using solar resource data that match the time resolution of the rotation angle time series to avoid errors coming from the interpolation process.
If you want to compare simulations between custom tracking and the default tracker position algorithm, the solar resource data you provide must be consistent with the tracker rotation input time series. This also needs to consider that the simulation time stamps with the default tracker position algorithm are always at the mid-point of the solar resource input time stamp periods.
Illustration of the interpolation process
SolarFarmer sets a representative time stamp for the hourly input data, using the midpoint of the data period as being the most representative time for the sun position to represent that hourly interval. These are the blue points in the plot below for global horizontal irradiance (GHI).
With higher resolution rotation time stamps, those midpoints are used to determine the closest previous and next representative time stamp in the hourly data. The interpolation for the rotation time stamps is based on those, using a simple linear interpolation for the rotation time stamp. This is the resulting data in the yellow line.
With this interpolation, there are over- and underpredictions when summing interpolated values and comparing to the original hourly input, as indicated by the yellow points. This is caused by the shape of the irradiance curve.