class SerialLayers: """ b: coordinates of boundaries of layers, b[0] is left boundary and b[-1] is right boundary of the domain [0,L]. a: values of the functions in each layer (len(a) = len(b)-1). U_0: u(x) value at left boundary x=0=b[0]. U_L: u(x) value at right boundary x=L=b[0]. """ def __init__(self, a, b, U_0, U_L, eps=0): self.a, self.b = np.asarray(a), np.asarray(b) assert len(a) == len(b) - 1, 'a and b do not have compatible lengths' self.eps = eps # smoothing parameter for smoothed a self.U_0, self.U_L = U_0, U_L # Smoothing parameter must be less than half the smallest material if eps > 0: assert eps < 0.5 * (self.b[1:] - self.b[:-1]).min(), 'too large eps' a_data = [[bi, ai] for bi, ai in zip(self.b, self.a)] domain = [b[0], b[-1]] self.a_func = PiecewiseConstant(domain, a_data, eps) # inv_a = 1/a is needed in formulas inv_a_data = [[bi, 1. / ai] for bi, ai in zip(self.b, self.a)] self.inv_a_func = PiecewiseConstant(domain, inv_a_data, eps) self.integral_of_inv_a_func = \ IntegratedPiecewiseConstant(domain, inv_a_data, eps) # Denominator in the exact formula is constant self.inv_a_0L = self.integral_of_inv_a_func(b[-1]) def exact_solution(self, x): solution = self.U_0 + (self.U_L-self.U_0)*\ self.integral_of_inv_a_func(x)/self.inv_a_0L return solution __call__ = exact_solution def plot(self): x, y_a = self.a_func.plot() x = np.asarray(x) y_a = np.asarray(y_a) y_u = self.exact_solution(x) import matplotlib.pyplot as plt plt.figure() plt.plot(x, y_u, 'b') plt.hold('on') # Matlab style plt.plot(x, y_a, 'r') ymin = -0.1 ymax = 1.2 * max(y_u.max(), y_a.max()) plt.axis([x[0], x[-1], ymin, ymax]) plt.legend(['solution $u$', 'coefficient $a$'], loc='upper left') if self.eps > 0: plt.title('Smoothing eps: %s' % self.eps) plt.savefig('tmp.pdf') plt.savefig('tmp.png') plt.show()
class SerialLayers: """ b: coordinates of boundaries of layers, b[0] is left boundary and b[-1] is right boundary of the domain [0,L]. a: values of the functions in each layer (len(a) = len(b)-1). U_0: u(x) value at left boundary x=0=b[0]. U_L: u(x) value at right boundary x=L=b[0]. """ def __init__(self, a, b, U_0, U_L, eps=0): self.a, self.b = np.asarray(a), np.asarray(b) assert len(a) == len(b)-1, 'a and b do not have compatible lengths' self.eps = eps # smoothing parameter for smoothed a self.U_0, self.U_L = U_0, U_L # Smoothing parameter must be less than half the smallest material if eps > 0: assert eps < 0.5*(self.b[1:] - self.b[:-1]).min(), 'too large eps' a_data = [[bi, ai] for bi, ai in zip(self.b, self.a)] domain = [b[0], b[-1]] self.a_func = PiecewiseConstant(domain, a_data, eps) # inv_a = 1/a is needed in formulas inv_a_data = [[bi, 1./ai] for bi, ai in zip(self.b, self.a)] self.inv_a_func = PiecewiseConstant(domain, inv_a_data, eps) self.integral_of_inv_a_func = \ IntegratedPiecewiseConstant(domain, inv_a_data, eps) # Denominator in the exact formula is constant self.inv_a_0L = self.integral_of_inv_a_func(b[-1]) def exact_solution(self, x): solution = self.U_0 + (self.U_L-self.U_0)*\ self.integral_of_inv_a_func(x)/self.inv_a_0L return solution __call__ = exact_solution def plot(self): x, y_a = self.a_func.plot() x = np.asarray(x); y_a = np.asarray(y_a) y_u = self.exact_solution(x) import matplotlib.pyplot as plt plt.figure() plt.plot(x, y_u, 'b') plt.hold('on') # Matlab style plt.plot(x, y_a, 'r') ymin = -0.1 ymax = 1.2*max(y_u.max(), y_a.max()) plt.axis([x[0], x[-1], ymin, ymax]) plt.legend(['solution $u$', 'coefficient $a$'], loc='upper left') if self.eps > 0: plt.title('Smoothing eps: %s' % self.eps) plt.savefig('tmp.pdf') plt.savefig('tmp.png') plt.show()
def __init__(self, a, b, U_0, U_L, eps=0): self.a, self.b = np.asarray(a), np.asarray(b) assert len(a) == len(b)-1, 'a and b do not have compatible lengths' self.eps = eps # smoothing parameter for smoothed a self.U_0, self.U_L = U_0, U_L # Smoothing parameter must be less than half the smallest material if eps > 0: assert eps < 0.5*(self.b[1:] - self.b[:-1]).min(), 'too large eps' a_data = [[bi, ai] for bi, ai in zip(self.b, self.a)] domain = [b[0], b[-1]] self.a_func = PiecewiseConstant(domain, a_data, eps) # inv_a = 1/a is needed in formulas inv_a_data = [[bi, 1./ai] for bi, ai in zip(self.b, self.a)] self.inv_a_func = PiecewiseConstant(domain, inv_a_data, eps) self.integral_of_inv_a_func = \ IntegratedPiecewiseConstant(domain, inv_a_data, eps) # Denominator in the exact formula is constant self.inv_a_0L = self.integral_of_inv_a_func(b[-1])