Modules

GridLAB-D™ implements classes and solvers by employing modules. Modules can be prebuilt and delivered as a dll, so, or dylib (depending on your computer platform and operating system), or they can be encoded directly in a GLM file as a runtime class.

The currently supported modules are:

  • Climate: contains weather data and reads TMY2 files.
  • Generators: distributed generator models act as a load on the system.
  • Powerflow: simulates the distribution level power grid models.
  • Residential: models a single-family home and various home appliances.
  • Reliability: runs one-off reliability analysis on Powerflow models.
  • Tape: observes the properties of individual objects or the aggregate properties of a group of objects.

The currently unsupported modules are:

  • Commercial: models office buildings.
  • Communications: models communications networks.
  • GLJava: provides JNI interface for loading modules written in Java.
  • Market: provides wholesale market simulation and responsive appliance.
  • Matlab: provides a Matlab interface for defining classes in Matlab. This is superseded by the Matlab link core function.
  • MatPower: solves optimal power flow using the MATPOWER solver.
  • Network: models balanced electric networks.
  • PLC: models programmable logic controllers.

As GridLAB-D™ is continuously updated and improved, the functionality of these unsupported modules has likely been achieved through alternative means. Where the documentation or theory behind these deprecated modules may be worthwhile to preserve for reference, those pages can be found in the Unimplemented section of the documentation.

The following modules provide debugging and I/O functions

  • Assert: Contains objects that are used in test modules by breaking the simulation if observed values deviate from expected values.
  • Tape: Object boundary condition I/O module.

We introduce these modules and how they fit into the big picture of GridLAB-D™ below.

Residential

The residential module provides classes for houses and the appliances typically found therein. To load the residential module, use the module directive in the preamble of your .glm file:

module residential;

The residential module uses several global variables to give you control over the module's behavior:

module residential {
  default_outdoor_temperature 74.0 degF;
  implicit_enduses LIGHTS|PLUGS|OCCUPANCY|DISHWASHER|MICROWAVE|FREEZER|REFRIGERATOR|RANGE|EVCHARGER|WATERHEATER|CLOTHESWASHER|DRYER;
}

Let's take a closer look at the house object and its end use loads.

House

The house object is the main class of object defined by the residential module. These represent typical single-family residential units in North America. They are defined with 110/220 volt distribution panels that allow various end use loads to be connected.

The principal property of house that determines its behavior is the floor_area. Most other properties are derived by default from the floor area. To change the floor area use

object house {
  floor_area 1250 sf;
  // ...
}

Other important properties are thermal integrity and glazing, which determine the thermal properties of the house. To change the thermal properties of a house, you can use the umbrella setting thermal_integrity_level. Individual insulation and airchange parameters can also be explicitly defined for a more granular house definition. Check out the full house parameter list for more information.

object house {
  // ...
  thermal_integrity_level ABOVE_NORMAL;
  glazing_treatment LOW_S;
  glazing_layers TWO;
  window_frame INSULATED;
  // ...
}

Implicit End Uses

By default, houses have end uses and appliances implicitly included. This feature is controlled by the implicit_enduses module variable. To disable all implicit definitions of end uses you must do the following:

module residential {
  implicit_enduses NONE;
}

Alternatively, you can include only some end uses:

module  residential {
  implicit_enduses LIGHTS|PLUGS|OCCUPANCY|WATERHEATER;
}

Implicit end uses are driven by the load shapes derived from the ELCAP project data collected by the Pacific Northwest National Laboratory for the Bonneville Power Administration during the late 1980's and early 1990's. These load shapes are defined in schedules that are integrated into the class definition of house.

Explicit End Uses

For certain end uses it is possible to substitute the implicit end use with an explicit model. The advantage of doing this lies within the added detail of an explicit model, which includes many of the thermal and logic features that are absent from the simple loadshape-based model.

For example, you can omit the WATERHEATER implicit end use and include the explicit waterheater model instead:

