def f(u): x, p = u[:3 * n], u[3 * n:6 * n] #lambc = lamb v = u[6 * n:] v = v.reshape((N, 1)) lambc = lamb + v x = x.reshape((n, 3)) p = p.reshape((n, 3)) dfdu = dfdu_lorenz(ad.array(xs[:-1]), 28, mod=ad) * dt + ad.eye(3).reshape( (1, 3, 3)) dJdu = dJdu_obj(ad.array(xs[:-1]), mod=ad) #dJdu = 0. fx = x[1:] + p[1:] * dot(x[:-1], x[:-1]).reshape( (-1, 1)) / lambc - dot(dfdu, x[:-1].reshape((N, 1, 3))) - dJdu fp = p[:-1] + x[:-1] * dot(p[1:], p[1:]).reshape( (-1, 1)) / lambc - x[:-1] - dot(dfdu.transpose( (0, 2, 1)), p[1:].reshape((N, 1, 3))) #return ad.concatenate((x[0]-ad.array(ti.flatten()), ad.ravel(fx), ad.ravel(fp), p[-1]-x[-1])) ##constraint #cons = 1e-2 cons = 1e-4 frob = dot(x[:-1], x[:-1]) * dot(p[1:], p[1:]) / (ad.ravel(lamb)**2) return ad.concatenate( (x[0] - ad.array(ti.flatten()), ad.ravel(fx), ad.ravel(fp), p[-1] - x[-1], ad.ravel(v) * (frob - cons)))
def set_coeff(self, x): # given a value for the parameters (KL coefficients), # construct the coefficients of the differential operator _e = 2.7182818284590451 self.x = npd.array(x.reshape((self.m, 1))) a = npd.dot(self.B, self.x) self.a = _e**a.reshape((self.nx, self.nx))
def recomputeForNumpad(u0, dt): assert len(u0) == len(dt) * 3 + 1 u = [ad.array(u0[0])] for i in len(dt): u1, u2, u3, u2nd = step(f, u[-1], dt[i], u0[i*3+1:i*3+4]) u.extend([u1, u2, u3]) return u, dt
def testHarmonicOscillator(self): T, N = 10, 100 u0 = ad.array([1., 0.]) t = np.linspace(0, T, N) u1 = pdeint(lambda u : ad.hstack([u[1], -u[0]]), u0, t) u2 = pdeint(lambda u : ad.hstack([u[1], -u[0]]), u0, [0, T]) accuracy = np.linalg.norm(ad.value(u1[-1] - u2[-1])) self.assertLess(accuracy, 5E-4)
def pdeint(f, u0, t, relTol=1E-4, absTol=1E-6, ret='array', disp=0): ''' To be used like ode23s, using numpad for Jacobian ''' def _roundTo2ToK(n): log2n = np.log2(max(1, n)) return 2**int(round(log2n)) u = ad.array(u0).copy() uHistory = [u] uTrajectory = Trajectory(f, ad.value(u)) dt = t[1] - t[0] for i in range(len(t) - 1): iSubdiv, nSubdiv = 0, _roundTo2ToK((t[i+1] - t[i]) / dt) dt = (t[i+1] - t[i]) / nSubdiv while iSubdiv < nSubdiv: uTmp1, uTmp2, u3rd, u2nd = step(f, u, dt) uNorm = np.linalg.norm(ad.value(u)) errNorm = np.linalg.norm(ad.value(u3rd) - ad.value(u2nd)) if errNorm > max(absTol, relTol * uNorm): dt, iSubdiv, nSubdiv = 0.5 * dt, 2 * iSubdiv, 2 * nSubdiv else: iSubdiv += 1 u = u3rd uTrajectory.append(ad.value(uTmp1), ad.value(uTmp2), ad.value(u), dt) if ret == 'array': u.obliviate() if disp: print(t[i] + (t[i+1] - t[i]) * iSubdiv / nSubdiv) if errNorm < 0.25 * max(absTol, relTol * uNorm) and \ iSubdiv % 2 == 0 and nSubdiv > 1: dt, iSubdiv, nSubdiv = 2 * dt, iSubdiv / 2, nSubdiv / 2 assert iSubdiv == nSubdiv uHistory.append(u) if ret == 'array': return np.array([ad.value(u) for u in uHistory]) elif ret == 'list': return uHistory elif ret == 'trajectory': return uTrajectory
##constraint #cons = 1e-2 cons = 1e-4 frob = dot(x[:-1], x[:-1]) * dot(p[1:], p[1:]) / (ad.ravel(lamb)**2) return ad.concatenate( (x[0] - ad.array(ti.flatten()), ad.ravel(fx), ad.ravel(fp), p[-1] - x[-1], ad.ravel(v) * (frob - cons))) xi = ts.flatten() pi = xi #u0 = np.concatenate((xi, pi)) v = np.zeros(N) u0 = np.concatenate((xi, pi, v)) u0 = ad.array(u0) u = ad.solve(f, u0, max_iter=1000, rel_tol=1e-12, abs_tol=1e-6) x, p = u[:3 * n]._value, u[3 * n:6 * n]._value x = x.reshape(n, 3) p = p.reshape(n, 3) #L = p[1:].reshape(N, 1, 3)*x[:-1].reshape(N, 3, 1)/lamb v = u[6 * n:]._value L = p[1:].reshape(N, 1, 3) * x[:-1].reshape(N, 3, 1) / (lamb + v.reshape(N, 1, 1))**2 plt.plot(x) #plt.plot(v) plt.show() #plt.plot(p) #plt.plot(dot(x[:-1], x[:-1])*dot(p[1:], p[1:])/(100.+v)**2) plt.plot(L[:, :, 0])
def adjoint(Jc,uc,etac,wc,u_adjc,eta_adjc,w_adjc,Guc,Getac,Gwc,muc): # uses global variables: J,u,eta,w,u_adj,eta_adj,w_adj,Gu,Geta,Gw, mu # compute adjoint updates dJdu = np.array(Jc.diff(uc).todense()).reshape(u_adjc.shape) Gu_u_adj = (Guc * u_adjc).sum() Geta_eta_adj = (Getac * eta_adjc).sum() Gw_w_adj = (Gwc * w_adjc).sum() # wrt u dGu_du = np.array((Gu_u_adj).diff(uc)).reshape(u_adjc.shape) dGeta_du = np.array((Geta_eta_adj).diff(uc)).reshape(u_adjc.shape) dGw_du = np.array((Gw_w_adj).diff(uc)).reshape(u_adjc.shape) dNdu = dJdu + dGu_du + dGeta_du + dGw_du # wrt eta dGu_deta = np.array((Gu_u_adj).diff(etac)).reshape(eta_adjc.shape) dGeta_deta = np.array((Geta_eta_adj).diff(etac)).reshape(eta_adjc.shape) dGw_deta = np.array((Gw_w_adj).diff(etac)).reshape(eta_adjc.shape) dNdeta = dGu_deta + dGeta_deta + dGw_deta # wrt w dGu_dw = np.array((Gu_u_adj).diff(wc)).reshape(w_adjc.shape) dGeta_dw = np.array((Geta_eta_adj).diff(wc)).reshape(w_adjc.shape) dGw_dw = np.array((Gw_w_adj).diff(wc)).reshape(w_adjc.shape) dNdw = dGu_dw + dGeta_dw + dGw_dw # wrt mu dGu_dmu = np.array(Gu_u_adj.diff(muc)) dGeta_dmu = np.array(Geta_eta_adj.diff(muc)) dGw_dmu = np.array(Gw_w_adj.diff(muc)) #compute reduced gradient red_grad = dGu_dmu + dGeta_dmu + dGw_dmu return dNdu, dNdeta, dNdw, red_grad.reshape(Jc.shape)
#initialize optimization loop ERR='' maxNiter = 1 # number of inner primal/adjoint Newton updates maxOiter = 1000 # number of optimization steps atol = 1e-7 # absolute tolerance for primal and adjoint convergence redtol = 1e-7 # absolute tolerance of reduced gradient stepsize = 1e-1 # step size for design updates # initialize Van-der-Pol setting if CASE == 'vanderpol': mu = 0.9 param = mu u0 = np.array([0.5,0.5]) dt,T = 0.01,10 tmp=int(T / dt) t = 30 + dt * np.arange(tmp) f = lambda u, t: vanderpol(u, mu) # init optimization target = 2.8 elif CASE == 'lorenz': params = np.linspace(27, 28, 5) param = params[0] u0 = np.array([0.5,0.5,0.5]) dt,T = 0.01, 10.0 t = 30 + dt * np.arange(int(T / dt)) f = lambda u, t: lorenz(u, param) target = 22.5