def pre_step(self, step, level_number): """ Default routine called before each step Args: step: the current step level_number: the current level number """ super(error_output, self).pre_step(step, level_number) L = step.levels[level_number] # This is a bit black magic: we are going to run pySDC within the hook to check the error against the "exact" # solution of the collocation problem description = step.params.description description['level_params']['restol'] = 1E-14 description['problem_params']['direct_solver'] = True controller_params = step.params.controller_params del controller_params[ 'hook_class'] # get rid of the hook, otherwise this will be an endless recursion.. controller_params['use_iteration_estimator'] = False controller_params['logger_level'] = 90 controller = controller_nonMPI(num_procs=1, description=description, controller_params=controller_params) self.uex, _ = controller.run(u0=L.u[0], t0=L.time, Tend=L.time + L.dt)
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['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 = controller_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"
def run_reference(Tend): """ Routine to run particular SDC variant Args: Tend (float): end time for dumping """ # load (incomplete) default parameters description, controller_params = setup_parameters_FFT() # setup parameters "in time" t0 = 0 # instantiate controller controller = controller_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 by variant (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) 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) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') print('Time to solution: %6.4f sec.' % timing[0][1]) print() computed_radii_tmp = sort_stats(filter_stats(stats, type='computed_radius'), sortby='time') computed_radii = np.array([item0[1] for item0 in computed_radii_tmp]) print(len(computed_radii_tmp), len(computed_radii)) fname = 'data/AC_reference_FFT_Tend{:.1e}'.format(Tend) np.savez_compressed(file=fname, uend=uend.values, radius=computed_radii)
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['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller_ref = controller_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 run_faulty_simulations(type=None, niters=None, cwd=''): """ A simple program to run faulty simulations Args: type (str): setup type niters (int): number of iterations in clean run f: file handler cwd (str): current workind directory """ if type == 'diffusion': description, controller_params = diffusion_setup() elif type == 'reaction': description, controller_params = reaction_setup() elif type == 'vanderpol': description, controller_params = vanderpol_setup() else: raise ValueError('No valid setup type provided, aborting..') # set time parameters t0 = 0.0 Tend = description['level_params']['dt'] filehandle_injections = open(cwd + 'data/dump_injections_' + type + '.txt', 'w') controller_params['hook_class'] = fault_hook description['sweeper_params']['allow_fault_correction'] = True description['sweeper_params'][ 'dump_injections_filehandle'] = filehandle_injections description['sweeper_params']['niters'] = niters # instantiate controller controller = controller_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) # number of runs nruns = 500 results = [] for nr in range(nruns): # this is where the iteration is happening uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) results.append(stats) filehandle_injections.close() dill.dump(results, open(cwd + "data/results_" + type + ".pkl", "wb"))
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 = controller_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_8_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_8_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 == 8 and max_iter == 8, "ERROR: number of iterations not as expected, got %s and %s" % \ (min_iter, max_iter)
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['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 = controller_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 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['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 = controller_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(): """ 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['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params # instantiate the controller controller = controller_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_clean_simulations(type=None): """ A simple code to run fault-free simulations Args: type (str): setup type f: file handler """ if type == 'diffusion': description, controller_params = diffusion_setup() elif type == 'reaction': description, controller_params = reaction_setup() elif type == 'vanderpol': description, controller_params = vanderpol_setup() else: raise ValueError('No valid setup type provided, aborting..') # set time parameters t0 = 0.0 Tend = description['level_params']['dt'] # instantiate controller controller = controller_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) # this is where the iteration is happening 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') # print('This clean run took %s iterations!' % iter_counts[0][1]) return iter_counts[0][1]
def run_SDC_variant(variant=None, inexact=False): """ Routine to run particular SDC variant Args: variant (str): string describing the variant inexact (bool): flag to use inexact nonlinear solve (or nor) Returns: results and statistics of the run """ # load (incomplete) default parameters description, controller_params = setup_parameters() # add stuff based on variant if variant == 'explicit': description['problem_class'] = allencahn_front_fullyimplicit description['sweeper_class'] = explicit else: raise NotImplemented('Wrong variant specified, got %s' % variant) # setup parameters "in time" t0 = 0 Tend = 1.0 / (16.0 * 128.0**2) # instantiate controller controller = controller_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) wrapped = wrapper(controller.run, u0=uinit, t0=t0, Tend=Tend) print(timeit.timeit(wrapped, number=10000) / 10000.0)
def pre_step(self, step, level_number): """ Default routine called before each step Args: step: the current step level_number: the current level number """ super(error_output, self).pre_step(step, level_number) L = step.levels[level_number] description = step.params.description description['level_params']['restol'] = 1E-14 description['problem_params']['direct_solver'] = True controller_params = step.params.controller_params del controller_params['hook_class'] controller_params['use_iteration_estimator'] = False controller_params['logger_level'] = 90 controller = controller_nonMPI(num_procs=1, description=description, controller_params=controller_params) self.uex, _ = controller.run(u0=L.u[0], t0=L.time, Tend=L.time + L.dt)
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 # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d # pass problem class 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() controller_params['mssdc_jac'] = True controller_params_jac = controller_params.copy() controller_params['mssdc_jac'] = False controller_params_gs = controller_params.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_jac = controller_nonMPI( num_procs=num_proc, controller_params=controller_params_jac, description=description_mssdc) controller_mssdc_gs = controller_nonMPI( num_procs=num_proc, controller_params=controller_params_gs, description=description_mssdc) controller_pfasst = controller_nonMPI(num_procs=num_proc, controller_params=controller_params, description=description_pfasst) # get initial values on finest level P = controller_mssdc_jac.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_jac, stats_mssdc_jac = controller_mssdc_jac.run(u0=uinit, t0=t0, Tend=Tend) uend_mssdc_gs, stats_mssdc_gs = controller_mssdc_gs.run(u0=uinit, t0=t0, Tend=Tend) # compute exact solution and compare for both runs uex = P.u_exact(Tend) err_mssdc_jac = abs(uex - uend_mssdc_jac) err_mssdc_gs = abs(uex - uend_mssdc_gs) err_pfasst = abs(uex - uend_pfasst) diff_jac = abs(uend_mssdc_jac - uend_pfasst) diff_gs = abs(uend_mssdc_gs - uend_pfasst) diff_jac_gs = abs(uend_mssdc_gs - uend_mssdc_jac) f = open('step_8_B_out.txt', 'w') out = 'Error PFASST: %12.8e' % err_pfasst f.write(out + '\n') print(out) out = 'Error parallel MSSDC: %12.8e' % err_mssdc_jac f.write(out + '\n') print(out) out = 'Error serial MSSDC: %12.8e' % err_mssdc_gs f.write(out + '\n') print(out) out = 'Diff PFASST vs. parallel MSSDC: %12.8e' % diff_jac f.write(out + '\n') print(out) out = 'Diff PFASST vs. serial MSSDC: %12.8e' % diff_gs f.write(out + '\n') print(out) out = 'Diff parallel vs. serial MSSDC: %12.8e' % diff_jac_gs 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_jac = filter_stats(stats_mssdc_jac, type='niter') filtered_stats_mssdc_gs = filter_stats(stats_mssdc_gs, 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_jac = sort_stats(filtered_stats_mssdc_jac, sortby='time') iter_counts_mssdc_gs = sort_stats(filtered_stats_mssdc_gs, sortby='time') # compute and print statistics for item_pfasst, item_mssdc_jac, item_mssdc_gs in \ zip(iter_counts_pfasst, iter_counts_mssdc_jac, iter_counts_mssdc_gs): out = 'Number of iterations for time %4.2f (PFASST/parMSSDC/serMSSDC): %2i / %2i / %2i' % \ (item_pfasst[0], item_pfasst[1], item_mssdc_jac[1], item_mssdc_gs[1]) f.write(out + '\n') print(out) f.close() # call helper routine to produce residual plot show_residual_across_simulation(stats_mssdc_jac, 'step_8_residuals_mssdc_jac.png') show_residual_across_simulation(stats_mssdc_gs, 'step_8_residuals_mssdc_gs.png') assert os.path.isfile('step_8_residuals_mssdc_jac.png') assert os.path.isfile('step_8_residuals_mssdc_gs.png') assert diff_jac < 3.1E-10, \ "ERROR: difference between PFASST and parallel MSSDC controller is too large, got %s" % diff_jac assert diff_gs < 3.1E-10, \ "ERROR: difference between PFASST and serial MSSDC controller is too large, got %s" % diff_gs assert diff_jac_gs < 3.1E-10, \ "ERROR: difference between parallel and serial MSSDC controller is too large, got %s" % diff_jac_gs
def run_simulations(type=None, ndim_list=None, Tend=None, nsteps_list=None, ml=False, nprocs=None): """ A simple test program to do SDC runs for the heat equation in various dimensions """ t0 = None dt = None description = None controller_params = None f = open('step_8_C_out.txt', 'a') for ndim in ndim_list: for nsteps in nsteps_list: if type == 'diffusion': # set time parameters t0 = 0.0 dt = (Tend - t0) / nsteps description, controller_params = setup_diffusion(dt, ndim, ml) elif type == 'advection': # set time parameters t0 = 0.0 dt = (Tend - t0) / nsteps description, controller_params = setup_advection(dt, ndim, ml) elif type == 'auzinger': assert ndim == 1 # set time parameters t0 = 0.0 dt = (Tend - t0) / nsteps description, controller_params = setup_auzinger(dt, ml) out = f'Running {type} in {ndim} dimensions with time-step size {dt}...\n' f.write(out + '\n') print(out) # Warning: this is black magic used to run an 'exact' collocation solver for each step within the hooks description['step_params']['description'] = description description['step_params']['controller_params'] = controller_params # instantiate controller controller = controller_nonMPI(num_procs=nprocs, 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 by type (number of iterations) iter_counts = sort_stats(filter_stats(stats, type='niter'), sortby='time') niters = np.array([item[1] for item in iter_counts]) out = f' Mean number of iterations: {np.mean(niters):4.2f}' f.write(out + '\n') print(out) # filter statistics by type (error after time-step) PDE_errors = sort_stats(filter_stats(stats, type='PDE_error_after_step'), sortby='time') coll_errors = sort_stats(filter_stats( stats, type='coll_error_after_step'), sortby='time') for iters, PDE_err, coll_err in zip(iter_counts, PDE_errors, coll_errors): assert coll_err[1] < description['step_params'][ 'errtol'], f'Error too high, got {coll_err[1]:8.4e}' out = f' Errors after step {PDE_err[0]:8.4f} with {iters[1]} iterations: ' \ f'{PDE_err[1]:8.4e} / {coll_err[1]:8.4e}' f.write(out + '\n') print(out) f.write('\n') print() # filter statistics by type (error after time-step) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') out = f'...done, took {timing[0][1]} seconds!' f.write(out + '\n') print(out) print() out = '-----------------------------------------------------------------------------' f.write(out + '\n') print(out) f.close()
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['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 = controller_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_simulation(): """ Routine to run the simulation of a second order problem """ # initialize level parameters level_params = dict() level_params['restol'] = 0.0 level_params['dt'] = 1.0 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussLobatto sweeper_params['num_nodes'] = [5, 3] sweeper_params['initial_guess'] = 'zero' # initialize problem parameters for the Penning trap problem_params = dict() problem_params['k'] = None # will be defined later problem_params['phase'] = 0.0 problem_params['amp'] = 1.0 # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize controller parameters controller_params = dict() controller_params['hook_class'] = stop_at_error_hook controller_params['logger_level'] = 30 # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = harmonic_oscillator description['sweeper_class'] = verlet description['level_params'] = level_params description['step_params'] = step_params description['space_transfer_class'] = particles_to_particles # set time parameters t0 = 0.0 Tend = 4.0 num_procs = 4 rlim_left = 0 rlim_right = 16.0 nstep = 34 ks = np.linspace(rlim_left, rlim_right, nstep)[1:] # qd_combinations = [('IE', 'EE'), ('IE', 'PIC'), # ('LU', 'EE'), ('LU', 'PIC'), # # ('MIN3', 'PIC'), ('MIN3', 'EE'), # ('PIC', 'EE'), ('PIC', 'PIC')] qd_combinations = [('IE', 'EE'), ('PIC', 'PIC')] results = dict() results['ks'] = ks for qd in qd_combinations: print('Working on combination (%s, %s)...' % qd) niters = np.zeros(len(ks)) for i, k in enumerate(ks): problem_params['k'] = k description['problem_params'] = problem_params sweeper_params['QI'] = qd[0] sweeper_params['QE'] = qd[1] description['sweeper_params'] = sweeper_params # instantiate the controller controller = controller_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) uex = P.u_exact(Tend) print('Error after run: %s' % 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') niters[i] = np.mean(np.array([item[1] for item in iter_counts])) # print('Worked on k = %s, took %s iterations' % (k, results[i])) results[qd] = niters fname = 'data/harmonic_k.dat' f = open(fname, 'wb') dill.dump(results, f) f.close() assert os.path.isfile(fname), 'Run for %s did not create stats file' % prob
def run_variants(variant=None, ml=None, num_procs=None): """ Main routine to run the different implementations of the heat equation with FEniCS Args: variant (str): specifies the variant ml (bool): use single or multiple levels num_procs (int): number of processors in time """ Tend = 1.0 t0 = 0.0 description, controller_params = setup(t0=t0, ml=ml) if variant == 'mass': # Note that we need to reduce the tolerance for the residual here, since otherwise the error will be too high description['level_params']['restol'] /= 500 description['problem_class'] = fenics_heat_mass description['sweeper_class'] = imex_1st_order_mass elif variant == 'mass_inv': description['problem_class'] = fenics_heat description['sweeper_class'] = imex_1st_order elif variant == 'weak': description['problem_class'] = fenics_heat_weak_imex description['sweeper_class'] = imex_1st_order else: raise NotImplementedError('Variant %s is not implemented' % variant) # quickly generate block of steps controller = controller_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(0.0) # 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) / abs(uex) f = open('step_7_A_out.txt', 'a') out = f'Variant {variant} with ml={ml} and num_procs={num_procs} -- error at time {Tend}: {err}' f.write(out + '\n') print(out) # 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') 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) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') out = f'Time to solution: {timing[0][1]:6.4f} sec.' f.write(out + '\n') print(out) if num_procs == 1: assert np.mean( niters ) <= 6.0, 'Mean number of iterations is too high, got %s' % np.mean( niters) assert err <= 4.1E-08, 'Error is too high, got %s' % err else: assert np.mean( niters ) <= 11.6, 'Mean number of iterations is too high, got %s' % np.mean( niters) assert err <= 4.0E-08, 'Error is too high, got %s' % err f.write('\n') print() f.close()
def main(comm=None): # 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'] = comm.Get_size() sweeper_params['comm'] = comm # 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 = ['IEpar', 'Qpar', 'MIN', 'MIN3'] 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[ 'sweeper_class'] = generic_implicit_MPI # pass sweeper description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters description[ 'step_params'] = step_params # pass step parameters # description['base_transfer_class'] = base_transfer_mpi 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 = controller_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) * 4 + 4, 'ERROR: did not get all results, got %s' % len(results) if comm.Get_rank() == 0: # write out for later visualization file = open('data/parallelSDC_iterations_precond_MPI.pkl', 'wb') pickle.dump(results, file) assert os.path.isfile('data/parallelSDC_iterations_precond_MPI.pkl' ), 'ERROR: pickle did not create file'
def run(sweeper_list, MPI_fake=True, controller_comm=MPI.COMM_WORLD, node_comm=None, node_list=None): # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 # 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'] = 2 problem_params['nvars'] = [(256,256), (128, 128)] problem_params['eps'] = [0.04] problem_params['newton_maxiter'] = 1 #50 problem_params['newton_tol'] = 1E-11 problem_params['lin_tol'] = 1E-12 problem_params['lin_maxiter'] = 450 #0 problem_params['radius'] = 0.25 problem_params['comm'] = node_comm #time_comm #MPI.COMM_WORLD #node_comm # This comes as read-in for the sweeper class sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 4 sweeper_params['QI'] = 'LU' sweeper_params['fixed_time_in_jacobian'] = 0 sweeper_params['comm'] = node_comm sweeper_params['node_list'] = node_list # 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'] = AC_jac description['problem_params'] = problem_params description['sweeper_params'] = sweeper_params description['step_params'] = step_params description['space_transfer_class'] = mesh_to_mesh #description['space_transfer_class'] = base_transfer_MPI #mesh_to_mesh #assert MPI.COMM_WORLD.Get_size() == sweeper_params['num_nodes'] # setup parameters "in time" t0 = 0 Tend = 0.024 # loop over the different sweepers and check results serial =True for sweeper in sweeper_list: description['sweeper_class'] = sweeper error_reduction = [] for dt in [1e-3]: print('Working with sweeper %s and dt = %s...' % (sweeper.__name__, dt)) level_params['dt'] = dt description['level_params'] = level_params # instantiate the controller and stuff if(sweeper.__name__=='generic_implicit'): if(controller_comm.Get_size()==1): controller = controller_nonMPI(num_procs=1, controller_params=controller_params, description=description) serial=False else: controller = controller_MPI(controller_params=controller_params, description=description, comm=controller_comm) elif (sweeper.__name__=='linearized_implicit_fixed_parallel_prec_MPI'or sweeper.__name__=="linearized_implicit_fixed_parallel_MPI" or sweeper.__name__=='linearized_implicit_fixed_parallel_prec'or sweeper.__name__=="linearized_implicit_fixed_parallel"): #if(node_comm is None): #description['base_transfer_class'] = base_transfer #controller = controller_MPI(controller_params=controller_params, description=description, comm=controller_comm) #else: # serial==False if (sweeper.__name__=='linearized_implicit_fixed_parallel_prec_MPI'or sweeper.__name__=="linearized_implicit_fixed_parallel_MPI"): description['base_transfer_class'] = base_transfer_MPI controller = controller_MPI(controller_params=controller_params, description=description, comm=controller_comm) else: controller = controller_MPI(controller_params=controller_params, description=description, comm=controller_comm) #controller = controller_nonMPI(num_procs=1, controller_params=controller_params, description=description) #serial=False elif (sweeper.__name__=='div_linearized_implicit_fixed_parallel_prec_MPI' or sweeper.__name__=='div_linearized_implicit_fixed_parallel_MPI'): description['base_transfer_class'] = div_base_transfer_MPI controller = controller_MPI(controller_params=controller_params, description=description, comm=controller_comm) serial==False if(serial==True): P = controller.S.levels[0].prob else: P = controller.MS[0].levels[0].prob # get initial values on finest level uinit = P.u_exact(t0) # call main function to get things done... MPI.COMM_WORLD.Barrier() t1 = MPI.Wtime() uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) t2 = MPI.Wtime() time =t2-t1 print( "My elapsed time is ", time) maxtime=time maxtime = np.zeros(1, dtype='float64') local_time = np.max(time).astype('float64') MPI.COMM_WORLD.Allreduce(local_time,maxtime, op=MPI.MAX) print( "Elapsed max time is ", maxtime[0]) if(True): #control the solution fname = 'ref_24.npz' loaded = np.load(fname) uref = loaded['uend'] print("Fehler ", np.linalg.norm(uref-uend.values, np.inf)) print("Abweichung vom Anfangswert ", np.linalg.norm(uinit.values-uend.values, np.inf)) # compute and print statistics filtered_stats = filter_stats(stats, type='niter') iter_counts = sort_stats(filtered_stats, sortby='time') niters = np.array([item[1] for item in iter_counts]) print("Iterationen SDC ", niters) print("Newton Iterationen ", P.newton_itercount) maxcount = np.zeros(1, dtype='float64') local_count = np.max(P.newton_itercount).astype('float64') MPI.COMM_WORLD.Allreduce(local_count,maxcount, op=MPI.MAX) print("maxiter ", maxcount[0]) if(serial==False): for pp in controller.MS: print("Newton Iter ", pp.levels[0].prob.newton_itercount) #print("lineare Iter ", pp.levels[0].prob.linear_count) #print("warning ", pp.levels[0].prob.warning_count) #print("time for linear solve ", pp.levels[0].prob.time_for_solve) else: print("Newton Iter ", controller.S.levels[0].prob.newton_itercount) #print("lineare Iter ", controller.S.levels[0].prob.linear_count) #print("warning ", controller.S.levels[0].prob.warning_count) #print("time for linear solve ", controller.S.levels[0].prob.time_for_solve) MPI.COMM_WORLD.Barrier() print("------------------------------------------------------------------------------------------------------------------------------------------")
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['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 = controller_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', 'v'] rcParams['figure.figsize'] = 2.5, 2.5 rcParams['pgf.rcfonts'] = False fig = plt.figure() for ii in range(0, np.size(cs_v)): x = np.arange(1, lastiter[ii, 0] - 1) y = convrate[ii, 0, 0:int(lastiter[ii, 0]) - 2] plt.plot(x, y, linestyle='-', marker=shape[ii], markersize=fs - 2, color=color[ii], label=r'$C_{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 do PFASST runs for the heat equation """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-14 level_params['dt'] = 0.9 / 32 level_params['nsweeps'] = 1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussLobatto sweeper_params['num_nodes'] = [5, 3, 2] sweeper_params['QI'] = [ 'LU' ] # For the IMEX sweeper, the LU-trick can be activated for the implicit part sweeper_params['initial_guess'] = 'spread' sweeper_params['do_coll_update'] = False # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.02 # diffusion coefficient problem_params['c'] = 1.0 # advection speed problem_params['freq'] = -1 # frequency for the test value problem_params['nvars'] = [256, 128, 64 ] # number of degrees of freedom for each level problem_params['L'] = 1.0 # length of the interval [-L/2, L/2] # initialize step parameters step_params = dict() step_params['maxiter'] = 10 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = libpfasst_output # fill description dictionary for easy step instantiation description = dict() # description['problem_class'] = advectiondiffusion1d_imex # pass problem class description[ 'problem_class'] = advectiondiffusion1d_implicit # pass problem class description['problem_params'] = problem_params # pass problem parameters # description['sweeper_class'] = imex_1st_order # pass sweeper description['sweeper_class'] = generic_implicit # 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_fft # pass spatial transfer class description['space_transfer_params'] = dict( ) # pass paramters for spatial transfer # set time parameters t0 = 0.0 Tend = level_params['dt'] num_proc = 1 # instantiate controller controller = controller_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) # print(controller.MS[0].levels[0].sweep.coll.Qmat) # print(controller.MS[0].levels[0].sweep.QI) # exit() # 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 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) print('Error: %8.4e' % err)
def run_variant(nlevels=None): """ Routine to run particular SDC variant Args: Returns: """ # load (incomplete) default parameters description, controller_params = setup_parameters() # add stuff based on variant if nlevels == 1: description['level_params']['nsweeps'] = 1 description['problem_params']['nvars'] = [(128, 128)] # description['problem_params']['nvars'] = [(32, 32)] elif nlevels == 2: description['level_params']['nsweeps'] = [1, 1] description['problem_params']['nvars'] = [(128, 128), (32, 32)] # description['problem_params']['nvars'] = [(32, 32), (16, 16)] else: raise NotImplemented('Wrong variant specified, got %s' % nlevels) out = 'Working on %s levels...' % nlevels print(out) # setup parameters "in time" t0 = 0.0 Tend = 0.032 # instantiate controller controller = controller_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 by variant (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) 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) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') print('Time to solution: %6.4f sec.' % timing[0][1]) fname = 'data/AC_reference_FFT_Tend{:.1e}'.format(Tend) + '.npz' loaded = np.load(fname) uref = loaded['uend'] err = np.linalg.norm(uref - uend.values, np.inf) print('Error vs. reference solution: %6.4e' % err) print() return stats
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['sweeper_class'] = imex_1st_order description['sweeper_params'] = sweeper_params description['step_params'] = step_params description['level_params'] = level_params # instantiate the controller controller = controller_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_variant(variant=None): """ Routine to run a particular variant Args: variant (str): string describing the variant """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-07 level_params['dt'] = 1E-03 / 2 level_params['nsweeps'] = 1 # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = 3 sweeper_params['initial_guess'] = 'zero' # This comes as read-in for the problem class problem_params = dict() problem_params['nu'] = 2 problem_params['eps'] = 0.04 problem_params['newton_maxiter'] = 100 problem_params['newton_tol'] = 1E-08 problem_params['lin_tol'] = 1E-09 problem_params['lin_maxiter'] = 100 problem_params['radius'] = 0.25 # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['hook_class'] = monitor # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = allencahn_fullyimplicit description['level_params'] = level_params # pass level parameters description['step_params'] = step_params # pass step parameters do_print = True # add stuff based on variant if variant == 'sl_serial': maxmeaniters = 5.0 sweeper_params['QI'] = ['LU'] problem_params['nvars'] = [(128, 128)] description[ 'problem_params'] = problem_params # pass problem parameters description['sweeper_class'] = generic_implicit # pass sweeper description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters elif variant == 'sl_parallel': maxmeaniters = 5.12 assert MPI.COMM_WORLD.Get_size() == sweeper_params['num_nodes'] sweeper_params['QI'] = ['MIN3'] sweeper_params['comm'] = MPI.COMM_WORLD problem_params['nvars'] = [(128, 128)] description[ 'problem_params'] = problem_params # pass problem parameters description['sweeper_class'] = generic_implicit_MPI # pass sweeper description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters do_print = MPI.COMM_WORLD.Get_rank() == 0 elif variant == 'ml_serial': maxmeaniters = 3.125 sweeper_params['QI'] = ['LU'] problem_params['nvars'] = [(128, 128), (64, 64)] description['space_transfer_class'] = mesh_to_mesh_fft2d description[ 'problem_params'] = problem_params # pass problem parameters description['sweeper_class'] = generic_implicit # pass sweeper description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters elif variant == 'ml_parallel': assert MPI.COMM_WORLD.Get_size() == sweeper_params['num_nodes'] maxmeaniters = 4.25 sweeper_params['QI'] = ['MIN3'] sweeper_params['comm'] = MPI.COMM_WORLD problem_params['nvars'] = [(128, 128), (64, 64)] description[ 'problem_params'] = problem_params # pass problem parameters description['sweeper_class'] = generic_implicit_MPI # pass sweeper description[ 'sweeper_params'] = sweeper_params # pass sweeper parameters description['space_transfer_class'] = mesh_to_mesh_fft2d description['base_transfer_class'] = base_transfer_MPI do_print = MPI.COMM_WORLD.Get_rank() == 0 else: raise NotImplemented('Wrong variant specified, got %s' % variant) if do_print: out = 'Working on %s variant...' % variant print(out) # setup parameters "in time" t0 = 0 Tend = 0.004 # instantiate controller controller = controller_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 by variant (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]) if do_print: out = ' Mean number of iterations: %4.2f' % np.mean(niters) assert np.mean(niters) <= maxmeaniters, 'ERROR: number of iterations is too high, got %s instead of %s' \ % (np.mean(niters), maxmeaniters) 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) print(' Iteration count (nonlinear/linear): %i / %i' % (P.newton_itercount, P.lin_itercount)) print(' Mean Iteration count per call: %4.2f / %4.2f' % (P.newton_itercount / max(P.newton_ncalls, 1), P.lin_itercount / max(P.lin_ncalls, 1))) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') print('Time to solution: %6.4f sec.' % timing[0][1]) return None
def run_simulation(spectral=None, ml=None, num_procs=None): """ A test program to do SDC, MLSDC and PFASST runs for the 2D NLS equation Args: spectral (bool): run in real or spectral space ml (bool): single or multiple levels num_procs (int): number of parallel processors """ comm = MPI.COMM_WORLD rank = comm.Get_rank() # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = 1E-01 / 2 level_params['nsweeps'] = [1] # 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 sweeper_params['initial_guess'] = 'zero' # initialize problem parameters problem_params = dict() if ml: problem_params['nvars'] = [(128, 128), (32, 32)] else: problem_params['nvars'] = [(128, 128)] problem_params['spectral'] = spectral problem_params['comm'] = comm # initialize step parameters step_params = dict() step_params['maxiter'] = 50 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 if rank == 0 else 99 # controller_params['predict_type'] = 'fine_only' # fill description dictionary for easy step instantiation description = dict() description['problem_params'] = problem_params # pass problem parameters description['problem_class'] = nonlinearschroedinger_imex description['sweeper_class'] = imex_1st_order 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'] = fft_to_fft # set time parameters t0 = 0.0 Tend = 1.0 f = None if rank == 0: f = open('step_7_B_out.txt', 'a') out = f'Running with ml={ml} and num_procs={num_procs}...' f.write(out + '\n') print(out) # instantiate controller controller = controller_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) uex = P.u_exact(Tend) err = abs(uex - uend) if rank == 0: # 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') niters = np.array([item[1] for item in iter_counts]) out = f' Min/Mean/Max number of iterations: ' \ f'{np.min(niters):4.2f} / {np.mean(niters):4.2f} / {np.max(niters):4.2f}' 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) out = f'Error: {err:6.4e}' f.write(out + '\n') print(out) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') out = f'Time to solution: {timing[0][1]:6.4f} sec.' f.write(out + '\n') print(out) assert err <= 1.133E-05, 'Error is too high, got %s' % err if ml: if num_procs > 1: maxmean = 12.5 else: maxmean = 6.6 else: maxmean = 12.7 assert np.mean( niters ) <= maxmean, 'Mean number of iterations is too high, got %s' % np.mean( niters) f.write('\n') print() f.close()
# Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = fenics_heat_mass description['problem_params'] = problem_params description['sweeper_class'] = imex_1st_order_mass description['sweeper_params'] = sweeper_params description['level_params'] = level_params description['step_params'] = step_params description['space_transfer_class'] = mesh_to_mesh_fenics description['base_transfer_class'] = base_transfer_mass description['base_transfer_params'] = base_transfer_params # quickly generate block of steps controller = controller_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 run_diffusion(nsweeps): """ A simple test program to test PFASST convergence for the heat equation with random initial data Args: nsweeps: number of fine sweeps to perform """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = 0.25 level_params['nsweeps'] = [nsweeps, 1] # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] sweeper_params['QI'] = ['LU'] sweeper_params['initial_guess'] = 'zero' # initialize problem parameters problem_params = dict() problem_params['freq'] = -1 # frequency for the test value problem_params['nvars'] = [127, 63 ] # 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'] = 2 space_transfer_params['periodic'] = False # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d # pass problem class description[ 'sweeper_class'] = generic_implicit # 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 * level_params['dt'] # set up number of parallel time-steps to run PFASST with num_proc = 4 results = dict() for i in range(-3, 10): ratio = level_params['dt'] / (1.0 / (problem_params['nvars'][0] + 1))**2 problem_params['nu'] = 10.0**i / ratio # diffusion coefficient description[ 'problem_params'] = problem_params # pass problem parameters out = 'Working on c = %6.4e' % problem_params['nu'] print(out) cfl = ratio * problem_params['nu'] out = ' CFL number: %4.2e' % cfl print(out) # instantiate controller controller = controller_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) # 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') niters = np.array([item[1] for item in iter_counts]) out = ' Mean number of iterations: %4.2f' % np.mean(niters) print(out) if nsweeps == 3 and (i == -3 or i == 9): assert np.mean(niters) <= 2, 'ERROR: too much iterations for diffusive asymptotics, got %s' \ % np.mean(niters) results[cfl] = np.mean(niters) fname = 'data/results_conv_diffusion_NS' + str(nsweeps) + '.pkl' file = open(fname, 'wb') pickle.dump(results, file) file.close() assert os.path.isfile(fname), 'ERROR: pickle did not create file'
def run_simulation(prob=None): """ Routine to run the simulation of a second order problem Args: prob (str): name of the problem """ if prob == 'outer_solar_system': description, controller_params = setup_outer_solar_system() # set time parameters t0 = 0.0 Tend = 10000.0 num_procs = 100 maxmeaniter = 6.0 elif prob == 'full_solar_system': description, controller_params = setup_full_solar_system() # set time parameters t0 = 0.0 Tend = 1000.0 num_procs = 100 maxmeaniter = 19.0 else: raise NotImplemented('Problem type not implemented, got %s' % prob) f = open(prob + '_out.txt', 'w') out = 'Running ' + prob + ' problem with %s processors...' % num_procs f.write(out + '\n') print(out) # instantiate the controller controller = controller_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) # 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) f.close() 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 run_SDC_variant(variant=None, inexact=False): """ Routine to run particular SDC variant Args: variant (str): string describing the variant inexact (bool): flag to use inexact nonlinear solve (or nor) Returns: results and statistics of the run """ # load (incomplete) default parameters description, controller_params = setup_parameters() # add stuff based on variant if variant == 'fully-implicit': description['problem_class'] = allencahn_periodic_fullyimplicit # description['problem_class'] = allencahn_front_finel description['sweeper_class'] = generic_implicit if inexact: description['problem_params']['newton_maxiter'] = 1 elif variant == 'semi-implicit': description['problem_class'] = allencahn_periodic_semiimplicit description['sweeper_class'] = imex_1st_order if inexact: description['problem_params']['lin_maxiter'] = 10 elif variant == 'multi-implicit': description['problem_class'] = allencahn_periodic_multiimplicit description['sweeper_class'] = multi_implicit if inexact: description['problem_params']['newton_maxiter'] = 1 description['problem_params']['lin_maxiter'] = 10 # elif variant == 'multi-implicit_v2': # description['problem_class'] = allencahn_multiimplicit_v2 # description['sweeper_class'] = multi_implicit # if inexact: # description['problem_params']['newton_maxiter'] = 1 else: raise NotImplemented('Wrong variant specified, got %s' % variant) if inexact: out = 'Working on inexact %s variant...' % variant else: out = 'Working on exact %s variant...' % variant print(out) # setup parameters "in time" t0 = 0 Tend = description['level_params']['dt'] # instantiate controller controller = controller_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) # plt_helper.plt.plot(uinit.values) # plt_helper.savefig('uinit', save_pdf=False, save_pgf=False, save_png=True) # # uex = P.u_exact(Tend) # plt_helper.plt.plot(uex.values) # plt_helper.savefig('uex', save_pdf=False, save_pgf=False, save_png=True) # exit() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) plt_helper.plt.plot(uend.values) plt_helper.savefig('uend', save_pdf=False, save_pgf=False, save_png=True) # exit() # filter statistics by variant (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) 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) print(' Iteration count (nonlinear/linear): %i / %i' % (P.newton_itercount, P.lin_itercount)) print(' Mean Iteration count per call: %4.2f / %4.2f' % (P.newton_itercount / max(P.newton_ncalls, 1), P.lin_itercount / max(P.lin_ncalls, 1))) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') print('Time to solution: %6.4f sec.' % timing[0][1]) print() return stats
def run_SDC_variant(variant=None, inexact=False): """ Routine to run particular SDC variant Args: variant (str): string describing the variant inexact (bool): flag to use inexact nonlinear solve (or nor) Returns: timing (float) niter (float) """ # load (incomplete) default parameters description, controller_params = setup_parameters() # add stuff based on variant if variant == 'fully-implicit': description['problem_class'] = petsc_fisher_fullyimplicit description['sweeper_class'] = generic_implicit elif variant == 'semi-implicit': description['problem_class'] = petsc_fisher_semiimplicit description['sweeper_class'] = imex_1st_order elif variant == 'multi-implicit': description['problem_class'] = petsc_fisher_multiimplicit description['sweeper_class'] = multi_implicit else: raise NotImplemented('Wrong variant specified, got %s' % variant) if inexact: description['problem_params']['nlsol_maxiter'] = 1 out = 'Working on inexact %s variant...' % variant else: out = 'Working on exact %s variant...' % variant print(out) # set time parameters t0 = 0.0 Tend = 1.0 # instantiate controller controller = controller_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) # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) # filter statistics by variant (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) 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) print('Iteration count (nonlinear/linear): %i / %i' % (P.snes_itercount, P.ksp_itercount)) print('Mean Iteration count per call: %4.2f / %4.2f' % (P.snes_itercount / max(P.snes_ncalls, 1), P.ksp_itercount / max(P.ksp_ncalls, 1))) timing = sort_stats(filter_stats(stats, type='timing_run'), sortby='time') print('Time to solution: %6.4f sec.' % timing[0][1]) print('Error vs. PDE solution: %6.4e' % err) print() assert err < 9.2E-05, 'ERROR: variant %s did not match error tolerance, got %s' % ( variant, err) assert np.mean( niters ) <= 10, 'ERROR: number of iterations is too high, got %s' % np.mean( niters) return timing[0][1], np.mean(niters)