module residential {
  implicit_enduses LIGHTS|PLUGS|OCCUPANCY; // omits waterheater
}
object house {
  object waterheater {
  };
}

Electric Panels

The house object includes an end use property that is used to collect energy consumption information about the house and the various electrical devices in it. The end use object is named panel and it contains the following information, among other things

<table-caption identifier="Table" id=tbl:electric-panel-properties } Property | Type | Unit | Description -- | -- | -- | -- panel.energy | complex | kVAh | the total energy consumed since the last meter reading panel.power | complex | kVA | the total power consumption of the load panel.power_factor | double | | the power factor of the load panel.constant_power |complex | kVA | the constant power portion of the total load panel.constant_current |complex | kVA | the constant current portion of the total load panel.constant_admittance | complex | kVA | the constant admittance portion of the total load panel.breaker_amps | double | A | the rated breaker amperage

For example, the following will collect the power consumption for the whole house given a power factor of 0.98

clock {
  timezone EST+5EDT;
  starttime '2000-01-01 00:00:00';
  stoptime '2001-01-01 00:00:00';
}
module residential {
  implicit_enduses LIGHTS|PLUGS|REFRIGERATOR|CLOTHESWASHER|DRYER;
}
module tape;
object house {
  panel.power_factor 0.98;
  object recorder {
    property panel.power;
    file panel_power.csv;
  };
  object waterheater {
  };
}

which produces the following output:

2000-01-01 00:00:00 EST,+5.0488+0.178767j
2000-01-01 00:07:23 EST,+0.5488+0.178767j
2000-01-01 01:00:00 EST,+0.4704+0.153229j
2000-01-01 02:00:00 EST,+0.4256+0.138635j
2000-01-01 04:00:00 EST,+0.4144+0.134987j
2000-01-01 05:00:00 EST,+0.4256+0.138635j
2000-01-01 06:00:00 EST,+0.4816+0.156877j
2000-01-01 07:00:00 EST,+0.5712+0.186063j
2000-01-01 08:00:00 EST,+0.672+0.218898j
2000-01-01 09:00:00 EST,+0.7056+0.229843j
...

Climate

An important feature of GridLAB-D™ is its ability to include the effect of weather and climate on the performance of systems. To add climate data to a simulation, you must load the climate module and use it to define a climate object:

module climate;
object climate {
  tmyfile "CA-Los_angeles.tmy2";
}

When the "house.glm" simulation is run using this new weather data, the results reflect the colder changing outdoor temperatures:

2000-01-01 00:00:00 EST,+5.0488+0.178767j
2000-01-01 00:00:01 EST,+11.0972+0.178767j
2000-01-01 00:04:15 EST,+5.0488+0.178767j
2000-01-01 00:07:23 EST,+0.5488+0.178767j
2000-01-01 00:12:28 EST,+6.5972+0.178767j
2000-01-01 00:16:20 EST,+0.5488+0.178767j
2000-01-01 00:26:14 EST,+6.5972+0.178767j
2000-01-01 00:29:54 EST,+0.5488+0.178767j
2000-01-01 00:41:18 EST,+6.5972+0.178767j
2000-01-01 00:44:51 EST,+0.5488+0.178767j
2000-01-01 00:57:18 EST,+6.5972+0.178767j
2000-01-01 01:00:00 EST,+6.36436+0.153229j

Powerflow

To include the electrical system in your model, you need to begin by loading the powerflow module:

module powerflow;

Like the other modules, powerflow has a number of module-level global variables. The most common are:

module powerflow {
  solver_method FBS; 
  default_maximum_voltage_error 0.001; 
}

The solver_method allows the user to select the type of solver to use, specifically Newton-Raphson (NR) and Forward Backward Sweep (FBS). FBS is used for radial systems only, and as implemented, is slightly faster on most systems. NR is used for meshed systems and supports a number of additional features, such as reliability and feeder reconfiguration. NR also has a far more robust "error check" functionality, as it is much more susceptible to topological errors. The default_maximum_voltage_error determines convergence criteria for the voltage solution in per unit (p.u.).

