Coverage for backend/PinchAnalysis/models/OptionModels.py: 100%
86 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2025-11-06 23:27 +0000
1from django.db import models
2from core.auxiliary.enums import uiEnums
3from core.auxiliary.models.PropertyValue import PropertyValue
4from core.auxiliary.models.PropertySet import PropertySet
5from core.auxiliary.enums import pinchEnums
6from django.db.models.signals import post_save
7from django.dispatch import receiver
8from core.auxiliary.models.PropertyInfo import PropertyInfo
10from typing import Literal
11from common.config_types import *
12from flowsheetInternals.unitops.config.config_methods import *
14from core.managers import AccessControlManager
19# Main Options PropKey Enum
20class MainOptionsPropKeys(models.TextChoices):
21 TIT_BUTTON_SELECTED = "PROP_MOP_0"
22 TS_BUTTON_SELECTED = "PROP_MOP_1"
23 TURBINE_WORK_BUTTON = "PROP_MOP_2"
24 AREA_BUTTON = "PROP_MOP_3"
25 ENERGY_RETROFIT_BUTTON = "PROP_MOP_4"
26 EXERGY_BUTTON = "PROP_MOP_5"
27 PRINT_PTS = "PROP_MOP_6"
28 PLOT_GRAPHS = "PROP_MOP_7"
30# Graph Options PropKey Enum
31class GraphOptionsPropKeys(models.TextChoices):
32 CC = "PROP_GOP_0"
33 SCC = "PROP_GOP_1"
34 BCC = "PROP_GOP_2"
35 GCC = "PROP_GOP_3"
36 GCC_NP = "PROP_GOP_4"
37 GCCU = "PROP_GOP_5"
38 LGCC = "PROP_GOP_6"
39 TOTAL_SITE = "PROP_GOP_7"
40 ERC = "PROP_GOP_8"
41 NLC = "PROP_GOP_9"
42 EC = "PROP_GOP_10"
44class TurbineOptionsPropKeys(models.TextChoices):
45 TURBINEFORM_T_TURBINE_BOX = "PROP_TOP_0"
46 TURBINEFORM_P_TURBINE_BOX = "PROP_TOP_1"
47 TURBINEFORM_MIN_EFF = "PROP_TOP_2"
48 TURBINEFORM_ELECTRICITY_PRICE = "PROP_TOP_3"
49 TURBINEFORM_LOAD = "PROP_TOP_4"
50 TURBINEFORM_MECH_EFF = "PROP_TOP_5"
51 TURBINEFORM_COMBOBOX = "PROP_TOP_6"
52 TURBINEFORM_ABOVE_PINCH_CHECKBOX = "PROP_TOP_7"
53 TURBINEFORM_BELOW_PINCH_CHECKBOX = "PROP_TOP_8"
54 TURBINEFORM_CONDESATE_FLASH_CORRECTION = "PROP_TOP_9"
58OptionSets = Literal["MainOptions", "TurbineOptions"]
60OptionsType = Dict[OptionSets, PropertiesType]
62pinch_options: OptionsType = {
63 "MainOptions": PropertiesType.model_validate({
64 MainOptionsPropKeys.TIT_BUTTON_SELECTED: { "displayName": "Totally Integrated Site", "value": True, "unitType": "dimensionless", "type": "checkbox" },
65 MainOptionsPropKeys.TS_BUTTON_SELECTED: { "displayName": "Total Site Heat Integration", "value": True, "unitType": "dimensionless", "type": "checkbox" },
66 MainOptionsPropKeys.TURBINE_WORK_BUTTON: { "displayName": "Turbine Shaft Work", "value": False, "unitType": "dimensionless", "type": "checkbox" },
67 MainOptionsPropKeys.AREA_BUTTON: { "displayName": "Target Area and Cost", "value": False, "unitType": "dimensionless", "type": "checkbox" },
68 MainOptionsPropKeys.ENERGY_RETROFIT_BUTTON: { "displayName": "Energy Retrofit", "value": False, "unitType": "dimensionless", "type": "checkbox" },
69 MainOptionsPropKeys.EXERGY_BUTTON: { "displayName": "Thermal Exergy", "value": False, "unitType": "dimensionless", "type": "checkbox" },
70 MainOptionsPropKeys.PRINT_PTS: { "displayName": "Print Problem Tables", "value": False, "unitType": "dimensionless", "type": "checkbox" },
71 }),
72 "TurbineOptions": PropertiesType.model_validate({
73 TurbineOptionsPropKeys.TURBINEFORM_T_TURBINE_BOX: { "displayName": "Inlet Temperature", "value": 450, "unitType": "temperature", "type": "numeric" },
74 TurbineOptionsPropKeys.TURBINEFORM_P_TURBINE_BOX: { "displayName": "Inlet Pressure", "value": 90, "unitType": "pressure", "type": "numeric" },
75 TurbineOptionsPropKeys.TURBINEFORM_MIN_EFF: { "displayName": "Minimum (Fixed)", "value": 0.1, "unitType": "dimensionless", "type": "numeric" },
76 TurbineOptionsPropKeys.TURBINEFORM_ELECTRICITY_PRICE: { "displayName": "Electricity Price", "value": 100, "unitType": "dimensionless", "type": "numeric" },
77 TurbineOptionsPropKeys.TURBINEFORM_LOAD: { "displayName": "Part Load Fraction", "value": 1.0, "unitType": "dimensionless", "type": "numeric" },
78 TurbineOptionsPropKeys.TURBINEFORM_MECH_EFF: { "displayName": "Mechanical Efficiency", "value": 1.0, "unitType": "dimensionless", "type": "numeric" },
79 TurbineOptionsPropKeys.TURBINEFORM_COMBOBOX: { "displayName": "Turbine Model", "value": pinchEnums.TurbineModel.MEDINA_FLORES, "unitType": "dimensionless", "type": "dropdown" },
80 TurbineOptionsPropKeys.TURBINEFORM_ABOVE_PINCH_CHECKBOX: { "displayName": "Above Pinch", "value": True, "unitType": "dimensionless", "type": "checkbox" },
81 TurbineOptionsPropKeys.TURBINEFORM_BELOW_PINCH_CHECKBOX: { "displayName": "Below Pinch", "value": False, "unitType": "dimensionless", "type": "checkbox" },
82 TurbineOptionsPropKeys.TURBINEFORM_CONDESATE_FLASH_CORRECTION: { "displayName": "High Pressure Condensate", "value": False, "unitType": "dimensionless", "type": "checkbox" },
83 }),
84}
86propKeyMapping = {
87 MainOptionsPropKeys.EXERGY_BUTTON: GraphOptionsPropKeys.EC,
88 MainOptionsPropKeys.TIT_BUTTON_SELECTED: GraphOptionsPropKeys.TOTAL_SITE,
89 MainOptionsPropKeys.ENERGY_RETROFIT_BUTTON: GraphOptionsPropKeys.ERC
90}
92# Receiver for updating graph options on main options change
93# Seems pretty expensive
94# TODO: Get a better way of doing this
95# @receiver(post_save, sender=PropertyInfo)
96# def update_main_options(sender, instance, **kwargs):
97# # Check if this PropertyInfo is related to MainOptions or GraphOptions
98# if instance.propKey in [MainOptionsPropKeys.EXERGY_BUTTON, MainOptionsPropKeys.TIT_BUTTON_SELECTED, MainOptionsPropKeys.ENERGY_RETROFIT_BUTTON]:
99# main_options = MainOptions.objects.get(selections=instance.set)
100# value = instance.value
101# property = main_options.graph_options.properties.ContainedProperties.get(propKey=propKeyMapping[instance.propKey])
102# property.access = uiEnums.PropertyType.RW if value else uiEnums.PropertyType.RO
103# property.save()
104# if instance.propKey == MainOptionsPropKeys.PLOT_GRAPHS:
105# graph_options = MainOptions.objects.get(selections=instance.set).graph_options
106# graph_options.is_active = instance.value
107# graph_options.save()
108# if instance.propKey == MainOptionsPropKeys.TURBINE_WORK_BUTTON:
109# turbine_options = MainOptions.objects.get(selections=instance.set).turbine_options
110# turbine_options.is_active = instance.value
111# turbine_options.save()
115# Additional options for turbine shaft work
116class TurbineOptions(models.Model):
117 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="TurbineOptions")
118 properties = models.ForeignKey(PropertySet, on_delete=models.CASCADE, default=None, null=True)
119 is_active = models.BooleanField(default=True)
121 created_at = models.DateTimeField(auto_now_add=True)
122 objects = AccessControlManager()
125 @classmethod
126 def create(cls, flowsheet, **kwargs):
127 # Create property set and options object
128 property_set = create_property_set_options("TurbineOptions", flowsheet)
129 instance = cls.objects.create(properties=property_set, flowsheet=flowsheet)
130 instance.save()
131 return instance
133# Main options for the system
134class MainOptions(models.Model):
135 flowsheet = models.ForeignKey("core_auxiliary.Flowsheet", on_delete=models.CASCADE, related_name="MainOptions")
136 selections = models.ForeignKey(PropertySet, on_delete=models.CASCADE, default=None, null=True)
137 turbine_options = models.ForeignKey(TurbineOptions, on_delete=models.CASCADE, default=None, null=True)
138 project_owner = models.OneToOneField("PinchAnalysis.StreamDataProject", on_delete=models.CASCADE, related_name="Options", null=True)
140 created_at = models.DateTimeField(auto_now_add=True)
141 objects = AccessControlManager()
144 @classmethod
145 def create(cls, project_owner, flowsheet, **kwargs):
146 # Create property set and options object
147 property_set = create_property_set_options("MainOptions", flowsheet)
148 turbine_options = TurbineOptions.create(flowsheet)
149 # graph_options = GraphOptions.create(flowsheet)
150 instance = cls.objects.create(selections=property_set, turbine_options=turbine_options, project_owner=project_owner, flowsheet=flowsheet)
151 instance.save()
152 return instance
155def create_property_set_options(option_set: OptionSets, flowsheet):
156 property_set = PropertySet.objects.create(flowsheet=flowsheet)
157 properties_to_create = []
158 properties_values_to_create = []
160 for key, schema in pinch_options[option_set].items():
161 property_info_data = get_property_fields(key, schema, property_set)
162 property_info, property_values = PropertyInfo.create(**property_info_data, flowsheet=flowsheet)
163 properties_to_create.append(property_info)
164 properties_values_to_create.extend(property_values)
165 PropertyInfo.objects.bulk_create(properties_to_create)
166 PropertyValue.objects.bulk_create(properties_values_to_create)
168 return property_set