def main(dt, Tend): # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = dt # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussLobatto sweeper_params['num_nodes'] = 3 # initialize problem parameters for the Penning trap problem_params = dict() problem_params['delta'] = 1 problem_params['a0'] = 0.07 problem_params['u0'] = np.array([[0, -1, 0], [0.05, 0.01, 0], [1], [1]]) # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params[ 'hook_class'] = particles_output # specialized hook class for more statistics and output controller_params['logger_level'] = 30 # controller_params['log_to_file'] = True # controller_params['fname'] = 'step_3_B_out.txt' # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = planewave_single description['problem_params'] = problem_params description['dtype_u'] = particles description['dtype_f'] = fields description['sweeper_class'] = boris_2nd_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params # description['space_transfer_class'] = particles_to_particles # this is only needed for more than 2 levels description['step_params'] = step_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = Tend # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_init() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) return uinit, stats, problem_params['a0']
def main(): """ Van der Pol's oscillator reference solution """ # set time parameters t0 = 0.0 Tend = 10.0 # initialize level parameters level_params = dict() level_params['restol'] = 1E-12 level_params['dt'] = (Tend - t0) / 2000.0 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 5 sweeper_params['QI'] = 'IE' # initialize problem parameters problem_params = dict() problem_params['newton_tol'] = 1E-14 problem_params['newton_maxiter'] = 50 problem_params['mu'] = 10 problem_params['u0'] = (2.0, 0) # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 20 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = vanderpol description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller_ref = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # get initial values on finest level P = controller_ref.MS[0].levels[0].prob uinit = P.u_exact(t0) uend_ref, stats_ref = controller_ref.run(u0=uinit, t0=t0, Tend=Tend) np.save('data/vdp_ref.npy', uend_ref.values)
def main(): """ Van der Pol's oscillator inc. visualization """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 sweeper_params['QI'] = 'LU' # initialize problem parameters problem_params = dict() problem_params['newton_tol'] = 1E-12 problem_params['newton_maxiter'] = 50 problem_params['mu'] = 5 problem_params['u0'] = (1.0, 0) # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params['hook_class'] = trajectories controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = vanderpol description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = 20.0 # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend)
def run_simulation(): """ A simple test program to run IMEX SDC for a single time step """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 4 # frequency for the test value problem_params['nvars'] = 1023 # number of degrees of freedom # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters (<-- this is new!) controller_params = dict() controller_params['logger_level'] = 30 # reduce verbosity of each run # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = heat1d_forced description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.1 Tend = 0.9 # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) return stats
def main(): """ A simple test program to demonstrate residual visualization """ # get parameters from Step 6, Part A description, controller_params, t0, Tend = set_parameters_ml() # use 8 processes here num_proc = 8 # instantiate controller controller = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare (for testing purposes only) uex = P.u_exact(Tend) err = abs(uex - uend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics min_iter = 99 max_iter = 0 f = open('step_7_A_out.txt', 'w') for item in iter_counts: out = 'Number of iterations for time %4.2f: %1i' % item f.write(out + '\n') print(out) min_iter = min(min_iter, item[1]) max_iter = max(max_iter, item[1]) f.close() # call helper routine to produce residual plot fname = 'step_7_residuals.png' show_residual_across_simulation(stats=stats, fname=fname) assert err < 6.1555e-05, 'ERROR: error is too large, got %s' % err assert os.path.isfile(fname), 'ERROR: residual plot has not been created' assert min_iter == 5 and max_iter == 7, "ERROR: number of iterations not as expected, got %s and %s" % \ (min_iter, max_iter)
def main(): """ The Auzinger test problem """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 sweeper_params['QI'] = 'LU' # initialize problem parameters problem_params = dict() problem_params['newton_tol'] = 1E-12 problem_params['newton_maxiter'] = 50 # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params['hook_class'] = trajectories controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = auzinger description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller = allinclusive_classic_nonMPI(num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = 20.0 # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) print('\nError: %8.6e' % err) plt.ioff() plt.show()
def main(): # initialize level parameters (part I) level_params = dict() level_params['restol'] = 1E-08 # initialize sweeper parameters (part I) sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 # initialize step parameters step_params = dict() step_params['maxiter'] = 100 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # set up list of Q-delta types and setups qd_list = ['LU', 'IE', 'IEpar', 'Qpar', 'MIN'] setup_list = [('heat', 63, [10.0 ** i for i in range(-3, 3)]), ('advection', 64, [10.0 ** i for i in range(-3, 3)]), ('vanderpol', 2, [0.1 * 2 ** i for i in range(0, 10)]), ('fisher', 63, [2 ** i for i in range(-2, 3)])] # setup_list = [('fisher', 63, [2 * i for i in range(1, 6)])] # pre-fill results with lists of setups results = dict() for setup, nvars, param_list in setup_list: results[setup] = (nvars, param_list) # loop over all Q-delta matrix types for qd_type in qd_list: # assign implicit Q-delta matrix sweeper_params['QI'] = qd_type # loop over all setups for setup, nvars, param_list in setup_list: # initialize problem parameters (part I) problem_params = dict() problem_params['nvars'] = nvars # number of degrees of freedom for each level # loop over all parameters for param in param_list: # fill description for the controller description = dict() description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit # pass sweeper description['sweeper_params'] = sweeper_params # pass sweeper parameters description['step_params'] = step_params # pass step parameters print('working on: %s - %s - %s' % (qd_type, setup, param)) # decide which setup to take if setup == 'heat': problem_params['nu'] = param problem_params['freq'] = 2 level_params['dt'] = 0.1 description['problem_class'] = heat1d description['problem_params'] = problem_params description['level_params'] = level_params # pass level parameters elif setup == 'advection': problem_params['c'] = param problem_params['order'] = 2 problem_params['freq'] = 2 level_params['dt'] = 0.1 description['problem_class'] = advection1d description['problem_params'] = problem_params description['level_params'] = level_params # pass level parameters elif setup == 'vanderpol': problem_params['newton_tol'] = 1E-09 problem_params['newton_maxiter'] = 20 problem_params['mu'] = param problem_params['u0'] = np.array([2.0, 0]) level_params['dt'] = 0.1 description['problem_class'] = vanderpol description['problem_params'] = problem_params description['level_params'] = level_params elif setup == 'fisher': problem_params['nu'] = 1 problem_params['lambda0'] = param problem_params['newton_maxiter'] = 20 problem_params['newton_tol'] = 1E-10 problem_params['interval'] = (-5, 5) level_params['dt'] = 0.01 description['problem_class'] = generalized_fisher description['problem_params'] = problem_params description['level_params'] = level_params else: print('Setup not implemented..', setup) exit() # instantiate controller controller = allinclusive_classic_nonMPI(num_procs=1, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=0, Tend=level_params['dt']) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # just one time-step, grep number of iteration and store niter = iter_counts[0][1] id = ID(setup=setup, qd_type=qd_type, param=param) results[id] = niter assert len(results) == (6 + 6 + 10 + 5) * 5 + 4, 'ERROR: did not get all results, got %s' % len(results) # write out for later visualization file = open('data/parallelSDC_iterations_precond.pkl', 'wb') pickle.dump(results, file) assert os.path.isfile('data/parallelSDC_iterations_precond.pkl'), 'ERROR: pickle did not create file'
def main(): # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.01 # This comes as read-in for the step class (this is optional!) step_params = dict() step_params['maxiter'] = 50 # This comes as read-in for the problem class problem_params = dict() problem_params['nu'] = 1 problem_params['nvars'] = 255 problem_params['lambda0'] = 5.0 problem_params['newton_maxiter'] = 50 problem_params['newton_tol'] = 1E-12 problem_params['interval'] = (-5, 5) # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 5 sweeper_params['QI'] = 'LU' sweeper_params['fixed_time_in_jacobian'] = 0 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = generalized_fisher_jac description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params sweeper_list = [generic_implicit, linearized_implicit_fixed_parallel_prec, linearized_implicit_fixed_parallel, linearized_implicit_parallel] f = open('parallelSDC_nonlinear_out.txt', 'w') uinit = None uex = None uend = None P = None # loop over the different sweepers and check results for sweeper in sweeper_list: description['sweeper_class'] = sweeper # instantiate the controller controller = allinclusive_classic_nonMPI(num_procs=1, controller_params=controller_params, description=description) # setup parameters "in time" t0 = 0 Tend = 0.1 # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) print('error at time %s: %s' % (Tend, err)) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics niters = np.array([item[1] for item in iter_counts]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) f.write(out + '\n') print(out) out = ' Range of values for number of iterations: %2i ' % np.ptp(niters) f.write(out + '\n') print(out) out = ' Position of max/min number of iterations: %2i -- %2i' % \ (int(np.argmax(niters)), int(np.argmin(niters))) f.write(out + '\n') print(out) out = ' Std and var for number of iterations: %4.2f -- %4.2f' % \ (float(np.std(niters)), float(np.var(niters))) f.write(out + '\n') f.write(out + '\n') print(out) f.write('\n') print() assert err < 3.686e-05, 'ERROR: error is too high for sweeper %s, got %s' % (sweeper.__name__, err) assert np.mean(niters) == 7.5 or np.mean(niters) == 4.0, \ 'ERROR: mean number of iterations not as expected, got %s' % np.mean(niters) f.close() results = dict() results['interval'] = problem_params['interval'] results['xvalues'] = np.array([(i + 1 - (P.params.nvars + 1) / 2) * P.dx for i in range(P.params.nvars)]) results['uinit'] = uinit.values results['uend'] = uend.values results['uex'] = uex.values # write out for later visualization file = open('data/parallelSDC_results_graphs.pkl', 'wb') pickle.dump(results, file) assert os.path.isfile('data/parallelSDC_results_graphs.pkl'), 'ERROR: pickle did not create file'
def run_penning_trap_simulation(): """ A simple test program to run IMEX SDC for a single time step of the penning trap example """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = 1.0 / 16 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 # initialize problem parameters for the Penning trap problem_params = dict() problem_params['omega_E'] = 4.9 # E-field frequency problem_params['omega_B'] = 25.0 # B-field frequency problem_params['u0'] = np.array([[10, 0, 0], [100, 0, 100], [1], [1]]) # initial center of positions problem_params['nparts'] = 1 # number of particles in the trap problem_params['sig'] = 0.1 # smoothing parameter for the forces # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params[ 'hook_class'] = particle_hook # specialized hook class for more statistics and output controller_params['log_to_file'] = True controller_params['fname'] = 'step_3_B_out.txt' # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = penningtrap description['problem_params'] = problem_params description['dtype_u'] = particles description['dtype_f'] = fields description['sweeper_class'] = boris_2nd_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = level_params['dt'] # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_init() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute error compared to know exact solution for one particle uex = P.u_exact(Tend) err = np.linalg.norm(uex.pos.values - uend.pos.values, np.inf) / np.linalg.norm(uex.pos.values, np.inf) return err, stats
def run_RDC(cwd=''): """ Van der Pol's oscillator with RDC, MLRDC and PFASST Args: cwd (string): current working directory Returns: list: list of errors and mean number of iterations (for testing) """ # set time parameters t0 = 0.0 Tend = 10.0 # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.25 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = Equidistant_RDC sweeper_params['num_nodes'] = 20 sweeper_params['QI'] = 'IE' # initialize problem parameters problem_params = dict() problem_params['newton_tol'] = 1E-12 problem_params['newton_maxiter'] = 50 problem_params['mu'] = 10 problem_params['u0'] = (2.0, 0) # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 50 base_transfer_params = dict() # base_transfer_params['finter'] = True # base_transfer_params['coll_iorder'] = 2 # base_transfer_params['coll_rorder'] = 2 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = vanderpol description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params description['space_transfer_class'] = mesh_to_mesh description['base_transfer_params'] = base_transfer_params results = [] ref_sol = np.load(cwd + 'data/vdp_ref.npy') # instantiate the controller controller_rdc = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # get initial values on finest level P = controller_rdc.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend_rdc, stats_rdc = controller_rdc.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats_rdc, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') mean_niter = np.mean(np.array([item[1] for item in iter_counts])) err = np.linalg.norm(uend_rdc.values - ref_sol, np.inf) / np.linalg.norm( ref_sol, np.inf) print('RDC : Mean number of iterations: %6.3f -- Error: %8.4e' % (mean_niter, err)) results.append((err, mean_niter)) sweeper_params['num_nodes'] = [sweeper_params['num_nodes'], 10] controller_mlrdc = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) uend_mlrdc, stats_mlrdc = controller_mlrdc.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats_mlrdc, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') mean_niter = np.mean(np.array([item[1] for item in iter_counts])) err = np.linalg.norm(uend_mlrdc.values - ref_sol, np.inf) / np.linalg.norm( ref_sol, np.inf) print('MLRDC : Mean number of iterations: %6.3f -- Error: %8.4e' % (mean_niter, err)) results.append((err, mean_niter)) controller_pfasst = allinclusive_classic_nonMPI( num_procs=10, controller_params=controller_params, description=description) uend_pfasst, stats_pfasst = controller_pfasst.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats_pfasst, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') mean_niter = np.mean(np.array([item[1] for item in iter_counts])) err = np.linalg.norm(uend_pfasst.values - ref_sol, np.inf) / np.linalg.norm(ref_sol, np.inf) print('PFASST(10): Mean number of iterations: %6.3f -- Error: %8.4e' % (mean_niter, err)) results.append((err, mean_niter)) return results
def run_simulation(): """ Routine to run the simulation of a second order problem """ description, controller_params = setup_fput() # set time parameters t0 = 0.0 # set this to 10000 to reproduce the picture in # http://www.scholarpedia.org/article/Fermi-Pasta-Ulam_nonlinear_lattice_oscillations Tend = 250.0 num_procs = 1 f = open('fput_out.txt', 'w') out = 'Running fput problem with %s processors...' % num_procs f.write(out + '\n') print(out) # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t=t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics # for item in iter_counts: # out = 'Number of iterations for time %4.2f: %2i' % item # f.write(out + '\n') # print(out) niters = np.array([item[1] for item in iter_counts]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) f.write(out + '\n') print(out) out = ' Range of values for number of iterations: %2i ' % np.ptp(niters) f.write(out + '\n') print(out) out = ' Position of max/min number of iterations: %2i -- %2i' % \ (int(np.argmax(niters)), int(np.argmin(niters))) f.write(out + '\n') print(out) out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float( np.std(niters)), float(np.var(niters))) f.write(out + '\n') print(out) # get runtime timing_run = sort_stats(filter_stats(stats, type='timing_run'), sortby='time')[0][1] out = '... took %6.4f seconds to run this.' % timing_run f.write(out + '\n') print(out) f.close() assert np.mean( niters ) <= 3.0, 'Mean number of iterations is too high, got %s' % np.mean(niters) fname = 'data/fput.dat' f = open(fname, 'wb') dill.dump(stats, f) f.close() assert os.path.isfile(fname), 'Run for %s did not create stats file'
def main(): """ A simple test program to do compare PFASST with multi-step SDC """ # initialize level parameters level_params = dict() level_params['restol'] = 5E-10 level_params['dt'] = 0.125 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 2 # frequency for the test value # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize space transfer parameters space_transfer_params = dict() space_transfer_params['rorder'] = 2 space_transfer_params['iorder'] = 6 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 40 controller_params['predict'] = False # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d # pass problem class description['dtype_u'] = mesh # pass data type for u description['dtype_f'] = mesh # pass data type for f description['sweeper_class'] = generic_LU # pass sweeper description['sweeper_params'] = sweeper_params # pass sweeper parameters description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters description[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # set up parameters for PFASST run problem_params['nvars'] = [63, 31] description['problem_params'] = problem_params.copy() description_pfasst = description.copy() # set up parameters for MSSDC run problem_params['nvars'] = [63] description['problem_params'] = problem_params.copy() description_mssdc = description.copy() # set time parameters t0 = 0.0 Tend = 1.0 # set up list of parallel time-steps to run PFASST/MSSDC with num_proc = 8 # instantiate controllers controller_mssdc = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description_mssdc) controller_pfasst = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description_pfasst) # get initial values on finest level P = controller_mssdc.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main functions to get things done... uend_pfasst, stats_pfasst = controller_pfasst.run(u0=uinit, t0=t0, Tend=Tend) uend_mssdc, stats_mssdc = controller_mssdc.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare for both runs uex = P.u_exact(Tend) err_mssdc = abs(uex - uend_mssdc) err_pfasst = abs(uex - uend_pfasst) diff = abs(uend_mssdc - uend_pfasst) f = open('step_7_B_out.txt', 'w') out = 'Error PFASST: %12.8e' % err_pfasst f.write(out + '\n') print(out) out = 'Error MSSDC: %12.8e' % err_mssdc f.write(out + '\n') print(out) out = 'Diff: %12.8e' % diff f.write(out + '\n') print(out) # filter statistics by type (number of iterations) filtered_stats_pfasst = filter_stats(stats_pfasst, type='niter') filtered_stats_mssdc = filter_stats(stats_mssdc, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts_pfasst = sort_stats(filtered_stats_pfasst, sortby='time') iter_counts_mssdc = sort_stats(filtered_stats_mssdc, sortby='time') # compute and print statistics for item_pfasst, item_mssdc in zip(iter_counts_pfasst, iter_counts_mssdc): out = 'Number of iterations for time %4.2f (PFASST/MSSDC): %1i / %1i' % \ (item_pfasst[0], item_pfasst[1], item_mssdc[1]) f.write(out + '\n') print(out) f.close() # call helper routine to produce residual plot show_residual_across_simulation(stats_mssdc, 'step_7_residuals_mssdc.png') assert os.path.isfile('step_7_residuals_mssdc.png') assert diff < 2.66E-09, "ERROR: difference between PFASST and MSSDC controller is too large, got %s" % diff
controller_params['logger_level'] = 20 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = fenics_heat description['problem_params'] = problem_params description['dtype_u'] = fenics_mesh description['dtype_f'] = fenics_mesh description['sweeper_class'] = generic_LU # pass sweeper (see part B) description['sweeper_params'] = sweeper_params # pass sweeper parameters description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters description['space_transfer_class'] = mesh_to_mesh_fenics # pass spatial transfer class description['space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # quickly generate block of steps controller = allinclusive_classic_nonMPI(num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) print('(classical) error at time %s: %s' % (Tend, abs(uex - uend) / abs(uex)))
def main(): """ A simple test program to compare SDC and MLSDC """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-09 level_params['dt'] = 0.1 # initialize sweeper parameters sweeper_params_sdc = dict() sweeper_params_sdc['collocation_class'] = CollGaussRadau_Right sweeper_params_sdc['num_nodes'] = 5 sweeper_params_mlsdc = dict() sweeper_params_mlsdc['collocation_class'] = CollGaussRadau_Right sweeper_params_mlsdc['num_nodes'] = [5, 3, 2] # initialize problem parameters problem_params_sdc = dict() problem_params_sdc['nu'] = 0.1 # diffusion coefficient problem_params_sdc['freq'] = 4 # frequency for the test value problem_params_sdc[ 'nvars'] = 1023 # number of degrees of freedom for each level problem_params_mlsdc = dict() problem_params_mlsdc['nu'] = 0.1 # diffusion coefficient problem_params_mlsdc['freq'] = 4 # frequency for the test value problem_params_mlsdc['nvars'] = [ 1023, 511, 255 ] # number of degrees of freedom for each level # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize space transfer parameters space_transfer_params = dict() space_transfer_params['rorder'] = 2 space_transfer_params['iorder'] = 6 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['predict'] = False # can turn on/off predictor here! # fill description dictionary for SDC description_sdc = dict() description_sdc['problem_class'] = heat1d # pass problem class description_sdc[ 'problem_params'] = problem_params_sdc # pass problem parameters description_sdc['dtype_u'] = mesh # pass data type for u description_sdc['dtype_f'] = mesh # pass data type for f description_sdc['sweeper_class'] = generic_LU # pass sweeper (see part B) description_sdc[ 'sweeper_params'] = sweeper_params_sdc # pass sweeper parameters description_sdc['level_params'] = level_params # pass level parameters description_sdc['step_params'] = step_params # pass step parameters # fill description dictionary for MLSDC description_mlsdc = dict() description_mlsdc['problem_class'] = heat1d # pass problem class description_mlsdc[ 'problem_params'] = problem_params_mlsdc # pass problem parameters description_mlsdc['dtype_u'] = mesh # pass data type for u description_mlsdc['dtype_f'] = mesh # pass data type for f description_mlsdc[ 'sweeper_class'] = generic_LU # pass sweeper (see part B) description_mlsdc[ 'sweeper_params'] = sweeper_params_mlsdc # pass sweeper parameters description_mlsdc['level_params'] = level_params # pass level parameters description_mlsdc['step_params'] = step_params # pass step parameters description_mlsdc[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description_mlsdc[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # instantiate the controller (no controller parameters used here) controller_sdc = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description_sdc) controller_mlsdc = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description_mlsdc) # set time parameters t0 = 0.0 Tend = 0.1 # get initial values on finest level P = controller_sdc.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main functions to get things done... uend_sdc, stats_sdc = controller_sdc.run(u0=uinit, t0=t0, Tend=Tend) uend_mlsdc, stats_mlsdc = controller_mlsdc.run(u0=uinit, t0=t0, Tend=Tend) # get number of iterations for both filtered_stats_sdc = filter_stats(stats_sdc, type='niter') filtered_stats_mlsdc = filter_stats(stats_mlsdc, type='niter') niter_sdc = sort_stats(filtered_stats_sdc, 'time')[0][1] niter_mlsdc = sort_stats(filtered_stats_mlsdc, 'time')[0][1] # compute exact solution and compare both uex = P.u_exact(Tend) err_sdc = abs(uex - uend_sdc) err_mlsdc = abs(uex - uend_mlsdc) diff = abs(uend_mlsdc - uend_sdc) # print out and check f = open('step_4_C_out.txt', 'a') out = 'Error SDC and MLSDC: %12.8e -- %12.8e' % (err_sdc, err_mlsdc) f.write(out + '\n') print(out) out = 'Difference SDC vs. MLSDC: %12.8e' % diff f.write(out + '\n') print(out) out = 'Number of iterations SDC and MLSDC: %2i -- %2i' % (niter_sdc, niter_mlsdc) f.write(out + '\n') print(out) assert diff < 6E-10, "ERROR: difference between MLSDC and SDC is higher than expected, got %s" % diff assert niter_sdc - niter_mlsdc <= 6, "ERROR: MLSDC required more iterations than expected, got %s" % niter_mlsdc
def main(): """ A simple test program to run PFASST for the advection equation in multiple ways... """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-09 level_params['dt'] = 0.0625 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] # initialize problem parameters problem_params = dict() problem_params['c'] = 1 # advection coefficient problem_params['freq'] = 4 # frequency for the test value problem_params['nvars'] = [128, 64 ] # number of degrees of freedom for each level problem_params['order'] = 4 problem_params['type'] = 'upwind' # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize space transfer parameters space_transfer_params = dict() space_transfer_params['rorder'] = 2 space_transfer_params['iorder'] = 6 space_transfer_params['periodic'] = True # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = advection1d # pass problem class description['problem_params'] = problem_params # pass problem parameters description['dtype_u'] = mesh # pass data type for u description['dtype_f'] = mesh # pass data type for f description[ 'sweeper_class'] = generic_implicit # pass sweeper (see part B) description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters description[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # set time parameters t0 = 0.0 Tend = 1.0 # set up list of parallel time-steps to run PFASST with nsteps = int(Tend / level_params['dt']) num_proc_list = [2**i for i in range(int(np.log2(nsteps) + 1))] # set up list of types of implicit SDC sweepers: LU and implicit Euler here QI_list = ['LU', 'IE'] niters_min_all = {} niters_max_all = {} f = open('step_5_C_out.txt', 'w') # loop over different types of implicit sweeper types for QI in QI_list: # define and set preconditioner for the implicit sweeper sweeper_params['QI'] = QI description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters # init min/max iteration counts niters_min_all[QI] = 99 niters_max_all[QI] = 0 # loop over different number of processes for num_proc in num_proc_list: out = 'Working with QI = %s on %2i processes...' % (QI, num_proc) f.write(out + '\n') print(out) # instantiate controller controller = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics niters = np.array([item[1] for item in iter_counts]) niters_min_all[QI] = min(np.mean(niters), niters_min_all[QI]) niters_max_all[QI] = max(np.mean(niters), niters_max_all[QI]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) f.write(out + '\n') print(out) out = ' Range of values for number of iterations: %2i ' % np.ptp( niters) f.write(out + '\n') print(out) out = ' Position of max/min number of iterations: %2i -- %2i' % \ (int(np.argmax(niters)), int(np.argmin(niters))) f.write(out + '\n') print(out) out = ' Std and var for number of iterations: %4.2f -- %4.2f' % \ (float(np.std(niters)), float(np.var(niters))) f.write(out + '\n') f.write(out + '\n') print(out) f.write('\n') print() assert err < 5.0716135e-04, "ERROR: error is too high, got %s" % err out = 'Mean number of iterations went up from %4.2f to %4.2f for QI = %s!' % \ (niters_min_all[QI], niters_max_all[QI], QI) f.write(out + '\n') print(out) f.write('\n\n') print() print() f.close()
def run_simulation(): """ A simple test program to run IMEX SDC for a single time step """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-06 level_params['dt'] = 1.0 / 16 # initialize sweeper parameters sweeper_params = dict() sweeper_params['num_nodes'] = 3 # initialize problem parameters problem_params = dict() problem_params['omega_E'] = 4.9 problem_params['omega_B'] = 25.0 problem_params['u0'] = np.array([[10, 0, 0], [100, 0, 100], [1], [1]]) problem_params['nparts'] = 1 problem_params['sig'] = 0.1 # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params['hook_class'] = particle_hook # specialized hook class for more statistics and output controller_params['logger_level'] = 30 # reduce verbosity of each run # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = penningtrap description['problem_params'] = problem_params description['dtype_u'] = particles description['dtype_f'] = fields description['sweeper_class'] = boris_2nd_order description['level_params'] = level_params description['step_params'] = step_params # assemble and loop over list of collocation classes coll_list = [CollGaussRadau_Right, CollGaussLegendre, CollGaussLobatto] stats_dict = dict() for cclass in coll_list: sweeper_params['collocation_class'] = cclass description['sweeper_params'] = sweeper_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI(num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = level_params['dt'] # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_init() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # gather stats in dictionary, collocation classes being the keys stats_dict[cclass.__name__] = stats return stats_dict
def main(): """ Particle cloud in a penning trap, incl. live visualization """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = 0.015625 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussLobatto sweeper_params['num_nodes'] = 3 # initialize problem parameters for the Penning trap problem_params = dict() problem_params['omega_E'] = 4.9 problem_params['omega_B'] = 25.0 problem_params['u0'] = np.array([[10, 0, 0], [100, 0, 100], [1], [1]]) problem_params['nparts'] = 10 problem_params['sig'] = 0.1 problem_params['Tend'] = 16.0 # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params['hook_class'] = particles_output # specialized hook class for more statistics and output controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = penningtrap description['problem_params'] = problem_params description['dtype_u'] = particles description['dtype_f'] = fields description['sweeper_class'] = boris_2nd_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params # description['space_transfer_class'] = particles_to_particles # this is only needed for more than 2 levels description['step_params'] = step_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI(num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = 1024 * 0.015625 # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_init() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) extract_stats = filter_stats(stats, type='etot') sortedlist_stats = sort_stats(extract_stats, sortby='time') energy = [entry[1] for entry in sortedlist_stats] plt.figure() plt.plot(energy, 'bo--') plt.xlabel('Time') plt.ylabel('Energy') plt.savefig('penningtrap_energy.png', rasterized=True, transparent=True, bbox_inches='tight')
def compute_RDC_errors(): """ Van der Pol's oscillator with RDC """ # initialize level parameters level_params = dict() level_params['restol'] = 0 level_params['dt'] = 10.0 / 40.0 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = Equidistant_RDC sweeper_params['num_nodes'] = 41 sweeper_params['QI'] = 'IE' # initialize problem parameters problem_params = dict() problem_params['newton_tol'] = 1E-14 problem_params['newton_maxiter'] = 50 problem_params['mu'] = 10 problem_params['u0'] = (2.0, 0) # initialize step parameters step_params = dict() step_params['maxiter'] = None # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = vanderpol description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller_rdc = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = 10.0 # get initial values on finest level P = controller_rdc.MS[0].levels[0].prob uinit = P.u_exact(t0) ref_sol = np.load('data/vdp_ref.npy') maxiter_list = range(1, 11) results = dict() results['maxiter_list'] = maxiter_list for maxiter in maxiter_list: # ugly, but much faster than re-initializing the controller over and over again controller_rdc.MS[0].params.maxiter = maxiter # call main function to get things done... uend_rdc, stats_rdc = controller_rdc.run(u0=uinit, t0=t0, Tend=Tend) err = np.linalg.norm(uend_rdc.values - ref_sol, np.inf) / np.linalg.norm(ref_sol, np.inf) print('Maxiter = %2i -- Error: %8.4e' % (controller_rdc.MS[0].params.maxiter, err)) results[maxiter] = err fname = 'data/vdp_results.pkl' file = open(fname, 'wb') pickle.dump(results, file) file.close() assert os.path.isfile(fname), 'ERROR: pickle did not create file'
def compute_and_plot_solutions(): """ Routine to compute and plot the solutions of SDC(2), IMEX, BDF-2 and RK for a multiscale problem """ num_procs = 1 t0 = 0.0 Tend = 3.0 nsteps = 154 # 154 is value in Vater et al. dt = Tend / float(nsteps) # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = dt # This comes as read-in for the step class step_params = dict() step_params['maxiter'] = 2 # This comes as read-in for the problem class problem_params = dict() problem_params['cadv'] = 0.05 problem_params['cs'] = 1.0 problem_params['nvars'] = [(2, 512)] problem_params['order_adv'] = 5 problem_params['waveno'] = 5 # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 2 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = dump_energy # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = acoustic_1d_imex_multiscale description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order description['sweeper_params'] = sweeper_params description['step_params'] = step_params description['level_params'] = level_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # instantiate standard integrators to be run for comparison trap = trapezoidal((P.A + P.Dx).astype('complex'), 0.5) bdf2_m = bdf2(P.A + P.Dx) dirk_m = dirk((P.A + P.Dx).astype('complex'), step_params['maxiter']) rkimex = rk_imex(P.A.astype('complex'), P.Dx.astype('complex'), step_params['maxiter']) y0_tp = np.concatenate((uinit.values[0, :], uinit.values[1, :])) y0_bdf = y0_tp y0_dirk = y0_tp.astype('complex') y0_imex = y0_tp.astype('complex') # Perform time steps with standard integrators for i in range(0, nsteps): # trapezoidal rule step ynew_tp = trap.timestep(y0_tp, dt) # BDF-2 scheme if i == 0: ynew_bdf = bdf2_m.firsttimestep(y0_bdf, dt) ym1_bdf = y0_bdf else: ynew_bdf = bdf2_m.timestep(y0_bdf, ym1_bdf, dt) # DIRK scheme ynew_dirk = dirk_m.timestep(y0_dirk, dt) # IMEX scheme ynew_imex = rkimex.timestep(y0_imex, dt) y0_tp = ynew_tp ym1_bdf = y0_bdf y0_bdf = ynew_bdf y0_dirk = ynew_dirk y0_imex = ynew_imex # Finished running standard integrators unew_tp, pnew_tp = np.split(ynew_tp, 2) unew_bdf, pnew_bdf = np.split(ynew_bdf, 2) unew_dirk, pnew_dirk = np.split(ynew_dirk, 2) unew_imex, pnew_imex = np.split(ynew_imex, 2) fs = 8 rcParams['figure.figsize'] = 2.5, 2.5 # rcParams['pgf.rcfonts'] = False fig = plt.figure() sigma_0 = 0.1 k = 7.0 * 2.0 * np.pi x_0 = 0.75 x_1 = 0.25 print('Maximum pressure in SDC: %5.3e' % np.linalg.norm(uend.values[1, :], np.inf)) print('Maximum pressure in DIRK: %5.3e' % np.linalg.norm(pnew_dirk, np.inf)) print('Maximum pressure in RK-IMEX: %5.3e' % np.linalg.norm(pnew_imex, np.inf)) if dirk_m.order == 2: plt.plot(P.mesh, pnew_bdf, 'd-', color='c', label='BDF-2', markevery=(50, 75)) p_slow = np.exp( -np.square(np.mod(P.mesh - problem_params['cadv'] * Tend, 1.0) - x_0) / (sigma_0 * sigma_0)) plt.plot(P.mesh, p_slow, '--', color='k', markersize=fs - 2, label='Slow mode', dashes=(10, 2)) if np.linalg.norm(pnew_imex, np.inf) <= 2: plt.plot(P.mesh, pnew_imex, '+-', color='r', label='IMEX(' + str(rkimex.order) + ')', markevery=(1, 75), mew=1.0) plt.plot(P.mesh, uend.values[1, :], 'o-', color='b', label='SDC(' + str(step_params['maxiter']) + ')', markevery=(25, 75)) plt.plot(P.mesh, pnew_dirk, '-', color='g', label='DIRK(' + str(dirk_m.order) + ')') plt.xlabel('x', fontsize=fs, labelpad=0) plt.ylabel('Pressure', fontsize=fs, labelpad=0) fig.gca().set_xlim([0, 1.0]) fig.gca().set_ylim([-0.5, 1.1]) fig.gca().tick_params(axis='both', labelsize=fs) plt.legend(loc='upper left', fontsize=fs, prop={'size': fs}, handlelength=3) fig.gca().grid() filename = 'data/multiscale-K' + str(step_params['maxiter']) + '-M' + str( sweeper_params['num_nodes']) + '.png' plt.gcf().savefig(filename, bbox_inches='tight')
def run_penning_trap_simulation(mlsdc, finter=False): """ A simple test program to run IMEX SDC for a single time step """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-07 level_params['dt'] = 1.0 / 8 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 5 # initialize problem parameters for the Penning trap problem_params = dict() problem_params['omega_E'] = 4.9 # E-field frequency problem_params['omega_B'] = 25.0 # B-field frequency problem_params['u0'] = np.array([[10, 0, 0], [100, 0, 100], [1], [1]]) # initial center of positions problem_params['nparts'] = 50 # number of particles in the trap problem_params['sig'] = 0.1 # smoothing parameter for the forces # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params[ 'hook_class'] = particle_hook # specialized hook class for more statistics and output controller_params['predict'] = False controller_params['logger_level'] = 30 transfer_params = dict() transfer_params['finter'] = finter # Fill description dictionary for easy hierarchy creation description = dict() if mlsdc: # MLSDC: provide list of two problem classes: one for the fine, one for the coarse level description['problem_class'] = [penningtrap, penningtrap_coarse] else: # SDC: provide only one problem class description['problem_class'] = penningtrap description['problem_params'] = problem_params description['dtype_u'] = particles description['dtype_f'] = fields description['sweeper_class'] = boris_2nd_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params description['space_transfer_class'] = particles_to_particles description['base_transfer_params'] = transfer_params # instantiate the controller (no controller parameters used here) controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.0 Tend = level_params['dt'] # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_init() # call and time main function to get things done... start_time = time.time() uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) end_time = time.time() - start_time return stats, end_time
def main(num_proc_list=None, fname=None, multi_level=True): """ A simple test program to compare classical and multigrid PFASST runs Args: num_proc_list: list of number of processes to test with fname: filename/path for output multi_level (bool): do multi-level run or single-level """ if multi_level: description, controller_params, t0, Tend = set_parameters_ml() else: assert all(num_proc == 1 for num_proc in num_proc_list), \ 'ERROR: single-elevel run can only use 1 processor, got %s' % num_proc_list description, controller_params, t0, Tend = set_parameters_sl() f = open(fname, 'w') # loop over different numbers of processes for num_proc in num_proc_list: out = 'Working with %2i processes...' % num_proc f.write(out + '\n') print(out) # instantiate controllers controller_classic = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description) controller_multigrid = allinclusive_multigrid_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description) # get initial values on finest level P = controller_classic.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main functions to get things done... uend_classic, stats_classic = controller_classic.run(u0=uinit, t0=t0, Tend=Tend) uend_multigrid, stats_multigrid = controller_multigrid.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare with both results uex = P.u_exact(Tend) err_classic = abs(uex - uend_classic) err_multigrid = abs(uex - uend_multigrid) diff = abs(uend_classic - uend_multigrid) out = 'Error classic: %12.8e' % err_classic f.write(out + '\n') print(out) out = 'Error multigrid: %12.8e' % err_multigrid f.write(out + '\n') print(out) out = 'Diff: %6.4e' % diff f.write(out + '\n') print(out) # filter statistics by type (number of iterations) filtered_stats_classic = filter_stats(stats_classic, type='niter') filtered_stats_multigrid = filter_stats(stats_multigrid, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts_classic = sort_stats(filtered_stats_classic, sortby='time') iter_counts_multigrid = sort_stats(filtered_stats_multigrid, sortby='time') # compute and print statistics for item_classic, item_multigrid in zip(iter_counts_classic, iter_counts_multigrid): out = 'Number of iterations for time %4.2f (classic/multigrid): %1i / %1i' % \ (item_classic[0], item_classic[1], item_multigrid[1]) f.write(out + '\n') print(out) if num_proc == 1: assert item_classic[1] == item_multigrid[1], \ 'ERROR: number of iterations differ between classic and multigrid controller by %2i' \ % (item_classic[1] - item_multigrid[1]) f.write('\n') print() assert all([item[1] <= 8 for item in iter_counts_multigrid]), \ "ERROR: weird iteration counts for multigrid, got %s" % iter_counts_multigrid assert diff < 3.5E-09, "ERROR: difference between classic and multigrid controller is too large, got %s" % diff f.close()
def main(cwd=''): """ Example running/comparing SDC and different standard integrators for the 2D Boussinesq equation Args: cwd (string): current working directory """ num_procs = 1 # setup parameters "in time" t0 = 0 Tend = 3000 Nsteps = 100 dt = Tend / float(Nsteps) # initialize level parameters level_params = dict() level_params['restol'] = 1E-15 level_params['dt'] = dt # initialize step parameters step_params = dict() step_params['maxiter'] = 4 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussLegendre sweeper_params['num_nodes'] = 3 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 20 controller_params['hook_class'] = gmres_tolerance # initialize problem parameters problem_params = dict() problem_params['nvars'] = [(4, 300, 30)] problem_params['u_adv'] = 0.02 problem_params['c_s'] = 0.3 problem_params['Nfreq'] = 0.01 problem_params['x_bounds'] = [(-150.0, 150.0)] problem_params['z_bounds'] = [(0.0, 10.0)] problem_params['order'] = [4] problem_params['order_upw'] = [5] problem_params['gmres_maxiter'] = [500] problem_params['gmres_restart'] = [10] problem_params['gmres_tol_limit'] = [1e-05] problem_params['gmres_tol_factor'] = [0.1] # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = boussinesq_2d_imex # pass problem class description['problem_params'] = problem_params # pass problem parameters description['dtype_u'] = mesh # pass data type for u description['dtype_f'] = rhs_imex_mesh # pass data type for f description['sweeper_class'] = imex_1st_order # pass sweeper (see part B) description['sweeper_params'] = sweeper_params # pass sweeper parameters description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters # ORDER OF DIRK/IMEX EQUAL TO NUMBER OF SDC ITERATIONS AND THUS SDC ORDER dirk_order = step_params['maxiter'] controller = allinclusive_classic_nonMPI(num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) cfl_advection = P.params.u_adv * dt / P.h[0] cfl_acoustic_hor = P.params.c_s * dt / P.h[0] cfl_acoustic_ver = P.params.c_s * dt / P.h[1] print("Horizontal resolution: %4.2f" % P.h[0]) print("Vertical resolution: %4.2f" % P.h[1]) print("CFL number of advection: %4.2f" % cfl_advection) print("CFL number of acoustics (horizontal): %4.2f" % cfl_acoustic_hor) print("CFL number of acoustics (vertical): %4.2f" % cfl_acoustic_ver) print("Running SplitExplicit ....") method_split = 'MIS4_4' # method_split = 'RK3' splitp = SplitExplicit(P, method_split, problem_params) u0 = uinit.values.flatten() usplit = np.copy(u0) print(np.linalg.norm(usplit)) for i in range(0, 2 * Nsteps): usplit = splitp.timestep(usplit, dt / 2) print(np.linalg.norm(usplit)) print("Running DIRK ....") dirkp = dirk(P, dirk_order) udirk = np.copy(u0) print(np.linalg.norm(udirk)) for i in range(0, Nsteps): udirk = dirkp.timestep(udirk, dt) print(np.linalg.norm(udirk)) print("Running RK-IMEX ....") rkimex = rk_imex(P, dirk_order) uimex = np.copy(u0) dt_imex = dt for i in range(0, Nsteps): uimex = rkimex.timestep(uimex, dt_imex) print(np.linalg.norm(uimex)) print("Running SDC...") uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # For reference solution, increase GMRES tolerance P.gmres_tol_limit = 1e-10 rkimexref = rk_imex(P, 5) uref = np.copy(u0) dt_ref = dt / 10.0 print("Running RK-IMEX reference....") for i in range(0, 10 * Nsteps): uref = rkimexref.timestep(uref, dt_ref) usplit = unflatten(usplit, 4, P.N[0], P.N[1]) udirk = unflatten(udirk, 4, P.N[0], P.N[1]) uimex = unflatten(uimex, 4, P.N[0], P.N[1]) uref = unflatten(uref, 4, P.N[0], P.N[1]) np.save(cwd + 'data/xaxis', P.xx) np.save(cwd + 'data/sdc', uend.values) np.save(cwd + 'data/dirk', udirk) np.save(cwd + 'data/rkimex', uimex) np.save(cwd + 'data/split', usplit) np.save(cwd + 'data/uref', uref) print("diff split ", np.linalg.norm(uref - usplit)) print("diff dirk ", np.linalg.norm(uref - udirk)) print("diff rkimex ", np.linalg.norm(uref - uimex)) print("diff sdc ", np.linalg.norm(uref - uend.values)) print(" #### Logging report for Split #### ") print("Total number of matrix multiplications: %5i" % splitp.logger.nsmall) print(" #### Logging report for DIRK-%1i #### " % dirkp.order) print("Number of calls to implicit solver: %5i" % dirkp.logger.solver_calls) print("Total number of GMRES iterations: %5i" % dirkp.logger.iterations) print("Average number of iterations per call: %6.3f" % (float(dirkp.logger.iterations) / float(dirkp.logger.solver_calls))) print(" ") print(" #### Logging report for RK-IMEX-%1i #### " % rkimex.order) print("Number of calls to implicit solver: %5i" % rkimex.logger.solver_calls) print("Total number of GMRES iterations: %5i" % rkimex.logger.iterations) print("Average number of iterations per call: %6.3f" % (float(rkimex.logger.iterations) / float(rkimex.logger.solver_calls))) print(" ") print(" #### Logging report for SDC-(%1i,%1i) #### " % (sweeper_params['num_nodes'], step_params['maxiter'])) print("Number of calls to implicit solver: %5i" % P.gmres_logger.solver_calls) print("Total number of GMRES iterations: %5i" % P.gmres_logger.iterations) print("Average number of iterations per call: %6.3f" % (float(P.gmres_logger.iterations) / float(P.gmres_logger.solver_calls)))
def main(): """ A simple test program to do PFASST runs for the heat equation """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.25 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] sweeper_params[ 'QI'] = 'LU' # For the IMEX sweeper, the LU-trick can be activated for the implicit part # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 8 # frequency for the test value problem_params['nvars'] = [511, 255 ] # number of degrees of freedom for each level # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize space transfer parameters space_transfer_params = dict() space_transfer_params['rorder'] = 2 space_transfer_params['iorder'] = 6 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d_forced # pass problem class description['problem_params'] = problem_params # pass problem parameters description['dtype_u'] = mesh # pass data type for u description['dtype_f'] = rhs_imex_mesh # pass data type for f description['sweeper_class'] = imex_1st_order # pass sweeper (see part B) description['sweeper_params'] = sweeper_params # pass sweeper parameters description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters description[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # set time parameters t0 = 0.0 Tend = 4.0 # set up list of parallel time-steps to run PFASST with nsteps = int(Tend / level_params['dt']) num_proc_list = [2**i for i in range(int(np.log2(nsteps) + 1))] f = open('step_5_B_out.txt', 'w') # loop over different number of processes and check results for num_proc in num_proc_list: out = 'Working with %2i processes...' % num_proc f.write(out + '\n') print(out) # instantiate controller controller = allinclusive_classic_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics for item in iter_counts: out = 'Number of iterations for time %4.2f: %2i' % item f.write(out + '\n') print(out) f.write('\n') print() niters = np.array([item[1] for item in iter_counts]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) f.write(out + '\n') print(out) out = ' Range of values for number of iterations: %2i ' % np.ptp( niters) f.write(out + '\n') print(out) out = ' Position of max/min number of iterations: %2i -- %2i' % \ (int(np.argmax(niters)), int(np.argmin(niters))) f.write(out + '\n') print(out) out = ' Std and var for number of iterations: %4.2f -- %4.2f' % ( float(np.std(niters)), float(np.var(niters))) f.write(out + '\n') print(out) f.write('\n\n') print() print() assert err < 1.3505E-04, "ERROR: error is too high, got %s" % err assert np.ptp( niters ) <= 2, "ERROR: range of number of iterations is too high, got %s" % np.ptp( niters) assert np.mean( niters ) <= 6.0, "ERROR: mean number of iteratiobs is too high, got %s" % np.mean( niters) f.close()
def compute_convergence_data(cwd=''): """ Routine to run the 1d acoustic-advection example with different orders Args: cwd (string): current working directory """ num_procs = 1 # initialize level parameters level_params = dict() level_params['restol'] = 1E-14 # This comes as read-in for the step class step_params = dict() # This comes as read-in for the problem class problem_params = dict() problem_params['cadv'] = 0.1 problem_params['cs'] = 1.00 problem_params['order_adv'] = 5 problem_params['waveno'] = 5 # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 sweeper_params['do_coll_update'] = True # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = dump_energy # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = acoustic_1d_imex description['dtype_u'] = mesh description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order description['sweeper_params'] = sweeper_params nsteps = np.zeros((3, 9)) nsteps[0, :] = [20, 30, 40, 50, 60, 70, 80, 90, 100] nsteps[1, :] = nsteps[0, :] nsteps[2, :] = nsteps[0, :] for order in [3, 4, 5]: error = np.zeros(np.shape(nsteps)[1]) # setup parameters "in time" t0 = 0 Tend = 1.0 if order == 3: file = open(cwd + 'data/conv-data.txt', 'w') else: file = open(cwd + 'data/conv-data.txt', 'a') step_params['maxiter'] = order description['step_params'] = step_params for ii in range(0, np.shape(nsteps)[1]): ns = nsteps[order - 3, ii] if (order == 3) or (order == 4): problem_params['nvars'] = [(2, int(2 * ns))] elif order == 5: problem_params['nvars'] = [(2, int(2 * ns))] description['problem_params'] = problem_params dt = Tend / float(ns) level_params['dt'] = dt description['level_params'] = level_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) if ii == 0: print("Time step: %4.2f" % dt) print("Fast CFL number: %4.2f" % (problem_params['cs'] * dt / P.dx)) print("Slow CFL number: %4.2f" % (problem_params['cadv'] * dt / P.dx)) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) error[ii] = np.linalg.norm(uex.values - uend.values, np.inf) / np.linalg.norm( uex.values, np.inf) file.write( str(order) + " " + str(ns) + " " + str(error[ii]) + "\n") file.close() for ii in range(0, np.shape(nsteps)[1]): print('error for nsteps= %s: %s' % (nsteps[order - 3, ii], error[ii]))
def main(): # initialize level parameters level_params = dict() level_params['restol'] = 1E-12 # This comes as read-in for the step class (this is optional!) step_params = dict() step_params['maxiter'] = 20 # This comes as read-in for the problem class problem_params = dict() problem_params['nu'] = 1 problem_params['nvars'] = 2047 problem_params['lambda0'] = 5.0 problem_params['newton_maxiter'] = 50 problem_params['newton_tol'] = 1E-12 problem_params['interval'] = (-5, 5) # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 5 sweeper_params['QI'] = 'LU' sweeper_params['fixed_time_in_jacobian'] = 0 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = err_reduction_hook # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = generalized_fisher_jac description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_params'] = sweeper_params description['step_params'] = step_params # setup parameters "in time" t0 = 0 Tend = 0.1 sweeper_list = [ generic_implicit, linearized_implicit_fixed_parallel, linearized_implicit_fixed_parallel_prec ] dt_list = [Tend / 2**i for i in range(1, 5)] results = dict() results['sweeper_list'] = [sweeper.__name__ for sweeper in sweeper_list] results['dt_list'] = dt_list # loop over the different sweepers and check results for sweeper in sweeper_list: description['sweeper_class'] = sweeper error_reduction = [] for dt in dt_list: print('Working with sweeper %s and dt = %s...' % (sweeper.__name__, dt)) level_params['dt'] = dt description['level_params'] = level_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics filtered_stats = filter_stats(stats, type='error_pre_iteration') error_pre = sort_stats(filtered_stats, sortby='iter')[0][1] filtered_stats = filter_stats(stats, type='error_post_iteration') error_post = sort_stats(filtered_stats, sortby='iter')[0][1] error_reduction.append(error_post / error_pre) print('error and reduction rate at time %s: %6.4e -- %6.4e' % (Tend, error_post, error_reduction[-1])) results[sweeper.__name__] = error_reduction print() file = open('data/error_reduction_data.pkl', 'wb') pickle.dump(results, file) file.close()
def run_simulation(prob=None): """ Routine to run the simulation of a second order problem Args: prob (str): name of the problem """ # check what problem type we have and set up corresponding description and variables if prob == 'harmonic': description, controller_params = setup_harmonic() # set time parameters t0 = 0.0 Tend = 50.0 num_procs = 100 maxmeaniter = 5.6 elif prob == 'henonheiles': description, controller_params = setup_henonheiles() # set time parameters t0 = 0.0 Tend = 25.0 num_procs = 100 maxmeaniter = 3.9 else: raise NotImplemented('Problem type not implemented, got %s' % prob) # instantiate the controller controller = allinclusive_classic_nonMPI(num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t=t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # filter statistics by type (number of iterations) filtered_stats = filter_stats(stats, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts = sort_stats(filtered_stats, sortby='time') # compute and print statistics # for item in iter_counts: # out = 'Number of iterations for time %4.2f: %2i' % item # print(out) niters = np.array([item[1] for item in iter_counts]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) print(out) out = ' Range of values for number of iterations: %2i ' % np.ptp(niters) print(out) out = ' Position of max/min number of iterations: %2i -- %2i' % \ (int(np.argmax(niters)), int(np.argmin(niters))) print(out) out = ' Std and var for number of iterations: %4.2f -- %4.2f' % (float(np.std(niters)), float(np.var(niters))) print(out) assert np.mean(niters) <= maxmeaniter, 'Mean number of iterations is too high, got %s' % np.mean(niters) fname = 'data/' + prob + '.dat' f = open(fname, 'wb') dill.dump(stats, f) f.close() assert os.path.isfile(fname), 'Run for %s did not create stats file' % prob
def main(): """ A simple test program to run IMEX SDC for a single time step """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 4 # frequency for the test value problem_params['nvars'] = 1023 # number of degrees of freedom # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize controller parameters controller_params = dict() controller_params['log_to_file'] = True controller_params['fname'] = 'step_2_C_out.txt' # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = heat1d_forced description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=1, controller_params=controller_params, description=description) # set time parameters t0 = 0.1 Tend = 0.3 # note that we are requesting 2 time steps here (dt is 0.1) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) f = open('step_2_C_out.txt', 'a') out = 'Error after SDC iterations: %8.6e' % err f.write(out) print(out) f.close() assert err <= 2E-5, "ERROR: controller doing IMEX SDC iteration did not reduce the error enough, got %s" % err
def compute_and_plot_itererror(): """ Routine to compute and plot the error over the iterations for difference cs values """ num_procs = 1 t0 = 0.0 Tend = 0.025 # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = Tend # This comes as read-in for the step class step_params = dict() step_params['maxiter'] = 15 # This comes as read-in for the problem class problem_params = dict() problem_params['cadv'] = 0.1 problem_params['nvars'] = [(2, 300)] problem_params['order_adv'] = 5 problem_params['waveno'] = 5 # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['do_coll_update'] = True # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = dump_energy # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = acoustic_1d_imex description['dtype_u'] = mesh description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order description['step_params'] = step_params description['level_params'] = level_params cs_v = [0.5, 1.0, 1.5, 5.0] nodes_v = [3] residual = np.zeros( (np.size(cs_v), np.size(nodes_v), step_params['maxiter'])) convrate = np.zeros( (np.size(cs_v), np.size(nodes_v), step_params['maxiter'] - 1)) lastiter = np.zeros( (np.size(cs_v), np.size(nodes_v))) + step_params['maxiter'] avg_convrate = np.zeros((np.size(cs_v), np.size(nodes_v))) P = None for cs_ind in range(0, np.size(cs_v)): problem_params['cs'] = cs_v[cs_ind] description['problem_params'] = problem_params for nodes_ind in np.arange(np.size(nodes_v)): sweeper_params['num_nodes'] = nodes_v[nodes_ind] description['sweeper_params'] = sweeper_params # instantiate the controller controller = allinclusive_classic_nonMPI( num_procs=num_procs, controller_params=controller_params, description=description) # get initial values on finest level P = controller.MS[0].levels[0].prob uinit = P.u_exact(t0) print("Fast CFL number: %4.2f" % (problem_params['cs'] * level_params['dt'] / P.dx)) print("Slow CFL number: %4.2f" % (problem_params['cadv'] * level_params['dt'] / P.dx)) # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) extract_stats = filter_stats(stats, type='residual_post_iteration') for k, v in extract_stats.items(): iter = getattr(k, 'iter') if iter is not -1: residual[cs_ind, nodes_ind, iter - 2] = v # Compute convergence rates for iter in range(0, step_params['maxiter'] - 1): if residual[cs_ind, nodes_ind, iter] < level_params['restol']: lastiter[cs_ind, nodes_ind] = iter else: convrate[cs_ind, nodes_ind, iter] = residual[cs_ind, nodes_ind, iter + 1] / \ residual[cs_ind, nodes_ind, iter] print(lastiter[cs_ind, nodes_ind]) avg_convrate[cs_ind, nodes_ind] = np.sum(convrate[cs_ind, nodes_ind, :]) / \ float(lastiter[cs_ind, nodes_ind]) # Plot the results fs = 8 color = ['r', 'b', 'g', 'c'] shape = ['o-', 'd-', 's-', '>-'] rcParams['figure.figsize'] = 2.5, 2.5 fig = plt.figure() for ii in range(0, np.size(cs_v)): x = np.arange(1, lastiter[ii, 0]) y = convrate[ii, 0, 0:int(lastiter[ii, 0]) - 1] plt.plot(x, y, shape[ii], markersize=fs - 2, color=color[ii], label=r'$C_{\rm fast}$=%4.2f' % (cs_v[ii] * level_params['dt'] / P.dx)) plt.legend(loc='upper right', fontsize=fs, prop={'size': fs - 2}) plt.xlabel('Iteration', fontsize=fs) plt.ylabel(r'$|| r^{k+1} ||_{\infty}/|| r^k ||_{\infty}$', fontsize=fs, labelpad=2) plt.xlim([0, step_params['maxiter']]) plt.ylim([0, 1.0]) plt.yticks(fontsize=fs) plt.xticks(fontsize=fs) filename = 'data/iteration.png' fig.savefig(filename, bbox_inches='tight')
def main(): """ A simple test program to setup a full multi-step multi-level hierarchy """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = 0.5 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient problem_params['freq'] = 4 # frequency for the test value problem_params['nvars'] = [31, 15, 7 ] # number of degrees of freedom for each level # initialize step parameters step_params = dict() step_params['maxiter'] = 20 # initialize space transfer parameters space_transfer_params = dict() space_transfer_params['rorder'] = 2 space_transfer_params['iorder'] = 6 # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d_forced # pass problem class description['problem_params'] = problem_params # pass problem parameters description['dtype_u'] = mesh # pass data type for u description['dtype_f'] = rhs_imex_mesh # pass data type for f description['sweeper_class'] = imex_1st_order # pass sweeper (see part B) description['sweeper_params'] = sweeper_params # pass sweeper parameters description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters description[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # instantiate controller controller = allinclusive_classic_nonMPI(num_procs=10, controller_params={}, description=description) # check number of levels f = open('step_5_A_out.txt', 'w') for i in range(len(controller.MS)): out = "Process %2i has %2i levels" % (i, len(controller.MS[i].levels)) f.write(out + '\n') print(out) f.close() assert all([len(S.levels) == 3 for S in controller.MS ]), "ERROR: not all steps have the same number of levels"