Coverage for backend/django/core/auxiliary/models/Scenario.py: 100%
83 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-06-23 21:51 +0000
1from django.core.validators import MaxValueValidator, MinValueValidator
2from django.db import models
3from .PropertyInfo import PropertyInfo
4from .PropertyValue import PropertyValue
5from flowsheetInternals.unitops.models.SimulationObject import SimulationObject
7from core.managers import AccessControlManager
9class ScenarioTabTypeEnum(models.TextChoices):
11 SteadyState = "steady state"
12 MultiSteadyState = "mss"
13 Dynamic = "dynamic"
15class ScenarioInputModeEnum(models.TextChoices):
16 Csv = "csv"
17 ParameterSweep = "parameter_sweep"
19class ParameterSweepMethodEnum(models.TextChoices):
20 Grid = "grid"
21 MonteCarlo = "monte_carlo"
22 Hammersley = "hammersley"
23 HaltonZaremba = "halton_zaremba", "Halton"
25class SolverOptionEnum(models.TextChoices):
26 Ipopt= "ipopt"
27 Ipopt_v2 = "ipopt_v2"
28 Ipopt_WaterTAP = "ipopt-watertap"
29 Bomin = "bonmin"
30 Petsc = "petsc"
33# Bound user-configurable solve timeouts to a range that is useful in practice:
34# short enough to stop obviously stuck solves quickly, but long enough to allow
35# legitimate large solves to finish without leaving them unbounded.
36SOLVE_TIMEOUT_MIN_SECONDS = 5
37SOLVE_TIMEOUT_MAX_SECONDS = 60 * 60
38SOLVE_TIMEOUT_DEFAULT_SECONDS = 300
42class Scenario(models.Model):
43 """
44 Stores all relevant information about an optimization
45 """
46 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="Optimizations")
47 # owner of the optimization
48 simulationObject = models.ForeignKey(SimulationObject, on_delete=models.CASCADE, related_name="optimizations", null=True)
49 displayName = models.CharField(max_length=64, blank=True, default="Scenario")
50 enable_optimization = models.BooleanField(default=False)
51 enable_dynamics = models.BooleanField(default=False)
52 state_name = models.CharField(max_length=64, blank=True, choices=ScenarioTabTypeEnum.choices, default=ScenarioTabTypeEnum.SteadyState)
53 mss_input_mode = models.CharField(
54 max_length=32,
55 choices=ScenarioInputModeEnum.choices,
56 default=ScenarioInputModeEnum.Csv,
57 )
58 num_time_steps = models.IntegerField(default=1)
59 simulation_length = models.FloatField(default=1.0)
60 simulation_length_units = models.CharField(max_length=32, blank=True)
61 Uploaded_fileName = models.CharField(max_length=64, blank=True, default="No file Chosen")
62 enable_rating = models.BooleanField(default=False)
63 solver_option = models.CharField(max_length=64, blank=True, choices=SolverOptionEnum.choices, default=SolverOptionEnum.Ipopt)
64 solve_timeout_seconds = models.PositiveIntegerField(
65 default=SOLVE_TIMEOUT_DEFAULT_SECONDS,
66 validators=[
67 MinValueValidator(SOLVE_TIMEOUT_MIN_SECONDS),
68 MaxValueValidator(SOLVE_TIMEOUT_MAX_SECONDS),
69 ],
70 )
71 is_LiveData = models.BooleanField(default=False)
72 disable_initialization = models.BooleanField(default=False)
73 skip_initialization_for_units_with_initial_values = models.BooleanField(default=False)
74 send_solve_complete_email = models.BooleanField(default=False)
75 degreesOfFreedom : models.QuerySet["OptimizationDegreesOfFreedom"]
77 # expression to minimize or maximize
78 objective = models.ForeignKey(PropertyInfo, on_delete=models.SET_NULL, null=True)
79 # boolean to find minimum or maximum or the objective
80 minimize = models.BooleanField(default=True)
82 created_at = models.DateTimeField(auto_now_add=True)
84 objects = AccessControlManager()
90class OptimizationDegreesOfFreedom(models.Model):
91 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="OptimizationDegreesOfFreedoms")
92 scenario = models.ForeignKey(Scenario, on_delete=models.CASCADE, related_name="degreesOfFreedom", null=True)
93 propertyValue: PropertyValue = models.ForeignKey(PropertyValue, on_delete=models.CASCADE, null=True)
94 upper_bound = models.FloatField(null=True, blank=True)
95 lower_bound = models.FloatField(null=True, blank=True)
96 created_at = models.DateTimeField(auto_now_add=True)
97 objects = AccessControlManager()
100class ParameterSweepDefinition(models.Model):
101 """Editable sampling definition used to generate MSS scenario input rows."""
103 flowsheet = models.ForeignKey(
104 "Flowsheet",
105 on_delete=models.CASCADE,
106 related_name="parameterSweepDefinitions",
107 )
108 scenario = models.OneToOneField(
109 Scenario,
110 on_delete=models.CASCADE,
111 related_name="parameterSweepDefinition",
112 )
113 method = models.CharField(
114 max_length=32,
115 choices=ParameterSweepMethodEnum.choices,
116 default=ParameterSweepMethodEnum.Grid,
117 )
118 sample_count = models.PositiveIntegerField(null=True, blank=True)
119 monte_carlo_seed = models.PositiveIntegerField(null=True, blank=True)
120 created_at = models.DateTimeField(auto_now_add=True)
121 updated_at = models.DateTimeField(auto_now=True)
123 objects = AccessControlManager()
126class ParameterSweepParameter(models.Model):
127 """One ordered target parameter within a generated MSS sweep definition."""
129 flowsheet = models.ForeignKey(
130 "Flowsheet",
131 on_delete=models.CASCADE,
132 related_name="parameterSweepParameters",
133 )
134 definition = models.ForeignKey(
135 ParameterSweepDefinition,
136 on_delete=models.CASCADE,
137 related_name="parameters",
138 )
139 property_value = models.ForeignKey(
140 PropertyValue,
141 on_delete=models.CASCADE,
142 related_name="parameterSweepParameters",
143 )
144 order = models.PositiveIntegerField()
145 lower_bound = models.DecimalField(max_digits=24, decimal_places=12)
146 upper_bound = models.DecimalField(max_digits=24, decimal_places=12)
147 step = models.DecimalField(max_digits=24, decimal_places=12, null=True, blank=True)
148 unit = models.CharField(max_length=32, blank=True)
149 target_label = models.CharField(max_length=255, blank=True)
150 created_at = models.DateTimeField(auto_now_add=True)
152 objects = AccessControlManager()
154 class Meta:
155 ordering = ["order", "id"]
156 constraints = [
157 models.UniqueConstraint(
158 fields=["definition", "property_value"],
159 name="unique_parameter_sweep_target",
160 ),
161 models.UniqueConstraint(
162 fields=["definition", "order"],
163 name="unique_parameter_sweep_order",
164 ),
165 ]