-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New parallel option that is fully consistent with FlorisModel (#982)
* Initial work on a consistent parallel FLORIS model (#977) * Copy for easier comparison and development. * temp commit to save progress. * Starting to build out new ParallelFlorisModel (name not yet fixed). * Begin building tests. * Cleanup and formatting. * Now able to use run() in parallel. * Switch to hidden _get_turbine_powers. * Add backcompatibility with existing parallel model; print timings; add powers_only option. * Example comparing timing. * Formatting fixes. * Test for return_turbine_powers_only flag. * Backcompatibility in configuration. * Appears there is no saving in calling run() twice---all overhead occurs again. * Fix type hints; default for n_wind_condition_splits; remove mistakenly committed yaw optimization function. * Tests for WindData objects; remove related comment. * Tests control setpoints (and add bugfix). Also limit number of workers for testing. * Update UncertainFlorisModel to work with new Parallel framework (#983) * Update uncertain floris model to accept par floris * Raise an error in old parallel floris model blocking passing in uncertain floris model * Add an example of parallelized uncertain floris * Expand parallel processing interface options (#985) * Update example to profile more fully. * Handling for pathos parallel processing package; comparison example to multiprocessing. * Add test for pathos interface. * Add concurrent handling. * minor doc updates. * add pathos requirement * Clean up of new ParFlorisModel class (#986) * Update example to profile more fully. * Handling for pathos parallel processing package; comparison example to multiprocessing. * Add test for pathos interface. * Add concurrent handling. * minor doc updates. * add pathos requirement * Change name to ParFlorisModel throughout. * Add deprecation warning for ParallelFlorisModel. * Add import; isort. * Update example to use ParFlorisModel. * Update tests; formatting. * Fix uncertain-parallel example; add uncertain-parallel test. * Update example docstring. * Remove temporary examples from repository. * Add examples and documentation for ParFlorisModel (#990) * Add short docstring * Minor comment change. * Add approx model to docs * A couple of rewordings and update to initial paragraph. --------- Co-authored-by: paulf81 <[email protected]>
- Loading branch information
Showing
17 changed files
with
1,334 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
"""Example 9: Parallel Models | ||
This example demonstrates how to use the ParFlorisModel class to parallelize the | ||
calculation of the FLORIS model. ParFlorisModel inherits from the FlorisModel | ||
and so can be used in the same way with a consistent interface. ParFlorisModel | ||
replaces the ParallelFlorisModel, which will be deprecated in a future release. | ||
""" | ||
|
||
import numpy as np | ||
|
||
from floris import ( | ||
FlorisModel, | ||
ParFlorisModel, | ||
TimeSeries, | ||
UncertainFlorisModel, | ||
) | ||
|
||
|
||
# When using parallel optimization it is important the "root" script include this | ||
# if __name__ == "__main__": block to avoid problems | ||
if __name__ == "__main__": | ||
# Instantiate the FlorisModel | ||
fmodel = FlorisModel("inputs/gch.yaml") | ||
|
||
# The ParFlorisModel can be instantiated either from a FlorisModel or from | ||
# the input file. | ||
pfmodel_1 = ParFlorisModel("inputs/gch.yaml") # Via input file | ||
pfmodel_2 = ParFlorisModel(fmodel) # Via FlorisModel | ||
|
||
# The ParFlorisModel has additional inputs which define the parallelization | ||
# but don't affect the output. | ||
pfmodel_3 = ParFlorisModel( | ||
fmodel, | ||
interface="multiprocessing", # Default | ||
max_workers=2, # Defaults to num_cpu | ||
n_wind_condition_splits=2, # Defaults to max_workers | ||
) | ||
|
||
# Define a simple inflow | ||
time_series = TimeSeries( | ||
wind_speeds=np.arange(1, 25, 0.5), wind_directions=270.0, turbulence_intensities=0.06 | ||
) | ||
|
||
# Demonstrate that interface and results are the same | ||
fmodel.set(wind_data=time_series) | ||
pfmodel_1.set(wind_data=time_series) | ||
pfmodel_2.set(wind_data=time_series) | ||
pfmodel_3.set(wind_data=time_series) | ||
|
||
fmodel.run() | ||
pfmodel_1.run() | ||
pfmodel_2.run() | ||
pfmodel_3.run() | ||
|
||
# Compare the results | ||
powers_fmodel = fmodel.get_turbine_powers() | ||
powers_pfmodel_1 = pfmodel_1.get_turbine_powers() | ||
powers_pfmodel_2 = pfmodel_2.get_turbine_powers() | ||
powers_pfmodel_3 = pfmodel_3.get_turbine_powers() | ||
|
||
print( | ||
f"Testing if outputs of fmodel and pfmodel_1 are " | ||
f"close: {np.allclose(powers_fmodel, powers_pfmodel_1)}" | ||
) | ||
print( | ||
f"Testing if outputs of fmodel and pfmodel_2 are " | ||
f"close: {np.allclose(powers_fmodel, powers_pfmodel_2)}" | ||
) | ||
print( | ||
f"Testing if outputs of fmodel and pfmodel_3 are " | ||
f"close: {np.allclose(powers_fmodel, powers_pfmodel_3)}" | ||
) | ||
|
||
# Because ParFlorisModel is a subclass of FlorisModel, it can also be used as | ||
# an input to the UncertainFlorisModel class. This allows for parallelization of | ||
# the uncertainty calculations. | ||
ufmodel = UncertainFlorisModel(fmodel) | ||
pufmodel = UncertainFlorisModel(pfmodel_1) | ||
|
||
# Demonstrate matched results | ||
ufmodel.set(wind_data=time_series) | ||
pufmodel.set(wind_data=time_series) | ||
|
||
ufmodel.run() | ||
pufmodel.run() | ||
|
||
powers_ufmodel = ufmodel.get_turbine_powers() | ||
powers_pufmodel = pufmodel.get_turbine_powers() | ||
|
||
print("--------------------") | ||
print( | ||
f"Testing if outputs of ufmodel and pufmodel are " | ||
f"close: {np.allclose(powers_ufmodel, powers_pufmodel)}" | ||
) |
2 changes: 1 addition & 1 deletion
2
...s/009_compare_farm_power_with_neighbor.py → ...s/010_compare_farm_power_with_neighbor.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
85 changes: 85 additions & 0 deletions
85
examples/examples_uncertain/003_uncertain_model_with_parallelization.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
"""Example: Uncertain Model With Parallelization | ||
This example demonstrates how to combined the parallelized model with the uncertain model | ||
""" | ||
|
||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
|
||
from floris import ( | ||
FlorisModel, | ||
TimeSeries, | ||
UncertainFlorisModel, | ||
) | ||
from floris.par_floris_model import ParFlorisModel | ||
|
||
|
||
# Following the refactoring of ParFlorisModel, the UncertainFlorisModel can be | ||
# parallelized by passing the ParFlorisModel as the model to be run. This example | ||
# demonstrates the usage and shows that the result obtained from the UncertainFlorisModel | ||
# with and without parallelization is the same. The results are compared to the nominal | ||
# results. | ||
|
||
# Instantiate a FlorisModel and ParallelFlorisModel using the GCH model | ||
fmodel = FlorisModel("../inputs/gch.yaml") | ||
pfmodel = ParFlorisModel("../inputs/gch.yaml") | ||
|
||
# Use the above model to declare a serial and parallel UncertainFlorisModel | ||
ufmodel = UncertainFlorisModel(fmodel) | ||
pufmodel = UncertainFlorisModel(pfmodel) | ||
|
||
|
||
# Define an inflow where wind direction is swept while | ||
# wind speed and turbulence intensity are held constant | ||
wind_directions = np.arange(240.0, 300.0, 1.0) | ||
time_series = TimeSeries( | ||
wind_directions=wind_directions, | ||
wind_speeds=8.0, | ||
turbulence_intensities=0.06, | ||
) | ||
|
||
# Define a two turbine farm and apply the inflow | ||
D = 126.0 | ||
layout_x = np.array([0, D * 6]) | ||
layout_y = [0, 0] | ||
|
||
# Apply to fmodel, ufmodel, and pufmodel | ||
fmodel.set( | ||
layout_x=layout_x, | ||
layout_y=layout_y, | ||
wind_data=time_series, | ||
) | ||
|
||
ufmodel.set( | ||
layout_x=layout_x, | ||
layout_y=layout_y, | ||
wind_data=time_series, | ||
) | ||
|
||
pufmodel.set( | ||
layout_x=layout_x, | ||
layout_y=layout_y, | ||
wind_data=time_series, | ||
) | ||
|
||
# Run the models | ||
fmodel.run() | ||
ufmodel.run() | ||
pufmodel.run() | ||
|
||
# Collect the farm power results from each model | ||
farm_powers_nom = fmodel.get_farm_power() / 1e3 | ||
farm_powers_unc = ufmodel.get_farm_power() / 1e3 | ||
farm_powers_punc = pufmodel.get_farm_power() / 1e3 | ||
|
||
# Compare the results | ||
fig, ax = plt.subplots() | ||
ax.plot(wind_directions, farm_powers_nom.flatten(), 'k-', label="Nominal power") | ||
ax.plot(wind_directions, farm_powers_unc.flatten(), 'bs-', label="Uncertain power") | ||
ax.plot(wind_directions, farm_powers_punc.flatten(), 'r.--', label="Parallel uncertain power") | ||
ax.grid(True) | ||
ax.legend() | ||
ax.set_xlabel("Wind Direction (deg)") | ||
ax.set_ylabel("Power (kW)") | ||
|
||
plt.show() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.