def compute(self, trajname, ics=None): assert self.funcspec.targetlang == 'python', \ ('Wrong target language for functional specification. ' 'Python needed for this class') assert isinstance(self.funcspec, RHSfuncSpec), ('Map system ' 'requires RHSfuncSpec type to proceed') self.diagnostics.clearWarnings() self.diagnostics.clearErrors() if ics is not None: self.set(ics=ics) xnames = self._var_ixmap # ensures correct order # wrap up each dictionary initial value as a singleton list alltData = [self.indepvariable.depdomain[0]] allxDataDict = dict(zip(xnames, map(listid, sortedDictValues(self.initialconditions, self.funcspec.vars)))) rhsfn = getattr(self,self.funcspec.spec[1]) # Check i.c.'s are well defined (finite) self.checkInitialConditions() self.setEventICs(self.initialconditions, self.globalt0) ic = sortedDictValues(self.initialconditions, self.funcspec.vars) plist = sortedDictValues(self.pars) extralist = copy(plist) ilist = [] if self.inputs: # inputVarList is a list of Variables listend = self.numpars + len(self.inputs) inputVarList = sortedDictValues(self.inputs) try: for f in inputVarList: f.diagnostics.clearWarnings() ilist.append(f(alltData[0], self.checklevel)) except AssertionError: print('External input call has t out of range: t = %f' % \ self.indepvariable.depdomain[0]) print('Maybe checklevel is 3 and initial time is not', \ 'completely inside valid time interval') raise except ValueError: print('External input call has value out of range: t = %f' % \ self.indepvariable.depdomain[0]) for f in inputVarList: if f.diagnostics.hasWarnings(): print('External input %s out of range:' % f.name) print(' t = %r, %s, %r' % (repr(f.diagnostics.warnings[-1][0]), f.name, repr(f.diagnostics.warnings[-1][1]))) raise else: listend = self.numpars inputVarList = [] extralist.extend(ilist) precevents = self.eventstruct.query(['precise']) if precevents != []: raise PyDSTool_ValueError('precise events are not valid for map systems') eventslist = self.eventstruct.query(['highlevel', 'active', 'notvarlinked']) termevents = self.eventstruct.query(['term'], eventslist) # initialize event info dictionaries Evtimes = {} Evpoints = {} for (evname, ev) in eventslist: Evtimes[evname] = [] Evpoints[evname] = [] if eventslist != []: if self._for_hybrid_DS: # self._for_hybrid_DS is set internally by HybridModel class # to ensure not to reset events, because they may be about to # flag on first step if previous hybrid state was the same # generator and, for example, two variables are synchronizing # so that their events get very close together. # Just reset the starttimes of these events for evname, ev in eventslist: ev.starttime = self.indepvariable.depdomain[0] else: self.eventstruct.resetHighLevelEvents(self.indepvariable.depdomain[0], eventslist) self.eventstruct.validateEvents(self.funcspec.vars + \ self.funcspec.auxvars + \ ['t'], eventslist) # per-iteration storage of variable data (initial values are irrelevant) xDataDict = {} # storage of all auxiliary variable data allaDataDict = {} anames = self.funcspec.auxvars avals = getattr(self,self.funcspec.auxspec[1])(*[self.indepvariable.depdomain[0], sortedDictValues(self.initialconditions, self.funcspec.vars), extralist]) for aix in range(len(anames)): aname = anames[aix] allaDataDict[aname] = [avals[aix]] # temp storage of first time at which terminal events found # (this is used for keeping the correct end point of new mesh) first_found_t = None tmesh = self.indepvariable.depdomain.sample(self.tstep, strict=False, avoidendpoints=self.checklevel>2) # Main loop breakwhile = False success = False x = ic notdone = True # did i=0 for initial condition already i = 1 while notdone: t = tmesh[i] ## COMPUTE NEXT STATE y from x try: y = rhsfn(t, x, extralist) except: print("Error in calling right hand side function:") self.showSpec() raise for xi in range(self.dimension): xDataDict[xnames[xi]] = y[xi] if not self.contains(self.variables[xnames[xi]].depdomain, y[xi], self.checklevel): self.diagnostics.warnings.append((W_TERMSTATEBD, (t, xnames[xi], y[xi], self.variables[xnames[xi]].depdomain))) breakwhile = True break # for loop if breakwhile: notdone = False continue avals = getattr(self,self.funcspec.auxspec[1])(*[t, sortedDictValues(xDataDict), extralist]) if eventslist != []: dataDict = copy(xDataDict) dataDict['t'] = t evsflagged = self.eventstruct.pollHighLevelEvents(None, dataDict, self.pars, eventslist) termevsflagged = [e for e in termevents if e in evsflagged] nontermevsflagged = [e for e in evsflagged if e not in termevsflagged] # register any non-terminating events in the warnings list if len(nontermevsflagged) > 0: evnames = [ev[0] for ev in nontermevsflagged] self.diagnostics.warnings.append((W_NONTERMEVENT, (t, evnames))) for evname in evnames: Evtimes[evname].append(t) xv = y av = array(avals) Evpoints[evname].append(concatenate((xv, av))) if termevsflagged != []: # active terminal event flagged at this time point # register the event in the warnings evnames = [ev[0] for ev in termevsflagged] self.diagnostics.warnings.append((W_TERMEVENT, \ (t, evnames))) for evname in evnames: Evtimes[evname].append(t) xv = y av = array(avals) Evpoints[evname].append(concatenate((xv, av))) notdone = False # ?? if continue here then won't add the event point to the # trajectory values being constructed! #continue alltData.append(t) for xi in range(self.dimension): allxDataDict[xnames[xi]].append(y[xi]) for aix in range(len(anames)): aname = anames[aix] allaDataDict[aname].append(avals[aix]) try: extralist[self.numpars:listend] = [f(*[t, self.checklevel]) \ for f in inputVarList] except ValueError: print('External input call caused value out of range error:', \ 't = %f' % t) for f in inputVarList: if f.hasWarnings(): print('External input variable %s out of range:' % f.name) print(' t = %r, %s, %r' % (repr(f.diagnostics.warnings[-1][0]), f.name, repr(f.diagnostics.warnings[-1][1]))) raise except AssertionError: print('External input call caused t out of range error: t = %f' % t) raise if i >= len(tmesh) - 1: notdone = False else: i += 1 x = y # update success flag success = not notdone # Check that any terminal events found terminated the code correctly if first_found_t is not None: assert self.diagnostics.warnings[-1][0] == W_TERMEVENT, ("Event finding code " "for terminal event failed") # Package up computed trajectory in Variable variables # Add external inputs warnings to self.dignostics.warnings, if any for f in inputVarList: for winfo in f.diagnostics.warnings: self.diagnostics.warnings.append((W_NONTERMSTATEBD, (winfo[0], f.name, winfo[1], f.depdomain))) # check for non-unique terminal event termcount = 0 for (w,i) in self.diagnostics.warnings: if w == W_TERMEVENT or w == W_TERMSTATEBD: termcount += 1 if termcount > 1: self.diagnostics.errors.append((E_NONUNIQUETERM, (alltData[-1], i[1]))) ## print 'Time interval adjusted according to %s: %s' % \ ## (self._warnmessages[w], str(i[0])+", "+ str(i[1])) # Create variables (self.variables contains no actual data) variables = copyVarDict(self.variables) # build event pointset information (reset previous trajectory's) self.trajevents = {} for (evname, ev) in eventslist: evpt = Evpoints[evname] if evpt == []: self.trajevents[evname] = None else: evpt = transpose(array(evpt)) self.trajevents[evname] = Pointset({'coordnames': xnames+anames, 'indepvarname': 't', 'coordarray': evpt, 'indepvararray': Evtimes[evname], 'indepvartype': self.variables[xnames[0]].indepvartype}) for x in xnames: if len(alltData) > 1: variables[x] = Variable(Pointset({'coordnames': [x], 'coordarray': allxDataDict[x], 'coordtype': self.variables[x].coordtype, 'indepvarname': 't', 'indepvararray': alltData, 'indepvartype': self.variables[x].indepvartype}), 't', x, x) else: raise PyDSTool_ValueError("Fewer than 2 data points computed") for a in anames: if len(alltData) > 1: variables[a] = Variable(Pointset({'coordnames': [a], 'coordarray': allaDataDict[a], 'coordtype': self.variables[a].coordtype, 'indepvarname': 't', 'indepvararray': alltData, 'indepvartype': self.variables[a].indepvartype}), 't', a, a) else: raise PyDSTool_ValueError("Fewer than 2 data points computed") if success: #self.validateSpec() self.defined = True return Trajectory(trajname, list(variables.values()), abseps=self._abseps, globalt0=self.globalt0, checklevel=self.checklevel, FScompatibleNames=self._FScompatibleNames, FScompatibleNamesInv=self._FScompatibleNamesInv, events=self.trajevents, modelNames=self.name, modelEventStructs=self.eventstruct) else: print('Trajectory computation failed') self.diagnostics.errors.append((E_COMPUTFAIL, (t, self._errorcodes[errcode]))) self.defined = False
def compute(self, trajname, ics=None): assert self.funcspec.targetlang == 'python', \ ('Wrong target language for functional specification. ' 'Python needed for this class') assert isinstance(self.funcspec, RHSfuncSpec), ('Map system ' 'requires RHSfuncSpec type to proceed') if self.defined: self.validateSpec() ## assert remain(self.initialconditions.keys(), ## self._xdatadict.keys()+self.funcspec.auxvars) == [],\ ## ('mismatching entries between initial conditions and ' ## 'declared variable names') self.clearWarnings() self.clearErrors() if ics is not None: self.set(ics=ics) xnames = self._var_ixmap # ensures correct order # wrap up each dictionary initial value as a singleton list alltData = [self.indepvariable.depdomain.get(0)] allxDataDict = dict(zip(xnames, map(listid, sortedDictValues(self.initialconditions, self.funcspec.vars)))) rhsfn = eval("self."+self.funcspec.spec[1]) # Check i.c.'s are well defined (finite) self.checkInitialConditions() self.setEventICs(self.initialconditions, self.globalt0) ic = sortedDictValues(self.initialconditions, self.funcspec.vars) plist = sortedDictValues(self.pars) extralist = copy(plist) ilist = [] if self.inputs: # inputVarList is a list of Variables listend = self.numpars + len(self.inputs) inputVarList = sortedDictValues(self.inputs) try: for f in inputVarList: f.clearWarnings ilist.append(f(alltData[0], self.checklevel)) except AssertionError: print 'External input call has t out of range: t = ', \ self.indepvariable.depdomain.get(0) print 'Maybe checklevel is 3 and initial time is not', \ 'completely inside valid time interval' raise except ValueError: print 'External input call has value out of range: t = ', \ self.indepvariable.depdomain.get(0) for f in inputVarList: if len(f.warnings): print 'External input %s out of range:' % f.name print ' t = ', repr(f.warnings[-1][0]), ', ', \ f.name, ' = ', repr(f.warnings[-1][1]) raise else: listend = self.numpars inputVarList = [] extralist.extend(ilist) precevents = self.eventstruct.query(['precise']) if precevents != []: raise PyDSTool_ValueError('precise events are not valid for map systems') eventslist = self.eventstruct.query(['highlevel', 'active', 'notvarlinked']) termevents = self.eventstruct.query(['term'], eventslist) # initialize event info dictionaries Evtimes = {} Evpoints = {} for (evname, ev) in eventslist: Evtimes[evname] = [] Evpoints[evname] = [] if eventslist != []: self.eventstruct.resetHighLevelEvents(self.indepvariable.depdomain.get(0), eventslist) self.eventstruct.validateEvents(self.funcspec.vars + \ self.funcspec.auxvars + \ ['t'], eventslist) # per-iteration storage of variable data (initial values are irrelevant) xDataDict = {} # storage of all auxiliary variable data allaDataDict = {} anames = self.funcspec.auxvars avals = apply(eval("self."+self.funcspec.auxspec[1]), [self.indepvariable.depdomain.get(0), sortedDictValues(self.initialconditions, self.funcspec.vars), extralist]) for aix in range(len(anames)): aname = anames[aix] allaDataDict[aname] = [avals[aix]] # temp storage of first time at which terminal events found # (this is used for keeping the correct end point of new mesh) first_found_t = None tmesh = self.indepvariable.depdomain.uniformSample(self.tstep, strict=False, avoidendpoints=self.checklevel>2) # Main loop breakwhile = False success = False x = ic notdone = True # did i=0 for initial condition already i = 1 while notdone: t = tmesh[i] ## COMPUTE NEXT STATE y from x try: y = rhsfn(t, x, extralist) except: print "Error in calling right hand side function:" self.showSpec() raise for xi in xrange(self.dimension): xDataDict[xnames[xi]] = y[xi] if not self.contains(self.variables[xnames[xi]].depdomain, y[xi], self.checklevel): self.warnings.append((W_TERMSTATEBD, (t, xnames[xi], y[xi], self.variables[xnames[xi]].depdomain))) breakwhile = True break # for loop if breakwhile: notdone = False continue if eventslist != []: dataDict = copy(xDataDict) dataDict['t'] = t evsflagged = self.eventstruct.pollHighLevelEvents(None, dataDict, self.pars, eventslist) termevsflagged = filter(lambda e: e in evsflagged, termevents) nontermevsflagged = filter(lambda e: e not in termevsflagged, evsflagged) # register any non-terminating events in the warnings list if len(nontermevsflagged) > 0: evnames = [ev[0] for ev in nontermevsflagged] self.warnings.append((W_NONTERMEVENT, (t, evnames))) for evname in evnames: Evtimes[evname].append(t) Evpoints[evname].append(y) if termevsflagged != []: # active terminal event flagged at this time point # register the event in the warnings evnames = [ev[0] for ev in termevsflagged] self.warnings.append((W_TERMEVENT, \ (t, evnames))) for evname in evnames: Evtimes[evname].append(t) Evpoints[evname].append(y) notdone = False continue alltData.append(t) for xi in range(self.dimension): allxDataDict[xnames[xi]].append(y[xi]) avals = apply(eval("self."+self.funcspec.auxspec[1]), [t, sortedDictValues(xDataDict), extralist]) for aix in range(len(anames)): aname = anames[aix] allaDataDict[aname].append(avals[aix]) try: extralist[self.numpars:listend] = [apply(f, [t, self.checklevel]) \ for f in inputVarList] except ValueError: print 'External input call caused value out of range error:', \ 't = ', t for f in inputVarList: if len(f.warnings): print 'External input variable %s out of range:' % f.name print ' t = ', repr(f.warnings[-1][0]), ', ', \ f.name, ' = ', repr(f.warnings[-1][1]) raise except AssertionError: print 'External input call caused t out of range error: t = ', t raise if i >= len(tmesh) - 1: notdone = False else: i += 1 x = y # update success flag success = not notdone # Check that any terminal events found terminated the code correctly if first_found_t is not None: assert self.warnings[-1][0] == W_TERMEVENT, ("Event finding code " "for terminal event failed") # Package up computed trajectory in Variable variables # Add external inputs warnings to self.warnings, if any for f in inputVarList: for winfo in f.warnings: self.warnings.append((W_NONTERMSTATEBD, (winfo[0], f.name, winfo[1], f.depdomain))) # check for non-unique terminal event termcount = 0 for (w,i) in self.warnings: if w == W_TERMEVENT or w == W_TERMSTATEBD: termcount += 1 if termcount > 1: self.errors.append((E_NONUNIQUETERM, (alltData[-1], i[1]))) ## print 'Time interval adjusted according to %s: %s' % \ ## (self._warnmessages[w], str(i[0])+", "+ str(i[1])) # Create variables (self.variables contains no actual data) variables = copyVarDict(self.variables) # build event pointset information (reset previous trajectory's) self.trajevents = {} for (evname, ev) in eventslist: evpt = Evpoints[evname] if evpt == []: self.trajevents[evname] = None else: evpt = transpose(array(evpt)) self.trajevents[evname] = Pointset({'coordnames': xnames, 'indepvarname': 't', 'coordarray': evpt, 'indepvararray': Evtimes[evname], 'indepvartype': self.variables[xnames[0]].indepvartype}) for x in xnames: if len(alltData) > 1: variables[x] = Variable(Pointset({'coordnames': [x], 'coordarray': allxDataDict[x], 'coordtype': self.variables[x].coordtype, 'indepvarname': 't', 'indepvararray': alltData, 'indepvartype': self.variables[x].indepvartype}), 't', x, x) else: raise PyDSTool_ValueError, "Fewer than 2 data points computed" for a in anames: if len(alltData) > 1: variables[a] = Variable(Pointset({'coordnames': [a], 'coordarray': allaDataDict[a], 'coordtype': self.variables[a].coordtype, 'indepvarname': 't', 'indepvararray': alltData, 'indepvartype': self.variables[a].indepvartype}), 't', a, a) else: raise PyDSTool_ValueError, "Fewer than 2 data points computed" if success: self.validateSpec() self.defined = True return Trajectory(trajname, variables.values(), self.globalt0, self.checklevel) else: print 'Trajectory computation failed' self.errors.append((E_COMPUTFAIL, (t, self._errorcodes[errcode]))) self.defined = False