Set up a workbook (Layout)
Design layout
Layout regions
Add a layout region
To add a layout region with a list of vertices that define the polygon, use the following function:
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Create a list of vertices that defines the polygon of the layout region to add
List<Location> layoutRegionVertices = new List<Location>();
double width = 100.0;
double height = 150.0;
double bottomLeftX = 402277.5;
double bottomLeftY = 5587965.9;
layoutRegionVertices.Add(new Location(bottomLeftX, bottomLeftY));
layoutRegionVertices.Add(new Location(bottomLeftX, bottomLeftY + height));
layoutRegionVertices.Add(new Location(bottomLeftX + width, bottomLeftY + height));
layoutRegionVertices.Add(new Location(bottomLeftX + width, bottomLeftY));
// Add a new layout region with these vertices
LayoutBoundary layoutRegion = siteLayout.AddLayoutRegion(layoutRegionVertices,
true, "Rect layout region 1");
Modify properties of a layout region
Depending on the site layout type (racks or trackers), use the RackLayoutParameters or TrackerLayoutParameters classes.
Rack layout parameters
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Use the last layout region in the list
LayoutBoundary layoutRegion = siteLayout.LayoutBoundaries.Last();
// Set the setback
layoutRegion.Setback = 5.0;
RackLayoutParameters rackLayoutParams = layoutRegion.RackLayoutParameters;
// Set the rack system specification for this layout region
rackLayoutParams.RackSystemSpecification =
Workbook.ComponentLibrary.RackSystemSpecifications.First();
// Set the Uc and Uv values
rackLayoutParams.PvsystCellTempModelParameters.ConstantHeatTransfer = 30.0;
rackLayoutParams.PvsystCellTempModelParameters.ConvectiveHeatTransfer = 1.0;
// Set the azimuth and tilt
rackLayoutParams.Azimuth = 181.0;
rackLayoutParams.Tilt = 25.0;
// Set the anchor distance from the top, and the pitch
rackLayoutParams.RowPositionParameters.SpacingZoneFromTop.AnchorDistanceFromTop = 5.0;
rackLayoutParams.RowPositionParameters.SpacingZoneFromTop.Pitch = 8.5;
layoutRegion.AutoFillAutomatically = true;
// Force the autofill algorithm to run
layoutRegion.RunAutoFill();
// Refresh display to make sure it's up to date
layoutRegion.RefreshDisplay();
Tracker layout parameters
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Use the last layout region in the list
LayoutBoundary layoutRegion = siteLayout.LayoutBoundaries.Last();
// Set the setback
layoutRegion.Setback = 5.0;
// Set the tracker system specification for this layout region
TrackerLayoutParameters trackerLayoutParams = layoutRegion.TrackerLayoutParameters;
trackerLayoutParams.TrackerSystemSpecification =
Workbook.ComponentLibrary.TrackerSystemSpecifications.First();
// Set the Uc and Uv values
trackerLayoutParams.PvsystCellTempModelParameters.ConstantHeatTransfer = 30.0;
trackerLayoutParams.PvsystCellTempModelParameters.ConvectiveHeatTransfer = 1.0;
// Set the system rotation and other tracker-specific properties
trackerLayoutParams.SystemRotation = 0.5;
trackerLayoutParams.TrackerPlacementMode = TrackerPlacementModeType.FollowTerrain;
trackerLayoutParams.DefaultAisleWidth = 10.0;
trackerLayoutParams.AlignAisles = true;
// Set the anchor offset and the pitch
trackerLayoutParams.RowPositionParameters.SpacingZoneFromTop.AnchorDistanceFromTop = 5.0;
trackerLayoutParams.RowPositionParameters.SpacingZoneFromTop.Pitch = 8.5;
layoutRegion.AutoFillAutomatically = true;
// Force the autofill algorithm to run
layoutRegion.RunAutoFill();
// Refresh display to make sure it's up to date
layoutRegion.RefreshDisplay();
Collection effects
You can also modify the wiring (collection) losses, which depend on the inverter. This is not dependent on the site layout type (racks or trackers).
// Define the cabling losses to update for all the inverters
const double cablingAcLosses = -0.005; // per unit (-0.5%)
const double cablingDcLosses = -0.015; // per unit (-1.5%)
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Iterate over the inverters in the site layout
foreach (InverterInstance inverterInstance in siteLayout.InverterInstances)
{
// Set AC collection effects (part of the inverter)
inverterInstance.OutputWiring.ReferenceGain = cablingAcLosses;
// Set DC collection effects (iterating over each inverter input)
foreach (InverterInputInstance inputInstance in inverterInstance.InputInstances)
{
inputInstance.DcCollectorEffect = cablingDcLosses;
}
}
Get all layout regions in a site layout
Use the following function to enumerate through the layout regions of a site layout:
IEnumerable<LayoutBoundary> SiteLayout.LayoutBoundaries
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
foreach (LayoutBoundary layoutRegion in siteLayout.LayoutBoundaries)
{
Toolbox.Log(string.Format("Layout region \"{0}\": number of polygon points: {1}",
layoutRegion.Name, layoutRegion.Points.Count()));
}
Remove layout regions
Remove all layout regions
Remove an individual layout region
void RemoveLayoutRegion(LayoutBoundary layoutBoundary)
Exclusion regions
Add an exclusion region
To add an exclusion region with a list of vertices that define the polygon, use the following function:
SiteLayout.AddExclusionRegion(string name, IEnumerable<I2DLocation> points)
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Create a list of vertices that defines the polygon of the exclusion region to add
List<Location> regionVertices = new List<Location>();
double width = 100.0;
double height = 150.0;
double bottomLeftX = 465278.6;
double bottomLeftY = 3157253.4;
regionVertices.Add(new Location(bottomLeftX, bottomLeftY));
regionVertices.Add(new Location(bottomLeftX, bottomLeftY + height));
regionVertices.Add(new Location(bottomLeftX + width, bottomLeftY + height));
regionVertices.Add(new Location(bottomLeftX + width, bottomLeftY));
// Add a new exclusion region with these vertices
ExclusionRegion exclusionRegion = siteLayout.AddExclusionRegion("Exclusion 1", regionVertices);
Get all exclusion regions in a site layout
Use the following function to enumerate through the exclusion regions of a site layout:
IEnumerable<ExclusionRegion> SiteLayout.ExclusionRegions
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
foreach (ExclusionRegion exclusionRegion in siteLayout.ExclusionRegions)
{
Toolbox.Log(string.Format("Exclusion region \"{0}\": number of polygon points: {1}",
exclusionRegion.Name, exclusionRegion.Points.Count()));
}
Remove exclusion regions
Remove all exclusion regions
void RemoveAllExclusionRegions()
Remove an individual exclusion region
void RemoveExclusionRegion(ExclusionRegion exclusionRegion)
Importing regions from files
There are a couple of useful functions for importing regions (layout regions and exclusion regions) from files:
- bool ImportRegionsFromGoogleEarthFile(string filePath, TrackerPlacementModeType? trackerPlacementMode = null
- void ImportRegionsFromShapefile(string shapefilePath)
Transformer instances
Add a transformer instance
To add a transformer instance to a site layout, use the following function:
SiteLayout.AddTransformerInstance(string name, IEnumerable<I2DLocation> points)
// Work with the currently visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Add a transformer instance at a location, with the given transformer specification
siteLayout.AddTransformerInstance(new Location(465270, 3157250),
Workbook.ComponentLibrary.TransformerSpecifications.First());
Remove all transformer instances
void RemoveAllTransformerInstances()
Removing objects from a site layout
There are a few more functions to help you remove all objects of a certain type from a layout region:
- void RemoveAllRacks() - Removes all the racks or trackers in a site layout
- void RemoveAllEmptyRacksOrTrackers() - Removes all the empty racks or trackers in a site layout
- void RemoveAllInverterInstances() - Removes all the inverter instances in a site layout
Updating a site layout from a Specify Site Definition
Use the void UpdateFromSpecifySiteDefinition(SpecifySiteDefinition specifySiteDefinition) function to update the site layout with a SpecifySiteDefinition object.
Electrical configuration
Functionality for adding/remove inverters to transformers is currently a little limited.
Linking an inverter instance to a transformer instance
You can use the following function to link an inverter instance to a transformer instance:
TransformerInstance.AddInverterInstance(InverterInstance inverterInstance)
// Work with the visible site layout
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
// Add a new transformer instance
siteLayout.AddTransformerInstance(new Location(402104, 5588035),
Workbook.ComponentLibrary.TransformerSpecifications.First());
// Add all the inverter instances to this new transformer
TransformerInstance newTransformer = siteLayout.TransformerInstances.Last();
foreach (InverterInstance inverter in siteLayout.InverterInstances)
{
newTransformer.AddInverterInstance(inverter);
}
Just be careful, there is currently not a function to remove an inverter instance from a transformer instance. So only use this function when the inverter instance isn't yet attached to a transformer. Otherwise it will be linked to two transformers, which can cause problems.
Displaying the module strings and indices
Once inverters, strings and modules have been added, you can iterate through them, and access the specific information (e.g., rack ID, module index (X and Y in the rack)).
// Print out the module strings on the inverter inputs of the first inverter in the site layout
InverterInstance firstInverter = Workbook.Domain.VisibleSiteLayout.InverterInstances.First();
int inverterInputIndex = 0;
foreach (InverterInputInstance inverterInput in firstInverter.InputInstances)
{
Toolbox.Log(string.Format("InvInput: {0}, number of module strings = {1}",
inverterInputIndex,
inverterInput.ModuleStrings.Count));
int moduleStringIndex = 0;
foreach (ModuleString moduleString in inverterInput.ModuleStrings)
{
foreach (ModuleIndex moduleIndex in moduleString.ModuleIndexes)
{
Toolbox.Log(string.Format(
"ModuleString: {0}, moduleIndex RackID: {1}, XIndexInRack = {2}, YIndexInRack = {3}",
moduleStringIndex,
moduleIndex.RackInstanceId,
moduleIndex.XIndexInRack,
moduleIndex.YIndexInRack));
}
moduleStringIndex++;
}
inverterInputIndex++;
}
Running the above code snippet on a site with the first inverter looking like the image below would return some output (just showing the start of it) similar to:
InvInput: 0, number of module strings = 13
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 9, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 8, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 7, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 6, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 5, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 4, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 3, YIndexInRack = 0
ModuleString: 0, moduleIndex RackID: 49833, XIndexInRack = 2, YIndexInRack = 0
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 9, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 8, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 7, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 6, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 5, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 4, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 3, YIndexInRack = 1
ModuleString: 1, moduleIndex RackID: 49833, XIndexInRack = 2, YIndexInRack = 1
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 9, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 8, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 7, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 6, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 5, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 4, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 3, YIndexInRack = 2
ModuleString: 2, moduleIndex RackID: 49833, XIndexInRack = 2, YIndexInRack = 2
ModuleString: 3, moduleIndex RackID: 49833, XIndexInRack = 1, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49833, XIndexInRack = 0, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 9, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 8, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 7, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 6, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 5, YIndexInRack = 0
ModuleString: 3, moduleIndex RackID: 49832, XIndexInRack = 4, YIndexInRack = 0
ModuleString: 4, moduleIndex RackID: 49833, XIndexInRack = 1, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49833, XIndexInRack = 0, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49832, XIndexInRack = 9, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49832, XIndexInRack = 8, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49832, XIndexInRack = 7, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49832, XIndexInRack = 6, YIndexInRack = 1
ModuleString: 4, moduleIndex RackID: 49832, XIndexInRack = 5, YIndexInRack = 1
...
You can see the XIndexInRack (how many modules 'along' the rack the module is), the YIndexInRack (how many modules 'up' the rack the module is), and the RackID, which is a unique identifier for a specific rack (or tracker).
Once you have a RackID, to get further information use the RackInstanceInfo class, e.g., to see the location of the rack/tracker's 4 corner points use the RackInstanceInfo.Quad property:
// Get a HashSet of all the rack Ids used by strings for the first inverter
HashSet<int> rackIdsForFirstInverter = new HashSet<int>();
InverterInstance firstInverter = Workbook.Domain.VisibleSiteLayout.InverterInstances.First();
foreach (InverterInputInstance inverterInput in firstInverter.InputInstances)
{
foreach (ModuleString moduleString in inverterInput.ModuleStrings)
{
foreach (ModuleIndex moduleIndex in moduleString.ModuleIndexes)
{
rackIdsForFirstInverter.Add(moduleIndex.RackInstanceId);
}
}
}
// Create a dictionary of RackInstanceInfo objects, keyed by RackId (for quick lookup)
SiteLayout siteLayout = Workbook.Domain.VisibleSiteLayout;
Dictionary<int, RackInstanceInfo> rackInfoDictionary
= siteLayout.RackInstanceInfos.ToDictionary(r => r.RackId, r => r);
foreach (int rackId in rackIdsForFirstInverter)
{
RackInstanceInfo rackInfo = rackInfoDictionary[rackId];
Quad rackQuad = rackInfo.RackQuad;
StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format("Rack: ID={0}", rackInfo.RackId));
sb.AppendLine(string.Format(" P1 = {0:0.00}, {1:0.00}, {2:0.00}",
rackQuad.Point1.X, rackQuad.Point1.Y, rackQuad.Point1.Z));
sb.AppendLine(string.Format(" P2 = {0:0.00}, {1:0.00}, {2:0.00}",
rackQuad.Point2.X, rackQuad.Point2.Y, rackQuad.Point2.Z));
sb.AppendLine(string.Format(" P3 = {0:0.00}, {1:0.00}, {2:0.00}",
rackQuad.Point3.X, rackQuad.Point3.Y, rackQuad.Point3.Z));
sb.AppendLine(string.Format(" P4 = {0:0.00}, {1:0.00}, {2:0.00}",
rackQuad.Point4.X, rackQuad.Point4.Y, rackQuad.Point4.Z));
Toolbox.Log(sb.ToString());
}
This will show something like this:
Rack: ID=49833
P1 = 300602.76, 4661576.81, 78.00
P2 = 300602.76, 4661581.62, 81.38
P3 = 300592.84, 4661581.62, 81.38
P4 = 300592.84, 4661576.81, 78.00
Rack: ID=49832
P1 = 300612.78, 4661576.81, 78.00
P2 = 300612.78, 4661581.62, 81.38
P3 = 300602.86, 4661581.62, 81.38
P4 = 300602.86, 4661576.81, 78.00
Rack: ID=49831
P1 = 300622.80, 4661576.81, 78.00
P2 = 300622.80, 4661581.62, 81.38
P3 = 300612.88, 4661581.62, 81.38
P4 = 300612.88, 4661576.81, 78.00
Rack: ID=49830
P1 = 300632.82, 4661576.81, 78.00
P2 = 300632.82, 4661581.62, 81.38
P3 = 300622.90, 4661581.62, 81.38
P4 = 300622.90, 4661576.81, 78.00
Review shading
Not currently available