Package hedge :: Module data
[hide private]
[frames] | no frames]

Source Code for Module hedge.data

  1  """Representations for given data, such as initial and boundary  
  2  conditions and source terms.""" 
  3   
  4  __copyright__ = "Copyright (C) 2007 Andreas Kloeckner" 
  5   
  6  __license__ = """ 
  7  This program is free software: you can redistribute it and/or modify 
  8  it under the terms of the GNU General Public License as published by 
  9  the Free Software Foundation, either version 3 of the License, or 
 10  (at your option) any later version. 
 11   
 12  This program is distributed in the hope that it will be useful, 
 13  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 15  GNU General Public License for more details. 
 16   
 17  You should have received a copy of the GNU General Public License 
 18  along with this program.  If not, see U{http://www.gnu.org/licenses/}. 
 19  """ 
 20   
 21   
 22   
 23   
 24  import hedge.mesh 
25 26 27 28 29 # helpers --------------------------------------------------------------------- 30 -class _ConstantFunctionContainer:
31 - def __init__(self, value):
32 self.value = value
33 34 @property
35 - def shape(self):
36 return self.value.shape
37
38 - def __call__(self, x, el):
39 return self.value
40
41 42 43 44 45 # interpolation wrappers ------------------------------------------------------ 46 -class IGivenFunction(object):
47 """Abstract interface for obtaining interpolants of I{time-independent} 48 functions. 49 """ 50
51 - def volume_interpolant(self, discr):
52 """Return the volume interpolant of this function with respect to 53 the L{discretization.Discretization} C{discr}. 54 """ 55 raise NotImplementedError
56
57 - def boundary_interpolant(self, discr, tag):
58 """Return the boundary interpolant of this function with respect to 59 the L{discretization.Discretization} discr at the boundary tagged with C{tag}. 60 """ 61 raise NotImplementedError
62
63 64 65 66 -class ITimeDependentGivenFunction(object):
67 """Abstract interface for obtaining interpolants of I{time-dependent} 68 functions. 69 """ 70
71 - def volume_interpolant(self, t, discr):
72 """Return the volume interpolant of this function with respect to 73 the L{discretization.Discretization} discr at time {t}. 74 """ 75 raise NotImplementedError
76
77 - def boundary_interpolant(self, t, discr, tag):
78 """Return the boundary interpolant of this function with respect to 79 the L{discretization.Discretization} discr at time C{t} at the boundary tagged with 80 C{tag}. 81 """ 82 raise NotImplementedError
83
84 85 86 87 -class GivenFunction(IGivenFunction):
88 """Adapter for a function M{f(x)} into an L{IGivenFunction}. 89 """
90 - def __init__(self, f):
91 """Initialize the caches and store the function C{f}. 92 93 @param f: a function mapping space to a scalar value. 94 If f.target_dimensions exists and equals M{n}, then f maps into an 95 M{n}-dimensional vector space instead. 96 """ 97 from weakref import WeakKeyDictionary 98 99 self.f = f 100 101 self.volume_cache = WeakKeyDictionary() 102 self.boundary_cache = WeakKeyDictionary()
103
104 - def volume_interpolant(self, discr):
105 try: 106 return self.volume_cache[discr] 107 except KeyError: 108 result = discr.interpolate_volume_function(self.f) 109 self.volume_cache[discr] = result 110 return result
111
112 - def boundary_interpolant(self, discr, tag):
113 try: 114 return self.boundary_cache[discr][tag] 115 except KeyError: 116 tag_cache = self.boundary_cache.setdefault(discr, {}) 117 result = discr.interpolate_boundary_function(self.f, tag) 118 tag_cache[tag] = result 119 return result
120
121 122 123 124 -class ConstantGivenFunction(GivenFunction):
125 """A L{GivenFunction} that has a constant value on all space. 126 """
127 - def __init__(self, value=0):
128 self.value = value 129 130 GivenFunction.__init__(self, _ConstantFunctionContainer(value))
131
132 133 134 135 -class GivenVolumeInterpolant(IGivenFunction):
136 """A constant-valued L{GivenFunction}. 137 """
138 - def __init__(self, discr, interpolant):
139 self.discr = discr 140 self.interpolant = interpolant
141
142 - def volume_interpolant(self, discr):
143 if discr != self.discr: 144 raise ValueError, "cross-interpolation between discretizations not supported" 145 return self.interpolant
146
147 - def boundary_interpolant(self, discr, tag):
148 if discr != self.discr: 149 raise ValueError, "cross-interpolation between discretizations not supported" 150 return discr.boundarize_volume_field(self.interpolant, tag)
151
152 153 154 155 156 -class TimeConstantGivenFunction(ITimeDependentGivenFunction):
157 """Adapts a L{GivenFunction} to have a (formal) time-dependency, being constant 158 over all time. 159 """
160 - def __init__(self, gf):
161 self.gf = gf
162
163 - def volume_interpolant(self, t, discr):
164 return self.gf.volume_interpolant(discr)
165
166 - def boundary_interpolant(self, t, discr, tag):
167 return self.gf.boundary_interpolant(discr, tag)
168
169 170 171 172 173 -def make_tdep_constant(x):
174 return TimeConstantGivenFunction(ConstantGivenFunction(x))
175
176 177 178 179 -class TimeHarmonicGivenFunction(ITimeDependentGivenFunction):
180 """Adapts an L{IGivenFunction} to have a harmonic time-dependency. 181 """
182 - def __init__(self, gf, omega, phase=0):
183 self.gf = gf 184 self.omega = omega 185 self.phase = phase
186
187 - def volume_interpolant(self, t, discr):
188 from math import sin 189 return sin(self.omega*t+self.phase)\ 190 *self.gf.volume_interpolant(discr)
191
192 - def boundary_interpolant(self, t, discr, tag):
193 from math import sin 194 return sin(self.omega*t+self.phase)\ 195 *self.gf.boundary_interpolant(discr, tag)
196
197 198 199 200 201 -class TimeIntervalGivenFunction(ITimeDependentGivenFunction):
202 """Adapts an L{IGivenFunction} to depend on time by "turning it on" 203 for the time interval [on_time, off_time), and having it be zero 204 the rest of the time. 205 """ 206
207 - def __init__(self, gf, on_time=0, off_time=1):
208 self.gf = gf 209 self.on_time = on_time 210 self.off_time = off_time 211 assert on_time <= off_time
212 213 214
215 - def volume_interpolant(self, t, discr):
216 if self.on_time <= t < self.off_time: 217 return self.gf.volume_interpolant(discr) 218 else: 219 # FIXME: not optimal 220 # difficult part here is to match shape 221 return 0*self.gf.volume_interpolant(discr)
222
223 - def boundary_interpolant(self, t, discr, tag):
224 if self.on_time <= t < self.off_time: 225 return self.gf.boundary_interpolant(discr, tag) 226 else: 227 # FIXME: not optimal 228 # difficult part here is to match shape 229 return 0*self.gf.boundary_interpolant(discr, tag)
230
231 232 233 234 -class TimeDependentGivenFunction(ITimeDependentGivenFunction):
235 """Adapts a function M{f(x,t)} into the L{GivenFunction} framework. 236 """
237 - def __init__(self, f):
238 self.f = f
239
240 - class ConstantWrapper:
241 - def __init__(self, f, t):
242 """Adapt a function `f(x, el, t) in such a way that it can be fed to 243 `interpolate_*_function()`. In particular, preserve the `shape` attribute. 244 """ 245 self.f = f 246 self.t = t
247 248 @property
249 - def shape(self):
250 return self.f.shape
251
252 - def __call__(self, x, el):
253 return self.f(x, el, self.t)
254
255 - def volume_interpolant(self, t, discr):
256 return discr.interpolate_volume_function(self.ConstantWrapper(self.f, t))
257
258 - def boundary_interpolant(self, t, discr, tag):
259 return discr.interpolate_boundary_function(self.ConstantWrapper(self.f, t), tag)
260