/sim/unitop/Stream.py

https://github.com/randfb/sim42
Python | 310 lines | 192 code | 53 blank | 65 comment | 54 complexity | 0a5587edc38d1ac197cec78900b00bd8 MD5 | raw file
  1. """Models streams
  2. Classes:
  3. Stream_Material -- Class for material stream. Inherits from UnitOperation
  4. Stream_Energy -- Class for energy stream. Inherits from UnitOperation
  5. """
  6. from sim.solver.Error import SimError
  7. from sim.solver.Variables import *
  8. from sim.solver import S42Glob
  9. from sim.solver.Ports import SIGNAL_TYPE_NONE
  10. from sim.solver.Messages import MessageHandler
  11. import UnitOperations
  12. VALID_UNIT_OPERATIONS = ['Stream_Material',
  13. 'Stream_Energy',
  14. 'Stream_Signal',
  15. 'ClonePort',
  16. 'SensorPort']
  17. class Stream_Material(UnitOperations.UnitOperation):
  18. """Class for material stream. Inherits from UnitOperation"""
  19. def __init__(self, initScript = None):
  20. """Init the stream"""
  21. super(Stream_Material, self).__init__(initScript)
  22. p = self.CreatePort(MAT|IN, IN_PORT)
  23. p.SetLocked(True)
  24. p = self.CreatePort(MAT|OUT, OUT_PORT)
  25. p.SetLocked(True)
  26. def AddObject(self, obj, name):
  27. """
  28. if object is clone port, create the appropriate kind of port
  29. other wise call parent method
  30. """
  31. if isinstance(obj, ClonePort):
  32. oldPort = self.GetPort(name)
  33. if oldPort:
  34. self.DeletePort(oldPort) # can't have duplicates
  35. if obj.incoming:
  36. self.CreatePort(MAT|IN, name)
  37. else:
  38. self.CreatePort(MAT|OUT, name)
  39. self.PushSolveOp(self)
  40. elif isinstance(obj, SensorPort):
  41. oldPort = self.GetPort(name)
  42. if oldPort:
  43. self.DeletePort(oldPort) # can't have duplicates
  44. port = self.CreatePort(SIG, name)
  45. port.SetSignalType(obj.varType)
  46. self.PushSolveOp(self)
  47. else:
  48. super(Stream_Material, self).AddObject(obj, name)
  49. def SensorShare(self, withPort):
  50. """
  51. Share any information from signal ports with material port withPort
  52. """
  53. sigPorts = self.GetPorts(SIG)
  54. for port in sigPorts:
  55. #Gets the type as a string with a name of the compound appended if necessary
  56. portTypeName = port.GetSignalType()
  57. #Get the compound name separately
  58. cmpName = port.GetCompoundName()
  59. if portTypeName != SIGNAL_TYPE_NONE and portTypeName != None:
  60. portValue = port.GetValue()
  61. if portValue != None:
  62. #Put the value into the material port
  63. if not cmpName:
  64. withPort.SetPropValue(portTypeName, portValue, CALCULATED_V)
  65. elif portTypeName[:len(CMPMOLEFRAC_VAR)] == CMPMOLEFRAC_VAR:
  66. withPort.SetPropValue(portTypeName, portValue, CALCULATED_V)
  67. else:
  68. #Any other variable per compound should be checked only for consistency
  69. #as those values can not be input
  70. withValue = withPort.GetPropValue(portTypeName)
  71. if withValue != None:
  72. port.SetValue(withValue, CALCULATED_V)
  73. else:
  74. #Put the value into the signal port
  75. withValue = withPort.GetPropValue(portTypeName)
  76. if withValue != None:
  77. port.SetValue(withValue, CALCULATED_V)
  78. def Solve(self):
  79. """Solve"""
  80. #if self.IsForgetting(): return
  81. inPort = self.GetPort(IN_PORT)
  82. outPort = self.GetPort(OUT_PORT)
  83. clonePorts = self.GetPorts(MAT|IN|OUT)
  84. idx = clonePorts.index(inPort)
  85. clonePorts.pop(idx)
  86. idx = clonePorts.index(outPort)
  87. clonePorts.pop(idx)
  88. hasClones = (len(clonePorts) > 0)
  89. #Start by flashing the inPort
  90. inPort.Flash()
  91. while 1:
  92. #Everything known in "signals" goes into the "out" port
  93. self.SensorShare(outPort)
  94. #Everything in "signals" and "out" goes into "in"
  95. #Everything in "in" goes into "out"
  96. inPort.ShareWith(outPort)
  97. if hasClones:
  98. # share with clones
  99. #Everything in "signals", "out" and "in" go into "clones"
  100. for port in clonePorts:
  101. inPort.ShareWith(port)
  102. # share between in and out again
  103. #Everything in "clones" that went into "in" now go into "out"
  104. inPort.ShareWith(outPort)
  105. for port in clonePorts:
  106. port.CalcFlows()
  107. inPort.CalcFlows()
  108. outPort.CalcFlows()
  109. #Everything new in "out" finally goes into the "signals"
  110. self.SensorShare(outPort)
  111. # only have to check one flash since everything was shared
  112. if not inPort.Flash(skipCalcFlows=1):
  113. break
  114. return 1
  115. def ValidateOk(self):
  116. if self.GetParameterValue(NULIQPH_PAR) <= 0: return 0
  117. return 1
  118. class ClonePort:
  119. """
  120. dummy class to allow AddObject to add clone ports to stream classes
  121. """
  122. def __init__(self, incoming=1):
  123. """
  124. incoming is true if input stream
  125. """
  126. self.incoming = incoming
  127. class SensorPort:
  128. """
  129. dummy object to allow Stream_Material.AddObject to add arbitrary signal ports
  130. """
  131. def __init__(self, varType):
  132. """
  133. varType is the type of signal
  134. """
  135. self.varType = varType
  136. class Stream_Energy(UnitOperations.UnitOperation):
  137. """Class for energy stream. Inherits from UnitOperation"""
  138. def __init__(self, initScript = None):
  139. """Init the stream"""
  140. super(Stream_Energy, self).__init__(initScript)
  141. p = self.CreatePort(ENE|IN, IN_PORT)
  142. p.SetLocked(True)
  143. p = self.CreatePort(ENE|OUT, OUT_PORT)
  144. p.SetLocked(True)
  145. def AddObject(self, obj, name):
  146. """
  147. if object is clone port, create the appropriate kind of port
  148. other wise call parent method
  149. """
  150. if isinstance(obj, ClonePort):
  151. oldPort = self.GetPort(name)
  152. if oldPort:
  153. self.DeletePort(oldPort) # can't have duplicates
  154. if obj.incoming:
  155. self.CreatePort(ENE|IN, name)
  156. else:
  157. self.CreatePort(ENE|OUT, name)
  158. self.PushSolveOp(self)
  159. elif isinstance(obj, SensorPort):
  160. oldPort = self.GetPort(name)
  161. if oldPort:
  162. self.DeletePort(oldPort) # can't have duplicates
  163. port = self.CreatePort(SIG, name)
  164. port.SetSignalType(ENERGY_VAR)
  165. self.PushSolveOp(self)
  166. else:
  167. super(Stream_Energy, self).AddObject(obj, name)
  168. def Solve(self):
  169. """Solve"""
  170. inPort = self.GetPort(IN_PORT)
  171. outPort = self.GetPort(OUT_PORT)
  172. ports = self.GetPorts(ENE|IN|OUT|SIG)
  173. for port in ports:
  174. inPort.ShareWith(port)
  175. if len(ports) > 2:
  176. # do again to avoid order dependance
  177. for port in ports:
  178. inPort.ShareWith(port)
  179. return 1
  180. class Stream_Signal(UnitOperations.UnitOperation):
  181. """Class for signal stream. Inherits from UnitOperation"""
  182. def __init__(self, initScript = None):
  183. """Init the stream"""
  184. super(Stream_Signal, self).__init__(initScript)
  185. p = self.CreatePort(SIG, IN_PORT)
  186. p.SetLocked(True)
  187. p = self.CreatePort(SIG, OUT_PORT)
  188. p.SetLocked(True)
  189. #self.SetParameterValue(SIGTYPE_PAR, GENERIC_VAR) # generic type by default
  190. self.SetParameterValue(SIGTYPE_PAR, None)
  191. def SetParameterValue(self, paramName, value):
  192. UnitOperations.UnitOperation.SetParameterValue(self, paramName, value)
  193. if paramName == SIGTYPE_PAR:
  194. for port in self.GetPorts():
  195. port.SetSignalType(value)
  196. def ValidateParameter(self, paramName, value):
  197. if not super(Stream_Signal, self).ValidateParameter(paramName, value):
  198. return 0
  199. if paramName == SIGTYPE_PAR:
  200. currName = self.parameters.get(SIGTYPE_PAR, None)
  201. if not currName: return 1
  202. currName = currName.split('_', 1)[0]
  203. validateName = value.split('_', 1)[0]
  204. equivalent = 1
  205. try:
  206. if PropTypes[currName].unitType != PropTypes[validateName].unitType:
  207. equivalent = S42Glob.unitSystem.IsEquivalentType(PropTypes[currName].unitType, PropTypes[validateName].unitType)
  208. except:
  209. #if it failed comparing, then assume they are equivalent
  210. pass
  211. if equivalent: return 1
  212. #The types are not equivalent. If any port is already connected, then
  213. #there will be a type conflict, hence, return false
  214. for port in self.GetPorts():
  215. conn = port.GetConnection()
  216. if conn != None:
  217. return 0
  218. return 1
  219. def DeleteObject(self, obj):
  220. if isinstance(obj, UnitOperations.OpParameter):
  221. if obj.GetName() in (SIGTYPE_PAR):
  222. self.InfoMessage('CantDeleteObject', (obj.GetPath(),), MessageHandler.errorMessage)
  223. return
  224. super(Stream_Signal, self).DeleteObject(obj)
  225. def AddObject(self, obj, name):
  226. """
  227. if object is clone port, create the appropriate kind of port
  228. other wise call parent method
  229. """
  230. if isinstance(obj, ClonePort):
  231. oldPort = self.GetPort(name)
  232. if oldPort:
  233. self.DeletePort(oldPort) # can't have duplicates
  234. port = self.CreatePort(SIG, name)
  235. type = self.GetParameterValue(SIGTYPE_PAR)
  236. if type != None:
  237. port.SetSignalType(type)
  238. self.PushSolveOp(self)
  239. else:
  240. super(Stream_Signal, self).AddObject(obj, name)
  241. def Solve(self):
  242. """Solve"""
  243. inPort = self.GetPort(IN_PORT)
  244. inPortType = inPort.GetSignalType()
  245. for i in range(2): # do twice to avoid order dependence
  246. for port in self.GetPorts(SIG):
  247. portType = port.GetSignalType()
  248. if inPortType != SIGNAL_TYPE_NONE:
  249. if portType == SIGNAL_TYPE_NONE:
  250. port.CreateProperty(inPortType)
  251. elif portType != SIGNAL_TYPE_NONE:
  252. inPort.CreateProperty(portType)
  253. inPortType = portType
  254. inPort.ShareWith(port)
  255. return 1