def diffusion_stencil(): """Create stencil and substitutions for the diffusion equation""" p = Function('p') dx2 = as_finite_diff(p(x, y, t).diff(x, x), [x - h, x, x + h]) dy2 = as_finite_diff(p(x, y, t).diff(y, y), [y - h, y, y + h]) dt = as_finite_diff(p(x, y, t).diff(t), [t, t + s]) eqn = Eq(dt, a * (dx2 + dy2)) stencil = solve(eqn, p(x, y, t + s))[0] return stencil, (p(x, y, t), p(x + h, y, t), p(x - h, y, t), p(x, y + h, t), p(x, y - h, t), s, h)
def get_space_derivatives(self, derivative_order, accuracy_order): global t, x, y, z #TODO: Generalize if accuracy_order != 2: raise ValueError('Only implemented for accuracy order 2') if derivative_order > 2: raise ValueError('Derivates only available until second order') h = self.h print self.fields if derivative_order==1: return (as_finite_diff(self.fields[0].function(x,y,z,t).diff(x), [x-h, x+h]), as_finite_diff(self.fields[0].function(x,y,z,t).diff(y), [y-h, y+h]), as_finite_diff(self.fields[0].function(x,y,z,t).diff(z), [z-h, z+h])) else: return (as_finite_diff(self.fields[0].function(x,y,z,t).diff(x,x), [x-h,x, x+h]), as_finite_diff(self.fields[0].function(x,y,z,t).diff(y,y), [y-h,y, y+h]), as_finite_diff(self.fields[0].function(x,y,z,t).diff(z,z), [z-h,z, z+h]))
def get_time_derivative(self, derivative_order, accuracy_order): global x, y, z t=self.t #TODO: Generalize if accuracy_order != 2: raise ValueError('Only implemented for accuracy order 2') if derivative_order > 2: raise ValueError('Derivates only available until second order') s = self.s print self.fields if derivative_order==1: return as_finite_diff(self.fields[0].function(x,y,z,t).diff(t), [t-s, t+s]) else: return as_finite_diff(self.fields[0].function(x,y,z,t).diff(t,t), [t-s,t, t+s])
def dt2(self): """Symbol for the second derivative wrt the t dimension""" _t = self.indices[0] width_t = int(self.time_order / 2) indt = [(_t + i * s) for i in range(-width_t, width_t + 1)] return as_finite_diff(self.diff(_t, _t), indt)
def test_stencil_derivative(shape, SymbolType, dimension): """Test symbolic behaviour when expanding stencil derivatives""" u = SymbolType(name='u', shape=shape) u.data[:] = 66.6 dx = u.diff(x) dxx = u.diff(x, x) # Check for sympy Derivative objects assert (isinstance(dx, Derivative) and isinstance(dxx, Derivative)) s_dx = as_finite_diff(dx, [x - x.spacing, x]) s_dxx = as_finite_diff(dxx, [x - x.spacing, x, x + x.spacing]) # Check stencil length of first and second derivatives assert (len(s_dx.args) == 2 and len(s_dxx.args) == 3) u_dx = s_dx.args[0].args[1] u_dxx = s_dx.args[0].args[1] # Ensure that devito meta-data survived symbolic transformation assert (u_dx.shape[-2:] == shape and u_dxx.shape[-2:] == shape) assert (np.allclose(u_dx.data, 66.6)) assert (np.allclose(u_dxx.data, 66.6))
def dt(self): """Symbol for the first derivative wrt the time dimension""" if self.time_order == 1: # This hack is needed for the first-order diffusion test indices = [t, t + s] else: width = int(self.time_order / 2) indices = [(t + i * s) for i in range(-width, width + 1)] return as_finite_diff(self.diff(t), indices)
def test_second_derivatives_space(derivative, dimension, order): """Test second derivative expressions against native sympy""" u = TimeData(name='u', shape=(20, 20, 20), time_order=2, space_order=order) expr = getattr(u, derivative) # Establish native sympy derivative expression width = int(order / 2) indices = [(dimension + i * h) for i in range(-width, width + 1)] s_expr = as_finite_diff(u.diff(dimension, dimension), indices) assert (simplify(expr - s_expr) == 0) # Symbolic equality assert (expr == s_expr) # Exact equailty
def dz4(self): """Symbol for the fourth derivative wrt the z dimension""" width_h = max(int(self.space_order / 2), 2) indz = [(z + i * z.spacing) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(z, z, z, z), indz)
def dy4(self): """Symbol for the fourth derivative wrt the y dimension""" width_h = max(int(self.space_order / 2), 2) indy = [(y + i * y.spacing) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(y, y, y, y), indy)
def dx4(self): """Symbol for the fourth derivative wrt the x dimension""" width_h = max(int(self.space_order / 2), 2) indx = [(x + i * x.spacing) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(x, x, x, x), indx)
def dz(self): """Symbol for the first derivative wrt the z dimension""" width_h = int(self.space_order/2) indz = [(z + i * h) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(z), indz)
def dy2(self): """Symbol for the second derivative wrt the y dimension""" width_h = int(self.space_order/2) indy = [(y + i * h) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(y, y), indy)
def dx2(self): """Symbol for the second derivative wrt the x dimension""" width_h = int(self.space_order/2) indx = [(x + i * h) for i in range(-width_h, width_h + 1)] return as_finite_diff(self.diff(x, x), indx)