Coverage for backend/core/auxiliary/models/RecycleData.py: 96%

38 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-11-06 23:27 +0000

1from django.db import models 

2from flowsheetInternals.unitops.models.SimulationObject import SimulationObject 

3from .PropertyInfo import PropertyInfo 

4 

5from core.managers import AccessControlManager 

6class RecycleData(models.Model): 

7 """ 

8 Recycle data for a recycle block simulation object 

9 Stores which tear object is connected to the recycle block 

10 """ 

11 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="RecycleDatas") 

12 # parent recycle block 

13 simulationObject = models.OneToOneField(SimulationObject, on_delete=models.CASCADE, related_name="recycleData", null=True) 

14 # tear object, makes properties of this object enabled 

15 tearObject = models.OneToOneField(SimulationObject, on_delete=models.SET_NULL, related_name="recycleConnection", null=True) 

16 

17 created_at = models.DateTimeField(auto_now_add=True) 

18 objects = AccessControlManager() 

19 

20 

21 

22 

23 def update(self, tear_object: SimulationObject | None) -> None: 

24 """ 

25 Update the tear object's properties to be enabled 

26 """ 

27 prev_tear = self.tearObject 

28 self.tearObject = tear_object 

29 self.save() 

30 

31 # reevaluate enabled properties 

32 if prev_tear is not None: 

33 # cleanup internal controls 

34 for prop in prev_tear.properties.containedProperties.all(): 

35 for prop_value in prop.values.all(): 

36 if prop_value.is_control_set_point() and not prop_value.is_externally_controlled(): 36 ↛ 38line 36 didn't jump to line 38 because the condition on line 36 was never true

37 # delete this control 

38 prop_value.controlSetPoint.delete() 

39 

40 prev_tear.reevaluate_properties_enabled() 

41 if tear_object is not None and prev_tear != tear_object: 

42 tear_object.reevaluate_properties_enabled() 

43 

44 # delete old property connections 

45 self.propertyConnections.all().delete() 

46 # create new property connections for the new tear object 

47 recycle_properties = [] 

48 if tear_object is not None: 

49 # hardcoded for now 

50 # default to mole_frac_comp/molarFlow fixed 

51 state_vars = { 

52 "mole_frac_comp": True, 

53 "flow_mol": True, 

54 "temperature": False, 

55 "pressure": False 

56 } 

57 for prop in tear_object.properties.containedProperties.filter(key__in=state_vars): 

58 recycle_properties.append( 

59 RecycleProperty(recycleData=self, propertyInfo=prop, fixed=state_vars[prop.key], flowsheet=self.flowsheet) 

60 ) 

61 

62 RecycleProperty.objects.bulk_create(recycle_properties) 

63 

64 

65 def clear(self) -> None: 

66 """ 

67 Clear the tear object 

68 """ 

69 self.update(None) 

70 

71 

72class RecycleProperty(models.Model): 

73 """ 

74 Used to store "fix var and remove the equality constraint" 

75 at the the tear object. Also contributes towards access 

76 levels for frontend and idaes_factory (meaning, is this property editable?) 

77 """ 

78 flowsheet = models.ForeignKey("Flowsheet", on_delete=models.CASCADE, related_name="RecycleProperties") 

79 recycleData = models.ForeignKey(RecycleData, on_delete=models.CASCADE, related_name="propertyConnections", null=True) 

80 # this relation may need to become PropertyValue eventually 

81 propertyInfo = models.OneToOneField(PropertyInfo, on_delete=models.CASCADE, related_name="recycleConnection", null=True) 

82 fixed = models.BooleanField(default=False) # if true, fix var and remove the equality constraint across the tear 

83 

84 created_at = models.DateTimeField(auto_now_add=True) 

85 objects = AccessControlManager() 

86 

87