Skip to content

Commit

Permalink
Merge pull request #3490 from architecture-building-systems/3483-cea-…
Browse files Browse the repository at this point in the history
…results-reader-analysis

New Features: Result reader - summary & analysis
  • Loading branch information
ShiZhongming authored Nov 8, 2024
2 parents 49b3223 + fabad99 commit b15007e
Show file tree
Hide file tree
Showing 11 changed files with 1,325 additions and 11 deletions.
Binary file modified cea/databases/CH/components/CONVERSION.xlsx
Binary file not shown.
Binary file modified cea/databases/DE/components/CONVERSION.xlsx
Binary file not shown.
Binary file modified cea/databases/SG/components/CONVERSION.xlsx
Binary file not shown.
20 changes: 17 additions & 3 deletions cea/default.config
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ albedo.type = RealParameter
albedo.help = Albedo of the terrain.

roof-grid = 10
roof-grid.type = IntegerParameter
roof-grid.type = RealParameter
roof-grid.help = Grid resolution for the roof surfaces. Use 200 (maximum) if you want only one point per surface.
roof-grid.category = Level of Detail

walls-grid = 200
walls-grid.type = IntegerParameter
walls-grid.type = RealParameter
walls-grid.help = Grid resolution for wall surfaces. Use 200 (maximum) if you want only one point per surface.
walls-grid.category = Level of Detail

Expand Down Expand Up @@ -394,7 +394,7 @@ buildings.help = List of buildings considered for the photovoltaic (PV), photovo

type-pvpanel = PV1
type-pvpanel.type = ChoiceParameter
type-pvpanel.choices = PV1, PV2, PV3
type-pvpanel.choices = PV1, PV2, PV3, PV4, PV5, PV6, PV7, PV8, PV9, PV10
type-pvpanel.help = Type of PV panel.

type-scpanel = FP
Expand Down Expand Up @@ -656,6 +656,20 @@ optimization = false
optimization.type = BooleanParameter
optimization.help = True if executing CEA district-energy-supply-system-optimization. Change default parameters under the respective tabs (i.e. supply system part 1 - decentralized and supply system part 2 - centralized, beta version) and Save to Config.

result-summary = true
result-summary.type = BooleanParameter
result-summary.help = True if generating a summary of the CEA results simulated.

[result-reader-summary]
all-scenarios = false
all-scenarios.type = BooleanParameter
all-scenarios.help = True if reading through and summarising the results for all scenarios under this project. False if reading and summarising the results for the current scenario only.

[result-reader-analytics]
all-scenarios = false
all-scenarios.type = BooleanParameter
all-scenarios.help = True if reading through and analysing the results for all scenarios under this project. False if reading and analysing the results for the current scenario only.

[test]
type = unittest
type.type = ChoiceParameter
Expand Down
2 changes: 1 addition & 1 deletion cea/demand/demand_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def calc_buildings_less_100m2(building_properties):
repeat(loads_output, n),
repeat(massflows_output, n),
repeat(temperatures_output, n),
repeat(config, n),
repeat(config, n),
repeat(debug, n))

# WRITE TOTAL YEARLY VALUES
Expand Down
18 changes: 18 additions & 0 deletions cea/scripts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,24 @@ Utilities:
input-files:
- [get_zone_geometry]

- name: result-reader-summary
label: Get result summary (beta)
description: Collection of useful CEA results
interfaces: [cli, dashboard]
module: cea.utilities.result_reader_summary
parameters: ['general:scenario', result-reader-summary]
input-files:
- [get_zone_geometry]

- name: result-reader-analytics
label: Get advanced analytics (beta)
description: Collection of advanced useful energy analytics
interfaces: [cli, dashboard]
module: cea.utilities.result_reader_analytics
parameters: ['general:scenario', result-reader-analytics]
input-files:
- [get_zone_geometry]

- name: create-mixed-use-type
label: Create mixed-use type
description: Creates a new use-type by aggregating values from a list of different use-types
Expand Down
28 changes: 28 additions & 0 deletions cea/technologies/solar/photovoltaic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,34 @@
__email__ = "[email protected]"
__status__ = "Production"

