Skip to content

Commit

Permalink
Adding solar controller and replacing AMR-Wind standin with FLORIS st…
Browse files Browse the repository at this point in the history
…andin in example 07 (#104)

* created dummy example for amr wind dummy + solar

* final commit before creating feature branch

* standalone solar pysam example

* working standalone example of solar pysam model

* removed time as explicit input in step

* working example of solar pysam and hercules (but pysam has a bug)

* changing hardcoded stoptime of 100 s to 1000 s to demo solar module

* cleaning before pull request review of misha's changes

* working solar pysam example with test amr wind

* adding updated results in jupyter notebook

* trying to run after git pull of develop

* solar model runs successfully, but there is a time issue

* correcting irradiance field and removing unnecessary comments

* removing unnecessary files

* removing test amr wind and solar example, saving for separate PR

* adding environment yaml file needed for pysam

* updating setup and docs to include pysam and restrict python version

* adding missing csv weather file

* Minor changes for running the code

* Minor cleanup in example.

* remove environment.yml

* adding solar module unit tests

* adding relative path for pytest functionality

* correcting ruff formatting and except

* more ruff formatting

* adding skeleton files for solar pv

* adding solar pysam description

* removing documentation changes, saving for a separate PR

* removing documentation changes, saving for a separate PR

* removing documentation changes, saving for a separate PR

* adding comments to the tests

* fix comments for PV

* adding documentation, moving lat long to input file, correcting irradiance output

* doc updates, code clean up

* docs updates

* minor cleanup

* ruff formatting and minor cleanup

* saving files before switching branches

* adding default inputs - not working yet

* calc max power for controls feedback optimization

* cleaning up code

* more code cleanup

* refactored to remove nested for loop, but no speed up

* fixing github vis

* starting setpoints feature, not working yet

* working initial pv plant controller

* first attempt at feeding in setpoints via external_data_file

* replacing amr wind standin with floris standin due to error in amrwind

* trying to run without external_data_file but getting zeros and floris is hanging

* hercules is hanging

* working version of floris and solar example

* working but messy version of solar controller

* adding the external data file

* cleaning up emulator.py

* cleaning up emulator.py

* working floris stand in and pv plant controller

* cleanup

* Ruff compatibility.

* cleaning up files

* fixing errors in tests

* fixing standalone example

* ruff changes

* removing amr_wind standin run script

* adding external_data_file solar_power_reference.csv

* clarifing controller input in README and fixing dc_power_mw error in test_read_output.ipynb

* Handling for when power_setpoints not available.

* Remove & on second call so that script terminates as expected.

* Updating units for results plots

* Make ruff compliant

* Make ruff compliant 2

---------

Co-authored-by: Genevieve Starke <Genevieve.Starke@nrel.gov>
Co-authored-by: misi9170 <michael.sinner@nrel.gov>
  • Loading branch information
3 people authored Apr 16, 2024
1 parent a128bd4 commit 6f9f4e3
Show file tree
Hide file tree
Showing 20 changed files with 41,950 additions and 619 deletions.
2 changes: 1 addition & 1 deletion docs/solar_pv.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `SolarPySAM` module uses [PySAM](https://nrel-pysam.readthedocs.io/en/main/o
2. A JSON file that specifies the PV plant system design (e.g. 100MW_1axis_pvsamv1.json).
The system location (latitude, longitude, and elevation) is specified in the input `yaml` file.

The example folder `07_amr_wind_standin_and_solar_pysam` specifies:
The example folder `07_floris_standin_and_solar_pysam` specifies:
- weather conditions on May 10, 2018 (from [this PySAM example](https://github.com/NREL/pysam/blob/main/Examples/NonAnnualSimulation.ipynb))
- latitude, longitude, and elevation of Golden, CO
- system design information for a 100 MW single-axis PV tracking system generated using the SAM GUI
Expand Down
17 changes: 0 additions & 17 deletions example_case_folders/07_amr_wind_standin_and_solar_pysam/README.md

This file was deleted.

This file was deleted.

This file was deleted.

30 changes: 30 additions & 0 deletions example_case_folders/07_floris_standin_and_solar_pysam/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Example 07: FLORIS Standin and Solar PySAM

## Description

This example demonstrates how to use the FLORIS Standin and a solar model using pysam.

## Running

To run the example, execute the following command in the terminal:

```bash
bash batch_script.sh
```


To run `hercules` using the PV plant controller, which provides power setpoints and adjusts the PV power output accordingly, ensure the following line is uncommented in `batch_script.sh`:

```
python3 hercules_runscript.py hercules_controller_input_000.yaml >> outputs/loghercules.log 2>&1 &
```

To run `hercules` without the PV plant controller, ensure the folling line is uncommented `batch_script.sh`:

```
python3 hercules_runscript.py hercules_input_000.yaml >> outputs/loghercules.log 2>&1 &
```

## Notes

Make sure hercules conda or venv is activated before running the example.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
# SIMULATION STOP #
#.......................................#
time.stop_time = 500.0 # Max (simulated) time to evolve
time.stop_time = 100.0 # Max (simulated) time to evolve
time.max_step = -1 # Max number of time steps

#¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨#
Expand Down Expand Up @@ -149,33 +149,17 @@ samplingLine.z_line.end = 5.0 5.0 1275.0
Actuator.type = UniformCtDisk
Actuator.UniformCtDisk.rotor_diameter = 126.0
Actuator.UniformCtDisk.hub_height = 90.0
Actuator.UniformCtDisk.thrust_coeff = 0.0 0.7 1.2
Actuator.UniformCtDisk.wind_speed = 0.0 10.0 12.0
Actuator.UniformCtDisk.thrust_coeff = 0.0 0.0 1.132034888 0.999470963 0.917697381 0.860849503 0.815371198 0.811614904 0.807939328 0.80443352 0.800993851 0.79768116 0.794529244 0.791495834 0.788560434 0.787217182 0.787127977 0.785839257 0.783812219 0.783568108 0.783328285 0.781194418 0.777292539 0.773464375 0.769690236 0.766001924 0.762348072 0.758760824 0.755242872 0.751792927 0.748434131 0.745113997 0.717806682 0.672204789 0.63831272 0.610176496 0.585456847 0.563222111 0.542912273 0.399312061 0.310517829 0.248633226 0.203543725 0.169616419 0.143478955 0.122938861 0.106515296 0.093026095 0.081648606 0.072197368 0.064388275 0.057782745 0.0 0.0
Actuator.UniformCtDisk.wind_speed = 0.0 2.9 3.0 4.0 5.0 6.0 7.0 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8.0 9.0 10.0 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 11.0 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 20.0 21.0 22.0 23.0 24.0 25.0 25.1 50.0
Actuator.UniformCtDisk.epsilon = 10.0
Actuator.UniformCtDisk.density = 1.225
Actuator.UniformCtDisk.diameters_to_sample = 1.0
Actuator.UniformCtDisk.num_points_r = 20
Actuator.UniformCtDisk.num_points_t = 5


Actuator.labels = T00 T01
# T02 T03 T04 T05 T06 T07
Actuator.JoukowskyDisk.thrust_coeff = 8.1672e-01 7.9044e-01 7.8393e-01 7.8624e-01 7.8824e-01 7.8942e-01 7.8902e-01 7.8740e-01 7.8503e-01 7.8237e-01 7.7955e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.7583e-01 7.6922e-01 7.4270e-01 5.5949e-01 4.6163e-01 3.8786e-01 3.2901e-01 2.8093e-01 2.4114e-01 2.0795e-01 1.8010e-01 1.5663e-01 1.3679e-01 1.1995e-01 1.0562e-01 9.3384e-02 8.2908e-02 7.3910e-02 6.6159e-02 5.9463e-02 5.3662e-02 4.8622e-02 4.4230e-02
Actuator.JoukowskyDisk.wind_speed = 3.0000e+00 3.5495e+00 4.0679e+00 4.5539e+00 5.0064e+00 5.4244e+00 5.8069e+00 6.1530e+00 6.4619e+00 6.7330e+00 6.9655e+00 7.1589e+00 7.3128e+00 7.4269e+00 7.5009e+00 7.5345e+00 7.5412e+00 7.5883e+00 7.6757e+00 7.8031e+00 7.9702e+00 8.1767e+00 8.4221e+00 8.7059e+00 9.0273e+00 9.3856e+00 9.7800e+00 1.0210e+01 1.0659e+01 1.0673e+01 1.1170e+01 1.1699e+01 1.2259e+01 1.2848e+01 1.3465e+01 1.4109e+01 1.4778e+01 1.5471e+01 1.6185e+01 1.6921e+01 1.7674e+01 1.8445e+01 1.9231e+01 2.0030e+01 2.0841e+01 2.1661e+01 2.2489e+01 2.3323e+01 2.4160e+01 2.5000e+01
Actuator.JoukowskyDisk.rpm = 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0000e+00 5.0861e+00 5.1954e+00 5.2765e+00 5.3290e+00 5.3529e+00 5.3577e+00 5.3912e+00 5.4532e+00 5.5437e+00 5.6625e+00 5.8092e+00 5.9836e+00 6.1851e+00 6.4135e+00 6.6681e+00 6.9483e+00 7.2535e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00 7.4992e+00
Actuator.JoukowskyDisk.rotor_diameter = 240.0
Actuator.JoukowskyDisk.hub_height = 150.0
Actuator.JoukowskyDisk.output_frequency = 100
Actuator.JoukowskyDisk.diameters_to_sample = 1.0
Actuator.JoukowskyDisk.num_points_r = 40
Actuator.JoukowskyDisk.num_points_t = 5
Actuator.JoukowskyDisk.num_blades = 3
Actuator.JoukowskyDisk.use_tip_correction = true
Actuator.JoukowskyDisk.use_root_correction = true
Actuator.JoukowskyDisk.epsilon = 5.0
Actuator.JoukowskyDisk.vortex_core_size = 24.0

Actuator.UniformCtDisk.yaw = 240.0

Actuator.labels = T00 T01

Actuator.T00.base_position = 2000.0 2000.0 0.0
Actuator.T01.base_position = 2500.0 2500.0 0.0
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ mkdir -p outputs
helics_broker -t zmq -f 2 --loglevel="debug" --local_port=$HELICS_PORT &
# For debugging add --consoleloglevel=trace

# Start the amr_standin
echo "Starting amr stand-in"
python3 hercules_runscript_amr_standin.py amr_input.inp >> outputs/logstandin.log 2>&1 &

# Start the controller center and pass in input file
echo "Starting hercules"
python3 hercules_runscript.py hercules_input_000.yaml >> outputs/loghercules.log 2>&1
# python3 hercules_runscript.py hercules_input_000.yaml >> outputs/loghercules.log 2>&1 &
python3 hercules_runscript.py hercules_controller_input_000.yaml >> outputs/loghercules.log 2>&1 &

# Start the floris standin
echo "Starting floris"
python3 floris_runscript.py amr_input.inp >> outputs/logfloris.log 2>&1

# If everything is successful
echo "Finished running hercules"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import sys

from hercules.floris_standin import launch_floris

# Check that one command line argument was given
if len(sys.argv) != 2:
raise Exception("Usage: python floris_runscript.py <amr_input_file>")

# # Get the first command line argument
# This is the name of the file to read
amr_input_file = sys.argv[1]
print(f"Running FLORIS standin with input file: {amr_input_file}")


launch_floris(amr_input_file)
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Input YAML for emy_python

# Name
name: example_000

###
# Describe this emulator setup
description: Floris and Solar PV

dt: 0.5

hercules_comms:

amr_wind:

wind_farm_0:
type: amr_wind_local #options are amr_wind or amr_wind_local
amr_wind_input_file: amr_input.inp

helics:

config:
name: hercules # What is the purpose of this name
use_dash_frontend: False
KAFKA: False
KAFKA_topics: EMUV1py
helics:
# deltat: 1 # This will be assigned in software
subscription_topics: [status]
publication_topics: [control]
endpoints: []
helicsport: 32000
publication_interval: 1
endpoint_interval: 1
starttime: 0
stoptime: 100 # must be at least 2*dt smaller than last timestep in weather file
Agent: ControlCenter

py_sims:

solar_farm_0: # The name of py_sim object 1

py_sim_type: SolarPySAM
weather_file_name: NonAnnualSimulation-sample_data-interpolated-daytime.csv
system_info_file_name: 100MW_1axis_pvsamv1.json
lat: 39.7442
lon: -105.1778
elev: 1829

# capacity: 100 # MW

initial_conditions:

power: 25 # MW
dni: 1000

controller:

external_data_file: solar_power_reference.csv




Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ name: example_000

###
# Describe this emulator setup
description: AMR Wind (Dummy) and Solar PV
description: Floris and Solar PV

dt: 0.5

Expand Down Expand Up @@ -33,7 +33,7 @@ hercules_comms:
publication_interval: 1
endpoint_interval: 1
starttime: 0
stoptime: 500
stoptime: 100
Agent: ControlCenter

py_sims:
Expand Down
Loading

0 comments on commit 6f9f4e3

Please sign in to comment.