Exemple #1
0
 def to_pointset(self):
     """Convert to a pointset"""
     bin_ixs = range(self.num_bins)
     return Pointset(indepvararray=list(range(self.num_bins)),
                     coorddict={self.coordinate: [self.bins[ix] \
                                                     for ix in bin_ixs],
                                'bin_limit_lo': [self.intervals[ix][0] \
                                                     for ix in bin_ixs],
                                'bin_limit_hi': [self.intervals[ix][1] \
                                                     for ix in bin_ixs]
                                 })
Exemple #2
0
    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 run(self, history, t_end):
        """history is a dictionary of t -> (event node name, {node name: state})
        values. Initial time of simulator will be the largest t in this
        dictionary.
        """
        self.curr_t = max(history.keys())
        assert t_end > self.curr_t, "t_end too small"
        self.state = history[self.curr_t][1].copy()

        # structural validation of model
        self.validate()
        node_names = sortedDictKeys(self.state)
        self.history = history.copy()
        done = False

        while not done:
            last_state = self.state.copy()
            print("\n ***", self.curr_t, self.history[self.curr_t][0],
                  self.state)

            next_t = Inf
            iters = 1
            nodes = self.nodes.copy()
            # set the last_t of each node
            self.set_node_state()

            try:
                proj_state = self.compile_next_state(nodes)
            except PyDSTool_BoundsError:
                print("Maps borked at", self.curr_t)
                done = True
                break
            print("Projected:", proj_state)
            for node, t in proj_state.items():
                if t > self.curr_t:
                    self.Q.push(t, node)
#            self.state[next_node] = self.Q.next_t

            if self.verbosity > 0:
                print("Took %i iterations to stabilize" % iters)
                self.display()

            t, next_node = self.Q.pop()
            while self.curr_t > t:
                t, next_node = self.Q.pop()
            self.curr_t = t
            self.history[self.curr_t] = (next_node, last_state)
            ##print " * last state =", last_state
            next_state = last_state
            next_state[next_node] = self.curr_t
            # must copy here to ensure history elements don't get
            # overwritten
            self.state = next_state.copy()

            if self.verbosity > 0:
                print("Next node is", next_node, "at time ", self.curr_t)
            done = self.curr_t >= t_end
            continue

            ##

            vals = sortedDictValues(projected_states)
            filt_vals = []
            min_val = Inf
            min_ix = None
            for i, v in enumerate(vals):
                if v > self.curr_t:
                    if v < min_val:
                        min_val = v
                        min_ix = i
##                else:
##                    # do not ignore projected times that are in the past relative to
##                    # curr_t! Must retrgrade curr_t to the earliest newly projected time.
##                    if v not in self.history:
##                        if v < min_val:
##                            min_val = v
##                            min_ix = i
            if min_ix is None:
                # no further events possible
                print("No further events possible, stopping!")
                break


##            if min_val < self.curr_t:
##                # clear later history
##                print "Clearing later history items that are invalid"
##                for t, s in sortedDictItems(self.history):
##                    if t > min_val:
##                        del self.history[t]
            self.curr_t = min_val
            next_state = self.state[1].copy()
            next_node = node_names[min_ix]
            next_state[next_node] = min_val
            self.history[min_val] = (next_node, next_state)
            self.state = (next_node, next_state)

            if self.verbosity > 0:
                print("Next node is", next_node, "at time ", self.curr_t)
            done = self.curr_t >= t_end

        ts, state_dicts = sortedDictLists(self.history, byvalue=False)
        vals = []
        for (evnode, vd) in state_dicts:
            vals.append([vd[nname] for nname in node_names])
        self.result = Pointset(indepvararray=ts,
                               indepvarname='t',
                               coordnames=node_names,
                               coordarray=array(vals).T)
Exemple #4
0
    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