@@ -1485,6 +1485,7 @@ def __init__(self, File=None, dir=None, loader='file', fString=None, autoload=Tr
14851485 self .LoadFromFile (File , dir )
14861486 # stuff that needs to be done before initmodel
14871487 self .__settings__ ['mode_substitute_assignment_rules' ] = False
1488+ self .__settings__ ['cvode_track_assignment_rules' ] = True
14881489 self .__settings__ ['display_compartment_warnings' ] = False
14891490 self ._TIME_ = 0.0 # this will be the built-in time
14901491 self .piecewise_functions = []
@@ -1931,6 +1932,7 @@ def InitialiseRules(self):
19311932 # defmod
19321933 self .__HAS_FORCED_FUNCS__ = False
19331934 self .__HAS_RATE_RULES__ = False
1935+ self ._CVODE_extra_output = []
19341936 rate_rules = {}
19351937 assignment_rules = {}
19361938 for ar in self .__rules__ :
@@ -1951,7 +1953,6 @@ def InitialiseRules(self):
19511953 code_string = ''
19521954 all_names = []
19531955 for ar in assignment_rules :
1954- name = assignment_rules [ar ]['name' ]
19551956 InfixParser .setNameStr ('self.' , '' )
19561957 InfixParser .parse (assignment_rules [ar ]['formula' ])
19571958 assignment_rules [ar ]['symbols' ] = InfixParser .names
@@ -1980,12 +1981,13 @@ def InitialiseRules(self):
19801981 keep += dep
19811982 rules = indep
19821983 for ar in indep + keep :
1984+ if self .__settings__ ['cvode_track_assignment_rules' ]:
1985+ self ._CVODE_extra_output .append (assignment_rules [ar ]['name' ])
19831986 evalCode = 'self.{} = {}\n ' .format (
1984- assignment_rules [ar ]['name' ], assignment_rules [ar ]['code_string' ],
1987+ assignment_rules [ar ]['name' ], assignment_rules [ar ]['code_string' ]
19851988 )
19861989 self ._NewRuleXCode .update ({assignment_rules [ar ]['name' ]: evalCode })
19871990 code_string += evalCode
1988-
19891991 print ('\n Assignment rule(s) detected.' )
19901992 self ._Function_forced = code_string
19911993 elif (
@@ -3037,8 +3039,7 @@ def InitialiseModel(self):
30373039 self .sim_time = numpy .arange (
30383040 self .sim_start , self .sim_end + sim_steps , sim_steps
30393041 )
3040- self .CVODE_extra_output = []
3041- self .CVODE_xdata = None
3042+ self ._CVODE_xdata = None
30423043 self .__SIMPLOT_OUT__ = []
30433044
30443045 # elasticity options
@@ -3781,9 +3782,9 @@ def CVODE_continue(self, tvec):
37813782 self .data_sim .setRates (rates , self .__reactions__ )
37823783 if self .__HAS_RATE_RULES__ :
37833784 self .data_sim .setRules (rrules , self .__rate_rules__ )
3784- if len (self .CVODE_extra_output ) > 0 :
3785- self .data_sim .setXData (self .CVODE_xdata , lbls = self .CVODE_extra_output )
3786- self .CVODE_xdata = None
3785+ if len (self ._CVODE_extra_output ) > 0 :
3786+ self .data_sim .setXData (self ._CVODE_xdata , lbls = self ._CVODE_extra_output )
3787+ self ._CVODE_xdata = None
37873788 if not simOK :
37883789 print ('Simulation failure' )
37893790 del sim_res
@@ -3831,32 +3832,27 @@ def ffull(t, s):
38313832 if self .__HAS_RATE_RULES__ :
38323833 initial = numpy .concatenate ([initial , rrules ])
38333834
3834- # # CVODE extra output
3835- # CVODE_XOUT = False
3836- # if len(self.CVODE_extra_output) > 0:
3837- # out = []
3838- # for d in self.CVODE_extra_output:
3839- # if (
3840- # hasattr(self, d)
3841- # and d
3842- # not in self.__species__ + self.__reactions__ + self.__rate_rules__
3843- # ):
3844- # out.append(d)
3845- # else:
3846- # print(
3847- # '\nWarning: CVODE is ignoring extra data ({}), it either doesn\'t exist or it\'s a species or rate.\n'.format(
3848- # d
3849- # )
3850- # )
3851- # if len(out) > 0:
3852- # self.CVODE_extra_output = out
3853- # CVODE_XOUT = True
3854- # del out
3855- #
3856- # if CVODE_XOUT:
3857- # self.CVODE_xdata = numpy.zeros(
3858- # (len(self.sim_time), len(self.CVODE_extra_output))
3859- # )
3835+ # CVODE extra output
3836+ self ._CVODE_XOUT = False
3837+ if len (self ._CVODE_extra_output ) > 0 :
3838+ out = []
3839+ for d in self ._CVODE_extra_output :
3840+ if (
3841+ hasattr (self , d )
3842+ and d
3843+ not in self .__species__ + self .__reactions__ + self .__rate_rules__
3844+ ):
3845+ out .append (d )
3846+ else :
3847+ print (
3848+ '\n Warning: CVODE is ignoring extra data ({}), it either doesn\' t exist or it\' s a species or rate.\n ' .format (
3849+ d
3850+ )
3851+ )
3852+ if len (out ) > 0 :
3853+ self ._CVODE_extra_output = out
3854+ self ._CVODE_XOUT = True
3855+ del out
38603856
38613857 problem = EventsProblem (self , rhs = rhs , y0 = initial )
38623858 # for direct access to the problem class
@@ -3909,11 +3905,6 @@ def ffull(t, s):
39093905 sim_res [x ] = self ._SpeciesAmountToConc (sim_res [x ])
39103906 if self .__HAS_RATE_RULES__ :
39113907 sim_res = numpy .concatenate ([sim_res , rrules ], axis = 1 )
3912- # if CVODE_XOUT:
3913- # self.CVODE_xdata[st, :] = self._EvalExtraData(
3914- # self.CVODE_extra_output
3915- # )
3916-
39173908
39183909 else :
39193910 # calculate rates from all species
@@ -4723,13 +4714,34 @@ def Simulate(self, userinit=0):
47234714 self .data_sim .setRates (rates , self .__reactions__ )
47244715 if self .__HAS_RATE_RULES__ :
47254716 self .data_sim .setRules (rrules , self .__rate_rules__ )
4726- if len (self .CVODE_extra_output ) > 0 :
4727- self .data_sim .setXData (self .CVODE_xdata , lbls = self .CVODE_extra_output )
4728- self .CVODE_xdata = None
4717+ if self ._CVODE_XOUT :
4718+ self ._CVODE_xdata = numpy .zeros ((len (self .sim_time ), len (self ._CVODE_extra_output )))
4719+ # get assignment rules
4720+ r = self .__rules__
4721+ ars = {name : r [name ] for name in r if r [name ]['type' ] == 'assignment' }
4722+ # loop through extra output and evaluate from simulation data
4723+ for i in range (len (self ._CVODE_extra_output )):
4724+ name = self ._CVODE_extra_output [i ]
4725+ self ._update_assignment_rule_code (ars [name ])
4726+ self ._CVODE_xdata [:, i ] = eval (ars [name ]['data_sim_string' ])
4727+ self .data_sim .setXData (self ._CVODE_xdata , lbls = self ._CVODE_extra_output )
4728+ self ._CVODE_xdata = None
47294729 if not simOK :
47304730 print ('Simulation failure' )
47314731 del sim_res
47324732
4733+ def _update_assignment_rule_code (self , rule ):
4734+ replacements = []
4735+ rule ['data_sim_string' ] = rule ['code_string' ]
4736+ for s in rule ['symbols' ]:
4737+ if s in self .__reactions__ or s in self .__rate_rules__ :
4738+ replacements .append ((s , 'data_sim.getSimData("' + s + '")[:,1]' ))
4739+ elif s in self .__species__ :
4740+ replacements .append (('(self.' + s + ')' ,
4741+ '(self.data_sim.getSimData("' + s + '")[:,1])' ))
4742+ for old , new in replacements :
4743+ rule ['data_sim_string' ] = rule ['data_sim_string' ].replace (old , new )
4744+
47334745 @property
47344746 def sim (self ):
47354747 if self ._sim is None and self .data_sim is not None :
0 commit comments