A triplex_meter must be connected to a triplex_line, which are used in residential buildings. Conversely, meter objects (3-phase) are utilized for commercial buildings, which use 3-phase power and are connected to a (3-phase) line. For example, to connect a house to the power system, a triplex meter is used:

object triplex_meter {
  name Meter1;
  nominal_voltage 120V;
  phases AS;
}
object house {
  parent Meter1;
  // class=..
}

This provides a connection point between the residential and powerflow modules where the triplex meter provides a voltage to the house panel and the house provides a description of the current load to the triplex meter. So, every house needs a triplex meter to connect to the electrical system (although multiple houses can connect to a single triplex meter). Conceptually, the triplex meter can be thought of as the customer meter, whether AMI, AMR, or electro-mechanical.

Up to this point, the example we have described only represents the circuit as seen at a residential house panel, or two 120V circuits and one 240V circuit. Commonly, this is designed as a triplex line connected to a triplex_node at the secondary side of a center-tap (or split-phase) transformer. The triplex line setup looks like:

object triplex_line_conductor {
  name "1/0 AA triplex";
  resistance 0.97;
  geometric_mean_radius 0.0111;
}
object triplex_line_configuration {
  name my_line_config;
  conductor_1 "1/0 AA triplex";
  conductor_2 "1/0 AA triplex";
  conductor_N "1/0 AA triplex";
  insulation_thickness 0.08;
  diameter 0.368;
}
object triplex_node {
  name Triplex_Node1;
  nominal_voltage 120V;
  phases AS;
}
object triplex_line {
  from Triplex_Node1;
  to Meter1;
  phases AS;
  length 100 ft;
  configuration my_line_config;
}
object triplex_meter {
  name Meter1;
  nominal_voltage 120V;
  phases AS;
}
object house {
  parent Meter1;
  // class=..
}

Notice the use of configuration or library objects. These are used for all line, transformer, and regulator objects that belong to the powerflow module, and are very helpful in large files, as a single configuration can be used repeatedly.

This system is still not connected to a three-phase distribution system, as signified by the phases AS. The 'S' indicates that this is a split-phase system (120V/240V), while the 'A' indicates it will be connected to the A-phase of the three-phase system. To connect the house circuit to a 1-, 2-, or 3-phase trunk of a distribution system, a center-tap (or split-phase) transformer is needed. The center-tap transformer and its configuration are defined by:

object transformer_configuration {
  name single_phase_transformer;
  connect_type SINGLE_PHASE_CENTER_TAPPED;
  install_type PADMOUNT;
  primary_voltage 7200 V;
  secondary_voltage 120 V;
  power_rating 50.0;
  powerA_rating 50.0;
  resistance 0.011;
  reactance 0.018;
}
object node {
  name Node1;
  nominal_voltage 7200V;
  phases ABCN;
}
object transformer {
  name center_tap_transformer_A;
  phases AS;
  from Node1;
  to Triplex_Node1;
  configuration single_phase_transformer;
}  
object triplex_node {
  name Triplex_Node1;
  nominal_voltage 120V;
  phases AS;
}
// class=..

The ratio of the primary_voltage to secondary_voltage defines the turn ratio of the transformer. The power_rating defines the base power (in kVA) for extracting the per unit reactance and resistance values. The connect_type defines the winding configuration of the transformer. Notice that Node1 contains phases ABCN. This defines all of the phases connected at this node. A two-phase system without a neutral would be defined as AC. In the FBS method, the from and to nodes (as shown in the transformer) define the topology of the system, with the from node being closer to the source, as the system is required to be radial. In the NR method, the order of the nodes is less important because of the meshed system being utilized. However, because of this, a swing or slack bus must be defined. This is done by including an additional line:

object node {
  bustype SWING;
  // class=..
}

