def test_direct_interpolation(self): for A in self.cases: S = classical_strength_of_connection(A, 0.0) splitting = split.RS(S) result = direct_interpolation(A, S, splitting) expected = reference_direct_interpolation(A, S, splitting) assert_almost_equal(result.todense(), expected.todense())
def test_RS_splitting(self): for A in self.cases: S = classical_strength_of_connection(A, 0.0) splitting = split.RS(S) assert (splitting.min() >= 0) # could be all 1s assert_equal(splitting.max(), 1) S.data[:] = 1 # check that all F-nodes are strongly connected to a C-node assert ((splitting + S * splitting).min() > 0)
def extend_hierarchy(levels, strength, CF, keep, prolongation_function): """Extend the multigrid hierarchy.""" def unpack_arg(v): if isinstance(v, tuple): return v[0], v[1] else: return v, {} A = levels[-1].A # Compute the strength-of-connection matrix C, where larger # C[i,j] denote stronger couplings between i and j. fn, kwargs = unpack_arg(strength) if fn == 'symmetric': C = symmetric_strength_of_connection(A, **kwargs) elif fn == 'classical': C = classical_strength_of_connection(A, **kwargs) elif fn == 'distance': C = distance_strength_of_connection(A, **kwargs) elif (fn == 'ode') or (fn == 'evolution'): C = evolution_strength_of_connection(A, **kwargs) elif fn == 'energy_based': C = energy_based_strength_of_connection(A, **kwargs) elif fn == 'algebraic_distance': C = algebraic_distance(A, **kwargs) elif fn == 'affinity': C = affinity_distance(A, **kwargs) elif fn is None: C = A else: raise ValueError('unrecognized strength of connection method: %s' % str(fn)) # Generate the C/F splitting fn, kwargs = unpack_arg(CF) if fn == 'RS': splitting = split.RS(C, **kwargs) elif fn == 'PMIS': splitting = split.PMIS(C, **kwargs) elif fn == 'PMISc': splitting = split.PMISc(C, **kwargs) elif fn == 'CLJP': splitting = split.CLJP(C, **kwargs) elif fn == 'CLJPc': splitting = split.CLJPc(C, **kwargs) elif fn == 'CR': splitting = CR(C, **kwargs) else: raise ValueError('unknown C/F splitting method (%s)' % CF) # Generate the interpolation matrix that maps from the coarse-grid to the # fine-grid baseline_P = direct_interpolation(A, C, splitting) coarse_nodes = np.nonzero(splitting)[0] # Create a prolongation matrix with the same coarse-fine splitting and sparsity pattern # as the baseline P = prolongation_function(A, coarse_nodes, baseline_P, C) # Generate the restriction matrix that maps from the fine-grid to the # coarse-grid R = P.T.tocsr() # Store relevant information for this level if keep: levels[-1].C = C # strength of connection matrix levels[-1].splitting = splitting # C/F splitting levels[-1].P = P # prolongation operator levels[-1].R = R # restriction operator levels.append(multilevel_solver.level()) # Form next level through Galerkin product A = R * A * P levels[-1].A = A