def projected_lifetime_output(
production_values,
lifetime_years,
max_performance=100,
annual_factor=0.54,
min_performance=80,
):
"""
Model the projected lifetime output of a PV module using a linear derating system
Authors:
- Justin McCarty
Args:
production_values (np.array shape(n_time_steps,)): electricity produced during the first year
lifetime_years (int): the expected lifetime of the module
max_performance (int, optional): _description_. Defaults to 100.
annual_factor (float, optional): _description_. Defaults to 0.54.
min_performance (int, optional): _description_. Defaults to 80.
Returns:
np.array: array with shape (lifetime_years, n_time_steps)
"""
derate_factors = np.linspace(
max_performance, max_performance - (lifetime_years * annual_factor), num=lifetime_years
).reshape(-1, 1)
derate_factors = np.clip(derate_factors, min_performance, None) / 100
lifetime_production = production_values * derate_factors
return lifetime_production

def calc_PV(locator, config, latitude, longitude, weather_data, datetime_local, building_name):
"""
Expand Down
22 changes: 16 additions & 6 deletions cea/utilities/batch_process_workflow.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""
Batch processing CEA commands over all scenarios in a project.
This is a first exploration for the ETH MiBS IDP 2023.
This was originally explored and created for the ETH MiBS IDP 2023.
"""

# TODO: change the hard-coded path; this is subject to a structural separation of project-based CEA Features from scenario-based CEA Features

import os
import subprocess
import sys
Expand All @@ -19,6 +21,10 @@
__email__ = "[email protected]"
__status__ = "Production"

# adding CEA to the environment
# Fix for running in PyCharm for users using micromamba
my_env = os.environ.copy()
my_env['PATH'] = f"{os.path.dirname(sys.executable)}:{my_env['PATH']}"

def exec_cea_commands(config, cea_scenario):
"""
Expand Down Expand Up @@ -59,11 +65,6 @@ def exec_cea_commands(config, cea_scenario):

optimization = config.batch_process_workflow.optimization

# adding CEA to the environment
# Fix for running in PyCharm for users using micromamba
my_env = os.environ.copy()
my_env['PATH'] = f"{os.path.dirname(sys.executable)}:{my_env['PATH']}"

# execute selected CEA commands
if zone_csv_to_shp:
zone_csv_path = os.path.join(cea_scenario, 'inputs/building-geometry/zone.csv')
Expand Down Expand Up @@ -215,6 +216,15 @@ def main(config):
print(err_msg.decode())
raise e

# Read and summarise project results
project_result_summary = config.batch_process_workflow.result_summary
if project_result_summary and project_boolean:
subprocess.run(['cea', 'result-reader-summary', '--all-scenarios', 'true'], env=my_env, check=True, capture_output=True)
elif project_result_summary and not project_boolean:
subprocess.run(['cea', 'result-reader-summary', '--all-scenarios', 'false'], env=my_env, check=True, capture_output=True)



# Print the time used for the entire processing
time_elapsed = time.perf_counter() - t0
print('The entire batch processing sequence is now completed - time elapsed: %d.2 seconds' % time_elapsed)
Expand Down
42 changes: 41 additions & 1 deletion cea/utilities/date.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,50 @@ def get_date_range_hours_from_year(year):
:rtype: pandas.data_range
"""

date_range = pd.date_range(start=str(year), end=str(year + 1), freq='H', inclusive='left')
date_range = pd.date_range(start=str(year), end=str(year + 1), freq='h', inclusive='left')

# Check if leap year and remove extra day
if isleap(year):
date_range = date_range[~((date_range.month == 2) & (date_range.day == 29))]

return date_range


def generate_season_masks(df):
"""
Generates boolean masks for meteorological seasons based on a DataFrame's DatetimeIndex.
Meteorological Seasons:
- Spring: March 1 to May 31
- Summer: June 1 to August 31
- Autumn: September 1 to November 30
- Winter: December 1 to February 28/29
Parameters:
----------
df : pd.DataFrame or pd.Series
DataFrame or Series with a DatetimeIndex.
Returns:
-------
dict
A dictionary containing boolean masks for each season.
Keys: 'spring', 'summer', 'autumn', 'winter'
"""
# Ensure the input has a DatetimeIndex
if not isinstance(df.index, pd.DatetimeIndex):
raise ValueError("The input must have a Pandas DatetimeIndex.")

# Extract the month from the index
month = df.index.month

# Define masks for each season
# TODO: enter a function to define the masks based on latitude (northern vs southern hemisphere summers)
masks = {
'spring': (month >= 3) & (month <= 5), # march, april, may
'summer': (month >= 6) & (month <= 8), # june, july, august
'autumn': (month >= 9) & (month <= 11), # september, october, november
'winter': (month == 12) | (month <= 2) # december, january, february
}

return masks
Loading

0 comments on commit b15007e

Please sign in to comment.