Summary
This experiment investigates solar panel tilt & orientation. Central composite design to maximize annual energy yield and minimize peak temperature by tuning tilt angle, azimuth, and row spacing.
The design varies 3 factors: tilt deg (deg), ranging from 10 to 50, azimuth deg (deg), ranging from 150 to 210, and row spacing m (m), ranging from 1.5 to 4.0. The goal is to optimize 2 responses: annual kwh (kWh/panel) (maximize) and peak temp c (C) (minimize). Fixed conditions held constant across all runs include latitude = 40N, panel watt = 400W.
A Central Composite Design (CCD) was selected to fit a full quadratic response surface model, including curvature and interaction effects. With 3 factors this produces 22 runs including center points and axial (star) points that extend beyond the factorial range.
Quadratic response surface models were fitted to capture potential curvature and factor interactions. The RSM contour plots below visualize how pairs of factors jointly affect each response.
Key Findings
For annual kwh, the most influential factors were row spacing m (41.5%), azimuth deg (34.6%), tilt deg (23.9%). The best observed value was 620.0 (at tilt deg = 30, azimuth deg = 180, row spacing m = 0.467823).
For peak temp c, the most influential factors were tilt deg (42.6%), azimuth deg (28.7%), row spacing m (28.7%). The best observed value was 57.0 (at tilt deg = 30, azimuth deg = 125.228, row spacing m = 2.75).
Recommended Next Steps
- Run confirmation experiments at the predicted optimal settings to validate the model.
- Consider whether any fixed factors should be varied in a future study.
Experimental Setup
Factors
| Factor | Low | High | Unit |
tilt_deg | 10 | 50 | deg |
azimuth_deg | 150 | 210 | deg |
row_spacing_m | 1.5 | 4.0 | m |
Fixed: latitude = 40N, panel_watt = 400W
Responses
| Response | Direction | Unit |
annual_kwh | ↑ maximize | kWh/panel |
peak_temp_c | ↓ minimize | C |
Configuration
{
"metadata": {
"name": "Solar Panel Tilt & Orientation",
"description": "Central composite design to maximize annual energy yield and minimize peak temperature by tuning tilt angle, azimuth, and row spacing"
},
"factors": [
{
"name": "tilt_deg",
"levels": [
"10",
"50"
],
"type": "continuous",
"unit": "deg"
},
{
"name": "azimuth_deg",
"levels": [
"150",
"210"
],
"type": "continuous",
"unit": "deg"
},
{
"name": "row_spacing_m",
"levels": [
"1.5",
"4.0"
],
"type": "continuous",
"unit": "m"
}
],
"fixed_factors": {
"latitude": "40N",
"panel_watt": "400W"
},
"responses": [
{
"name": "annual_kwh",
"optimize": "maximize",
"unit": "kWh/panel"
},
{
"name": "peak_temp_c",
"optimize": "minimize",
"unit": "C"
}
],
"settings": {
"operation": "central_composite",
"test_script": "use_cases/127_solar_panel_tilt/sim.sh"
}
}
Experimental Matrix
The Central Composite Design produces 22 runs. Each row is one experiment with specific factor settings.
| Run | tilt_deg | azimuth_deg | row_spacing_m |
| 1 | 30 | 180 | 2.75 |
| 2 | 50 | 150 | 4 |
| 3 | 10 | 210 | 1.5 |
| 4 | 30 | 234.772 | 2.75 |
| 5 | 30 | 180 | 2.75 |
| 6 | -6.51484 | 180 | 2.75 |
| 7 | 30 | 180 | 0.467823 |
| 8 | 30 | 180 | 2.75 |
| 9 | 50 | 210 | 1.5 |
| 10 | 66.5148 | 180 | 2.75 |
| 11 | 30 | 180 | 2.75 |
| 12 | 30 | 125.228 | 2.75 |
| 13 | 30 | 180 | 2.75 |
| 14 | 10 | 150 | 4 |
| 15 | 30 | 180 | 2.75 |
| 16 | 50 | 150 | 1.5 |
| 17 | 30 | 180 | 5.03218 |
| 18 | 50 | 210 | 4 |
| 19 | 30 | 180 | 2.75 |
| 20 | 10 | 150 | 1.5 |
| 21 | 10 | 210 | 4 |
| 22 | 30 | 180 | 2.75 |
Step-by-Step Workflow
1
Preview the design
$ doe info --config use_cases/127_solar_panel_tilt/config.json
2
Generate the runner script
$ doe generate --config use_cases/127_solar_panel_tilt/config.json \
--output use_cases/127_solar_panel_tilt/results/run.sh --seed 42
3
Execute the experiments
$ bash use_cases/127_solar_panel_tilt/results/run.sh
4
Analyze results
$ doe analyze --config use_cases/127_solar_panel_tilt/config.json
5
Get optimization recommendations
$ doe optimize --config use_cases/127_solar_panel_tilt/config.json
6
Multi-objective optimization
With 2 competing responses, use --multi to find the best compromise via Derringer–Suich desirability.
$ doe optimize --config use_cases/127_solar_panel_tilt/config.json --multi
7
Generate the HTML report
$ doe report --config use_cases/127_solar_panel_tilt/config.json \
--output use_cases/127_solar_panel_tilt/results/report.html
Features Exercised
| Feature | Value |
| Design type | central_composite |
| Factor types | continuous (all 3) |
| Arg style | double-dash |
| Responses | 2 (annual_kwh ↑, peak_temp_c ↓) |
| Total runs | 22 |
Analysis Results
Generated from actual experiment runs using the DOE Helper Tool.
Response: annual_kwh
Top factors: row_spacing_m (41.5%), azimuth_deg (34.6%), tilt_deg (23.9%).
ANOVA
| Source | DF | SS | MS | F | p-value |
| Source | DF | SS | MS | F | p-value |
| tilt_deg | 4 | 6985.2500 | 1746.3125 | 12.977 | 0.0009 |
| azimuth_deg | 4 | 6509.5833 | 1627.3958 | 12.093 | 0.0011 |
| row_spacing_m | 4 | 6449.2500 | 1612.3125 | 11.981 | 0.0012 |
| Lack | of | Fit | 2 | 6733.9167 | 3366.9583 |
| Pure | Error | 7 | 942.0000 | | |
| Error | 9 | 7675.9167 | 134.5714 | | |
| Total | 21 | 27620.0000 | 1315.2381 | | |
Pareto Chart
Main Effects Plot
Normal Probability Plot of Effects
Half-Normal Plot of Effects
Model Diagnostics
Response: peak_temp_c
Top factors: tilt_deg (42.6%), azimuth_deg (28.7%), row_spacing_m (28.7%).
ANOVA
| Source | DF | SS | MS | F | p-value |
| Source | DF | SS | MS | F | p-value |
| tilt_deg | 4 | 56.8182 | 14.2045 | 0.446 | 0.7730 |
| azimuth_deg | 4 | 95.1515 | 23.7879 | 0.747 | 0.5839 |
| row_spacing_m | 4 | 57.1515 | 14.2879 | 0.449 | 0.7713 |
| Lack | of | Fit | 2 | 145.8220 | 72.9110 |
| Pure | Error | 7 | 222.8750 | | |
| Error | 9 | 368.6970 | 31.8393 | | |
| Total | 21 | 577.8182 | 27.5152 | | |
Pareto Chart
Main Effects Plot
Normal Probability Plot of Effects
Half-Normal Plot of Effects
Model Diagnostics
Response Surface Plots
3D surfaces fitted with quadratic RSM. Red dots are observed data points.
annual kwh azimuth deg vs row spacing m
annual kwh tilt deg vs azimuth deg
annual kwh tilt deg vs row spacing m
peak temp c azimuth deg vs row spacing m
peak temp c tilt deg vs azimuth deg
peak temp c tilt deg vs row spacing m
Multi-Objective Optimization
When responses compete, Derringer–Suich desirability finds the best compromise.
Each response is scaled to a 0–1 desirability, then combined via a weighted geometric mean.
Overall Desirability
D = 0.8272
Per-Response Desirability
| Response | Weight | Desirability | Predicted | Dir |
annual_kwh |
1.5 |
|
587.00 0.7518 587.00 kWh/panel |
↑ |
peak_temp_c |
1.0 |
|
57.00 0.9545 57.00 C |
↓ |
Recommended Settings
| Factor | Value |
tilt_deg | 30 deg |
azimuth_deg | 180 deg |
row_spacing_m | 5.03218 m |
Source: from observed run #17
Trade-off Summary
Sacrifice = how much worse than single-objective best.
| Response | Predicted | Best Observed | Sacrifice |
peak_temp_c | 57.00 | 57.00 | +0.00 |
Top 3 Runs by Desirability
| Run | D | Factor Settings |
| #13 | 0.7265 | tilt_deg=66.5148, azimuth_deg=180, row_spacing_m=2.75 |
| #18 | 0.7123 | tilt_deg=30, azimuth_deg=180, row_spacing_m=2.75 |
Model Quality
| Response | R² | Type |
peak_temp_c | 0.1558 | linear |
Full Multi-Objective Output
============================================================
MULTI-OBJECTIVE OPTIMIZATION
Method: Derringer-Suich Desirability Function
============================================================
Overall desirability: D = 0.8272
Response Weight Desirability Predicted Direction
---------------------------------------------------------------------
annual_kwh 1.5 0.7518 587.00 kWh/panel ↑
peak_temp_c 1.0 0.9545 57.00 C ↓
Recommended settings:
tilt_deg = 30 deg
azimuth_deg = 180 deg
row_spacing_m = 5.03218 m
(from observed run #17)
Trade-off summary:
annual_kwh: 587.00 (best observed: 620.00, sacrifice: +33.00)
peak_temp_c: 57.00 (best observed: 57.00, sacrifice: +0.00)
Model quality:
annual_kwh: R² = 0.0953 (linear)
peak_temp_c: R² = 0.1558 (linear)
Top 3 observed runs by overall desirability:
1. Run #17 (D=0.8272): tilt_deg=30, azimuth_deg=180, row_spacing_m=5.03218
2. Run #13 (D=0.7265): tilt_deg=66.5148, azimuth_deg=180, row_spacing_m=2.75
3. Run #18 (D=0.7123): tilt_deg=30, azimuth_deg=180, row_spacing_m=2.75
Full Analysis Output
=== Main Effects: annual_kwh ===
Factor Effect Std Error % Contribution
--------------------------------------------------------------
row_spacing_m 85.0000 7.7320 41.5%
azimuth_deg 71.0000 7.7320 34.6%
tilt_deg 49.0000 7.7320 23.9%
=== ANOVA Table: annual_kwh ===
Source DF SS MS F p-value
-----------------------------------------------------------------------------
tilt_deg 4 6985.2500 1746.3125 12.977 0.0009
azimuth_deg 4 6509.5833 1627.3958 12.093 0.0011
row_spacing_m 4 6449.2500 1612.3125 11.981 0.0012
Lack of Fit 2 6733.9167 3366.9583 25.020 0.0006
Pure Error 7 942.0000 134.5714
Error 9 7675.9167 134.5714
Total 21 27620.0000 1315.2381
=== Summary Statistics: annual_kwh ===
tilt_deg:
Level N Mean Std Min Max
------------------------------------------------------------
-6.51484 1 525.0000 0.0000 525.0000 525.0000
10 4 535.2500 60.0187 472.0000 589.0000
30 12 574.0000 25.6905 510.0000 620.0000
50 4 553.0000 29.2575 511.0000 573.0000
66.5148 1 532.0000 0.0000 532.0000 532.0000
azimuth_deg:
Level N Mean Std Min Max
------------------------------------------------------------
125.228 1 581.0000 0.0000 581.0000 581.0000
150 4 547.2500 52.0537 472.0000 589.0000
180 12 571.1667 25.5551 525.0000 620.0000
210 4 541.0000 43.9621 496.0000 584.0000
234.772 1 510.0000 0.0000 510.0000 510.0000
row_spacing_m:
Level N Mean Std Min Max
------------------------------------------------------------
0.467823 1 569.0000 0.0000 569.0000 569.0000
1.5 4 553.2500 40.6151 496.0000 589.0000
2.75 12 563.0000 26.6833 510.0000 588.0000
4 4 535.0000 52.8835 472.0000 584.0000
5.03218 1 620.0000 0.0000 620.0000 620.0000
=== Main Effects: peak_temp_c ===
Factor Effect Std Error % Contribution
--------------------------------------------------------------
tilt_deg 10.0000 1.1183 42.6%
azimuth_deg 6.7500 1.1183 28.7%
row_spacing_m 6.7500 1.1183 28.7%
=== ANOVA Table: peak_temp_c ===
Source DF SS MS F p-value
-----------------------------------------------------------------------------
tilt_deg 4 56.8182 14.2045 0.446 0.7730
azimuth_deg 4 95.1515 23.7879 0.747 0.5839
row_spacing_m 4 57.1515 14.2879 0.449 0.7713
Lack of Fit 2 145.8220 72.9110 2.290 0.1717
Pure Error 7 222.8750 31.8393
Error 9 368.6970 31.8393
Total 21 577.8182 27.5152
=== Summary Statistics: peak_temp_c ===
tilt_deg:
Level N Mean Std Min Max
------------------------------------------------------------
-6.51484 1 71.0000 0.0000 71.0000 71.0000
10 4 65.0000 8.4853 57.0000 77.0000
30 12 66.2500 4.9198 57.0000 74.0000
50 4 66.7500 3.5940 64.0000 72.0000
66.5148 1 61.0000 0.0000 61.0000 61.0000
azimuth_deg:
Level N Mean Std Min Max
------------------------------------------------------------
125.228 1 66.0000 0.0000 66.0000 66.0000
150 4 69.2500 6.4485 63.0000 77.0000
180 12 66.0833 5.3336 57.0000 74.0000
210 4 62.5000 3.8730 57.0000 66.0000
234.772 1 68.0000 0.0000 68.0000 68.0000
row_spacing_m:
Level N Mean Std Min Max
------------------------------------------------------------
0.467823 1 71.0000 0.0000 71.0000 71.0000
1.5 4 67.5000 8.8129 57.0000 77.0000
2.75 12 65.5833 5.0535 57.0000 74.0000
4 4 64.2500 1.5000 63.0000 66.0000
5.03218 1 69.0000 0.0000 69.0000 69.0000
Optimization Recommendations
=== Optimization: annual_kwh ===
Direction: maximize
Best observed run: #2
tilt_deg = 30
azimuth_deg = 180
row_spacing_m = 0.467823
Value: 620.0
RSM Model (linear, R² = 0.3634, Adj R² = 0.2573):
Coefficients:
intercept +559.0000
tilt_deg -19.8848
azimuth_deg +5.3482
row_spacing_m -16.1368
RSM Model (quadratic, R² = 0.4990, Adj R² = 0.1233):
Coefficients:
intercept +552.9737
tilt_deg -19.8848
azimuth_deg +5.3482
row_spacing_m -16.1368
tilt_deg*azimuth_deg +14.0000
tilt_deg*row_spacing_m -12.7500
azimuth_deg*row_spacing_m -1.0000
tilt_deg^2 -0.2369
azimuth_deg^2 +3.5131
row_spacing_m^2 +5.7632
Curvature analysis:
row_spacing_m coef=+5.7632 convex (has a minimum)
azimuth_deg coef=+3.5131 convex (has a minimum)
tilt_deg coef=-0.2369 concave (has a maximum)
Notable interactions:
tilt_deg*azimuth_deg coef=+14.0000 (synergistic)
tilt_deg*row_spacing_m coef=-12.7500 (antagonistic)
azimuth_deg*row_spacing_m coef=-1.0000 (antagonistic)
Predicted optimum (from linear model, at observed points):
tilt_deg = 10
azimuth_deg = 210
row_spacing_m = 1.5
Predicted value: 600.3698
Surface optimum (via L-BFGS-B, linear model):
tilt_deg = 10
azimuth_deg = 210
row_spacing_m = 1.5
Predicted value: 600.3698
Model quality: Weak fit — consider adding center points or using a different design.
Factor importance:
1. row_spacing_m (effect: 85.5, contribution: 43.2%)
2. tilt_deg (effect: 61.5, contribution: 31.1%)
3. azimuth_deg (effect: 50.8, contribution: 25.7%)
=== Optimization: peak_temp_c ===
Direction: minimize
Best observed run: #17
tilt_deg = 30
azimuth_deg = 125.228
row_spacing_m = 2.75
Value: 57.0
RSM Model (linear, R² = 0.0187, Adj R² = -0.1449):
Coefficients:
intercept +66.0909
tilt_deg +0.6549
azimuth_deg +0.3822
row_spacing_m -0.4003
RSM Model (quadratic, R² = 0.4097, Adj R² = -0.0329):
Coefficients:
intercept +65.2356
tilt_deg +0.6550
azimuth_deg +0.3822
row_spacing_m -0.4003
tilt_deg*azimuth_deg +2.3750
tilt_deg*row_spacing_m +1.6250
azimuth_deg*row_spacing_m +2.1250
tilt_deg^2 +0.7776
azimuth_deg^2 -1.3224
row_spacing_m^2 +1.8276
Curvature analysis:
row_spacing_m coef=+1.8276 convex (has a minimum)
azimuth_deg coef=-1.3224 concave (has a maximum)
tilt_deg coef=+0.7776 convex (has a minimum)
Notable interactions:
tilt_deg*azimuth_deg coef=+2.3750 (synergistic)
azimuth_deg*row_spacing_m coef=+2.1250 (synergistic)
tilt_deg*row_spacing_m coef=+1.6250 (synergistic)
Predicted optimum (from quadratic model, at observed points):
tilt_deg = 50
azimuth_deg = 210
row_spacing_m = 4
Predicted value: 73.2804
Surface optimum (via L-BFGS-B, quadratic model):
tilt_deg = 10
azimuth_deg = 210
row_spacing_m = 2.71591
Predicted value: 62.0418
Model quality: Weak fit — consider adding center points or using a different design.
Factor importance:
1. azimuth_deg (effect: 10.5, contribution: 37.5%)
2. row_spacing_m (effect: 9.5, contribution: 33.9%)
3. tilt_deg (effect: 8.0, contribution: 28.6%)