1
2 from __future__ import division
3
4 from allimports import *
5 from baseclasses import ctsGen, theGenSpecHelper
6 from PyDSTool.utils import *
7 from PyDSTool.common import *
8 from PyDSTool.Interval import uncertain
9
10
11 from numpy import Inf, NaN, isfinite, sometrue, alltrue, array, arange, \
12 transpose, shape
13 import math, random
14 from copy import copy, deepcopy
15 try:
16
17 import psyco
18 HAVE_PSYCO = True
19 except ImportError:
20 HAVE_PSYCO = False
21
22
24 """Embedded dynamical system form specifying a trajectory.
25
26 The embedded system is assumed to be of type Model.
27 """
28
29 _validKeys = ['globalt0', 'xdomain', 'tdata', 'tdomain',
30 'ics', 'pars', 'checklevel', 'pdomain', 'abseps']
31 _needKeys = ctsGen._needKeys + ['specfn', 'system']
32 _optionalKeys = ctsGen._optionalKeys + ['tdomain', 'pars', 'pdomain', 'xdomain',
33 'ics', 'vars', 'tdata', 'enforcebounds',
34 'activatedbounds']
35
37 ctsGen.__init__(self, kw)
38 dispatch_list = ['tdomain', 'tdata', 'xtype', 'xdomain',
39 'ics', 'pars', 'pdomain', 'system']
40 if 'varspecs' in kw:
41 raise PyDSTool_KeyError('varspecs option invalid for EmbeddedSysGen '
42 'class')
43 if 'inputs' in kw:
44 raise PyDSTool_KeyError('inputs option invalid for EmbeddedSysGen '
45 'class')
46 try:
47 kw['varspecs'] = kw['system'].query('vardomains')
48 except (KeyError, AttributeError):
49 raise PyDSTool_KeyError("Model-type system must be provided")
50 self.funcspec = args(**self._kw_process_dispatch(dispatch_list, kw))
51 self.funcspec.vars = kw['varspecs'].keys()
52 self.funcspec.auxvars = []
53
54 del kw['varspecs']
55 self.indepvartype = float
56 try:
57 self._embed_spec = kw['specfn']
58 except:
59 raise "Must provide a function for the specification of this system"
60 else:
61 self.foundKeys += 1
62 self.eventstruct = EventStruct()
63 self.checkArgs(kw)
64 assert self.eventstruct.getLowLevelEvents() == [], \
65 "Events are not supported for EmbeddedSysGen class"
66 assert self.eventstruct.getHighLevelEvents() == [], \
67 "Events are not supported for EmbeddedSysGen class"
68 self.indepvariable = Variable(listid, Interval('t_domain',
69 self.indepvartype,
70 self.tdomain, self._abseps),
71 Interval('t', self.indepvartype, self.tdata,
72 self._abseps), 't')
73 self._register(self.indepvariable)
74 for x in self.xdomain.keys():
75
76 try:
77 xinterval=Interval(x, self.xtype[x], self.xdomain[x], self._abseps)
78 except KeyError, e:
79 raise PyDSTool_KeyError('Mismatch between declared variables '
80 'and xspecs: ' + str(e))
81
82
83 self.variables[x] = Variable(None, self.indepvariable.depdomain,
84 xinterval, x)
85
86
87
88 - def compute(self, trajname, ics=None):
89 """
90 """
91 if ics is not None:
92 self.set(ics=ics)
93 self._solver.set(pars=self.pars,
94 globalt0=self.globalt0,
95 ics=self.initialconditions,
96 checklevel=self.checklevel,
97 abseps=self._abseps)
98 self.diagnostics.clearWarnings()
99 self.diagnostics.clearErrors()
100 if not self.defined:
101 self._register(self.variables)
102
103 try:
104 traj = self._embed_spec(self._solver)
105 except:
106 print "Error in user-provided embedded system"
107 raise
108 self.defined = True
109 traj.name = trajname
110 return traj
111
112
114 """Report whether generator has an explicit user-specified Jacobian
115 with respect to pars associated with it."""
116 return self._solver.haveJacobian_pars()
117
119 """Report whether generator has an explicit user-specified Jacobian
120 associated with it."""
121 return self._solver.haveJacobian()
122
123
124 - def set(self, **kw):
125 """Set ExplicitFnGen parameters"""
126 if remain(kw.keys(), self._validKeys) != []:
127 raise KeyError("Invalid keys in argument")
128 if 'globalt0' in kw:
129
130 ctsGen.set(self, globalt0=kw['globalt0'])
131 if 'checklevel' in kw:
132
133 ctsGen.set(self, checklevel=kw['checklevel'])
134 if 'abseps' in kw:
135
136 ctsGen.set(self, abseps=kw['abseps'])
137
138
139 if 'xdomain' in kw:
140 for k_temp, v in kw['xdomain'].iteritems():
141 k = self._FScompatibleNames(k_temp)
142 if k in self.xdomain.keys():
143 if isinstance(v, _seq_types):
144 assert len(v) == 2, \
145 "Invalid size of domain specification for "+k
146 if v[0] >= v[1]:
147 raise PyDSTool_ValueError('xdomain values must be'
148 'in order of increasing '
149 'size')
150 elif isinstance(v, _num_types):
151 pass
152 else:
153 raise PyDSTool_TypeError('Invalid type for xdomain spec'
154 ' '+k)
155 self.xdomain[k] = v
156 else:
157 raise ValueError('Illegal variable name')
158 try:
159 self.variables[k].depdomain.set(v)
160 except TypeError:
161 raise TypeError('xdomain must be a dictionary of variable'
162 ' names -> valid interval 2-tuples or '
163 'singletons')
164 if 'pdomain' in kw:
165 for k_temp, v in kw['pdomain'].iteritems():
166 k = self._FScompatibleNames(k_temp)
167 if k in self.pars.keys():
168 if isinstance(v, _seq_types):
169 assert len(v) == 2, \
170 "Invalid size of domain specification for "+k
171 if v[0] >= v[1]:
172 raise PyDSTool_ValueError('pdomain values must be'
173 'in order of increasing '
174 'size')
175 else:
176 self.pdomain[k] = copy(v)
177 elif isinstance(v, _num_types):
178 self.pdomain[k] = [v, v]
179 else:
180 raise PyDSTool_TypeError('Invalid type for pdomain spec'
181 ' '+k)
182 else:
183 raise ValueError('Illegal parameter name')
184 try:
185 self.parameterDomains[k].depdomain.set(v)
186 except TypeError:
187 raise TypeError('pdomain must be a dictionary of parameter'
188 ' names -> valid interval 2-tuples or '
189 'singletons')
190 if 'tdata' in kw:
191 self.tdata = kw['tdata']
192 if 'tdomain' in kw:
193 self.tdomain = kw['tdomain']
194 self.indepvariable.indepdomain.set(self.tdomain)
195 if self.tdomain[0] > self.tdata[0]:
196 if self.indepvariable.indepdomain.contains(self.tdata[0]) == uncertain:
197 self.diagnostics.warnings.append((W_UNCERTVAL,
198 (self.tdata[0],self.tdomain)))
199 else:
200 print 'tdata cannot be specified below smallest '\
201 'value in tdomain\n (possibly due to uncertain bounding).'\
202 ' It has been automatically adjusted from\n ', self.tdata[0], \
203 'to', self.tdomain[0], '(difference of', \
204 self.tdomain[0]-self.tdata[0], ')'
205 self.tdata[0] = self.tdomain[0]
206 if self.tdomain[1] < self.tdata[1]:
207 if self.indepvariable.indepdomain.contains(self.tdata[1]) == uncertain:
208 self.diagnostics.warnings.append((W_UNCERTVAL,
209 (self.tdata[1],self.tdomain)))
210 else:
211 print 'tdata cannot be specified above largest '\
212 'value in tdomain\n (possibly due to uncertain bounding).'\
213 ' It has been automatically adjusted from\n ', \
214 self.tdomain[1], 'to', \
215 self.tdomain[1], '(difference of', \
216 self.tdata[1]-self.tdomain[1], ')'
217 self.tdata[1] = self.tdomain[1]
218 self.indepvariable.depdomain.set(self.tdata)
219 if 'ics' in kw:
220 for k_temp, v in kw['ics'].iteritems():
221 k = self._FScompatibleNames(k_temp)
222 if k in self.xdomain.keys():
223 self._xdatadict[k] = ensurefloat(v)
224 else:
225 raise ValueError('Illegal variable name')
226 self.initialconditions.update(self._xdatadict)
227 if 'pars' in kw:
228 if not self.pars:
229 raise ValueError('No pars were declared for this object'
230 ' at initialization.')
231 for k_temp, v in kw['pars'].iteritems():
232 k = self._FScompatibleNames(k_temp)
233 if k in self.pars:
234 cval = self.parameterDomains[k].contains(v)
235 if self.checklevel < 3:
236 if cval is not notcontained:
237 self.pars[k] = ensurefloat(v)
238 if cval is uncertain and self.checklevel == 2:
239 print 'Warning: Parameter value at bound'
240 else:
241 raise PyDSTool_ValueError('Parameter value out of '
242 'bounds')
243 else:
244 if cval is contained:
245 self.pars[k] = ensurefloat(v)
246 elif cval is uncertain:
247 raise PyDSTool_UncertainValueError('Parameter value'
248 ' at bound')
249 else:
250 raise PyDSTool_ValueError('Parameter value out of'
251 ' bounds')
252 else:
253 raise PyDSTool_AttributeError('Illegal parameter name')
254
255
257 ctsGen.validateSpec(self)
258 try:
259 for v in self.variables.values():
260 assert isinstance(v, Variable)
261 assert not self.inputs
262 except AssertionError:
263 print 'Invalid system specification'
264 raise
265
266
269
270
271
272
273
274 symbolMapDict = {}
275
276
277 theGenSpecHelper.add(EmbeddedSysGen, symbolMapDict, 'python', None)
278