def __init__(self, y, u, Retau): self.y = np.copy(y) self.q = np.copy(u.astype(np.float)) self.Retau = Retau self.verbose = True self.n = np.size(y) self.writedir = "." self.maxiter = 20 self.tol = 1e-13 self.dt = 1e10 self.neq = 1 self.nu = 1e-4 self.rho = 1.0 self.dp = calc_dp(self.Retau, self.nu) self.beta = np.ones_like(u) self.objective = TestObjective()
def __init__(self, T_inf, ngrid = 31, verbose=False, userealbeta=False): self.T_inf = T_inf self.grid = 1 self.x = self.get_grid(ngrid) self.T = np.ones_like(self.x)*self.T_inf self.T = self.T.astype(np.complex) self.n = self.T.size self.dt = 1.0e1 self.maxiter = 100 self.h = 0.5 self.eps_0 = 5.0e-4 self.tol = 1e-6 self.noise = np.random.randn(np.size(self.T))*0.1 self.objective = TestObjective() self.verbose = verbose self.beta = np.ones_like(self.T) self.userealbeta = userealbeta
def __init__(self, y, u, Retau): self.y = np.copy(y) self.q = np.copy(u.astype(np.complex)) self.Retau = Retau # self.n = np.size(y) self.writedir = "." self.maxiter = 20 self.tol = 1e-13 self.dt = 1e10 self.neq = 1 self.nu = 1e-4 self.rho = 1.0 self.dp = calc_dp(self.Retau, self.nu) self.beta = np.ones_like(u) self.objective = TestObjective()
class HeatBase(object): def __init__(self, T_inf, ngrid = 31, verbose=False, userealbeta=False): self.T_inf = T_inf self.grid = 1 self.x = self.get_grid(ngrid) self.T = np.ones_like(self.x)*self.T_inf self.T = self.T.astype(np.complex) self.n = self.T.size self.dt = 1.0e1 self.maxiter = 100 self.h = 0.5 self.eps_0 = 5.0e-4 self.tol = 1e-6 self.noise = np.random.randn(np.size(self.T))*0.1 self.objective = TestObjective() self.verbose = verbose self.beta = np.ones_like(self.T) self.userealbeta = userealbeta def get_eps(self, T): eps = 1.0 + 5.0*np.sin(3.0*np.pi/200.0*T) + np.exp(0.02*T) + self.noise eps = eps*1e-4 assert(eps.size == T.size) return eps def get_grid(self, n): x = np.loadtxt("y") xr = x[::-1] xx = np.zeros(2*x.size - 1) xx[:x.size] = x[:] xx[x.size:] = 1.0 - xr[1:] if n != 401: N = n xx = np.linspace(0.0, 1.0, N) return xx def calc_residual(self, T): x = self.x T_inf = self.T_inf eps = self.get_eps(T) h = self.h R = np.zeros_like(T) R = -diff2(x, T) - eps*(T_inf**4 - T**4) - h*(T_inf - T) R[0] = T[0] R[-1] = T[-1] return R def calc_residual_jacobian(self, T, dT=1e-25): n = np.size(T) dRdT = np.zeros([n, n], dtype=T.dtype) for i in range(n): T[i] = T[i] + 1j*dT R = self.calc_residual(T) dRdT[:,i] = np.imag(R[:])/dT T[i] = T[i] - 1j*dT return dRdT def calc_dt(self): return self.dt*np.ones(self.n) def step(self, T, dt): R = self.calc_residual(T) dRdT = self.calc_residual_jacobian(T) dt = self.calc_dt() A = np.zeros_like(dRdT) n = self.n for i in range(0, n): A[i,i] = 1./dt[i] A = A - dRdT dT = linalg.solve(A, R) l2norm = np.sqrt(sum(R**2))/np.size(R) return dT, l2norm def boundary(self, T): plt.ion() plt.figure(1) plt.clf() plt.plot(self.x, T) plt.pause(0.0001) def save(self, T): if self.verbose: np.savetxt("solution/T", T.astype(np.float64)) np.savetxt("solution/x", self.x.astype(np.float64)) def solve(self): T = np.copy(self.T) dt = self.dt for i in range(self.maxiter): dT, l2norm = self.step(T, dt) T[:] = T[:] + dT[:] #self.boundary(T) if self.verbose: print "Iteration: %i Norm: %1.2e"%(i, l2norm) self.save(T) if l2norm < self.tol: break if l2norm > self.tol: print "DID NOT CONVERGE" self.T[:] = T[:] if l2norm > self.tol: return False else: return True def calc_delJ_delbeta(self, T, beta): n = np.size(beta) dbeta = 1e-20 dJdbeta = np.zeros_like(beta) for i in range(n): beta[i] = beta[i] + 1j*dbeta F = self.objective.objective(T, beta) dJdbeta[i] = np.imag(F)/dbeta beta[i] = beta[i] - 1j*dbeta return dJdbeta def calc_delJ_delT(self, T, beta): n = np.size(T) dT = 1e-30 dJdT = np.zeros_like(T) for i in range(n): T[i] = T[i] + 1j*dT F = self.objective.objective(T, beta) dJdT[i] = np.imag(F)/dT T[i] = T[i] - 1j*dT return dJdT def calc_delJ_delT_jac(self, T, beta, i): n = np.size(T) dT = 1e-30 dJdT = np.zeros_like(T) T[i] = T[i] + 1j*dT F = self.objective.objective_jac(T, beta, i) dJdT[i] = np.imag(F)/dT T[i] = T[i] - 1j*dT return dJdT def calc_psi(self, T, beta): dRdT = self.calc_residual_jacobian(T) dJdT = self.calc_delJ_delT(T, beta) psi = linalg.solve(dRdT.transpose(), -dJdT.transpose()) return psi def calc_psi_jac(self, T, beta, i): dRdT = self.calc_residual_jacobian(T) dJdT = self.calc_delJ_delT_jac(T, beta, i) psi = linalg.solve(dRdT.transpose(), -dJdT.transpose()) return psi def calc_delR_delbeta(self, T): nb = np.size(self.beta) n = np.size(T) dbeta = 1e-30 dRdbeta = np.zeros([n,nb], dtype=T.dtype) for i in range(nb): self.beta[i] = self.beta[i] + 1j*dbeta R = self.calc_residual(T) dRdbeta[:,i] = np.imag(R[:])/dbeta self.beta[i] = self.beta[i] - 1j*dbeta return dRdbeta def calc_sensitivity(self): T = self.T beta = self.beta psi = self.calc_psi(T, beta) delJdelbeta = self.calc_delJ_delbeta(T, beta) delRdelbeta = self.calc_delR_delbeta(T) dJdbeta = delJdelbeta + psi.transpose().dot(delRdelbeta) return dJdbeta def calc_sensitivity_jac(self, i): T = self.T beta = self.beta psi = self.calc_psi_jac(T, beta, i) delRdelbeta = self.calc_delR_delbeta(T) dJdbeta = psi.transpose().dot(delRdelbeta) return dJdbeta def calc_hessian_fd(self): n = np.size(self.T) H = np.zeros([n, n]) dbeta = 1e-5 beta = self.beta.copy() for i in range(n): self.beta[i] = beta[i] - dbeta self.solve() dJdbeta_jm = self.calc_sensitivity() self.beta[i] = beta[i] + dbeta self.solve() dJdbeta_jp = self.calc_sensitivity() H[i,:] = (dJdbeta_jp - dJdbeta_jm)/(2.0*dbeta) self.beta[:] = beta[:] return H def calc_post_cov(self): #nb = np.size(self.beta) #n = np.size(self.T) #jac = np.zeros([n, n]) #for i in range(n): # jac[i, :] = self.calc_sensitivity_jac(i) #H = jac.transpose().dot(jac)/self.objective.sigma_obs**2 + np.eye(n)/self.objective.sigma_prior**2 H = self.calc_hessian_fd() Cov = np.linalg.inv(H + 1e-10*np.eye(self.n)) return Cov def calc_beta(self, T): T_inf = self.T_inf eps = self.get_eps(T) beta = eps/self.eps_0 + self.h/self.eps_0*(T_inf - T)/((T_inf**4 - T**4) + 1e-16) return beta
class LaminarEquation(object): def __init__(self, y, u, Retau): self.y = np.copy(y) self.q = np.copy(u.astype(np.complex)) self.Retau = Retau # self.n = np.size(y) self.writedir = "." self.maxiter = 20 self.tol = 1e-13 self.dt = 1e10 self.neq = 1 self.nu = 1e-4 self.rho = 1.0 self.dp = calc_dp(self.Retau, self.nu) self.beta = np.ones_like(u) self.objective = TestObjective() def calc_residual(self, q): R = np.zeros_like(q) R[:] = self.calc_momentum_residual(q) return R def calc_momentum_residual(self, q): u = q[0:self.n] y = self.y uyy = diff2(y, u) R = self.beta*self.nu*uyy - self.dp/self.rho R[0] = -u[0] R[-1] = (1.5*u[-1] - 2.0*u[-2] + 0.5*u[-3])/(y[-1] - y[-2]) return R def calc_delJ_delbeta(self, q, beta): n = np.size(beta) dbeta = 1e-20 dJdbeta = np.zeros_like(beta) for i in range(n): beta[i] = beta[i] + 1j*dbeta F = self.objective.objective(q, beta) dJdbeta[i] = np.imag(F)/dbeta beta[i] = beta[i] - 1j*dbeta return dJdbeta def calc_delJ_delq(self, q, beta): n = np.size(q) dq = 1e-30 dJdq = np.zeros_like(q) for i in range(n): q[i] = q[i] + 1j*dq F = self.objective.objective(q, beta) dJdq[i] = np.imag(F)/dq q[i] = q[i] - 1j*dq return dJdq def calc_psi(self, q, beta): dRdq = self.calc_residual_jacobian(q).astype(np.complex) dJdq = self.calc_delJ_delq(q, beta) psi = linalg.solve(dRdq.transpose(), -dJdq.transpose()) return psi def calc_delR_delbeta(self, q): nb = np.size(self.beta) n = np.size(q) dbeta = 1e-30 dRdbeta = np.zeros([n,nb], dtype=q.dtype) for i in range(nb): self.beta[i] = self.beta[i] + 1j*dbeta R = self.calc_residual(q) dRdbeta[:,i] = np.imag(R[:])/dbeta self.beta[i] = self.beta[i] - 1j*dbeta return dRdbeta def calc_sensitivity(self): q = self.q.astype(np.complex) beta = self.beta.astype(np.complex) psi = self.calc_psi(q, beta) delJdelbeta = self.calc_delJ_delbeta(q, beta) delRdelbeta = self.calc_delR_delbeta(q) dJdbeta = delJdelbeta + psi.transpose().dot(delRdelbeta) return dJdbeta def calc_residual_jacobian(self, q, dq=1e-25): n = np.size(q) dRdq = np.zeros([n, n], dtype=q.dtype) for i in range(n): q[i] = q[i] + 1j*dq R = self.calc_residual(q) dRdq[:,i] = np.imag(R[:])/dq q[i] = q[i] - 1j*dq return dRdq def calc_dt(self): return self.dt*np.ones(self.n) def step(self, q, dt): R = self.calc_residual(q) dRdq = self.calc_residual_jacobian(q) dt = self.calc_dt() A = np.zeros_like(dRdq) n = self.n for i in range(0, n): A[i,i] = 1./dt[i] A = A - dRdq dq = linalg.solve(A, R) l2norm = np.sqrt(sum(R**2))/np.size(R) return dq, l2norm def boundary(self, q): pass def solve(self): q = np.copy(self.q) dt = self.dt for i in range(self.maxiter): dq, l2norm = self.step(q, dt) q[:] = q[:] + dq[:] self.boundary(q) if self.verbose: print "Iteration: %i Norm: %1.2e"%(i, l2norm) self.save(q) if l2norm < self.tol: self.postprocess(q) break self.postprocess(q) self.q[:] = q[:] if l2norm > 1e-2: return True else: return False def plot(self): plt.figure(1) plt.plot(self.y, self.q[0:self.n], 'r-') plt.show() def postprocess(self, q): q = q.astype(np.float64) n = self.n u = q[0:n] self.utau = self.Retau*self.nu*2.0 self.yp = self.y*self.utau/self.nu self.up = u/self.utau self.uap = self.analytic_solution()/self.utau def save(self, q): q = q.astype(np.float64) n = self.n u = q[0:n] np.savetxt("%s/u"%self.writedir, u) def analytic_solution(self): return self.dp/(2*self.nu*self.rho)*(self.y**2 - self.y)
class LaminarEquation(object): def __init__(self, y, u, Retau): self.y = np.copy(y) self.q = np.copy(u.astype(np.float)) self.Retau = Retau self.verbose = True self.n = np.size(y) self.writedir = "." self.maxiter = 20 self.tol = 1e-13 self.dt = 1e10 self.neq = 1 self.nu = 1e-4 self.rho = 1.0 self.dp = calc_dp(self.Retau, self.nu) self.beta = np.ones_like(u) self.objective = TestObjective() def calc_residual(self, q, dtype=None): R = np.zeros_like(q) if dtype == ad.adouble: R = ad.adouble(R) R[:] = self.calc_momentum_residual(q) return R def calc_momentum_residual(self, q): u = q[0:self.n] y = self.y uyy = diff2(y, u) R = self.beta * self.nu * uyy - self.dp / self.rho R[0] = -u[0] R[-1] = (1.5 * u[-1] - 2.0 * u[-2] + 0.5 * u[-3]) / (y[-1] - y[-2]) return R def calc_delJ_delbeta(self, q, beta): n = np.size(beta) beta_c = beta.copy() beta = ad.adouble(beta) tag = 1 ad.trace_on(tag) ad.independent(beta) F = self.objective.objective(q, beta) #print ad.value(F) ad.dependent(F) ad.trace_off() beta = beta_c dJdbeta = calc_jacobian(beta, tag=tag, sparse=False) return dJdbeta def calc_delJ_delq(self, q, beta): n = np.size(q) q_c = q.copy() q = ad.adouble(q) tag = 2 ad.trace_on(tag) ad.independent(q) F = self.objective.objective(q, beta) ad.dependent(F) ad.trace_off() q = q_c dJdq = calc_jacobian(q, tag=tag, sparse=False) return dJdq def calc_psi(self, q, beta): dRdq = self.calc_residual_jacobian(q).astype(np.float) dJdq = self.calc_delJ_delq(q, beta) psi = linalg.solve(dRdq.transpose(), -dJdq.transpose()) return psi def calc_delR_delbeta(self, q): nb = np.size(self.beta) n = np.size(q) beta_c = self.beta.copy() self.beta = ad.adouble(self.beta) tag = 3 ad.trace_on(tag) ad.independent(self.beta) R = self.calc_residual(q, dtype=ad.adouble) ad.dependent(R) ad.trace_off() self.beta = beta_c dRdbeta = calc_jacobian(self.beta, tag=tag, sparse=False) return dRdbeta def calc_sensitivity(self): q = self.q.astype(np.float) #print self.beta beta = self.beta.astype(np.float) psi = self.calc_psi(q, beta) delJdelbeta = self.calc_delJ_delbeta(q, beta) delRdelbeta = self.calc_delR_delbeta(q) dJdbeta = delJdelbeta + psi.transpose().dot(delRdelbeta) return dJdbeta.reshape(beta.shape) def calc_sensitivity_fd(self, dbeta=1e-4): n = self.beta.size q = self.q beta = self.beta F = self.objective.objective(q, beta) dJdbeta = np.zeros_like(beta) Fb = self.objective.objective(q, beta) for i in range(n): beta[i] += dbeta self.solve() F = self.objective.objective(q, beta) beta[i] -= dbeta dJdbeta[i] = (F - Fb) / dbeta return dJdbeta def calc_residual_jacobian(self, q, dq=1e-25): n = np.size(q) q_c = q.copy() q = ad.adouble(q) tag = 0 ad.trace_on(tag) ad.independent(q) R = self.calc_residual(q) ad.dependent(R) ad.trace_off() options = np.array([0, 0, 0, 0], dtype=int) q = q_c dRdq = calc_jacobian(q, tag=tag, shape=(n, n)) #pat = ad.sparse.jac_pat(tag, q_c, options) #if 1: # result = ad.colpack.sparse_jac_no_repeat(tag, q, options) #else: # result = ad.colpack.sparse_jac_repeat(tag, q, nnz, ridx, cidx, values) #nnz = result[0] #ridx = result[1] #cidx = result[2] #values = result[3] #dRdq = sp.csr_matrix((values, (ridx, cidx)), shape=(n, n)) #dRdq = np.zeros([n, n], dtype=q.dtype) #for i in range(n): # q[i] = q[i] + 1j*dq # R = self.calc_residual(q) # dRdq[:,i] = np.imag(R[:])/dq # q[i] = q[i] - 1j*dq return dRdq def calc_dt(self): return self.dt * np.ones(self.n) def step(self, q, dt): R = self.calc_residual(q) dRdq = self.calc_residual_jacobian(q) dt = self.calc_dt() A = np.zeros_like(dRdq) n = self.n for i in range(0, n): A[i, i] = 1. / dt[i] A = A - dRdq dq = linalg.solve(A, R) l2norm = np.sqrt(sum(R**2)) / np.size(R) return dq, l2norm def boundary(self, q): pass def solve(self): q = np.copy(self.q) dt = self.dt for i in range(self.maxiter): dq, l2norm = self.step(q, dt) q[:] = q[:] + dq[:] self.boundary(q) if self.verbose: print "Iteration: %i Norm: %1.2e" % (i, l2norm) self.save(q) if l2norm < self.tol: self.postprocess(q) break self.postprocess(q) self.q[:] = q[:] if l2norm > 1e-2: return True else: return False def plot(self): plt.figure(1) plt.plot(self.y, self.q[0:self.n], 'r-') plt.show() def postprocess(self, q): q = q.astype(np.float64) n = self.n u = q[0:n] self.utau = self.Retau * self.nu * 2.0 self.yp = self.y * self.utau / self.nu self.up = u / self.utau self.uap = self.analytic_solution() / self.utau def save(self, q): q = q.astype(np.float64) n = self.n u = q[0:n] np.savetxt("%s/u" % self.writedir, u) def analytic_solution(self): return self.dp / (2 * self.nu * self.rho) * (self.y**2 - self.y)