Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gses/feature dcacratio #335

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
44e4402
include greenheart data files in greenheart path
jaredthomas68 Jun 12, 2024
c3f5b72
Merge remote-tracking branch 'myfork/greensteel-eco-sync' into greens…
Jun 12, 2024
c003b59
correct path name
jaredthomas68 Jun 12, 2024
2077f68
Merge remote-tracking branch 'myfork/greensteel-eco-sync' into greens…
Jun 12, 2024
9419710
fix logging error and get all opex breakdown values as floats
jaredthomas68 Jun 13, 2024
41b94f4
Merge remote-tracking branch 'myfork/greensteel-eco-sync' into greens…
Jun 13, 2024
3de59c2
add data tables init
jaredthomas68 Jun 13, 2024
adc6029
Merge remote-tracking branch 'myfork/greensteel-eco-sync' into greens…
Jun 13, 2024
11bf341
correct greenheart data path spec
jaredthomas68 Jun 13, 2024
a02bde7
Merge remote-tracking branch 'myfork/greensteel-eco-sync' into greens…
jaredthomas68 Jun 13, 2024
888b09a
adjust plant visualization
jaredthomas68 Jun 19, 2024
d77fdf0
include power and h2 metrics tracking openmdao
jaredthomas68 Jun 26, 2024
2adeaeb
add lcoh as constraint and add std_h2 as objective
jaredthomas68 Jun 26, 2024
c7a3a50
constraint on battery power and energy as battery discharge time
jaredthomas68 Jul 10, 2024
2da630f
update battery_discharge_time constraint
jaredthomas68 Jul 16, 2024
188ddc5
remove meta data entry for battert_dicharge_time
jaredthomas68 Jul 17, 2024
a178fee
add closing paren)
jaredthomas68 Jul 17, 2024
8c5ac25
set input defautls for battery
jaredthomas68 Jul 17, 2024
b898091
add dc_ac_ratio as an input to pvplant
jaredthomas68 Aug 7, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions greenheart/tools/eco/finance.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,9 +530,9 @@ def run_opex(

# solar opex
if "pv" in hopp_config["technologies"].keys():
solar_opex = hopp_results["hybrid_plant"].pv.om_fixed + np.sum(
solar_opex = (hopp_results["hybrid_plant"].pv.om_fixed + np.sum(
hopp_results["hybrid_plant"].pv.om_variable
)
))[0]
if solar_opex < 0.1:
raise (RuntimeWarning(f"Solar OPEX returned as {solar_opex}"))
else:
Expand Down Expand Up @@ -1646,7 +1646,6 @@ def run_profast_full_plant_model(
) # TODO check decay

# ------------------------------------ solve and post-process -----------------------------

sol = pf.solve_price()

df = pf.cash_flow_out
Expand Down
6 changes: 3 additions & 3 deletions greenheart/tools/eco/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -1263,7 +1263,7 @@ def add_turbines(ax, turbine_x, turbine_y, radius, color):
],
ylim=[
round((np.min([np.min(turbine_y), onshorey]) - 1000), ndigits=roundto),
round(np.max(turbine_y + 4000), ndigits=roundto),
round(1.25*np.max(turbine_y), ndigits=roundto),
],
)
# ax[ax_index_wind_plant].autoscale()
Expand Down Expand Up @@ -1407,8 +1407,8 @@ def save_energy_flows(
output.update({"battery discharge [kW]": [(int(p>0))*p*1E3 for p in battery_power_out_mw]}) # convert from MW to kW and extract only discharging
output.update({"battery charge [kW]": [-(int(p<0))*p*1E3 for p in battery_power_out_mw]}) # convert from MW to kW and extract only charging
output.update({"battery state of charge [%]": hybrid_plant.battery.outputs.dispatch_SOC})

output.update({"total renewable energy production hourly [kW]": [solver_results[0]]*simulation_length})
output.update({"total renewable energy production hourly [kW]": hybrid_plant.grid.generation_profile[0:simulation_length]})
output.update({"grid energy usage hourly [kW]": [solver_results[1]]*simulation_length})
output.update({"desal energy hourly [kW]": [solver_results[2]]*simulation_length})
output.update({"electrolyzer energy hourly [kW]": electrolyzer_physics_results["power_to_electrolyzer_kw"]})
Expand Down
14 changes: 14 additions & 0 deletions greenheart/tools/optimization/gc_PoseOptimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,20 @@ def set_constraints(self, opt_prob, hi: Optional[Union[None, HoppInterface]] = N
opt_prob.model.add_subsystem("con_pv_platform_area", subsys=om.ExecComp(['pv_platform_ratio=pv_area/platform_area']), promotes=["*"])
opt_prob.model.add_constraint("pv_platform_ratio", upper=upper)

if self.config.greenheart_config["opt_options"]["constraints"]["lcoh"]["flag"]:
upper = self.config.greenheart_config["opt_options"]["constraints"]["lcoh"]["upper"]
opt_prob.model.add_constraint("lcoh", upper=upper)

if "battery_discharge_time" in self.config.greenheart_config["opt_options"]["constraints"].keys():
if self.config.greenheart_config["opt_options"]["constraints"]["battery_discharge_time"]["flag"]:
lower = self.config.greenheart_config["opt_options"]["constraints"]["battery_discharge_time"]["lower"]
upper = self.config.greenheart_config["opt_options"]["constraints"]["battery_discharge_time"]["upper"]
opt_prob.model.add_subsystem("con_battery_discharge_time", subsys=om.ExecComp(['battery_discharge_time=battery_capacity_kwh/battery_capacity_kw']), promotes=["*"])
opt_prob.model.set_input_defaults('battery_capacity_kw', units="kW", val=0.0)
opt_prob.model.set_input_defaults('battery_capacity_kwh', units="kW*h", val=0.0)
opt_prob.model.add_constraint("battery_discharge_time", lower=lower, upper=upper)


# User constraints
user_constr = self.config.greenheart_config["opt_options"]["constraints"]["user"]
for k in range(len(user_constr)):
Expand Down
20 changes: 20 additions & 0 deletions greenheart/tools/optimization/openmdao.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ def setup(self):
# add outputs
self.add_output("lcoe", units="USD/(kW*h)", val=0.0, desc="levelized cost of energy")
self.add_output("lcoh", units="USD/kg", val=0.0, desc="levelized cost of hydrogen")

if self.options["config"].output_level == 8:
self.add_output("std_h2", units="kg", val=0.0, desc="standard deviation of hydrogen production")
self.add_output("std_p", units="kW", val=0.0, desc="standard deviation of power production")
self.add_output("mean_h2", units="kg", val=0.0, desc="mean hourly hydrogen production")
self.add_output("mean_p", units="kW", val=0.0, desc="mean hourly power production")

if "steel" in self.options["config"].greenheart_config.keys():
self.add_output("lcos", units="USD/t", val=0.0, desc="levelized cost of steel")
if "ammonia" in self.options["config"].greenheart_config.keys():
Expand Down Expand Up @@ -115,9 +122,22 @@ def compute(self, inputs, outputs):
pv_area = greenheart_output.hopp_results['hybrid_plant'].pv.footprint_area
platform_area = greenheart_output.platform_results["toparea_m2"]

h2_hourly = greenheart_output.electrolyzer_physics_results["H2_Results"]["Hydrogen Hourly Production [kg/hr]"]
mean_h2 = np.average(h2_hourly)
std_h2 = np.std(h2_hourly)
p_hourly = greenheart_output.hourly_energy_breakdown["total renewable energy production hourly [kW]"]
mean_p = np.average(p_hourly)
std_p = np.std(p_hourly)

outputs["lcoe"] = lcoe
outputs["lcoh"] = lcoh

if self.options["config"].output_level == 8:
outputs["std_h2"] = std_h2
outputs["mean_h2"] = mean_h2
outputs["std_p"] = std_p
outputs["mean_p"] = mean_p

if "steel" in self.options["config"].greenheart_config.keys():
outputs["lcos"] = steel_finance.sol.get("price")
if "ammonia" in self.options["config"].greenheart_config.keys():
Expand Down
4 changes: 2 additions & 2 deletions hopp/simulation/technologies/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ def simulate_grid_connection(
power_met = np.where(final_power_array > schedule, schedule, final_power_array)
self.capacity_factor_load = np.sum(power_met) / np.sum(schedule) * 100

logger.info('Percent of time firm power requirement is met: ', np.round(self.time_load_met,2))
logger.info('Percent total firm power requirement is satisfied: ', np.round(self.capacity_factor_load,2))
logger.info('Percent of time firm power requirement is met: %.2f', self.time_load_met)
logger.info('Percent total firm power requirement is satisfied: %.2f', self.capacity_factor_load)

ERS_keys = ['min_regulation_hours', 'min_regulation_power']
if dispatch_options is not None and dispatch_options.use_higher_hours:
Expand Down
5 changes: 5 additions & 0 deletions hopp/simulation/technologies/pv/pv_plant.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class PVConfig(BaseClass):
- an object representing a `CustomFinancialModel` or `Singleowner.Singleowner` instance

dc_degradation: Annual DC degradation for lifetime simulations [%/year]
dc_ac_ratio: DC to AC inverter loading ratio [ratio]
approx_nominal_efficiency: approx nominal efficiency depends on module type (standard crystalline silicon 19%, premium 21%, thin film 18%) [decimal]
module_unit_mass: Mass of the individual module unit (default to 11.092). [kg/m2]
"""
Expand All @@ -44,6 +45,7 @@ class PVConfig(BaseClass):
layout_model: Optional[Union[dict, PVLayout]] = field(default=None)
fin_model: Optional[Union[str, dict, FinancialModelType]] = field(default=None)
dc_degradation: Optional[List[float]] = field(default=None)
dc_ac_ratio: Optional[float] = field(default=None)
approx_nominal_efficiency: Optional[float] = field(default=0.19)
module_unit_mass: Optional[float] = field(default=11.092)

Expand Down Expand Up @@ -100,6 +102,9 @@ def __attrs_post_init__(self):
self.dc_degradation = self.config.dc_degradation
else:
self.dc_degradation = [0]

if self.config.dc_ac_ratio is not None:
self.dc_ac_ratio = self.config.dc_ac_ratio

if self.config.approx_nominal_efficiency is not None:
self.approx_nominal_efficiency = self.config.approx_nominal_efficiency
Expand Down
39 changes: 21 additions & 18 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,36 @@
VERSION = version_file.read().strip()

# Get package data
base_path = Path("hopp")
package_data_files = [
base_path / "hydrogen" / "h2_storage" / "pressure_vessel" / "compressed_gas_storage_model_20221021" / "Tankinator.xlsx",
*base_path.glob("hydrogen/h2_transport/data_tables/*.csv"),
*base_path.glob("tools/analysis/bos/BOSLookup.csv"),
*base_path.glob("simulation/technologies/layout/flicker_data/*shadow.txt"),
*base_path.glob("simulation/technologies/layout/flicker_data/*flicker.txt"),
*base_path.glob("simulation/technologies/csp/pySSC_daotk/libs/*"),
*base_path.glob("simulation/technologies/csp/pySSC_daotk/tower_data/*"),
*base_path.glob("simulation/technologies/csp/pySSC_daotk/trough_data/*"),
*base_path.glob("simulation/technologies/dispatch/cbc_solver/cbc-win64/*"),
*base_path.glob("simulation/resource_files/*"),
*base_path.glob("simulation/resource_files/*/*")
hopp_base_path = Path("hopp")
hopp_package_data_files = [
*hopp_base_path.glob("tools/analysis/bos/BOSLookup.csv"),
*hopp_base_path.glob("simulation/technologies/layout/flicker_data/*shadow.txt"),
*hopp_base_path.glob("simulation/technologies/layout/flicker_data/*flicker.txt"),
*hopp_base_path.glob("simulation/technologies/csp/pySSC_daotk/libs/*"),
*hopp_base_path.glob("simulation/technologies/csp/pySSC_daotk/tower_data/*"),
*hopp_base_path.glob("simulation/technologies/csp/pySSC_daotk/trough_data/*"),
*hopp_base_path.glob("simulation/technologies/dispatch/cbc_solver/cbc-win64/*"),
*hopp_base_path.glob("simulation/resource_files/*"),
*hopp_base_path.glob("simulation/resource_files/*/*")
]

greenheart_base_path = Path("greenheart")
greenheart_package_data_files = [
*greenheart_base_path.glob("simulation/technologies/hydrogen/h2_storage/pressure_vessel/compressed_gas_storage_model_20221021/Tankinator.xlsx"),
*greenheart_base_path.glob("simulation/technologies/hydrogen/h2_transport/data_tables/*.csv")
]

package_data = {
"hopp": [str(file.relative_to(base_path)) for file in package_data_files],
"greenheart": [],
"ProFAST": []
"hopp": [str(file.relative_to(hopp_base_path)) for file in hopp_package_data_files],
"greenheart": [str(file.relative_to(greenheart_base_path)) for file in greenheart_package_data_files]
}

setup(
name=NAME,
version=VERSION,
url=URL,
description=DESCRIPTION,
long_description=(base_path.parent / "RELEASE.md").read_text(),
long_description=(hopp_base_path.parent / "RELEASE.md").read_text(),
long_description_content_type='text/markdown',
license='BSD 3-Clause',
author=AUTHOR,
Expand All @@ -51,6 +54,6 @@
packages=find_packages(),
package_data=package_data,
include_package_data=True,
install_requires=(base_path.parent / "requirements.txt").read_text().splitlines(),
install_requires=(hopp_base_path.parent / "requirements.txt").read_text().splitlines(),
tests_require=['pytest', 'pytest-subtests', 'responses']
)
Loading