def __init__(self, fine_level, coarse_level, base_transfer_params, space_transfer_class, space_transfer_params): """ Initialization routine Args: fine_level (pySDC.Level.level): fine level connected with the base_transfer operations coarse_level (pySDC.Level.level): coarse level connected with the base_transfer operations base_transfer_params (dict): parameters for the base_transfer operations space_transfer_class: class to perform spatial transfer space_transfer_params (dict): parameters for the space_transfer operations """ self.params = _Pars(base_transfer_params) # set up logger self.logger = logging.getLogger('transfer') # just copy by object self.fine = fine_level self.coarse = coarse_level fine_grid = self.fine.sweep.coll.nodes coarse_grid = self.coarse.sweep.coll.nodes if len(fine_grid) == len(coarse_grid): self.Pcoll = sp.eye(len(fine_grid)).toarray() self.Rcoll = sp.eye(len(fine_grid)).toarray() else: self.Pcoll = th.interpolation_matrix_1d(fine_grid, coarse_grid, k=self.params.coll_iorder, pad=0, equidist_nested=False).toarray() self.Rcoll = th.restriction_matrix_1d(fine_grid, coarse_grid, k=self.params.coll_rorder, pad=0).toarray() # set up spatial transfer self.space_transfer = space_transfer_class(fine_prob=self.fine.prob, coarse_prob=self.coarse.prob, params=space_transfer_params)
def check_Q_transfer(collclass): """ A simple test program to check the order of the Q interpolation/restriction """ for M in range(3, 9): Mfine = M Mcoarse = int((Mfine + 1) / 2.0) coll_fine = collclass(Mfine, 0, 1) coll_coarse = collclass(Mcoarse, 0, 1) assert coll_fine.left_is_node == coll_coarse.left_is_node, 'ERROR: should be using the same class for coarse and fine Q' if not coll_fine.left_is_node: fine_grid = np.concatenate(([0], coll_fine.nodes)) coarse_grid = np.concatenate(([0], coll_coarse.nodes)) else: fine_grid = coll_fine.nodes coarse_grid = coll_coarse.nodes for order in range(2, coll_coarse.num_nodes + 1): Pcoll = th.interpolation_matrix_1d(fine_grid, coarse_grid, k=order, pad=0) Rcoll = th.restriction_matrix_1d(fine_grid, coarse_grid, k=order, pad=0) for polyorder in range(1, order + 2): coeff = np.random.rand(polyorder) ufine = polyval(fine_grid, coeff) ucoarse = polyval(coarse_grid, coeff) uinter = Pcoll.dot(ucoarse) urestr = Rcoll.dot(ufine) err_inter = np.linalg.norm(uinter - ufine, np.inf) err_restr = np.linalg.norm(urestr - ucoarse, np.inf) if polyorder <= order: assert err_inter < 2E-15, "ERROR: Q-interpolation order is not reached, got %s" % err_inter assert err_restr < 2E-15, "ERROR: Q-restriction order is not reached, got %s" % err_restr else: assert err_inter > 2E-15, "ERROR: Q-interpolation order is higher than expected, got %s" % polyorder
def __init__(self, fine_level, coarse_level, params): """ Initialization routine Args: fine_level: fine level connected with the transfer operations (passed to parent) coarse_level: coarse level connected with the transfer operations (passed to parent) params: parameters for the transfer operators """ # invoke super initialization super(mesh_to_mesh_1d_periodic, self).__init__(fine_level, coarse_level, params) fine_grid = np.array( [i * fine_level.prob.dx for i in range(fine_level.prob.nvars)]) coarse_grid = np.array( [i * coarse_level.prob.dx for i in range(coarse_level.prob.nvars)]) # if number of variables is the same on both levels, Rspace and Pspace are identity if self.init_c == self.init_f: self.Rspace = np.eye(self.init_c) # assemble restriction as transpose of interpolation else: if params['rorder'] == 1: self.Rspace = th.restriction_matrix_1d(fine_grid, coarse_grid, k=1, periodic=True) else: self.Rspace = 0.5 * th.interpolation_matrix_1d( fine_grid, coarse_grid, k=params['rorder'], periodic=True).T # if number of variables is the same on both levels, Rspace and Pspace are identity if self.init_f == self.init_c: self.Pspace = np.eye(self.init_f) else: self.Pspace = th.interpolation_matrix_1d(fine_grid, coarse_grid, k=params['iorder'], periodic=True) # print(self.Rspace.todense()) # print(self.Pspace.todense()) # exit() pass
def check_Q_transfer_minimal(collclass): """ A simple test program to check the order of the Q interpolation/restriction for only 2 coarse nodes """ Mcoarse = 2 coll_coarse = collclass(Mcoarse, 0, 1) for M in range(3, 9): Mfine = M coll_fine = collclass(Mfine, 0, 1) assert coll_fine.left_is_node == coll_coarse.left_is_node, 'ERROR: should be using the same class for coarse and fine Q' fine_grid = coll_fine.nodes coarse_grid = coll_coarse.nodes Pcoll = th.interpolation_matrix_1d(fine_grid, coarse_grid, k=2, pad=0, equidist_nested=False) Rcoll = th.restriction_matrix_1d(fine_grid, coarse_grid, k=2, pad=0) for polyorder in range(1,3): coeff = np.random.rand(polyorder) ufine = polyval(fine_grid,coeff) ucoarse = polyval(coarse_grid,coeff) uinter = Pcoll.dot(ucoarse) urestr = Rcoll.dot(ufine) err_inter = np.linalg.norm(uinter-ufine, np.inf) err_restr = np.linalg.norm(urestr-ucoarse, np.inf) if polyorder <= 2: assert err_inter < 2E-15, "ERROR: Q-interpolation order is not reached, got %s" %err_inter assert err_restr < 2E-15, "ERROR: Q-restriction order is not reached, got %s" % err_restr else: assert err_inter > 2E-15, "ERROR: Q-interpolation order is higher than expected, got %s" % polyorder
def __init__(self, fine_prob, coarse_prob, params): """ Initialization routine Args: fine_prob: fine problem coarse_prob: coarse problem params: parameters for the transfer operators """ if 'iorder' not in params: raise TransferError('Need iorder parameter for spatial transfer') if 'rorder' not in params: raise TransferError('Need rorder parameter for spatial transfer') # invoke super initialization super(mesh_to_mesh, self).__init__(fine_prob, coarse_prob, params) if type(self.fine_prob.params.nvars) is tuple: if type(self.coarse_prob.params.nvars) is not tuple: raise TransferError( 'nvars parameter of coarse problem needs to be a tuple') if not len(self.fine_prob.params.nvars) == len( self.coarse_prob.params.nvars): raise TransferError( 'nvars parameter of fine and coarse level needs to have the same length' ) elif type(self.fine_prob.params.nvars) is int: if type(self.coarse_prob.params.nvars) is not int: raise TransferError( 'nvars parameter of coarse problem needs to be an int') else: raise TransferError("unknow type of nvars for transfer, got %s" % self.fine_prob.params.nvars) # we have a 1d problem if type(self.fine_prob.params.nvars) is int: # if number of variables is the same on both levels, Rspace and Pspace are identity if self.coarse_prob.params.nvars == self.fine_prob.params.nvars: self.Rspace = sp.eye(self.coarse_prob.params.nvars) self.Pspace = sp.eye(self.fine_prob.params.nvars) # assemble restriction as transpose of interpolation else: if not self.params.periodic: fine_grid = np.array([ (i + 1) * self.fine_prob.dx for i in range(self.fine_prob.params.nvars) ]) coarse_grid = np.array([ (i + 1) * self.coarse_prob.dx for i in range(self.coarse_prob.params.nvars) ]) else: fine_grid = np.array([ i * self.fine_prob.dx for i in range(self.fine_prob.params.nvars) ]) coarse_grid = np.array([ i * self.coarse_prob.dx for i in range(self.coarse_prob.params.nvars) ]) if self.params.rorder <= 1: self.Rspace = th.restriction_matrix_1d( fine_grid, coarse_grid, k=self.params.rorder, periodic=self.params.periodic) else: self.Rspace = 0.5 * th.interpolation_matrix_1d( fine_grid, coarse_grid, k=self.params.rorder, periodic=self.params.periodic).T self.Pspace = th.interpolation_matrix_1d( fine_grid, coarse_grid, k=self.params.iorder, periodic=self.params.periodic) # we have an n-d problem else: Rspace = [] Pspace = [] for i in range(len(self.fine_prob.params.nvars)): # if number of variables is the same on both levels, Rspace and Pspace are identity if self.coarse_prob.params.nvars == self.fine_prob.params.nvars: Rspace.append(sp.eye(self.coarse_prob.params.nvars[i])) Pspace.append(sp.eye(self.fine_prob.params.nvars[i])) # assemble restriction as transpose of interpolation else: if not self.params.periodic: fine_grid = np.array([ (j + 1) * self.fine_prob.dx for j in range(self.fine_prob.params.nvars[i]) ]) coarse_grid = np.array([ (j + 1) * self.coarse_prob.dx for j in range(self.coarse_prob.params.nvars[i]) ]) else: fine_grid = np.array([ j * self.fine_prob.dx for j in range(self.fine_prob.params.nvars[i]) ]) coarse_grid = np.array([ j * self.coarse_prob.dx for j in range(self.coarse_prob.params.nvars[i]) ]) if self.params.iorder <= 1: Rspace.append( th.restriction_matrix_1d( fine_grid, coarse_grid, k=self.params.iorder, periodic=self.params.periodic).T) else: Rspace.append(0.5 * th.interpolation_matrix_1d( fine_grid, coarse_grid, k=self.params.iorder, periodic=self.params.periodic).T) Pspace.append( th.interpolation_matrix_1d( fine_grid, coarse_grid, k=self.params.iorder, periodic=self.params.periodic)) # kronecker 1-d operators for n-d self.Pspace = Pspace[0] for i in range(1, len(Pspace)): self.Pspace = sp.kron(self.Pspace, Pspace[i], format='csc') self.Rspace = Rspace[0] for i in range(1, len(Rspace)): self.Rspace = sp.kron(self.Rspace, Rspace[i], format='csc')
def __init__(self, fine_level, coarse_level, base_transfer_params, space_transfer_class, space_transfer_params): """ Initialization routine Args: fine_level (pySDC.Level.level): fine level connected with the base_transfer operations coarse_level (pySDC.Level.level): coarse level connected with the base_transfer operations base_transfer_params (dict): parameters for the base_transfer operations space_transfer_class: class to perform spatial transfer space_transfer_params (dict): parameters for the space_transfer operations """ # short helper class to add params as attributes class __Pars(FrozenClass): def __init__(self, pars): self.finter = False self.coll_iorder = 2 self.coll_rorder = 1 for k, v in pars.items(): setattr(self, k, v) self._freeze() self.params = __Pars(base_transfer_params) # set up logger self.logger = logging.getLogger('transfer') # just copy by object self.fine = fine_level self.coarse = coarse_level # for Q-based transfer, check if we need to add 0 to the list of nodes if not self.fine.sweep.coll.left_is_node: fine_grid = np.concatenate(([0], self.fine.sweep.coll.nodes)) coarse_grid = np.concatenate(([0], self.coarse.sweep.coll.nodes)) else: fine_grid = self.fine.sweep.coll.nodes coarse_grid = self.coarse.sweep.coll.nodes if self.params.coll_iorder > len(coarse_grid): self.logger.warning( 'requested order of Q-interpolation is not valid, resetting to %s' % len(coarse_grid)) self.params.coll_iorder = len(coarse_grid) if self.params.coll_rorder != 1: self.logger.warning( 'requested order of Q-restriction is != 1, can lead to weird behavior!' ) # set up preliminary transfer matrices for Q-based coarsening Pcoll = th.interpolation_matrix_1d(fine_grid, coarse_grid, k=self.params.coll_iorder, pad=0).toarray() Rcoll = th.restriction_matrix_1d(fine_grid, coarse_grid, k=self.params.coll_rorder, pad=0).toarray() # pad transfer matrices if necessary if self.fine.sweep.coll.left_is_node: self.Pcoll = np.zeros((self.fine.sweep.coll.num_nodes + 1, self.coarse.sweep.coll.num_nodes + 1)) self.Rcoll = np.zeros((self.coarse.sweep.coll.num_nodes + 1, self.fine.sweep.coll.num_nodes + 1)) self.Pcoll[1:, 1:] = Pcoll self.Rcoll[1:, 1:] = Rcoll else: self.Pcoll = Pcoll self.Rcoll = Rcoll # set up spatial transfer self.space_transfer = space_transfer_class( fine_prob=self.fine.prob, coarse_prob=self.coarse.prob, params=space_transfer_params)