def run_pfasst(MS,u0,t0,dt,Tend): """ Main driver for running the serial version of SDC, MLSDC and PFASST (virtual parallelism) Args: MS: block of steps (list) u0: initial values on the finest level t0: initial time dt: step size (could be changed here e.g. for adaptivity) Tend: end time Returns: end values on the finest level stats object containing statistics for each step, each level and each iteration """ # fixme: add ring parallelization as before # fixme: use error classes for send/recv and stage errors # fixme: last need to be able to send even if values have not been fetched yet (ring!) # some initializations uend = None num_procs = len(MS) # initial ordering of the steps: 0,1,...,Np-1 slots = [p for p in range(num_procs)] # initialize time variables of each step for p in slots: MS[p].status.dt = dt # could have different dt per step here MS[p].status.time = t0 + sum(MS[j].status.dt for j in range(p)) MS[p].status.step = p # determine which steps are still active (time < Tend) active = [MS[p].status.time < Tend - np.finfo(float).eps for p in slots] # compress slots according to active steps, i.e. remove all steps which have times above Tend active_slots = list(itertools.compress(slots, active)) # initialize block of steps with u0 MS = restart_block(MS,active_slots,u0) # call pre-start hook MS[active_slots[0]].levels[0].hooks.dump_pre(MS[p].status) # main loop: as long as at least one step is still active (time < Tend), do something while any(active): # loop over all active steps (in the correct order) for p in active_slots: # print(p,MS[p].status.stage) MS[p] = pfasst(MS[p]) # if all active steps are done (for block-parallelization, need flag to distinguish (FIXME)) if all([MS[p].status.done for p in active_slots]): # uend is uend of the last active step in the list uend = MS[active_slots[-1]].levels[0].uend # FIXME: only true for non-ring-parallelization? # determine new set of active steps and compress slots accordingly active = [MS[p].status.time+num_procs*MS[p].status.dt < Tend - np.finfo(float).eps for p in slots] active_slots = list(itertools.compress(slots, active)) # increment timings for now active steps for p in active_slots: MS[p].status.time += num_procs*MS[p].status.dt MS[p].status.step += num_procs # restart active steps (reset all values and pass uend to u0) MS = restart_block(MS,active_slots,uend) # fixme: for ring parallelization # update first and last # update slots # update pred_cnt # This is only for ring-parallelization # indx = np.argsort([MS[p].time for p in slots]) # slots = slots[indx] # active = [MS[p].time < Tend for p in slots] # if all(not active[p] for p in slots): # for p in slots: # MS[p].time = return uend,stats.return_stats()
def run_pfasst(MS,u0,t0,dt,Tend): """ Main driver for running the serial version of SDC, MLSDC and PFASST (virtual parallelism) Args: MS: block of steps (list) u0: initial values on the finest level t0: initial time dt: step size (could be changed here e.g. for adaptivity) Tend: end time Returns: end values on the finest level stats object containing statistics for each step, each level and each iteration """ # fixme: use error classes for send/recv and stage errors # some initializations uend = None num_procs = len(MS) if num_procs > 1: assert len(MS[0].levels) > 1 # initial ordering of the steps: 0,1,...,Np-1 slots = [p for p in range(num_procs)] # initialize time variables of each step for p in slots: MS[p].status.dt = dt # could have different dt per step here MS[p].status.time = t0 + sum(MS[j].status.dt for j in range(p)) MS[p].status.step = p # determine which steps are still active (time < Tend) active = [MS[p].status.time < Tend - np.finfo(float).eps for p in slots] # compress slots according to active steps, i.e. remove all steps which have times above Tend active_slots = list(itertools.compress(slots, active)) # initialize block of steps with u0 MS = restart_block(MS,active_slots,u0) # call pre-start hook MS[active_slots[0]].levels[0].hooks.dump_pre(MS[p].status) # main loop: as long as at least one step is still active (time < Tend), do something while any(active): MS_active = [] for p in active_slots: MS_active.append(MS[p]) MS_active = pfasst(MS_active) for p in range(len(MS_active)): MS[active_slots[p]] = MS_active[p] # if all active steps are done if all([MS[p].status.done for p in active_slots]): # uend is uend of the last active step in the list uend = MS[active_slots[-1]].levels[0].uend # determine new set of active steps and compress slots accordingly active = [MS[p].status.time+num_procs*MS[p].status.dt < Tend - np.finfo(float).eps for p in slots] active_slots = list(itertools.compress(slots, active)) # increment timings for now active steps for p in active_slots: MS[p].status.time += num_procs*MS[p].status.dt MS[p].status.step += num_procs # restart active steps (reset all values and pass uend to u0) MS = restart_block(MS,active_slots,uend) return uend,stats.return_stats()