def __init__(self, V, options=None): # See if we have dofmap if not is_function_space(V): raise ValueError("V is not a function space.") # Only allow 2d and 3d meshes if V.mesh().geometry().dim() == 1: raise ValueError("Only 2d and 3d meshes are supported.") # Get MPI info try: from dolfin import mpi_comm_world self.mpi_size = MPI.size(mpi_comm_world()) self.mpi_rank = MPI.rank(mpi_comm_world()) except ImportError: self.mpi_size = MPI.num_processes() self.mpi_rank = MPI.process_number() # Analyze the space V self.V = V self.dofmaps = extract_dofmaps(self.V) self.bounds = bounds(self.V) # Rewrite default plotting options if they are provided by user self.options = {"colors": {"mesh_entities": "hsv", "mesh": "Blues"}, "xkcd": False, "markersize": 40} if options is not None: self.options.update(options) # Keep track of the plots self.plots = []
def save_results(problem, solver, num_dofs, mesh_size, time_step, functional, error): 'Save results to file.' # Print summary if MPI.process_number() == 0: print '' print 'Problem |', problem print 'Solver |', solver print 'Unknowns |', num_dofs print 'Mesh size |', mesh_size print 'Time step |', time_step print 'Functional |', functional print 'Error |', error # Print DOLFIN summary set_log_active(True) list_timings() # Append to file, let each dx, dt have its own log file results_dir = problem.options['results_dir'] dx = problem.options['refinement_level'] dt = problem.options['dt_division'] name = '%s_%s_results_dx%d_dt%d.log' % (str(problem), str(solver), dx, dt) filename = os.path.join(results_dir, name) # create the dir for results if needed if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) with open(filename, 'a') as f: f.write('%s, %s, %s, %d, %.15g, %.15g, %.15g, %s\n' % (time.asctime(), problem, solver, num_dofs, mesh_size, time_step, functional, str(error)))
def save_results(problem, solver, num_dofs, mesh_size, time_step, functional, error): 'Save results to file.' # Print summary if MPI.process_number() == 0 : print '' print 'Problem |', problem print 'Solver |', solver print 'Unknowns |', num_dofs print 'Mesh size |', mesh_size print 'Time step |', time_step print 'Functional |', functional print 'Error |', error # Print DOLFIN summary set_log_active(True) list_timings() # Append to file, let each dx, dt have its own log file results_dir = problem.options['results_dir'] dx = problem.options['refinement_level'] dt = problem.options['dt_division'] name = '%s_%s_results_dx%d_dt%d.log' % (str(problem), str(solver), dx, dt) filename = os.path.join(results_dir, name) # create the dir for results if needed if not os.path.exists(os.path.dirname(filename)): os.makedirs(os.path.dirname(filename)) with open(filename, 'a') as f: f.write('%s, %s, %s, %d, %.15g, %.15g, %.15g, %s\n' % (time.asctime(), problem, solver, num_dofs, mesh_size, time_step, functional, str(error)))
def solve(solver_name, problem_name, options): 'Solve the problem by solver with options.' # Set cpp_compiler options parameters["form_compiler"]["cpp_optimize"] = True # Set debug level set_log_active(options['debug']) # Set refinement level options['N'] = mesh_sizes[options['refinement_level']] # Create problem and solver problem = Problem(problem_name, options) solver = Solver(solver_name, options) time_step = solver.get_timestep(problem)[0] if MPI.process_number() == 0 and options['verbose']: print 'Problem: ' + str(problem) print 'Solver: ' + str(solver) # Solve problem with solver wct = time.time() u, p = solver.solve(problem) # Compute elapsed time wct = time.time() - wct # Compute number of degrees of freedom num_dofs = u.vector().size() + p.vector().size() # Get the mesh size mesh_size = u.function_space().mesh().hmin() # Get functional value and error functional, error = solver.eval() # Save results cpu_time = solver.cputime() save_results(problem, solver, num_dofs, mesh_size, time_step, functional, error) return 0
def save_convergence_plot(errors, element_sizes, title, legend, order, offset = 0.8, show_title = True, xlabel = 'Element size [m]', ylabel = r"$\mathcal E$ error"): ''' Creates a convergence plot ''' if MPI.process_number() != 0: return # Plot the errors scaling = 0.7 rc('text', usetex=True) plt.figure(1, figsize=(scaling*7,scaling*4)) plt.xlabel('Element size') plt.ylabel('Error') if show_title: plt.title(title) plt.loglog(element_sizes, errors, 'gx', label = legend, color = 'k') # Construct an error plot with the expected order c = errors[-1]/element_sizes[-1]**order*offset expected_errors = [c*element_size**order for element_size in element_sizes] print order if order == 1.0: order_str = "First order" elif order == 2.0: order_str = "Second order" else: order_str = str(order) + " order" plt.loglog(element_sizes, expected_errors, label = order_str, color = 'k') plt.legend(loc=4) #plt.axis([min(element_sizes)*1.01, max(element_sizes)*1.01, min(errors)*1.01, max(errors)*1.01]) plt.gcf().subplots_adjust(bottom=0.15) plt.xlabel(xlabel) plt.ylabel(ylabel) filename = '_'.join(title.split()).lower() print 'Saving as: ', filename plt.savefig(filename + '.png') plt.savefig(filename + '.pdf') plt.close()
def __init__(self, V, options=None): # See if we have dofmap if not is_function_space(V): raise ValueError('V is not a function space.') # Only allow 2d and 3d meshes if V.mesh().geometry().dim() == 1: raise ValueError('Only 2d and 3d meshes are supported.') # Get MPI info try: from dolfin import mpi_comm_world self.mpi_size = MPI.size(mpi_comm_world()) self.mpi_rank = MPI.rank(mpi_comm_world()) except ImportError: self.mpi_size = MPI.num_processes() self.mpi_rank = MPI.process_number() # Analyze the space V self.V = V self.dofmaps = extract_dofmaps(self.V) self.elements = extract_elements(self.V) self.bounds = bounds(self.V) # Rewrite default plotting options if they are provided by user self.options = { 'colors': { 'mesh_entities': 'hsv', 'mesh': 'Blues' }, 'xkcd': False, 'markersize': 40 } if options is not None: self.options.update(options) # Keep track of the plots self.plots = []
def main(args): 'Parse command-line arguments and run solver' # Check arguments if not len(args) >= 2: usage() return 2 # Get problem and solver problem_name, solver_name = args[:2] # Get options options = OPTIONS.copy() for arg in args[2:]: try: key, value = arg.split('=') try: options[key] = eval(value) except: options[key] = str(value) except: print 'Warning: Unhandled command-line argument', arg # Parse the spatial and time stepping options. # If either refinement_level or dt_division are lists feed the items of # list one by one type_dx = type(options['refinement_level']) type_dt = type(options['dt_division']) if type_dx is list: if type_dt is int: # Do a dx convergence study if MPI.process_number() == 0: print_color( 'Dx convergence study, dt=%d' % options['dt_division'], 'cyan') refinement_levels = copy.copy(options['refinement_level']) # loop over dx for refinement_level in refinement_levels: if MPI.process_number() == 0: print_color('\tRefinement level %d' % refinement_level, 'yellow') options['refinement_level'] = refinement_level # solve with fixed dt and changing dx # Warn user about running dx convergence with changing dt, this happens # if problem has no dt _options = options.copy() _options['N'] = mesh_sizes[_options['refinement_level']] _problem = Problem(problem_name, _options) if _problem.dt is None: print_color( ' Warning: Dx convergence study with changing dt', 'pink') solve(solver_name, problem_name, options) else: raise ValueError( 'Use fixed dt_division with changing refinement_level!') elif type_dx is int: if type_dt is list: # Do a dt convergence study if MPI.process_number() == 0: print_color( 'Dt convergence study, dx=%d' % options['refinement_level'], 'cyan') dt_divisions = copy.copy(options['dt_division']) # loop over dt for dt_division in dt_divisions: if MPI.process_number() == 0: print_color('\tDt division %d' % dt_division, 'yellow') options['dt_division'] = dt_division #solve with fixed dx and changing dt solve(solver_name, problem_name, options) elif type(options['dt_division']) is int: if MPI.process_number() == 0: print_color('Fixed dx and dt', 'cyan') # solve with fixed dx and fixed dt solve(solver_name, problem_name, options) else: raise ValueError("options['dt_division'] must be int of list!") else: raise ValueError("options['refinement_level'] must be int of list!") return 0
def main(args): 'Parse command-line arguments and run solver' # Check arguments if not len(args) >= 2: usage() return 2 # Get problem and solver problem_name, solver_name = args[:2] # Get options options = OPTIONS.copy() for arg in args[2:]: try: key, value = arg.split('=') try: options[key] = eval(value) except: options[key] = str(value) except: print 'Warning: Unhandled command-line argument', arg # Parse the spatial and time stepping options. # If either refinement_level or dt_division are lists feed the items of # list one by one type_dx = type(options['refinement_level']) type_dt = type(options['dt_division']) if type_dx is list: if type_dt is int: # Do a dx convergence study if MPI.process_number() == 0: print_color('Dx convergence study, dt=%d' % options['dt_division'], 'cyan') refinement_levels = copy.copy(options['refinement_level']) # loop over dx for refinement_level in refinement_levels: if MPI.process_number() == 0: print_color('\tRefinement level %d' % refinement_level, 'yellow') options['refinement_level'] = refinement_level # solve with fixed dt and changing dx # Warn user about running dx convergence with changing dt, this happens # if problem has no dt _options = options.copy() _options['N'] = mesh_sizes[_options['refinement_level']] _problem = Problem(problem_name, _options) if _problem.dt is None: print_color(' Warning: Dx convergence study with changing dt', 'pink') solve(solver_name, problem_name, options) else: raise ValueError('Use fixed dt_division with changing refinement_level!') elif type_dx is int: if type_dt is list: # Do a dt convergence study if MPI.process_number() == 0: print_color('Dt convergence study, dx=%d' % options['refinement_level'],'cyan') dt_divisions = copy.copy(options['dt_division']) # loop over dt for dt_division in dt_divisions: if MPI.process_number() == 0: print_color('\tDt division %d' % dt_division, 'yellow') options['dt_division'] = dt_division #solve with fixed dx and changing dt solve(solver_name, problem_name, options) elif type(options['dt_division']) is int: if MPI.process_number() == 0: print_color('Fixed dx and dt', 'cyan') # solve with fixed dx and fixed dt solve(solver_name, problem_name, options) else: raise ValueError("options['dt_division'] must be int of list!") else: raise ValueError("options['refinement_level'] must be int of list!") return 0