def evaluate(solution): x = solution["parameters"] m = 3 coll = CollGaussRadau_Right(num_nodes=m, tleft=0.0, tright=1.0) # coll = CollGaussLobatto(num_nodes=m, tleft=0.0, tright=1.0) # coll = EquidistantNoLeft(num_nodes=m, tleft=0.0, tright=1.0) Q = coll.Qmat[1:, 1:] var = [x['x'+str(j)] for j in range(1, m + 1)] # var = [x['x' + str(j) + 'r'] + 1j * x['x' + str(j) + 'i'] for j in range(1, m + 1)] Qd = np.diag(var) # THIS WORKS REALLY WELL! No need to take imaginary parts in x, though (found minimum has zero imaginary parts) k = 0 obj_val = 0.0 for i in range(-8, 8): for l in range(-8, 8): k += 1 lamdt = -10 ** i + 1j * 10 ** l R = lamdt * np.linalg.inv(np.eye(m) - lamdt * Qd).dot(Q - Qd) rhoR = max(abs(np.linalg.eigvals(np.linalg.matrix_power(R, 1)))) obj_val += rhoR obj_val /= k solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution
def evaluate(solution): x = solution["parameters"] m = 5 coll = CollGaussRadau_Right(num_nodes=m, tleft=0.0, tright=1.0) Q = coll.Qmat[1:, 1:] var = [x['x' + str(j)] for j in range(1, m)] # var = [x['x' + str(j) + 'r'] + 1j * x['x' + str(j) + 'i'] for j in range(1, m + 1)] Qd = np.zeros((m, m)) Qd[1, 0] = var[0] Qd[2, 1] = var[1] Qd[3, 2] = var[2] Qd[4, 3] = var[3] # THIS WORKS REALLY WELL! No need to take imaginary parts in x, though (found minimum has zero imaginary parts) k = 0 obj_val = 0.0 for i in range(-8, 1): for l in range(-8, 1): k += 1 lamdt = -10**i + 1j * 10**l R = lamdt * np.linalg.inv(np.eye(m) - lamdt * Qd).dot(Q - Qd) rhoR = max(abs(np.linalg.eigvals(R))) obj_val += rhoR obj_val /= k solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution
def evaluate(solution): x = solution["parameters"] m = 5 coll = CollGaussRadau_Right(num_nodes=m, tleft=0.0, tright=1.0) Q = coll.Qmat[1:, 1:] Qd = np.array([[x['x11'], x['x12'], x['x13'], x['x14'], x['x15']], [0.0, x['x22'], x['x23'], x['x24'], x['x25']], [0.0, 0.0, x['x33'], x['x34'], x['x35']], [0.0, 0.0, 0.0, x['x44'], x['x45']], [0.0, 0.0, 0.0, 0.0, x['x55']]]) k = 0 obj_val = 0.0 for i in range(-8, 8): for l in range(-8, 8): k += 1 lamdt = -10**i + 1j * 10**l R = lamdt * np.linalg.inv(np.eye(m) - lamdt * Qd).dot(Q - Qd) rhoR = max(abs(np.linalg.eigvals(R))) obj_val += rhoR obj_val /= k solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution
def iterate(x, k_impl, k_expl, _u0, N): k = k_impl + k_expl coll = CollGaussRadau_Right(num_nodes, 0, 1) Q = coll.Qmat[1:, 1:] C = identity(num_nodes*N) - dt * scipy.sparse.kron(Q, sp.diags(k)) u0 = np.concatenate((_u0, _u0, _u0), axis=None) u = np.concatenate((_u0, _u0, _u0), axis=None) print("u", u) Qdmat = np.zeros_like(Q) np.fill_diagonal(Qdmat, x) QD_expl = np.zeros(Q.shape) for m in range(coll.num_nodes): QD_expl[m, 0:m] = coll.delta_m[0:m] mat0_i =[] mat1_i =[] mat2_i =[] for i in k_impl: #hier wuerde jetzt von RL fuer jedes kappa ein Qd gewaehlt werden mat0_i = np.concatenate((mat0_i, x[0]*i), axis=None) mat1_i = np.concatenate((mat1_i, x[1]*i), axis=None) mat2_i = np.concatenate((mat2_i, x[2]*i), axis=None) mat_i = sp.diags(np.concatenate((mat0_i, mat1_i, mat2_i), axis=None) ) Pinv_impl = np.linalg.inv( np.eye(coll.num_nodes*N) - dt * ( mat_i + scipy.sparse.kron(QD_expl, sp.diags(k_expl)) ) , ) residual = u0 - C @ u done = False err = False niter = 0 while not done and not niter >= 50 and not err: niter += 1 u = np.squeeze( np.array( u + Pinv_impl @ (u0 - C @ u) )) residual = np.squeeze( np.array( u0 - C @ u )) norm_res = np.linalg.norm(residual, np.inf) print(norm_res) if np.isnan(norm_res) or np.isinf(norm_res): niter = 51 break done = norm_res < restol print("niter", niter) return niter, u
def calc_default_initial_residual(M, lam, dt): coll = CollGaussRadau_Right(M, 0, 1) Q = coll.Qmat[1:, 1:] return ((np.ones(coll.num_nodes, dtype=np.complex128)) - (np.eye(coll.num_nodes) - lam * dt * Q) @ (np.ones(coll.num_nodes, dtype=np.complex128)))
def __init__( self, M, lambda_real_interval, lambda_imag_interval, ): super().__init__() self.M = M self.coll = CollGaussRadau_Right(M, 0, 1) self.Q = self.coll.Qmat[1:, 1:] self.lambda_real_interval = lambda_real_interval self.lambda_imag_interval = lambda_imag_interval
def evaluate(solution): x = solution["parameters"] m = 5 coll = CollGaussRadau_Right(num_nodes=m, tleft=0.0, tright=1.0) Q = coll.Qmat[1:, 1:] var = [x['x'+str(j)] for j in range(1, m + 1)] obj_val = max(abs(np.linalg.eigvals(np.eye(m) - np.diag(var).dot(Q)))) solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution
def evaluate(solution): x = solution["parameters"] m = 3 coll = CollGaussRadau_Right(num_nodes=m, tleft=0.0, tright=1.0) # coll = CollGaussLobatto(num_nodes=m, tleft=0.0, tright=1.0) # coll = EquidistantNoLeft(num_nodes=m, tleft=0.0, tright=1.0) # print(coll.nodes) # exit() Q = coll.Qmat[1:, 1:] var = [x['x'+str(j)] for j in range(1, m + 1)] # var = [x['x' + str(j) + 'r'] + 1j * x['x' + str(j) + 'i'] for j in range(1, m + 1)] Qd = np.diag(var) nsteps = 4 E = np.zeros((nsteps, nsteps)) np.fill_diagonal(E[1:, :], 1) Ea = E.copy() # Ea[0, -1] = 0.125 # Ea = np.zeros(E.shape) # Da, Va = np.linalg.eig(Ea) # Via = np.linalg.inv(Va) N = np.zeros((m, m)) N[:, -1] = 1 # THIS WORKS REALLY WELL! No need to take imaginary parts in x, though (found minimum has zero imaginary parts) k = 0 obj_val = 0.0 for i in range(-8, 8): for l in range(-8, 8): k += 1 lamdt = -10 ** i + 1j * 10 ** l Rf = np.linalg.inv(np.eye(nsteps * m) - lamdt * np.kron(np.eye(nsteps), Qd)).dot(lamdt * np.kron(np.eye(nsteps), Q - Qd) + np.kron(E, N)) Rc = np.linalg.inv(np.eye(nsteps * m) - lamdt * np.kron(np.eye(nsteps), Qd) - np.kron(E, N)).dot(lamdt * np.kron(np.eye(nsteps), Q - Qd)) rhoR = max(abs(np.linalg.eigvals(Rc.dot(Rf)))) obj_val += rhoR obj_val /= k solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution
def iterate(x, k, _u0): coll = CollGaussRadau_Right(num_nodes, 0, 1) Q = coll.Qmat[1:, 1:] C = identity(num_nodes*N) - dt * scipy.sparse.kron(Q, sp.diags(k)) u0 = np.concatenate((_u0, _u0, _u0), axis=None) u = np.concatenate((_u0, _u0, _u0), axis=None) Qdmat = np.zeros_like(Q) np.fill_diagonal(Qdmat, x) mat0 =[] mat1 =[] mat2 =[] for i in k: #hier wuerde jetzt von RL fuer jedes kappa ein Qd gewaehlt werden mat0 = np.concatenate((mat0, x[0]*i), axis=None) mat1 = np.concatenate((mat1, x[1]*i), axis=None) mat2 = np.concatenate((mat2, x[2]*i), axis=None) mat = sp.diags(np.concatenate((mat0, mat1, mat2), axis=None) ) Pinv = np.linalg.inv( np.eye(coll.num_nodes*N) - dt * mat, ) residual = u0 - C @ u done = False err = False niter = 0 while not done and not niter >= 50 and not err: niter += 1 u = np.squeeze( np.array( u + Pinv @ (u0 - C @ u) )) residual = np.squeeze( np.array( u0 - C @ u )) norm_res = np.linalg.norm(residual, np.inf) if np.isnan(norm_res) or np.isinf(norm_res): niter = 51 break done = norm_res < restol return niter, u
def main(): """ A simple test program to compute the order of accuracy in time """ # initialize problem parameters problem_params = {} problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 4 # frequency for the test value problem_params['nvars'] = 16383 # number of DOFs in space # instantiate problem prob = heat1d(problem_params=problem_params, dtype_u=mesh, dtype_f=mesh) # instantiate collocation class, relative to the time interval [0,1] coll = CollGaussRadau_Right(num_nodes=3, tleft=0, tright=1) # assemble list of dt dt_list = [0.1 / 2**p for p in range(0, 4)] # run accuracy test for all dt results = run_accuracy_check(prob=prob, coll=coll, dt_list=dt_list) # get order of accuracy order = get_accuracy_order(results) f = open('step_1_D_out.txt', 'w') for l in range(len(order)): out = 'Expected order: %2i -- Computed order %4.3f' % (5, order[l]) f.write(out + '\n') print(out) f.close() # visualize results plot_accuracy(results) assert os.path.isfile('step_1_accuracy_test_coll.png') assert all( np.isclose(order, 2 * coll.num_nodes - 1, rtol=0.4) ), "ERROR: did not get order of accuracy as expected, got %s" % order
def __init__( self, M, lambda_real_interval, lambda_imag_interval, batch_size, rng_key, ): super().__init__() self.M = M self.coll = CollGaussRadau_Right(M, 0, 1) self.Q = self.coll.Qmat[1:, 1:] self.lambda_real_interval = lambda_real_interval self.lambda_imag_interval = lambda_imag_interval self.batch_size = batch_size self.rng_key = rng_key self.lam_real_low = self.lambda_real_interval[0] self.lam_real_high = self.lambda_real_interval[1] self.lam_imag_low = self.lambda_imag_interval[0] self.lam_imag_high = self.lambda_imag_interval[1]
def compute_and_plot_specrad(): """ Compute and plot spectral radius of smoother iteration matrix for a whole range of eigenvalues """ # setup_list = [('LU', 'to0'), ('LU', 'toinf'), ('IE', 'to0'), ('IE', 'toinf')] # setup_list = [('LU', 'to0'), ('LU', 'toinf')] # setup_list = [('IE', 'to0'), ('IE', 'toinf')] # setup_list = [('LU', 'toinf'), ('IE', 'toinf')] setup_list = [('IE', 'full'), ('LU', 'full')] # setup_list = [('EX', 'to0'), ('PIC', 'to0')] # set up plotting parameters params = { 'legend.fontsize': 24, 'figure.figsize': (12, 8), 'axes.labelsize': 24, 'axes.titlesize': 24, 'xtick.labelsize': 24, 'ytick.labelsize': 24, 'lines.linewidth': 3 } plt.rcParams.update(params) Nnodes = 3 Nsteps = 4 coll = CollGaussRadau_Right(Nnodes, 0, 1) Qmat = coll.Qmat[1:, 1:] Nmat = np.zeros((Nnodes, Nnodes)) Nmat[:, -1] = 1 Emat = np.zeros((Nsteps, Nsteps)) np.fill_diagonal(Emat[1:, :], 1) for qd_type, conv_type in setup_list: if qd_type == 'LU': QT = coll.Qmat[1:, 1:].T [_, _, U] = LA.lu(QT, overwrite_a=True) QDmat = U.T elif qd_type == 'IE': QI = np.zeros(np.shape(coll.Qmat)) for m in range(coll.num_nodes + 1): QI[m, 1:m + 1] = coll.delta_m[0:m] QDmat = QI[1:, 1:] elif qd_type == 'EE': QE = np.zeros(np.shape(coll.Qmat)) for m in range(coll.num_nodes + 1): QE[m, 0:m] = coll.delta_m[0:m] QDmat = QE[1:, 1:] elif qd_type == 'PIC': QDmat = np.zeros(np.shape(coll.Qmat[1:, 1:])) elif qd_type == 'EX': QT = coll.Qmat[1:, 1:].T [_, _, U] = LA.lu(QT, overwrite_a=True) QDmat = np.tril(U.T, k=-1) print(QDmat) else: raise NotImplementedError('qd_type %s is not implemented' % qd_type) # lim_specrad = max(abs(np.linalg.eigvals(np.eye(Nnodes) - np.linalg.inv(QDmat).dot(Qmat)))) # print('qd_type: %s -- lim_specrad: %6.4e -- conv_type: %s' % (qd_type, lim_specrad, conv_type)) if conv_type == 'to0': ilim_left = -4 ilim_right = 2 rlim_left = 2 rlim_right = -4 elif conv_type == 'toinf': ilim_left = 0 ilim_right = 11 rlim_left = 6 rlim_right = 0 elif conv_type == 'full': ilim_left = -10 ilim_right = 11 rlim_left = 10 rlim_right = -11 else: raise NotImplementedError('conv_type %s is not implemented' % conv_type) ilam_list = 1j * np.logspace(ilim_left, ilim_right, 201) rlam_list = -1 * np.logspace(rlim_left, rlim_right, 201) assert (rlim_right - rlim_left + 1) % 5 == 0 assert (ilim_right - ilim_left - 1) % 5 == 0 assert (len(rlam_list) - 1) % 5 == 0 assert (len(ilam_list) - 1) % 5 == 0 Prho = np.zeros((len(rlam_list), len(ilam_list))) for idr, rlam in enumerate(rlam_list): for idi, ilam in enumerate(ilam_list): dxlam = rlam + ilam mat = np.linalg.inv( np.eye(Nnodes * Nsteps) - dxlam * np.kron(np.eye(Nsteps), QDmat)).dot( dxlam * np.kron(np.eye(Nsteps), (Qmat - QDmat)) + np.kron(Emat, Nmat)) mat = np.linalg.matrix_power(mat, Nnodes) Prho[idr, idi] = max(abs(np.linalg.eigvals(mat))) print(np.amax(Prho)) fig, ax = plt.subplots(figsize=(15, 10)) ax.set_xticks([ i + 0.5 for i in range(0, len(rlam_list), int(len(rlam_list) / 5)) ]) ax.set_xticklabels([ r'-$10^{%d}$' % i for i in range( rlim_left, rlim_right, int((rlim_right - rlim_left + 1) / 5)) ]) ax.set_yticks([ i + 0.5 for i in range(0, len(ilam_list), int(len(ilam_list) / 5)) ]) ax.set_yticklabels([ r'$10^{%d}i$' % i for i in range( ilim_left, ilim_right, int((ilim_right - ilim_left - 1) / 5)) ]) cmap = plt.get_cmap('Reds') pcol = plt.pcolor(Prho.T, cmap=cmap, norm=LogNorm(vmin=1E-09, vmax=1E-00)) plt.colorbar(pcol) plt.xlabel(r'$Re(\Delta t\lambda)$') plt.ylabel(r'$Im(\Delta t\lambda)$') fname = 'data/heatmap_smoother_' + conv_type + '_Nsteps' + str(Nsteps) + '_M' + \ str(Nnodes) + '_' + qd_type + '.png' plt.savefig(fname, rasterized=True, transparent=True, bbox_inches='tight')
def compute_and_plot_specrad(Nnodes, lam): """ Compute and plot the spectral radius of the smoother for different step-sizes Args: Nnodes: number of collocation nodes lam: test parameter representing the spatial problem """ coll = CollGaussRadau_Right(Nnodes, 0, 1) Qmat = coll.Qmat[1:, 1:] # do LU decomposition of QT (St. Martin's trick) QT = coll.Qmat[1:, 1:].T [_, _, U] = LA.lu(QT, overwrite_a=True) QDmat = U.T Nmat = np.zeros((Nnodes, Nnodes)) Nmat[:, -1] = 1 Nsteps_list = [64, 256] color_list = ['red', 'blue'] marker_list = ['s', 'o'] setup_list = zip(Nsteps_list, color_list, marker_list) xlist = [0.1**i for i in range(11)] rc('font', **{"sans-serif": ["Arial"], "size": 24}) plt.subplots(figsize=(15, 10)) for Nsteps, color, marker in setup_list: Emat = np.zeros((Nsteps, Nsteps)) np.fill_diagonal(Emat[1:, :], 1) Prho_list = [] predict_list = [] for x in xlist: mat = np.linalg.inv( np.eye(Nnodes * Nsteps) - x * lam * np.kron(np.eye(Nsteps), QDmat)).dot( x * lam * np.kron(np.eye(Nsteps), (Qmat - QDmat)) + np.kron(Emat, Nmat)) Prho_list.append(max(abs(np.linalg.eigvals(mat)))) # predict_list.append((1 + x) ** (1.0 - 1.0 / (Nnodes * Nsteps)) * x ** (1.0 / (Nnodes * Nsteps))) predict_list.append(x**(1.0 / (Nsteps))) if len(predict_list) > 1: print(x, predict_list[-1], Prho_list[-1], Prho_list[-2] / Prho_list[-1], predict_list[-2] / predict_list[-1]) plt.loglog(xlist, Prho_list, linestyle='-', linewidth=3, color=color, marker=marker, markersize=10, label='spectral radius, L=' + str(Nsteps)) plt.loglog(xlist, [item for item in predict_list], linestyle='--', linewidth=2, color=color, marker=marker, markersize=10, label='estimate, L=' + str(Nsteps)) ax = plt.gca() ax.invert_xaxis() plt.xlabel('time-step size') plt.ylabel('spectral radius') plt.legend(loc=3, numpoints=1) plt.grid() plt.ylim([1E-02, 1E01]) if type(lam) is complex: fname = 'data/smoother_specrad_to0_L64+256_M' + str( Nnodes) + 'LU_imag.png' else: fname = 'data/smoother_specrad_to0_L64+256_M' + str( Nnodes) + 'LU_real.png' plt.savefig(fname, rasterized=True, transparent=True, bbox_inches='tight')
def __init__(self, M, dt): coll = CollGaussRadau_Right(M, 0, 1) self.Q = jnp.array(coll.Qmat[1:, 1:]) self.M = M self.dt = dt
def __init__( self, M=None, dt=None, restol=None, prec=None, seed=None, lambda_real_interval=[-100, 0], lambda_imag_interval=[0, 0], lambda_real_interpolation_interval=None, norm_factor=1, residual_weight=0.5, step_penalty=0.1, reward_iteration_only=None, reward_strategy='iteration_only', collect_states=False, use_doubles=True, do_scale=True, example=1, #0 = TestEquation nvars=1000, dtype=np.complex128, #np.float64, model=None, params=None, nu=None, imex=True): self.np_random = None self.niter = None self.restol = restol self.dt = dt self.M = M self.coll = CollGaussRadau_Right(M, 0, 1) self.num_nodes = self.coll.num_nodes self.Q = self.coll.Qmat[1:, 1:] self.C = None self.lam = None #self.u0 = np.ones(M, dtype=np.complex128) self.old_res = None self.prec = prec self.initial_residual = None self.initial_residual_time = None if (example == 0): print("running TEST-Equation") self.nvars = 1 elif (example == 1): print("running Heat-Equation") self.nvars = nvars self.nu = nu self.imex = imex self.model = model self.params = params self.example = example self.dtype = np.complex128 self.prob = None self.linear = False self.lambda_real_interval = lambda_real_interval self.lambda_real_interval_reversed = list( reversed(lambda_real_interval)) self.lambda_imag_interval = lambda_imag_interval self.lambda_real_interpolation_interval = \ lambda_real_interpolation_interval self.norm_factor = norm_factor self.residual_weight = residual_weight self.step_penalty = step_penalty if reward_iteration_only is None: self.reward_strategy = reward_strategy.lower() elif reward_iteration_only: self.reward_strategy = 'iteration_only' else: self.reward_strategy = 'residual_change' self.collect_states = False #collect_states self.do_scale = do_scale self.num_episodes = 0 # self.rewards = [] # self.episode_rewards = [] # self.norm _resids = [] # Setting the spaces: both are continuous, observation box # artificially bounded by some large numbers # note that because lambda can be complex, U can be complex, # i.e. the observation space should be complex self.observation_space = spaces.Box( low=-1E10, high=+1E10, shape=(M * self.nvars * 2, self.max_iters) if collect_states else (2, M * self.nvars), dtype=np.complex128, ) # I read somewhere that the actions should be scaled to [-1,1], # values will be real. self.action_space = spaces.Box( low=-1.0, high=1.0, shape=(M, ), dtype=np.float64 if use_doubles else np.float32, ) self.seed(seed) self.state = None if collect_states: self.old_states = np.zeros((M * 2, self.max_iters), dtype=np.complex128)
def SDC(): M = 9 Mc = int((M + 1) / 2) # Mc = 1 dt = 1.0 lamb = -1.0 tol = 1E-10 coll = CollGaussRadau_Right(M, 0, 1) collc = CollGaussRadau_Right(Mc, 0, 1) collc2 = CollGaussRadau_Right(1, 0, 1) Q = coll.Qmat[1:,1:] Qc = collc.Qmat[1:,1:] Qc2 = collc2.Qmat[1:,1:] _, _, U = sp.linalg.lu(Q.T, overwrite_a=False) Qd = U.T _, _, U = sp.linalg.lu(Qc.T, overwrite_a=False) Qdc = U.T _, _, U = sp.linalg.lu(Qc2.T, overwrite_a=False) Qdc2 = U.T # Qd = np.zeros((M, M)) # Qdc = np.zeros((Mc,Mc)) I = get_transfer_matrix_Q(coll.nodes, collc.nodes) R = get_transfer_matrix_Q(collc.nodes, coll.nodes) Id = np.eye(M) # # print(I) # print(R) C = Id - dt * lamb * Q Cc = np.eye(Mc) - dt * lamb * Qc Cc2 = np.eye(1) - dt * lamb * Qc2 P = Id - dt * lamb * Qd Pc = np.eye(Mc) - dt * lamb * Qdc Pc2 = np.eye(1) - dt * lamb * Qdc2 Pinv = np.linalg.inv(P) Pcinv = np.linalg.inv(Pc) u0 = 1.0 u = np.zeros(M, dtype=np.complex128) u[0] = u0 res = C.dot(u) - np.ones(M) * u0 k = 0 while np.linalg.norm(res, np.inf) > tol and k < 100: u += Pinv.dot(np.ones(M) * u0 - C.dot(u)) res = C.dot(u) - np.ones(M) * u0 k += 1 print(k, np.linalg.norm(res, np.inf)) print() I2 = get_transfer_matrix_Q(collc.nodes, collc2.nodes) R2 = get_transfer_matrix_Q(collc2.nodes, collc.nodes) K = k E = np.zeros((K, K)) np.fill_diagonal(E[1:, :], 1) S = np.kron(np.eye(K), P) - np.kron(E, P - C) Rfull = np.kron(np.eye(K), R) Ifull = np.kron(np.eye(K), I) R2full = np.kron(np.eye(K), R2) I2full = np.kron(np.eye(K), I2) # Sc = Rfull.dot(S).dot(Ifull) Sc = np.kron(np.eye(K), Pc) - np.kron(E, Pc - Cc) Sc2 = np.kron(np.eye(K), Pc2) - np.kron(E, Pc2 - Cc2) Scinv = np.linalg.inv(Sc) Sinv = np.linalg.inv(S) Sc2inv = np.linalg.inv(Sc2) Sdiaginv = np.linalg.inv(np.kron(np.eye(K), P)) Scdiaginv = np.linalg.inv(np.kron(np.eye(K), Pc)) Sc2diaginv = np.linalg.inv(np.kron(np.eye(K), Pc2)) u0vec = np.kron(np.ones(K), np.ones(M) * u0) u = np.zeros(M * K, dtype=np.complex128) l = 0 res = C.dot(u[-M:]) - np.ones(M) * u0 while np.linalg.norm(res, np.inf) > tol and l < K: # u += Sainv.dot(u0vec - S.dot(u)) u += Sdiaginv.dot(u0vec - S.dot(u)) uH = Rfull.dot(u) uHold = uH.copy() rhsH = Rfull.dot(u0vec) + Sc.dot(uH) - Rfull.dot(S.dot(u)) uH = Scinv.dot(rhsH) # uH += Scdiaginv.dot(rhsH - Sc.dot(uH)) # uH2 = R2full.dot(uH) # uH2old = uH2.copy() # rhsH2 = R2full.dot(rhsH) + Sc2.dot(uH2) - R2full.dot(Sc.dot(uH)) # uH2 = Sc2inv.dot(rhsH2) # uH += I2full.dot(uH2 - uH2old) # uH += Scdiaginv.dot(rhsH - Sc.dot(uH)) u += Ifull.dot(uH - uHold) u += Sdiaginv.dot(u0vec - S.dot(u)) res = C.dot(u[-M:]) - np.ones(M) * u0 l += 1 print(l, np.linalg.norm(res, np.inf)) print() Ea = E.copy() Ea[0, -1] = 1E+00 Sa = np.kron(np.eye(K), P) - np.kron(Ea, P - C) Sainv = np.linalg.inv(Sa) u0vec = np.kron(np.ones(K), np.ones(M) * u0) u = np.zeros(M * K, dtype=np.complex128) l = 0 res = C.dot(u[-M:]) - np.ones(M) * u0 while np.linalg.norm(res, np.inf) > tol and l < K: u += Sainv.dot(u0vec - S.dot(u)) res = C.dot(u[-M:]) - np.ones(M) * u0 l += 1 print(l, np.linalg.norm(res, np.inf)) print() Da, Va = np.linalg.eig(Ea) Da = np.diag(Da) Vainv = np.linalg.inv(Va) # print(Ea - Va.dot(Da).dot(Vainv)) # exit() Dafull = np.kron(np.eye(K), P) - np.kron(Da, P - C) # Dafull = Ifull.dot(np.kron(np.eye(K), Pc) - np.kron(Da, Pc - Cc)).dot(Rfull) Dafull = np.kron(np.eye(K) - Da, np.eye(M) - P) DaPfull = np.kron(np.eye(K), P) Dafullinv = np.linalg.inv(Dafull) DaPfullinv = np.linalg.inv(DaPfull) Vafull = np.kron(Va, np.eye(M)) Vafullinv = np.kron(Vainv, np.eye(M)) u0vec = np.kron(np.ones(K), np.ones(M) * u0) u = np.zeros(M * K, dtype=np.complex128) l = 0 res = C.dot(u[-M:]) - np.ones(M) * u0 while np.linalg.norm(res, np.inf) > tol and l < K: rhs = Vafullinv.dot(u0vec - Sa.dot(u)) # x = np.zeros(u.shape, dtype=np.complex128) # x += DaPfullinv.dot(rhs - Dafull.dot(x)) # x += DaPfullinv.dot(rhs - Dafull.dot(x)) # x += DaPfullinv.dot(rhs - Dafull.dot(x)) # x += DaPfullinv.dot(rhs - Dafull.dot(x)) # u += x u += Dafullinv.dot(rhs) u = Vafull.dot(u) res = C.dot(u[-M:]) - np.ones(M) * u0 l += 1 print(l, np.linalg.norm(res, np.inf)) print()
def step_(self, action): num_nodes = self.num_nodes dt = 0.01 #self.dt N = self.nvars restol = 1e-6 L = 10 nu = self.nu c = 1. dx = L / N x = np.arange(-L / 2, L / 2, dx) kx = np.arange(-L / 2, L / 2, dx) for i in range(0, len(kx)): kx[i] = 2 * np.pi / L * i ddx = 2 * np.pi * np.fft.fftfreq(N, d=dx) lap = -np.power(ddx, 2) k_impl = nu * lap k_expl = -c * ddx freq = 1 _u0 = np.arange(-L / 2, L / 2, dx) omega = 2.0 * np.pi * freq _u0 = np.sin(omega * (x - c * 0)) * np.exp(0 * nu * omega**2) #_u0 = u_exact_ad(0) u0hat = np.fft.fft(_u0) k = k_impl + k_expl coll = CollGaussRadau_Right(num_nodes, 0, 1) Q = coll.Qmat[1:, 1:] C = identity(num_nodes * N) - dt * scipy.sparse.kron(Q, sp.diags(k)) u0 = np.concatenate((_u0, _u0, _u0), axis=None) u = np.concatenate((_u0, _u0, _u0), axis=None) Qdmat = np.zeros_like(Q) np.fill_diagonal(Qdmat, x) QD_expl = np.zeros(Q.shape) for m in range(coll.num_nodes): QD_expl[m, 0:m] = coll.delta_m[0:m] iterationen = [] j = 0 it = 0 for i in k: u0 = [u0hat[j], u0hat[j], u0hat[j]] u = [u0hat[j], u0hat[j], u0hat[j]] C = identity(self.num_nodes) - self.dt * self.Q * i mat0 = [] mat1 = [] mat2 = [] mat0 = np.concatenate( (mat0, self.model(self.params, k_impl[j])[0][0] * k_impl[j]), axis=None) mat1 = np.concatenate( (mat1, self.model(self.params, k_impl[j])[0][1] * k_impl[j]), axis=None) mat2 = np.concatenate( (mat2, self.model(self.params, k_impl[j])[0][2] * k_impl[j]), axis=None) mat = sp.diags(np.concatenate((mat0, mat1, mat2), axis=None)) Pinv = np.linalg.inv( np.eye(self.coll.num_nodes) - self.dt * mat - dt * QD_expl * k_expl[j], ) residual = np.squeeze(np.array(u0 - C @ u)) done = False err = False self.niter = 0 while not done and not self.niter >= self.max_iters and not err: self.niter += 1 u = np.squeeze( np.array(u + Pinv @ np.squeeze(np.array((u0 - C @ u))))) residual = np.squeeze(np.array(u0 - C @ u)) norm_res = np.linalg.norm(residual, np.inf) #print(norm_res) if np.isnan(norm_res) or np.isinf(norm_res): self.niter = 51 break done = norm_res < self.restol #print(i, self.niter) it = max(it, self.niter) iterationen.append(self.niter) j = j + 1 reward = -1 done = True print("iterationen", iterationen) self.state = (u, residual) info = { 'residual': norm_res, 'niter': it, #self.niter,#iterationen, 'lam': self.lam, #-k, #self.lam, 'nvars': self.nvars, 'nu': self.nu } return (self.state, reward, done, info)
def __init__( self, M=None, dt=None, restol=None, prec=None, seed=None, batch_size=None, lambda_real_interval=[-100, 0], lambda_imag_interval=[0, 0], lambda_real_interpolation_interval=None, norm_factor=1, residual_weight=0.5, step_penalty=0.1, reward_iteration_only=None, reward_strategy='iteration_only', collect_states=False, use_doubles=True, do_scale=True, ): self.rng_key = None self.niter = None self.restol = restol self.dt = dt self.M = M self.coll = CollGaussRadau_Right(M, 0, 1) self.Q = self.coll.Qmat[1:, 1:] self.C = None self.lam = None self.u0 = jnp.ones(M, dtype=jnp.complex128) self.old_res = None self.prec = prec self.initial_residual = None self.batch_size = batch_size self.lambda_real_interval = jnp.array(lambda_real_interval) self.lambda_real_interval_reversed = list( reversed(lambda_real_interval)) self.lambda_imag_interval = jnp.array(lambda_imag_interval) self.lambda_real_interpolation_interval = \ lambda_real_interpolation_interval self.norm_factor = norm_factor self.residual_weight = residual_weight self.step_penalty = step_penalty if reward_iteration_only is None: self.reward_strategy = reward_strategy.lower() elif reward_iteration_only: self.reward_strategy = 'iteration_only' else: self.reward_strategy = 'residual_change' self.collect_states = collect_states self.do_scale = do_scale self.num_episodes = 0 # self.rewards = [] # self.episode_rewards = [] # self.norm_resids = [] # Setting the spaces: both are continuous, observation box # artificially bounded by some large numbers # note that because lambda can be complex, U can be complex, # i.e. the observation space should be complex self.observation_space = spaces.Box( low=-1E10, high=+1E10, shape=((batch_size, M * 2, self.max_iters) if collect_states else (batch_size, 2 * M)), # shape=(M * 2, self.max_iters) if collect_states else (2 * M + 1), dtype=jnp.complex128, ) # I read somewhere that the actions should be scaled to [-1,1], # values will be real. self.action_space = spaces.Box( low=-1.0, high=1.0, shape=(batch_size, M), dtype=jnp.float64 if use_doubles else jnp.float32, ) self.seed(seed) self.state = None if collect_states: self.old_states = jnp.zeros((batch_size, M * 2, self.max_iters), dtype=jnp.complex128) self._setup_jit()
def step(self, action): num_nodes = self.num_nodes dt = 0.01 #self.dt N = self.nvars restol = 1e-8 L = 10 nu = 10 c = 1. dx = L / N x = np.arange(-L / 2, L / 2, dx) nu = self.nu kx = np.arange(-L / 2, L / 2, dx) for i in range(0, len(kx)): kx[i] = 2 * np.pi / L * i ddx = 2 * np.pi * np.fft.fftfreq(N, d=dx) lap = -np.power(ddx, 2) k_impl = nu * lap k_expl = -c * ddx freq = 1 _u0 = np.arange(-L / 2, L / 2, dx) omega = 2.0 * np.pi * freq _u0 = np.sin(omega * (x - c * 0)) * np.exp(0 * nu * omega**2) #_u0 = u_exact_ad(0) u0hat = np.fft.fft(_u0) k = k_impl + k_expl coll = CollGaussRadau_Right(num_nodes, 0, 1) Q = coll.Qmat[1:, 1:] C = identity(num_nodes * N) - dt * scipy.sparse.kron(Q, sp.diags(k)) u0 = np.concatenate((u0hat.copy(), u0hat.copy(), u0hat.copy()), axis=None) u = np.concatenate((u0hat.copy(), u0hat.copy(), u0hat.copy()), axis=None) #print("u", u) Qdmat = np.zeros_like(Q) MIN = [ 0.3203856825077055, 0.1399680686269595, 0.3716708461097372, ] np.fill_diagonal(Qdmat, MIN) QD_expl = np.zeros(Q.shape) for m in range(coll.num_nodes): QD_expl[m, 0:m] = coll.delta_m[0:m] #C = identity(self.num_nodes*self.nvars) - self.dt * scipy.sparse.kron(self.Q, sp.diags(k)) if self.prec is None: if nu == 0: print("k_impl", k_impl) mat0 = [] mat1 = [] mat2 = [] if self.imex: for i in k_impl: #mat0 = np.concatenate((mat0, MIN[0]*i), axis=None) #mat1 = np.concatenate((mat1, MIN[1]*i), axis=None) #mat2 = np.concatenate((mat2, MIN[2]*i), axis=None) mat0 = np.concatenate( (mat0, self.model(self.params, i)[0][0] * i), axis=None) mat1 = np.concatenate( (mat1, self.model(self.params, i)[0][1] * i), axis=None) mat2 = np.concatenate( (mat2, self.model(self.params, i)[0][2] * i), axis=None) else: for i in k: #mat0 = np.concatenate((mat0, MIN[0]*i), axis=None) #mat1 = np.concatenate((mat1, MIN[1]*i), axis=None) #mat2 = np.concatenate((mat2, MIN[2]*i), axis=None) mat0 = np.concatenate( (mat0, self.model(self.params, i)[0][0] * i), axis=None) mat1 = np.concatenate( (mat1, self.model(self.params, i)[0][1] * i), axis=None) mat2 = np.concatenate( (mat2, self.model(self.params, i)[0][2] * i), axis=None) mat = sp.diags( np.concatenate((mat0, mat1, mat2), axis=None) ) # + scipy.sparse.kron(QD_expl, sp.diags(k_expl)) #sp.diags(np.concatenate((mat0_, mat1_, mat2_), axis=None) ) else: scaled_action = self._scale_action(action) Qdmat = self._get_prec(scaled_action=scaled_action) if self.imex: if self.prec.upper() == 'LU': mat = scipy.sparse.kron( Qdmat, sp.diags(k_impl)) + scipy.sparse.kron( QD_expl, sp.diags(k_expl)) else: mat = scipy.sparse.kron(Qdmat, sp.diags(k_impl)) else: mat = scipy.sparse.kron(Qdmat, sp.diags(k)) Pinv = np.linalg.inv( np.eye(self.coll.num_nodes * self.nvars) - dt * mat, ) residual = u0 - C @ u done = False err = False self.niter = 0 while not done and not self.niter >= self.max_iters and not err: self.niter += 1 #print(u.shape, u0.shape, Pinv.shape, C.shape) u = np.squeeze(np.array(u + Pinv @ (u0 - C @ u))) residual = np.squeeze(np.array(u0 - C @ u)) norm_res = np.linalg.norm(residual, np.inf) print(norm_res) if np.isnan(norm_res) or np.isinf(norm_res): self.niter = 51 break done = norm_res < self.restol u = u.reshape(self.coll.num_nodes, self.nvars) u__ = np.zeros_like(u) for i in range(len(u)): u__[i] = np.fft.ifft(u[i]) reward = -1 done = True _u = u.reshape(self.num_nodes, self.nvars) _res = residual.reshape(self.num_nodes, self.nvars) self.state = (u, residual) if self.collect_states and self.niter < 50: self.old_states[:, self.niter] = np.concatenate( (np.array([ np.linalg.norm(_u[i], np.inf) for i in range(self.num_nodes) ]), np.array([ np.linalg.norm(_res[i], np.inf) for i in range(self.num_nodes) ]))) info = { 'residual': norm_res, 'niter': self.niter, 'nvars': self.nvars, #self.lam, 'nu': self.nu } if self.collect_states: return (self.old_states, reward, done, info) else: return ((np.array([ np.linalg.norm(_u[i], np.inf) for i in range(self.num_nodes) ]), np.array([ np.linalg.norm(_res[i], np.inf) for i in range(self.num_nodes) ])), reward, done, info ) #(self.state, reward, done, info)
def main(): def rho(x): return max(abs(np.linalg.eigvals(np.eye(M) - np.diag([x[i] for i in range(M)]).dot(coll.Qmat[1:, 1:])))) M = 2 coll = CollGaussRadau_Right(M, 0, 1) x0 = np.ones(M) d = opt.minimize(rho, x0, method='Nelder-Mead') print(d) numsteps = 800 xdim = np.linspace(0, 8, numsteps) ydim = np.linspace(0, 13, numsteps) minfield = np.zeros((len(xdim), len(ydim))) for idx, x in enumerate(xdim): for idy, y in enumerate(ydim): minfield[idx, idy] = max(abs(np.linalg.eigvals(np.eye(M) - np.diag([x, y]).dot(coll.Qmat[1:, 1:])))) # Set up plotting parameters params = {'legend.fontsize': 20, 'figure.figsize': (12, 8), 'axes.labelsize': 20, 'axes.titlesize': 20, 'xtick.labelsize': 16, 'ytick.labelsize': 16, 'lines.linewidth': 3 } plt.rcParams.update(params) matplotlib.style.use('classic') plt.figure() plt.pcolor(xdim, ydim, minfield.T, cmap='Reds', vmin=0, vmax=1) plt.text(d.x[0], d.x[1], 'X', horizontalalignment='center', verticalalignment='center') plt.xlim((min(xdim), max(xdim))) plt.ylim((min(ydim), max(ydim))) plt.xlabel('component 1') plt.ylabel('component 2') cbar = plt.colorbar() cbar.set_label('spectral radius') fname = 'data/parallelSDC_minimizer_full.png' plt.savefig(fname, rasterized=True, bbox_inches='tight') plt.figure() xdim_part = xdim[int(0.25 * numsteps):int(0.75 * numsteps) + 1] ydim_part = ydim[0:int(0.25 * numsteps)] minfield_part = minfield[int(0.25 * numsteps):int(0.75 * numsteps) + 1, 0:int(0.25 * numsteps)] plt.pcolor(xdim_part, ydim_part, minfield_part.T, cmap='Reds', vmin=0, vmax=1) plt.text(d.x[0], d.x[1], 'X', horizontalalignment='center', verticalalignment='center') plt.xlim((min(xdim_part), max(xdim_part))) plt.ylim((min(ydim_part), max(ydim_part))) plt.xlabel('component 1') plt.ylabel('component 2') cbar = plt.colorbar() cbar.set_label('spectral radius') fname = 'data/parallelSDC_minimizer_zoom.png' plt.savefig(fname, rasterized=True, bbox_inches='tight')
def evaluate(solution): x = solution["parameters"] mf = 3 collf = CollGaussRadau_Right(num_nodes=mf, tleft=0.0, tright=1.0) # coll = CollGaussLobatto(num_nodes=m, tleft=0.0, tright=1.0) # coll = EquidistantNoLeft(num_nodes=m, tleft=0.0, tright=1.0) Qf = collf.Qmat[1:, 1:] Idf = np.eye(mf) QT = Qf.T [_, _, U] = scipy.linalg.lu(QT, overwrite_a=True) Qdf = U.T mc = int((mf + 1) / 2) collc = CollGaussRadau_Right(num_nodes=mc, tleft=0.0, tright=1.0) # coll = CollGaussLobatto(num_nodes=m, tleft=0.0, tright=1.0) # coll = EquidistantNoLeft(num_nodes=m, tleft=0.0, tright=1.0) Qc = collc.Qmat[1:, 1:] Idc = np.eye(mc) QT = Qc.T [_, _, U] = scipy.linalg.lu(QT, overwrite_a=True) Qdc = U.T sum1r = x['x11r'] + x['x12r'] + x['x13r'] sum2r = x['x21r'] + x['x22r'] + x['x23r'] sum1i = x['x11i'] + x['x12i'] sum2i = x['x21i'] + x['x22i'] sum3i = x['x31i'] + x['x32i'] if sum1r == 0.0 or sum2r == 0.0 or sum1i == 0.0 or sum2i == 0.0 or sum3i == 0.0: solution["metrics"] = {} solution["metrics"]["rho"] = 99 return solution Tr = np.array([[x['x11r'] / sum1r, x['x12r'] / sum1r, x['x13r'] / sum1r], [x['x21r'] / sum2r, x['x22r'] / sum2r, x['x23r'] / sum2r]]) Ti = np.array([[x['x11i'] / sum1i, x['x12i'] / sum1i], [x['x21i'] / sum2i, x['x22i'] / sum2i], [x['x31i'] / sum3i, x['x32i'] / sum3i]]) # THIS WORKS REALLY WELL! No need to take imaginary parts in x, though (found minimum has zero imaginary parts) k = 0 obj_val = 0.0 for i in range(-8, 8): for l in range(-8, 8): k += 1 lamdt = -10**i + 1j * 10**l C = Idf - lamdt * Qf Pf = Idf - lamdt * Qdf Rf = Idf - np.linalg.inv(Pf).dot(C) Pc = Idc - lamdt * Qdc Rc = Idf - Ti.dot(np.linalg.inv(Pc)).dot(Tr).dot(C) R = Rf.dot(Rc) rhoR = max(abs(np.linalg.eigvals(R))) obj_val += rhoR obj_val /= k solution["metrics"] = {} solution["metrics"]["rho"] = obj_val return solution