def test_grid_transfer_copy_interpolation(): """ Test constructor """ grid_transfer_copy = GridTransferCopy() np.testing.assert_equal(True, isinstance(grid_transfer_copy.interpolation(VectorSimple()), VectorSimple))
def test_grid_transfer_copy_constructor(): """ Test constructor """ grid_transfer_copy = GridTransferCopy() np.testing.assert_equal(True, isinstance(grid_transfer_copy, GridTransferCopy))
def main(): def output_fcn(self): # Set path to solution path = 'results/petsc' # Create path if not existing pathlib.Path(path).mkdir(parents=True, exist_ok=True) # Save solution with corresponding time point to file np.save( path + '/petsc' + str(self.comm_time_rank) + str(self.comm_space_rank), [[[ self.t[0][i], self.comm_space_rank, self.u[0][i].get_values().getArray() ] for i in self.index_local[0]]]) # Split the communicator into space and time communicator comm_world = MPI.COMM_WORLD comm_x, comm_t = split_communicator(comm_world, 4) # Create PETSc DMDA grids nx = 129 ny = 129 dmda_coarse = PETSc.DMDA().create([nx, ny], stencil_width=1, comm=comm_x) dmda_fine = dmda_coarse.refine() # Set up the problem heat_petsc_0 = HeatPetsc(dmda=dmda_fine, comm_x=comm_x, freq=1, a=1.0, t_start=0, t_stop=1, nt=33) heat_petsc_1 = HeatPetsc(dmda=dmda_coarse, comm_x=comm_x, freq=1, a=1.0, t_interval=heat_petsc_0.t[::2]) heat_petsc_2 = HeatPetsc(dmda=dmda_coarse, comm_x=comm_x, freq=1, a=1.0, t_interval=heat_petsc_1.t[::2]) # Setup three-level MGRIT solver with the space and time communicators and # solve the problem mgrit = Mgrit(problem=[heat_petsc_0, heat_petsc_1, heat_petsc_2], transfer=[ GridTransferPetsc(fine_prob=dmda_fine, coarse_prob=dmda_coarse), GridTransferCopy() ], comm_time=comm_t, comm_space=comm_x, output_fcn=output_fcn) info = mgrit.solve() import time if comm_t.Get_rank() == 0: time.sleep(1) sol = [] path = 'results/petsc/' for filename in os.listdir(path): data = np.load(path + filename, allow_pickle=True).tolist()[0] sol += data sol = [item for item in sol if item[1] == comm_x.Get_rank()] sol.sort(key=lambda tup: tup[0]) u_e = heat_petsc_0.u_exact( t=heat_petsc_0.t[-1]).get_values().getArray() diff = sol[-1][2] - u_e print('Difference at time point', heat_petsc_0.t[-1], ':', np.linalg.norm(diff, np.inf), '(space rank', comm_x.Get_rank(), ')')
def __init__(self, problem: List[Application], transfer: List[GridTransfer] = None, max_iter: int = 100, tol: float = 1e-7, nested_iteration: bool = True, cf_iter: int = 1, cycle_type: str = 'V', comm_time: MPI.Comm = MPI.COMM_WORLD, comm_space: MPI.Comm = MPI.COMM_NULL, logging_lvl: int = logging.INFO, output_fcn=None, output_lvl=1, t_norm=2, random_init_guess: bool = False) -> None: """ Initialize MGRIT solver. :param problem: List of problems (one for each MGRIT level) :param transfer: List of spatial transfer operators (one for each pair of consecutive MGRIT levels) :param max_iter: Maximum number of iterations :param tol: stopping tolerance :param nested_iteration: With (True) or without (False) nested iterations :param cf_iter: Number of CF relaxations in each MGRIT iteration :param cycle_type: 'F' or 'V' cycle :param comm_time: Time communicator :param comm_space: Space communicator :param logging_lvl: Logging level: Value = 10: Debug logging level -> Runtime of all components Value = 20: Info logging level -> Information per MGRIT iteration + summary at the end Value = 30: No logging level -> No information :param output_fcn: Function for saving solution values to file :param output_lvl: Output level, possible values 0, 1, 2: 0 -> output_fcn is never called 1 -> output_fcn is called at the end of the simulation 2 -> output_fcn is called after each MGRIT iteration :param random_init_guess: Use (True) or do not use (False) random initial guess """ logging.basicConfig(format='%(levelname)s - %(asctime)s - %(message)s', datefmt='%d-%m-%y %H:%M:%S', level=logging_lvl, stream=sys.stdout) # Set standard grid transfer operators if no transfer operators are given if transfer is None: transfer = [GridTransferCopy() for _ in range(len(problem) - 1)] # Check input parameters if len(problem) != (len(transfer) + 1): raise Exception( 'There should be exactly one transfer operator for each level except the coarsest grid' ) for i in range(len(problem) - 1): if len(problem[i].t) < len(problem[i + 1].t): raise Exception('The time grid on level ' + str(i + 1) + ' contains more time points than level ' + str(i)) if cycle_type != 'V' and cycle_type != 'F': raise Exception("Cycle-type " + str(cycle_type) + " is not implemented. Choose 'V' or 'F'") if output_lvl not in [0, 1, 2]: raise Exception("Unknown output level. Choose 0, 1 or 2.") for lvl in range(1, len(problem)): if len( set(problem[lvl - 1].t.tolist()).intersection( set(problem[lvl].t.tolist()))) != len(problem[lvl].t): raise Exception('Some points from level ' + str(lvl - 1) + ' are not points of level ' + str(lvl)) if t_norm not in [1, 2, 3]: raise Exception( 'Unknown norm. Please choose 1 (one norm), 2 (two-norm) or 3 (inf-norm)' ) self.comm_time = comm_time self.comm_space = comm_space self.comm_time_rank = self.comm_time.Get_rank() self.comm_time_size = self.comm_time.Get_size() if self.comm_time_size > len(problem[0].t): raise Exception( 'More processors than time points. Not useful and not implemented yet' ) # Check if spatial parallelism is used if self.comm_space != MPI.COMM_NULL: self.spatial_parallel = True self.comm_space_rank = self.comm_space.Get_rank() self.comm_space_size = self.comm_space.Get_size() else: self.spatial_parallel = False self.comm_space_rank = -99 self.comm_space_size = 1 # Start timer for setup time self.comm_time.barrier() runtime_setup_start = time.time() self.log_info(f"Start setup") # Initialize MGRIT parameters self.problem = problem # List of problems (one per MGRIT level) self.lvl_max = len(problem) # Max number of MGRIT levels self.step = [ ] # List of time integration routines (one per MGRIT level) self.u = [] # List of solutions (one per MGRIT level) self.v = [] # List of restricted unknowns (one per MGRIT level) self.g = [] # List of FAS right-hand sides (one per MGRIT level) self.t = [] # List of local time intervals (one per MGRIT level) self.m = [] # List of coarsening factors self.restriction = [ ] # List of restriction operators (one per MGRIT level - except for coarsest) self.interpolation = [ ] # List of interpolation operators (one per MGRIT level - except for coarsest) self.tol = tol # Convergence tolerance self.conv = np.zeros(max_iter + 1) # Convergence information after each iteration self.cf_iter = cf_iter # Number of CF-relaxations self.cycle_type = cycle_type # Cycle type, F or V self.random_init_guess = random_init_guess # Random initial guess self.iter_max = max_iter # Maximum number of iterations self.solve_iter = 0 # MGRIT iteration number; for output self.nes_it = nested_iteration # Local nested iteration value self.runtime_solve = 0 # Solve runtime self.runtime_setup = 0 # Setup runtime self.int_start = 0 # Index of first time point of local time interval self.int_stop = 0 # Index of last time points of local time interval self.cpts = [] # Global index of local C-points self.index_local_c = [] # Local indices of C-Points self.index_local_f = [] # Local indices of F-Points self.index_local = [] # Local indices of all points self.g_coarsest = [ ] # FAS residual for the time stepping on coarsest grid self.u_coarsest = [] # Solution for the time stepping on coarsest grid self.comm_front = [] # Communication inside F-relax per MGRIT level self.comm_back = [] # Communication inside F-relax per MGRIT level self.first_is_f_point = [] # Communication after C-relax self.first_is_c_point = [] # Communication after F-relax self.last_is_f_point = [] # Communication after F-relax self.last_is_c_point = [] # Communication after C-relax self.send_to = [] # Which process contains next time point self.get_from = [] # Which process contains previous time point self.global_t = [] # Global time information self.t_norm = 1 if t_norm == 1 else None if t_norm == 2 else np.inf # Time norm # Set output level and output function self.output_lvl = output_lvl # Output level, only 0,1,2 if output_fcn is not None and callable(output_fcn): self.output_fcn = output_fcn else: self.output_fcn = None # Set local MGRIT parameters for lvl in range(self.lvl_max): self.t.append(np.copy(problem[lvl].t)) if lvl != self.lvl_max - 1: self.restriction.append(transfer[lvl].restriction) self.interpolation.append(transfer[lvl].interpolation) if lvl < self.lvl_max - 1: tmp_cpts = np.where( np.in1d(self.problem[lvl].t, self.problem[lvl + 1].t))[0] tmp_m = np.diff(tmp_cpts)[0] self.m.append(int(tmp_m)) if not np.all( np.isclose(np.diff(tmp_cpts), np.diff(tmp_cpts) [0])) and self.comm_time_rank == 0: logging.warning('Non-uniform coarsening between level ' + str(lvl) + ' and ' + str(lvl + 1) + '. Poorly tested.') else: self.m.append(1) self.setup_points_and_comm_info(lvl=lvl) self.step.append(problem[lvl].step) self.create_u(lvl=lvl) self.create_v_g(lvl=lvl) # Create coarse grid problem for direct solve self.create_coarsest_level() # Use or do not use nested iteration if nested_iteration: self.nested_iteration() # Stop timer for setup time self.comm_time.barrier() self.runtime_setup = time.time() - runtime_setup_start if self.output_fcn is not None and self.output_lvl == 2: self.output_fcn(self) self.log_info(f"Setup took {self.runtime_setup} s")
def run_V_FCF_17_17_17_17_17(): def output_fcn(self): now = 'V_FCF_17_17_17_17_17' pathlib.Path('results/' + now + '/' + str(self.solve_iter)).mkdir( parents=True, exist_ok=True) jl = [self.u[0][i].jl for i in self.index_local[0]] ia = [self.u[0][i].ia for i in self.index_local[0]] ib = [self.u[0][i].ib for i in self.index_local[0]] ic = [self.u[0][i].ic for i in self.index_local[0]] ua = [self.u[0][i].ua for i in self.index_local[0]] ub = [self.u[0][i].ub for i in self.index_local[0]] uc = [self.u[0][i].uc for i in self.index_local[0]] tr = [self.u[0][i].tr for i in self.index_local[0]] sol = { 'jl': jl, 'ia': ia, 'ib': ib, 'ic': ic, 'ua': ua, 'ub': ub, 'uc': uc, 'tr': tr, 'time': self.runtime_solve, 'conv': self.conv, 't': self.problem[0].t, 'time_setup': self.runtime_setup } np.save( 'results/' + now + '/' + str(self.solve_iter) + '/' + str(self.t[0][-1]), sol) nonlinear = True pwm = True t_start = 0 t_stop = 0.01025390625 # Complete machine_0 = InductionMachine( nonlinear=nonlinear, pwm=pwm, t_start=t_start, t_stop=t_stop, grid='im_3kW_17k', path_im3kw=os.getcwd() + '/../../src/pymgrit/induction_machine/im_3kW/', path_getdp=os.getcwd() + '/../../src/pymgrit/induction_machine/getdp/getdp', nt=10753) first_level = np.hstack((np.arange(0, len(machine_0.t))[::42], np.arange(0, len(machine_0.t))[::42][1:] - 1)) first_level.sort() machine_0.t = machine_0.t[first_level] machine_0.nt = len(first_level) machine_1 = InductionMachine( nonlinear=nonlinear, pwm=pwm, t_start=t_start, t_stop=t_stop, grid='im_3kW_17k', path_im3kw=os.getcwd() + '/../../src/pymgrit/induction_machine/im_3kW/', path_getdp=os.getcwd() + '/../../src/pymgrit/induction_machine/getdp/getdp', nt=2**8 + 1) machine_2 = InductionMachine( nonlinear=nonlinear, pwm=pwm, t_start=t_start, t_stop=t_stop, grid='im_3kW_17k', path_im3kw=os.getcwd() + '/../../src/pymgrit/induction_machine/im_3kW/', path_getdp=os.getcwd() + '/../../src/pymgrit/induction_machine/getdp/getdp', nt=2**6 + 1) machine_3 = InductionMachine( nonlinear=nonlinear, pwm=pwm, t_start=t_start, t_stop=t_stop, grid='im_3kW_17k', path_im3kw=os.getcwd() + '/../../src/pymgrit/induction_machine/im_3kW/', path_getdp=os.getcwd() + '/../../src/pymgrit/induction_machine/getdp/getdp', nt=2**4 + 1) machine_4 = InductionMachine( nonlinear=nonlinear, pwm=pwm, t_start=t_start, t_stop=t_stop, grid='im_3kW_17k', path_im3kw=os.getcwd() + '/../../src/pymgrit/induction_machine/im_3kW/', path_getdp=os.getcwd() + '/../../src/pymgrit/induction_machine/getdp/getdp', nt=2**2 + 1) problem = [machine_0, machine_1, machine_2, machine_3, machine_4] transfer = [ GridTransferCopy(), GridTransferCopy(), GridTransferCopy(), GridTransferCopy() ] mgrit = MgritMachineConvJl(problem=problem, transfer=transfer, nested_iteration=True, output_fcn=output_fcn, tol=1, cycle_type='V', cf_iter=1) mgrit.solve()
def main(): def rhs(x, t): """ Right-hand side of 1D heat equation example problem at a given space-time point (x,t), -sin(pi*x)(sin(t) - a*pi^2*cos(t)), a = 1 Note: exact solution is np.sin(np.pi * x) * np.cos(t) :param x: spatial grid point :param t: time point :return: right-hand side of 1D heat equation example problem at point (x,t) """ return -np.sin(np.pi * x) * (np.sin(t) - 1 * np.pi**2 * np.cos(t)) def init_cond(x): """ Initial condition of 1D heat equation example, u(x,0) = sin(pi*x) :param x: spatial grid point :return: initial condition of 1D heat equation example problem """ return np.sin(np.pi * x) # Construct a four-level multigrid hierarchy for the 1d heat example # * use a coarsening factor of 2 in time on all levels # * apply spatial coarsening by a factor of 2 on the first two levels heat0 = Heat1D(x_start=0, x_end=2, nx=2**4 + 1, a=1, rhs=rhs, init_cond=init_cond, t_start=0, t_stop=2, nt=2**7 + 1) heat1 = Heat1D(x_start=0, x_end=2, nx=2**3 + 1, a=1, rhs=rhs, init_cond=init_cond, t_interval=heat0.t[::2]) heat2 = Heat1D(x_start=0, x_end=2, nx=2**2 + 1, a=1, rhs=rhs, init_cond=init_cond, t_interval=heat1.t[::2]) heat3 = Heat1D(x_start=0, x_end=2, nx=2**2 + 1, a=1, rhs=rhs, init_cond=init_cond, t_interval=heat2.t[::2]) problem = [heat0, heat1, heat2, heat3] # Specify a list of grid transfer operators of length (#levels - 1) for the transfer between two consecutive levels # * Use the new class GridTransferHeat to apply spatial coarsening for transfers between the first three levels # * Use PyMGRIT's core class GridTransferCopy for the transfer between the last two levels (no spatial coarsening) transfer = [GridTransferHeat(), GridTransferHeat(), GridTransferCopy()] # Setup four-level MGRIT solver and solve the problem mgrit = Mgrit(problem=problem, transfer=transfer) info = mgrit.solve()