def process_tavg(args): infs = {} # Interrogate files passed by the shell for fname in args.infs: # Load solution files and obtain solution times inf = read_pyfr_data(fname) tinf = Inifile(inf['stats']).getfloat('solver-time-integrator', 'tcurr') # Retain if solution time is within limits if args.limits is None or args.limits[0] <= tinf <= args.limits[1]: infs[tinf] = inf # Verify that solutions were computed on the same mesh if inf['mesh_uuid'] != infs[infs.keys()[0]]['mesh_uuid']: raise RuntimeError('Solution files in scope were not computed ' 'on the same mesh') # Sort the solution times, check for sufficient files in scope stimes = sorted(infs.keys()) if len(infs) <= 1: raise RuntimeError('More than one solution file is required to ' 'compute an average') # Initialise progress bar, and the average with first solution pb = ProgressBar(0, 0, len(stimes), 0) avgs = {name: infs[stimes[0]][name].copy() for name in infs[stimes[0]]} solnfs = [name for name in avgs.keys() if name.startswith('soln')] # Weight the initialised trapezoidal mean dtnext = stimes[1] - stimes[0] for name in solnfs: avgs[name] *= 0.5 * dtnext pb.advance_to(1) # Compute the trapezoidal mean up to the last solution file for i in xrange(len(stimes[2:])): dtlast = dtnext dtnext = stimes[i + 2] - stimes[i + 1] # Weight the current solution, then add to the mean for name in solnfs: avgs[name] += 0.5 * (dtlast + dtnext) * infs[stimes[i + 1]][name] pb.advance_to(i + 2) # Weight final solution, update mean and normalise for elapsed time for name in solnfs: avgs[name] += 0.5 * dtnext * infs[stimes[-1]][name] avgs[name] *= 1.0 / (stimes[-1] - stimes[0]) pb.advance_to(i + 3) # Compute and assign stats for a time-averaged solution stats = Inifile() stats.set('time-average', 'tmin', stimes[0]) stats.set('time-average', 'tmax', stimes[-1]) stats.set('time-average', 'ntlevels', len(stimes)) avgs['stats'] = stats.tostr() outf = open(args.outf, 'wb') np.savez(outf, **avgs)
def _process_common(args, mesh, soln, cfg): # Prefork to allow us to exec processes after MPI is initialised if hasattr(os, 'fork'): from pytools.prefork import enable_prefork enable_prefork() # Import but do not initialise MPI from mpi4py import MPI # Manually initialise MPI MPI.Init() # Ensure MPI is suitably cleaned up register_finalize_handler() # Create a backend backend = get_backend(args.backend, cfg) # Get the mapping from physical ranks to MPI ranks rallocs = get_rank_allocation(mesh, cfg) # Construct the solver solver = get_solver(backend, rallocs, mesh, soln, cfg) # If we are running interactively then create a progress bar if args.progress and MPI.COMM_WORLD.rank == 0: pb = ProgressBar(solver.tstart, solver.tcurr, solver.tend) # Register a callback to update the bar after each step callb = lambda intg: pb.advance_to(intg.tcurr) solver.completed_step_handlers.append(callb) # Execute! solver.run()
def main(): from mpi4py import MPI ap = ArgumentParser(prog='pyfr-sim', description='Runs a PyFR simulation') ap.add_argument('--verbose', '-v', action='count') ap.add_argument('--backend', '-b', default='cuda', help='Backend to use') ap.add_argument('--progress', '-p', action='store_true', help='show a progress bar') ap.add_argument('--nansweep', '-n', metavar='N', type=int, help='check for NaNs every N steps') sp = ap.add_subparsers(help='sub-command help') ap_run = sp.add_parser('run', help='run --help') ap_run.add_argument('mesh', help='mesh file') ap_run.add_argument('cfg', type=FileType('r'), help='config file') ap_run.set_defaults(process=process_run) ap_restart = sp.add_parser('restart', help='restart --help') ap_restart.add_argument('mesh', help='mesh file') ap_restart.add_argument('soln', help='solution file') ap_restart.add_argument('cfg', nargs='?', type=FileType('r'), help='new config file') ap_restart.set_defaults(process=process_restart) # Parse the arguments args = ap.parse_args() mesh, soln, cfg = args.process(args) # Ensure MPI is suitably cleaned up register_finalize_handler() # Create a backend backend = get_backend(args.backend, cfg) # Get the mapping from physical ranks to MPI ranks rallocs = get_rank_allocation(mesh, cfg) # Construct the solver solver = get_solver(backend, rallocs, mesh, soln, cfg) # If we are running interactively then create a progress bar if args.progress and MPI.COMM_WORLD.rank == 0: pb = ProgressBar(solver.tstart, solver.tcurr, solver.tend) # Register a callback to update the bar after each step callb = lambda intg: pb.advance_to(intg.tcurr) solver.completed_step_handlers.append(callb) # NaN sweeping if args.nansweep: def nansweep(intg): if intg.nsteps % args.nansweep == 0: if any(np.isnan(np.sum(s)) for s in intg.soln): raise RuntimeError('NaNs detected at t = {}'.format( intg.tcurr)) solver.completed_step_handlers.append(nansweep) # Execute! solver.run()