All other nodes are assumed to be PQ buses, as PV buses are not directly supported (an "effective" PV bus must be created by activating/designing appropriate controls in the generator at that node). The system can be built up from here, connecting a series of node and link objects until the SWING node is reached, typically at the primary or secondary side of the substation transformer.

This example shows the IEEE 4-node radial test feeder with the load replaced with the previously described split-phase circuit.

module powerflow {
  solver_method NR;
>

Electric Panel Properties

object overhead_line_conductor {
  name overhead_line_conductor100;
  geometric_mean_radius 0.0244;
  resistance 0.306;
}

object overhead_line_conductor {
  name overhead_line_conductor101;
  geometric_mean_radius 0.00814;
  resistance 0.592;
}

object line_spacing {
  name line_spacing200;
  distance_AB 2.5;
  distance_BC 4.5;
  distance_AC 7.0;
  distance_AN 5.656854;
  distance_BN 4.272002;
  distance_CN 5.0;
}

object line_configuration {
  name line_configuration300;
  conductor_A overhead_line_conductor100;
  conductor_B overhead_line_conductor100;
  conductor_C overhead_line_conductor100;
  conductor_N overhead_line_conductor101;
  spacing line_spacing200;
}

object transformer_configuration {
  name transformer_configuration400;
  connect_type 1;
  power_rating 6000;
  powerA_rating 2000;
  powerB_rating 2000;
  powerC_rating 2000;
  primary_voltage 12470;
  secondary_voltage 4160;
  resistance 0.01;
  reactance 0.06;
}

object node {
  name node1;
  bustype SWING;
  phases "ABCN";
  voltage_A +7199.558+0.000j;
  voltage_B -3599.779-6235.000j;
  voltage_C -3599.779+6235.000j;
  nominal_voltage 7200;
}

object overhead_line {
  phases "ABCN";
  from node1;
  to node2;
  length 2000;
  configuration line_configuration300;
}

object node {
  name node2;
  phases "ABCN";
  voltage_A +7199.558+0.000j;
  voltage_B -3599.779-6235.000j;
  voltage_C -3599.779+6235.000j;
  nominal_voltage 7200;
}

object transformer {
  name transformer23;
  phases "ABCN";
  from node2;
  to node3;
  configuration transformer_configuration400;
}

object node {
  name node3;
  phases "ABCN";
  voltage_A +2401.777+0.000j;
  voltage_B -1200.889-2080.000j;
  voltage_C -1200.889+2080.000j;
  nominal_voltage 2400;
}

object overhead_line:34 {
  phases "ABCN";
  from node3;
  to load4;
  length 2500;
  configuration line_configuration300;
}

object load {
  name load4;
  phases "ABCN";
  voltage_A +2401.777+0.000j;
  voltage_B -1200.889-2080.000j;
  voltage_C -1200.889+2080.000j;
  constant_power_A +1800000.000+871779.789j;
  constant_power_B +1800000.000+871779.789j;
  constant_power_C +1800000.000+871779.789j;
  nominal_voltage 2400;
}

More complex circuits can be designed with additional loads. The Taxonomy of Prototypical Feeders are good examples of standard distribution system models containing static load values. Replacing these static load values with more advanced house (and other) models creates a time-series, powerflow solution which evolves as a function of the interactions between all of the objects.

Taxonomy feeders are often used as the backbone upon which to build more complex, populated feeder models. A feeder generator API can be found in the TESP distribution at .../tesp_support/api/gld_feeder_generator.py. Using the API requires a TESP installation, instructions for which are found here. To read more about how to use "gld_feeder_generator.py", visit the TESP documentation.

Tape

The tape module implements objects that can be used to establish and change the boundary condition on a model, and observes the properties of individual objects or the aggregate properties of a group of objects. Player and shaper tapes are used for updating the model at specified times from a file. Recorder and collector tapes are used for collecting information from the model.

We've already seen a few examples using recorders, so let's compare that to the collector object. Important properties of a collector are its group, the property it records, and the file it saves to. A basic example of a collector might look something like this.

object collector {
  name transformerLosses;
  group class=transformer;
  property sum(power_losses.real),sum(power_losses.mag);
  file "transformer_losses.csv";
}

Collectors are different from recorders in that they aggregate multiple object properties into a single value. They do not use the parent property but instead use the group property to form a collection of objects over which the aggregate is taken.

Property

The group property specifies the grouping rule for creating a collection. Groups may be specified using any registered property of the object, such as class, size, parent, id, or rank. The property value is aggregated as a minimum, maximum, count, average, standard deviation, mean, variance (2nd moment), mean bias error (1st moment), or kurtosis (3rd moment). If the property is a complex number, the property must be specified in the form

property.part

where part is real, imag (for imaginary), mag for magnitude, ang for the angle in degrees, or arg for angle in radians.

For example, a collector over all water heater objects might aggregate the power property using

count(power),min(power),max(power),std(power)

which would print the number of water heaters, the minimum power used by any one water heater, the maximum power used, and the standard deviation of the power used by the set of water heaters.

Aggregating options are min, max, count, avg, std, mean, var, mbe, kur, sum, prod, skew, and gamma.

For example,

object collector {
  group "class=triplex_meter AND groupid=Residential"
  property max(measured_voltage_1);
  file max_houe_voltage.csv;
}

Putting it All Together

As an example, open up sample_model.glm with a text editor. At the top of this model file you'll see a number of module declarations such as:

module tape;
module generators;

module powerflow{
  solver_method FBS;
  default_maximum_voltage_error 1e-9;
  line_limits FALSE;
};

module climate;

module residential {
  implicit_enduses NONE;
  ANSI_voltage_check FALSE;
};

module powerflow {
    solver_method FBS;
    NR_iteration_limit 100;
};

Each of these module statements links in a portion of the code base that enables specific functionality in this particular GridLAB-D™ model.

Looking further down the model you'll see that most of the statement groups begin with object, such as:

object node {     
      name R1-12-47-1_node_613;     
      parent R1-12-47-1_meter_21;     
      phases ABCN;     
      voltage_A 7216.88+0.0j;     
      voltage_B -3608.44-6250j;     
      voltage_C -3608.44+6250j;     
      nominal_voltage 7216.88;     
} 
.
.
.
object overhead_line {     
      groupid Distribution_Line;
      name R1-12-47-1_ol_299;     
      phases ABCN;     
      from R1-12-47-1_node_4;     
      to R1-12-47-1_node_25;     
      length 487.200;     
      configuration line_configuration_22;     
} 
.
.
.
object house {
  name myHouse;
  parent tpm2_R1-12-47-1_tm_21;
  floor_area random.normal(1750,400);
  heating_setpoint 70;
  cooling_setpoint 78;
  air_temperature 79;
}

Each one of these objects is a specific instance of a particular class (node, overhead_line, house). As a part of each class are a set of algorithms and equations that define how all objects of this class should behave. For example, the code in the overhead_line class will be used to define how much of a voltage drop should occur as a given amount of current flows through the line.

There can (and often will be) multiple instances of a class in a given model or .glm though each one will likely be unique due to the specific values associated with each parameter in the object definitions. For example, look at two particular overhead_line objects in the model:

  object overhead_line {     
      groupid Distribution_Line;
      name R1-12-47-1_ol_298;     
      phases ABCN;     
      from R1-12-47-1_node_3;     
      to R1-12-47-1_node_21;     
      length 167.609;     
      configuration line_configuration_22;     
} 
.
.
.
object overhead_line {     
      groupid Distribution_Line;
      name R1-12-47-1_ol_290;     
      phases ABCN;     
      from R1-12-47-1_node_11;     
      to R1-12-47-1_node_12;     
      length 283.154;     
      configuration line_configuration_22;     
}

These are both overhead_line objects and though they use the same equations to define their operation in the simulation, you can see that each has different lengths (among other differences). Because of these differences, the equations of the overhead line class will produce a different voltage drop across each overhead line instance.