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 = allinclusive_multigrid_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 run_diffusion(QI): """ A simple test program to test PFASST convergence for the heat equation with random initial data Args: QI: preconditioner """ # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['nsweeps'] = [3, 1] # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] sweeper_params['QI'] = [QI, 'LU'] sweeper_params['spread'] = False # initialize problem parameters problem_params = dict() problem_params['nu'] = 0.1 # diffusion coefficient 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'] = 200 # 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 controller_params['predict'] = False # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d # 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['sweeper_params'] = sweeper_params # pass sweeper 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 number of parallel time-steps to run PFASST with fname = 'data/results_conv_diffusion_Linf_QI' + str(QI) + '.txt' file = open(fname, 'w') writer = csv.writer(file) writer.writerow(('num_proc', 'niter')) file.close() for i in range(0, 13): num_proc = 2**i level_params['dt'] = (Tend - t0) / num_proc description['level_params'] = level_params # pass level parameters out = 'Working on num_proc = %5i' % num_proc print(out) cfl = problem_params['nu'] * level_params['dt'] / ( 1.0 / (problem_params['nvars'][0] + 1))**2 out = ' CFL number: %4.2e' % cfl print(out) # instantiate controller controller = allinclusive_multigrid_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) file = open(fname, 'a') writer = csv.writer(file) writer.writerow((num_proc, np.mean(niters))) file.close() assert os.path.isfile(fname), 'ERROR: pickle did not create file'
def run_SDC_variant(variant=None, inexact=False, cwd=''): """ Routine to run particular SDC variant Args: variant (str): string describing the variant inexact (bool): flag to use inexact nonlinear solve (or nor) cwd (str): current working directory 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_grayscott_fullyimplicit description['dtype_f'] = petsc_data description['sweeper_class'] = generic_implicit elif variant == 'semi-implicit': description['problem_class'] = petsc_grayscott_semiimplicit description['dtype_f'] = rhs_imex_petsc_data description['sweeper_class'] = imex_1st_order elif variant == 'multi-implicit': description['problem_class'] = petsc_grayscott_multiimplicit description['dtype_f'] = rhs_2comp_petsc_data description['sweeper_class'] = multi_implicit else: raise NotImplemented('Wrong variant specified, got %s' % variant) if inexact: description['problem_params']['lsol_maxiter'] = 2 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 = allinclusive_multigrid_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) # load reference solution to compare with fname = cwd + 'data/GS_reference.dat' viewer = PETSc.Viewer().createBinary(fname, 'r') uex = P.u_exact(t0) uex.values = PETSc.Vec().load(viewer) 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. reference solution: %6.4e' % err) print() assert err < 3E-06, '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)
def run_reference(): """ Helper routine to create a reference solution using very high order SDC and small time-steps """ description, controller_params = setup_parameters() description['problem_class'] = petsc_grayscott_semiimplicit description['dtype_f'] = rhs_imex_petsc_data description['sweeper_class'] = imex_1st_order description['sweeper_params']['num_nodes'] = 9 description['level_params']['dt'] = 0.01 # set time parameters t0 = 0.0 Tend = 1.0 # instantiate controller controller = allinclusive_multigrid_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) 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]) fname = 'data/GS_reference.dat' viewer = PETSc.Viewer().createBinary(fname, 'w') viewer.view(uend.values) assert os.path.isfile(fname), 'ERROR: PETSc did not create file' return None
def run_advection(nsweeps): """ A simple test program to test PFASST convergence for the periodic advection equation 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' ] # For the IMEX sweeper, the LU-trick can be activated for the implicit part sweeper_params['spread'] = False # initialize problem parameters problem_params = dict() problem_params['freq'] = 64 # frequency for the test value problem_params['nvars'] = [128, 64 ] # number of degrees of freedom for each level problem_params['order'] = 2 problem_params['type'] = 'center' # 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'] = True # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 controller_params['predict'] = False # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = advection1d # 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_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, 12): ratio = level_params['dt'] / (1.0 / (problem_params['nvars'][0] + 1)) problem_params['c'] = 10.0**i / ratio # diffusion coefficient description[ 'problem_params'] = problem_params # pass problem parameters out = 'Working on nu = %6.4e' % problem_params['c'] print(out) cfl = ratio * problem_params['c'] out = ' CFL number: %4.2e' % cfl print(out) # instantiate controller controller = allinclusive_multigrid_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) results[cfl] = np.mean(niters) fname = 'data/results_conv_advection_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 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 # 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 # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 20 # 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 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 # instantiate controller controller = allinclusive_multigrid_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) # The following is used only for statistics and output, the main show is over now.. # compute exact solution and compare uex = P.u_exact(Tend) err = abs(uex - uend) print('\nError (vs. exact solution) at time %4.2f: %6.4e\n' % (Tend, err)) 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: print('Number of iterations for time %4.2f: %2i' % item) niters = np.array([item[1] for item in iter_counts]) print(' Mean number of iterations: %4.2f' % np.mean(niters)) print(' Range of values for number of iterations: %2i ' % np.ptp(niters)) print(' Position of max/min number of iterations: %2i -- %2i' % (int(np.argmax(niters)), int(np.argmin(niters))))
def compare_controllers(type=None, par=0.0, f=None): """ A simple test program to compare PFASST runs with matrix-based and matrix-free controllers Args: type (str): setup type par (float) parameter for controlling stiffness f: file handler """ # set time parameters t0 = 0.0 Tend = 1.0 if type == 'diffusion': description, controller_params = diffusion_setup(par) elif type == 'advection': description, controller_params = advection_setup(par) elif type == 'testequation': description, controller_params = testequation_setup() else: raise ValueError('No valis setup type provided, aborting..') out = '\nWorking with %s setup and parameter %3.1e..' % (type, par) f.write(out + '\n') print(out) # instantiate controller controller_mat = allinclusive_matrix_nonMPI( num_procs=4, controller_params=controller_params, description=description) controller_nomat = allinclusive_multigrid_nonMPI( num_procs=4, controller_params=controller_params, description=description) # get initial values on finest level P = controller_nomat.MS[0].levels[0].prob uinit = P.u_exact(t0) uex = P.u_exact(Tend) # this is where the iteration is happening uend_mat, stats_mat = controller_mat.run(u0=uinit, t0=t0, Tend=Tend) uend_nomat, stats_nomat = controller_nomat.run(u0=uinit, t0=t0, Tend=Tend) diff = abs(uend_mat - uend_nomat) err_mat = abs(uend_mat - uex) err_nomat = abs(uend_nomat - uex) out = ' Error (mat/nomat) vs. exact solution: %6.4e -- %6.4e' % ( err_mat, err_nomat) f.write(out + '\n') print(out) out = ' Difference between both results: %6.4e' % diff f.write(out + '\n') print(out) assert diff < 2.3E-15, 'ERROR: difference between matrix-based and matrix-free result is too large, got %s' % diff # filter statistics by type (number of iterations) filtered_stats_mat = filter_stats(stats_mat, type='niter') filtered_stats_nomat = filter_stats(stats_nomat, type='niter') # convert filtered statistics to list of iterations count, sorted by process iter_counts_mat = sort_stats(filtered_stats_mat, sortby='time') iter_counts_nomat = sort_stats(filtered_stats_nomat, sortby='time') out = ' Iteration counts for matrix-based version: %s' % iter_counts_mat f.write(out + '\n') print(out) out = ' Iteration counts for matrix-free version: %s' % iter_counts_nomat f.write(out + '\n') print(out) assert iter_counts_nomat == iter_counts_mat, \ 'ERROR: number of iterations differ between matrix-based and matrix-free controller'
def main(): """ A simple test program to do PFASST runs for the heat equation """ # set up number of parallel time-steps to run PFASST with num_proc = 16 # initialize level parameters level_params = dict() level_params['restol'] = 1E-08 level_params['dt'] = 1.0 / num_proc level_params['nsweeps'] = [3, 1] # initialize sweeper parameters sweeper_params = dict() sweeper_params['collocation_class'] = CollGaussRadau_Right sweeper_params['num_nodes'] = [3] sweeper_params['QI'] = ['LU2', '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'] = -1 # frequency for the test value problem_params['nvars'] = [128, 64] # 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'] = True # initialize controller parameters controller_params = dict() controller_params['logger_level'] = 30 # controller_params['hook_class'] = error_output # fill description dictionary for easy step instantiation description = dict() description['problem_class'] = heat1d_periodic # 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['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 = 1.0 # instantiate controller controller = allinclusive_multigrid_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 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('CFL number: %4.2f' % (level_params['dt'] * problem_params['nu'] / (1.0 / problem_params['nvars'][0])**2)) print('Error: %8.4e' % err)
def main(): # initialize level parameters level_params = dict() level_params['restol'] = 1E-10 level_params['dt'] = None # This comes as read-in for the step class (this is optional!) step_params = dict() step_params['maxiter'] = None # This comes as read-in for the problem class problem_params = dict() problem_params['nu'] = 0.01 problem_params['freq'] = 2 problem_params['nvars'] = [2**7, 2**6] # 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'] = ['IE', 'PIC'] sweeper_params['spread'] = False sweeper_params['do_coll_update'] = False # 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'] = 20 controller_params['predict'] = False # Fill description dictionary for easy hierarchy creation description = dict() description['problem_class'] = heat1d_periodic description['dtype_u'] = mesh description['dtype_f'] = mesh #rhs_imex_mesh description['sweeper_class'] = generic_implicit #imex_1st_order description['sweeper_params'] = sweeper_params description['step_params'] = step_params description['level_params'] = level_params description['problem_params'] = problem_params description[ 'space_transfer_class'] = mesh_to_mesh # pass spatial transfer class description[ 'space_transfer_params'] = space_transfer_params # pass paramters for spatial transfer # setup parameters "in time" t0 = 0.0 Tend = 1.0 dt_list = [Tend / 2**i for i in range(0, 6)] niter_list = [100] #[1, 2, 3, 4] for niter in niter_list: err = 0 for dt in dt_list: print('Working with dt = %s and k = %s iterations...' % (dt, niter)) description['step_params']['maxiter'] = niter description['level_params']['dt'] = dt # Tend = t0 + dt # instantiate the controller controller = allinclusive_multigrid_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 = compute_collocation_solution(controller) # print(abs(uex - P.u_exact(Tend))) uex = P.u_exact(Tend) err_new = abs(uex - uend) print(' error at time %s: %s' % (Tend, err_new)) if err > 0: print(' order of accuracy: %6.4f' % (np.log(err / err_new) / np.log(2))) err = err_new # # 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) 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) print()
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['spread'] = True 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 controller_params['predict'] = False # 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['dtype_u'] = mesh # pass data type for u # description['dtype_f'] = rhs_imex_mesh # pass data type for f description['dtype_f'] = mesh # pass data type for f # 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 = allinclusive_multigrid_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 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_multigrid_nonMPI( num_procs=num_proc, controller_params=controller_params, description=description_mssdc) controller_pfasst = allinclusive_multigrid_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 < 1E-10, "ERROR: difference between PFASST and MSSDC controller is too large, got %s" % diff
def main(): # 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'] = 1 problem_params['nvars'] = 2047 problem_params['lambda0'] = 1.0 problem_params['newton_maxiter'] = 50 problem_params['newton_tol'] = 1E-10 problem_params['interval'] = (-1, 1) # 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['spread'] = False sweeper_params['do_coll_update'] = False # 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 description['problem_params'] = problem_params description['dtype_u'] = mesh description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit description['sweeper_params'] = sweeper_params description['step_params'] = step_params # setup parameters "in time" t0 = 0 Tend = 1.0 dt_list = [Tend / 2 ** i for i in range(0, 4)] err = 0 for dt in dt_list: print('Working with dt = %s...' % dt) level_params['dt'] = dt description['level_params'] = level_params # instantiate the controller controller = allinclusive_multigrid_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_new = abs(uex - uend) print('error at time %s: %s' % (Tend, err_new)) if err > 0: print('order of accuracy: %6.4f' % (np.log(err / err_new) / np.log(2))) err = err_new # 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)
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 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 == 'semi-implicit': description['problem_class'] = allencahn2d_imex description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order else: raise NotImplemented('Wrong variant specified, got %s' % variant) # setup parameters "in time" t0 = 0 Tend = 0.032 # instantiate controller controller = allinclusive_multigrid_nonMPI( num_procs=8, 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.imshow(uinit.values) # plt_helper.plt.show() # call main function to get things done... uend, stats = controller.run(u0=uinit, t0=t0, Tend=Tend) # plt_helper.plt.imshow(uend.values) # plt_helper.plt.show() # 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() 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: 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_fullyimplicit description['dtype_f'] = mesh description['sweeper_class'] = generic_implicit if inexact: description['problem_params']['newton_maxiter'] = 1 elif variant == 'semi-implicit': description['problem_class'] = allencahn_semiimplicit description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order if inexact: description['problem_params']['lin_maxiter'] = 10 elif variant == 'semi-implicit_v2': description['problem_class'] = allencahn_semiimplicit_v2 description['dtype_f'] = rhs_imex_mesh description['sweeper_class'] = imex_1st_order if inexact: description['problem_params']['newton_maxiter'] = 1 elif variant == 'multi-implicit': description['problem_class'] = allencahn_multiimplicit description['dtype_f'] = rhs_comp2_mesh 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['dtype_f'] = rhs_comp2_mesh 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 = 0.032 # instantiate controller controller = allinclusive_multigrid_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) 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]) fname = 'data/AC_reference_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 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 = allinclusive_multigrid_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