1 |
jgs |
123 |
#!/usr/bin/python |
2 |
|
|
|
3 |
|
|
|
4 |
|
|
import unittest |
5 |
|
|
from modelframe import * |
6 |
|
|
import math |
7 |
|
|
from cStringIO import StringIO |
8 |
|
|
from xml.dom import minidom |
9 |
|
|
|
10 |
|
|
class XMLDocumentTestCase(unittest.TestCase): |
11 |
|
|
|
12 |
|
|
def setUp(self): |
13 |
|
|
|
14 |
|
|
o1=ODETEST(debug=False) |
15 |
|
|
o1.u=10 |
16 |
|
|
o2=ODETEST(debug=False) |
17 |
|
|
o2.u=-10. |
18 |
|
|
o1.f=Link(o2,"u") |
19 |
|
|
o2.f=Link(o1,"u") |
20 |
|
|
m=Messenger() |
21 |
|
|
o1.dt=0.01 |
22 |
|
|
m.message=Link(o1) |
23 |
|
|
s=ExplicitSimulation([Simulation([o1,o2],debug=False),m],debug=False) |
24 |
|
|
s.run() |
25 |
|
|
output = StringIO() |
26 |
|
|
s.writeXML(output) |
27 |
|
|
output.reset() |
28 |
|
|
outputList = output.readlines() |
29 |
|
|
self.xmlList = outputList |
30 |
|
|
|
31 |
|
|
def testFirstLine(self): |
32 |
|
|
firstLine = self.xmlList[0] |
33 |
|
|
self.assertEqual('<?xml version="1.0" ?>\n', firstLine) |
34 |
|
|
|
35 |
|
|
def testEsysHeader(self): |
36 |
|
|
header = self.xmlList[1] |
37 |
|
|
self.assertEqual('<ESys>\n', header) |
38 |
|
|
|
39 |
|
|
def testEsysFooter(self): |
40 |
|
|
footer = self.xmlList[-1] |
41 |
|
|
self.assertEqual('</ESys>\n', footer) |
42 |
|
|
|
43 |
|
|
def testSimulationHeader(self): |
44 |
|
|
pass |
45 |
|
|
|
46 |
|
|
def testSimulationFooter(self): |
47 |
|
|
pass |
48 |
|
|
|
49 |
|
|
class SimulationTestCase(unittest.TestCase): |
50 |
|
|
def setUp(self): |
51 |
|
|
o1=ODETEST(debug=False) |
52 |
|
|
o1.u=10 |
53 |
|
|
o2=ODETEST(debug=False) |
54 |
|
|
o2.u=-10. |
55 |
|
|
o1.f=Link(o2,"u") |
56 |
|
|
o2.f=Link(o1,"u") |
57 |
|
|
m=Messenger() |
58 |
|
|
o1.dt=0.01 |
59 |
|
|
m.message=Link(o1) |
60 |
|
|
self.s=s=ExplicitSimulation([Simulation([o1,o2],debug=False),m],debug=False) |
61 |
|
|
s.run() |
62 |
|
|
output = StringIO() |
63 |
|
|
s.writeXML(output) |
64 |
|
|
output.reset() |
65 |
|
|
self.xml = output.read() |
66 |
|
|
|
67 |
|
|
def testSimulation(self): |
68 |
|
|
assert "<Link" in self.xml, "I should see a link" |
69 |
|
|
|
70 |
|
|
o = parse(self.xml) |
71 |
|
|
output = StringIO() |
72 |
|
|
o.writeXML(output) |
73 |
|
|
output.reset() |
74 |
|
|
xml = output.read() |
75 |
|
|
assert '<Link' in xml, "Missing a link! It should be in this!" |
76 |
|
|
|
77 |
|
|
|
78 |
|
|
|
79 |
|
|
|
80 |
|
|
class LinkTestCase(unittest.TestCase): |
81 |
|
|
|
82 |
|
|
|
83 |
|
|
def setUp(self): |
84 |
|
|
|
85 |
|
|
self.o1=ODETEST(debug=False) |
86 |
|
|
#self.o1.u=10 |
87 |
|
|
self.o2=ODETEST(debug=False) |
88 |
|
|
self.o2.u=-10. |
89 |
|
|
self.o1.f=Link(self.o2,"u") |
90 |
|
|
self.o2.f=Link(self.o1,"u") |
91 |
|
|
self.o2.declareParameter(child=self.o1) |
92 |
|
|
|
93 |
|
|
def testLinkCreation(self): |
94 |
|
|
self.o1.f=Link(self.o2,"u") |
95 |
|
|
assert self.o1.f |
96 |
|
|
|
97 |
|
|
|
98 |
|
|
def testLinkValue(self): |
99 |
|
|
self.assertEqual(self.o1.f, -10) |
100 |
|
|
|
101 |
|
|
def testLinkTarget(self): |
102 |
|
|
pass |
103 |
|
|
|
104 |
|
|
def testLinkDefaultAttribute(self): |
105 |
|
|
Link(self.o2) |
106 |
|
|
|
107 |
|
|
def testLinkXML(self): |
108 |
|
|
s = StringIO() |
109 |
|
|
self.o2.writeXML(s) |
110 |
|
|
s.reset() |
111 |
|
|
xmlout = s.read() |
112 |
|
|
assert '<Link' in xmlout |
113 |
|
|
|
114 |
|
|
def testLinkTargetXML(self): |
115 |
|
|
pass |
116 |
|
|
|
117 |
|
|
class ParamaterSetTestCase(unittest.TestCase): |
118 |
|
|
|
119 |
|
|
|
120 |
|
|
def setUp(self): |
121 |
|
|
self.p = ParameterSet() |
122 |
|
|
self.p.declareParameter(gamma1=1.,gamma2=2.,gamma3=3.) |
123 |
|
|
|
124 |
|
|
def testParameterSetCreation(self): |
125 |
|
|
self.assertEqual(self.p.gamma1, 1.) |
126 |
|
|
|
127 |
|
|
def testParameterSetXMLCreation(self): |
128 |
|
|
s = StringIO() |
129 |
|
|
self.p.writeXML(s) |
130 |
|
|
s.reset() |
131 |
|
|
xmlout = s.read() |
132 |
|
|
assert ("gamma1" in xmlout) |
133 |
|
|
assert ("gamma2" in xmlout) |
134 |
|
|
assert ("gamma3" in xmlout) |
135 |
|
|
parsable = minidom.parseString(xmlout) |
136 |
|
|
assert parsable.getElementsByTagName("ParameterSet") |
137 |
|
|
|
138 |
|
|
def testParameterSetFromXML(self): |
139 |
|
|
doc = self._dom() |
140 |
|
|
pset = ParameterSet.fromDom(doc.getElementsByTagName("ParameterSet")[0]) |
141 |
|
|
assert (isinstance(pset, ParameterSet)) |
142 |
|
|
self.assertEqual(self.p.gamma1,pset.gamma1) |
143 |
|
|
|
144 |
|
|
|
145 |
|
|
def testParameterSetWithChildrenFromXML(self): |
146 |
|
|
p2 = ParameterSet() |
147 |
|
|
p2.declareParameter(s="abc", f=3.) |
148 |
|
|
self.p.declareParameter(child=p2) |
149 |
|
|
doc = self._dom() |
150 |
|
|
pset = ParameterSet.fromDom(doc.getElementsByTagName("ParameterSet")[0]) |
151 |
|
|
self.assertEqual(self.p.child.f, pset.child.f) |
152 |
|
|
|
153 |
|
|
def testParameterSetChild(self): |
154 |
|
|
p2 = ParameterSet() |
155 |
|
|
p2.declareParameter(s="abc", f=3.) |
156 |
|
|
self.p.declareParameter(child=p2) |
157 |
|
|
self.assertEqual(self.p.child.s, "abc") |
158 |
|
|
self.assertEqual(self.p.child.f, 3.) |
159 |
|
|
|
160 |
|
|
def _dom(self): |
161 |
|
|
s = StringIO() |
162 |
|
|
self.p.writeXML(s) |
163 |
|
|
s.reset() |
164 |
|
|
xmlout = s.read() |
165 |
|
|
doc = minidom.parseString(xmlout) |
166 |
|
|
return doc |
167 |
|
|
|
168 |
|
|
class ModeltoDomTestCase(unittest.TestCase): |
169 |
|
|
|
170 |
|
|
def _dom(self): |
171 |
|
|
s = StringIO() |
172 |
|
|
self.o1.writeXML(s) |
173 |
|
|
s.reset() |
174 |
|
|
xmlout = s.read() |
175 |
|
|
doc = minidom.parseString(xmlout) |
176 |
|
|
return doc |
177 |
|
|
|
178 |
|
|
def setUp(self): |
179 |
|
|
self.o1=ODETEST(debug=False) |
180 |
|
|
|
181 |
|
|
def testModelExists(self): |
182 |
|
|
assert self._dom().getElementsByTagName("Model") |
183 |
|
|
#print self._dom().toxml() |
184 |
|
|
|
185 |
|
|
def testModelhasID(self): |
186 |
|
|
assert int(self._dom().getElementsByTagName("Model")[0].getAttribute("id"))>99 |
187 |
|
|
|
188 |
|
|
class Messenger(Model): |
189 |
|
|
def __init__(self, *args, **kwargs): |
190 |
|
|
Model.__init__(self, *args, **kwargs) |
191 |
|
|
self.declareParameter(message="none") |
192 |
|
|
|
193 |
|
|
def doInitialization(self,t): |
194 |
|
|
self.__t=t |
195 |
|
|
#print "I start talking now!" |
196 |
|
|
|
197 |
|
|
def doStep(self,dt): |
198 |
|
|
self.__t+=dt |
199 |
|
|
#print "Message (time %e) : %s "%(self.__t,self.message) |
200 |
|
|
|
201 |
|
|
def doFinalization(self): |
202 |
|
|
#print "I have no more to say!" |
203 |
|
|
pass |
204 |
|
|
|
205 |
|
|
|
206 |
|
|
|
207 |
|
|
class ODETEST(Model): |
208 |
|
|
""" implements a solver for the ODE |
209 |
|
|
|
210 |
|
|
du/dt=a*u+f(t) |
211 |
|
|
|
212 |
|
|
we use a implicit euler scheme : |
213 |
|
|
|
214 |
|
|
u_n-u_{n-1}= dt*a u_n + st*f(t_n) |
215 |
|
|
|
216 |
|
|
to get u_n we run an iterative process |
217 |
|
|
|
218 |
|
|
u_{n.k}=u_{n-1}+dt*(a u_{n.i-1} + f(t_n)) |
219 |
|
|
|
220 |
|
|
|
221 |
|
|
input for this model are step size dt, end time tend and a value for |
222 |
|
|
a, f and initial value for u. we need also a tolerance tol for a |
223 |
|
|
stopping criterion. |
224 |
|
|
|
225 |
|
|
""" |
226 |
|
|
|
227 |
|
|
def __init__(self, *args, **kwargs): |
228 |
|
|
Model.__init__(self, *args, **kwargs) |
229 |
|
|
self.declareParameter(tend=1.,dt=0.1,a=0.9,u=10.,f=0.,message="",tol=1.e-8) |
230 |
|
|
|
231 |
|
|
def doInitialization(self,t): |
232 |
|
|
self.__tn=t |
233 |
|
|
self.__iter=0 |
234 |
|
|
|
235 |
|
|
def doIterationInitialization(self,dt): |
236 |
|
|
self.__iter=0 |
237 |
|
|
self.__u_last=self.u |
238 |
|
|
|
239 |
|
|
def doIterationStep(self,dt): |
240 |
|
|
self.__iter+=1 |
241 |
|
|
self.__u_old=self.u |
242 |
|
|
self.u=self.__u_last+dt*(self.a*self.__u_old+self.f) |
243 |
|
|
|
244 |
|
|
def terminate(self): |
245 |
|
|
if self.__iter<1: |
246 |
|
|
return False |
247 |
|
|
else: |
248 |
|
|
return abs(self.__u_old-self.u)<self.tol*abs(self.u) |
249 |
|
|
|
250 |
|
|
def doIterationFinalization(self,dt): |
251 |
|
|
self.__tn+=dt |
252 |
|
|
self.message="current error = %e"%abs(self.u-10.*math.exp((self.a-1.)*self.__tn)) |
253 |
|
|
|
254 |
|
|
def getSafeTimeStepSize(self,dt): |
255 |
|
|
return min(self.dt,1./(abs(self.a)+1.)) |
256 |
|
|
|
257 |
|
|
def finalize(self): |
258 |
|
|
return self.__tn>=self.tend |
259 |
|
|
|
260 |
|
|
|
261 |
|
|
if __name__ == "__main__": |
262 |
|
|
unittest.main() |
263 |
|
|
|