示例#1
0
def test_waves_1d_first_order(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    ux = field.Field(name='ux', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    τ1 = field.Field(name='τ1', dist=d, dtype=dtype)
    τ2 = field.Field(name='τ2', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    xb1 = dx(u).domain.bases[0]
    P1 = field.Field(name='P1', dist=d, bases=(xb1, ), dtype=dtype)
    P2 = field.Field(name='P2', dist=d, bases=(xb1, ), dtype=dtype)
    P1['c'][-1] = 1
    P2['c'][-1] = 1
    problem = problems.EVP([u, ux, τ1, τ2], a)
    problem.add_equation((a * u + dx(ux) + P1 * τ1, 0))
    problem.add_equation((ux - dx(u) + P2 * τ2, 0))
    problem.add_equation((u(x=0), 0))
    problem.add_equation((u(x=np.pi), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    i_sort = np.argsort(solver.eigenvalues)
    solver.eigenvalues = solver.eigenvalues[i_sort]
    solver.eigenvectors = solver.eigenvectors[:, i_sort]
    # Check solution
    solver.set_state(0, solver.subproblems[0].subsystems[0])
    eigenfunction = u['g'] / np.max(u['g'])
    sol = np.sin(x) / np.max(np.sin(x))
    assert np.allclose(eigenfunction, sol)
示例#2
0
def test_waves_1d(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    τ1 = field.Field(name='τ1', dist=d, dtype=dtype)
    τ2 = field.Field(name='τ2', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    xb2 = dx(dx(u)).domain.bases[0]
    P1 = field.Field(name='P1', dist=d, bases=(xb2, ), dtype=dtype)
    P2 = field.Field(name='P2', dist=d, bases=(xb2, ), dtype=dtype)
    P1['c'][-1] = 1
    P2['c'][-2] = 1
    problem = problems.EVP([u, τ1, τ2], a)
    problem.add_equation((a * u + dx(dx(u)) + P1 * τ1 + P2 * τ2, 0))
    problem.add_equation((u(x=0), 0))
    problem.add_equation((u(x=np.pi), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    i_sort = np.argsort(solver.eigenvalues)
    sorted_eigenvalues = solver.eigenvalues[i_sort]
    # Check solution
    Nmodes = Nx // 4
    k = np.arange(Nmodes) + 1
    assert np.allclose(sorted_eigenvalues[:Nmodes], k**2)
示例#3
0
def test_heat_1d_periodic(x_basis_class, Nx, timestepper, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = basis.ComplexFourier(c, size=Nx, bounds=(0, 2 * np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    F = field.Field(name='F', dist=d, bases=(xb, ), dtype=dtype)
    F['g'] = -np.sin(x)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    dt = operators.TimeDerivative
    problem = problems.IVP([u])
    problem.add_equation((-dt(u) + dx(dx(u)), F))
    # Solver
    solver = solvers.InitialValueSolver(problem, timestepper)
    dt = 1e-5
    iter = 10
    for i in range(iter):
        solver.step(dt)
    # Check solution
    amp = 1 - np.exp(-solver.sim_time)
    u_true = amp * np.sin(x)
    assert np.allclose(u['g'], u_true)
示例#4
0
def test_chebyshev_libraries_forward(N, alpha, dealias, dtype, library):
    """Tests that fast Chebyshev transforms match matrix transforms."""
    c = coords.Coordinate('x')
    d = distributor.Distributor([c])
    # Matrix
    b_mat = basis.Ultraspherical(c,
                                 size=N,
                                 alpha0=0,
                                 alpha=alpha,
                                 bounds=(-1, 1),
                                 dealias=dealias,
                                 library='matrix')
    u_mat = field.Field(dist=d, bases=(b_mat, ), dtype=dtype)
    u_mat.preset_scales(dealias)
    u_mat['g'] = np.random.randn(int(np.ceil(dealias * N)))
    # Library
    b_lib = basis.Ultraspherical(c,
                                 size=N,
                                 alpha0=0,
                                 alpha=alpha,
                                 bounds=(-1, 1),
                                 dealias=dealias,
                                 library=library)
    u_lib = field.Field(dist=d, bases=(b_lib, ), dtype=dtype)
    u_lib.preset_scales(dealias)
    u_lib['g'] = u_mat['g']
    assert np.allclose(u_mat['c'], u_lib['c'])
示例#5
0
def test_sin_nlbvp(Nx, dtype, dealias, basis_class):
    ncc_cutoff = 1e-10
    tolerance = 1e-10
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    xb = basis_class(c, size=Nx, bounds=(0, 1), dealias=dealias)
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb,), dtype=dtype)
    τ = field.Field(name='τ', dist=d, dtype=dtype)
    xb1 = xb.clone_with(a=xb.a+1, b=xb.b+1)
    P = field.Field(name='P', dist=d, bases=(xb1,), dtype=dtype)
    P['c'][-1] = 1
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.NLBVP([u, τ])
    problem.add_equation((dx(u) + τ*P, np.sqrt(1-u*u)))
    problem.add_equation((u(x=0), 0))
    # Solver
    solver = solvers.NonlinearBoundaryValueSolver(problem, ncc_cutoff=ncc_cutoff)
    # Initial guess
    u['g'] = x
    # Iterations
    def error(perts):
        return np.sum([np.sum(np.abs(pert['c'])) for pert in perts])
    err = np.inf
    while err > tolerance:
        solver.newton_iteration()
        err = error(solver.perturbations)
    # Check solution
    u_true = np.sin(x)
    u.change_scales(1)
    assert np.allclose(u['g'], u_true)
示例#6
0
def test_jacobi_ncc_solve(N, a0, b0, k_ncc, k_arg, dealias, dtype):
    """
    This tests for aliasing errors when solving the equation
        f(x)*u(x) = f(x)*g(x).

    With 3/2 dealiasing, the RHS product will generally contain aliasing
    errors in the last 2*max(k_ncc, k_arg) modes. We can eliminate these
    by zeroing the corresponding number of modes of f(x) and/or g(x).
    """
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a=a0, b=b0, bounds=(0, 1), dealias=dealias)
    b_ncc = b.clone_with(a=a0+k_ncc, b=b0+k_ncc)
    b_arg = b.clone_with(a=a0+k_arg, b=b0+k_arg)
    f = field.Field(dist=d, bases=(b_ncc,), dtype=dtype)
    g = field.Field(dist=d, bases=(b_arg,), dtype=dtype)
    u = field.Field(dist=d, bases=(b_arg,), dtype=dtype)
    f['g'] = np.random.randn(*f['g'].shape)
    g['g'] = np.random.randn(*g['g'].shape)
    kmax = max(k_ncc, k_arg)
    if kmax > 0 and dealias < 2:
        f['c'][-kmax:] = 0
        g['c'][-kmax:] = 0
    problem = problems.LBVP([u])
    problem.add_equation((f*u, f*g))
    solver = solvers.LinearBoundaryValueSolver(problem)
    solver.solve()
    assert np.allclose(u['c'], g['c'])
示例#7
0
def test_jacobi_differentiate(N, a, b, k, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1))
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b,), dtype=dtype)
    f['g'] = x**5
    fx = operators.Differentiate(f, c).evaluate()
    assert np.allclose(fx['g'], 5*x**4)
示例#8
0
def test_jacobi_convert_constant(N, a, b, k, dtype, layout):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1))
    fc = field.Field(dist=d, dtype=dtype)
    fc['g'] = 1
    fc[layout]
    f = operators.convert(fc, (b,)).evaluate()
    assert np.allclose(fc['g'], f['g'])
示例#9
0
def test_jacobi_convert_explicit(N, a, b, k, dtype, layout):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1))
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b,), dtype=dtype)
    f['g'] = x**5
    fx = operators.Differentiate(f, c)
    f[layout]
    g = operators.convert(f, fx.domain.bases).evaluate()
    assert np.allclose(g['g'], f['g'])
示例#10
0
def test_jacobi_interpolate(N, a, b, k, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1))
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b,), dtype=dtype)
    f['g'] = x**5
    results = []
    for p in [0, 1, np.random.rand()]:
        fp = operators.Interpolate(f, c, p).evaluate()
        results.append(np.allclose(fp['g'], p**5))
    assert all(results)
示例#11
0
def test_fourier_convert_constant(N, bounds, dtype, layout):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    if dtype == np.float64:
        b = basis.RealFourier(c, size=N, bounds=bounds)
    elif dtype == np.complex128:
        b = basis.ComplexFourier(c, size=N, bounds=bounds)
    fc = field.Field(dist=d, dtype=dtype)
    fc['g'] = 1
    fc[layout]
    f = operators.convert(fc, (b, )).evaluate()
    assert np.allclose(fc['g'], f['g'])
示例#12
0
def test_jacobi_ufunc(N, a, b, dtype, dealias, func):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    b = basis.Jacobi(c, size=N, a=a, b=b, bounds=(0, 1), dealias=dealias)
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b, ), dtype=dtype)
    if func is np.arccosh:
        f['g'] = 1 + x**2
    else:
        f['g'] = x**2
    g0 = func(f['g'])
    g = func(f).evaluate()
    assert np.allclose(g['g'], g0)
示例#13
0
def test_fourier_integrate(N, bounds, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    if dtype == np.float64:
        b = basis.RealFourier(c, size=N, bounds=bounds)
    elif dtype == np.complex128:
        b = basis.ComplexFourier(c, size=N, bounds=bounds)
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b, ), dtype=dtype)
    k = 4 * np.pi / (bounds[1] - bounds[0])
    f['g'] = 1 + np.sin(k * x + 0.1)
    fi = operators.Integrate(f, c).evaluate()
    assert np.allclose(fi['g'], bounds[1] - bounds[0])
示例#14
0
def test_RF_scalar_roundtrip(N, dealias):
    if comm.size == 1:
        c = coords.Coordinate('x')
        d = distributor.Distributor([c])
        xb = basis.RealFourier(c, size=N, bounds=(0, 1), dealias=dealias)
        x = xb.local_grid(dealias)
        # Scalar transforms
        u = field.Field(dist=d, bases=(xb, ), dtype=np.float64)
        u.preset_scales(dealias)
        u['g'] = ug = np.cos(2 * np.pi * x + np.pi / 4)
        u['c']
        assert np.allclose(u['g'], ug)
    else:
        pytest.skip("Can only test 1D transform in serial")
示例#15
0
def test_jacobi_convert_implicit(N, a, b, k, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a0=a, b0=b, a=a+k, b=b+k, bounds=(0, 1))
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b,), dtype=dtype)
    f['g'] = x**5
    fx = operators.Differentiate(f, c).evaluate()
    g = field.Field(dist=d, bases=(b,), dtype=dtype)
    problem = problems.LBVP([g])
    problem.add_equation((g, fx))
    solver = solvers.LinearBoundaryValueSolver(problem)
    solver.solve()
    assert np.allclose(g['g'], fx['g'])
示例#16
0
def test_J_scalar_roundtrip(a, b, N, dealias, dtype):
    if comm.size == 1:
        c = coords.Coordinate('x')
        d = distributor.Distributor([c])
        xb = basis.Jacobi(c, a=a, b=b, size=N, bounds=(0, 1), dealias=dealias)
        x = xb.local_grid(dealias)
        # Scalar transforms
        u = field.Field(dist=d, bases=(xb, ), dtype=dtype)
        u.preset_scales(dealias)
        u['g'] = ug = 2 * x**2 - 1
        u['c']
        assert np.allclose(u['g'], ug)
    else:
        pytest.skip("Can only test 1D transform in serial")
示例#17
0
def test_jacobi_ncc_eval(N, a0, b0, k_ncc, k_arg, dealias, dtype):
    """
    This tests for aliasing errors when evaluating the product
        f(x) * g(x)
    as both an NCC operator and with the pseudospectral method.

    With 3/2 dealiasing, the product will generally contain aliasing
    errors in the last 2*max(k_ncc, k_arg) modes. We can eliminate these
    by zeroing the corresponding number of modes of f(x) and/or g(x).
    """
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    b = basis.Jacobi(c, size=N, a=a0, b=b0, bounds=(0, 1), dealias=dealias)
    b_ncc = b.clone_with(a=a0+k_ncc, b=b0+k_ncc)
    b_arg = b.clone_with(a=a0+k_arg, b=b0+k_arg)
    f = field.Field(dist=d, bases=(b_ncc,), dtype=dtype)
    g = field.Field(dist=d, bases=(b_arg,), dtype=dtype)
    f['g'] = np.random.randn(*f['g'].shape)
    g['g'] = np.random.randn(*g['g'].shape)
    x = b.local_grid(1)
    f['g'] = np.cos(6*x)
    g['g'] = np.cos(6*x)
    kmax = max(k_ncc, k_arg)
    if kmax > 0 and dealias < 2:
        f['c'][-kmax:] = 0
        g['c'][-kmax:] = 0
    vars = [g]
    w0 = f * g
    w1 = w0.reinitialize(ncc=True, ncc_vars=vars)
    problem = problems.LBVP(vars)
    problem.add_equation((w1, 0))
    solver = solvers.LinearBoundaryValueSolver(problem)
    w1.store_ncc_matrices(vars, solver.subproblems)
    w0 = w0.evaluate()
    w2 = field.Field(dist=d, bases=(b,), dtype=dtype)
    w2.preset_scales(w2.domain.dealias)
    w2['g'] = w0['g']
    w2['c']
    w0['c']
    print(np.max(np.abs(w2['g'] - w0['g'])))
    w2 = operators.Convert(w2, w0.domain.bases[0]).evaluate()
    w1 = w1.evaluate_as_ncc()
    assert np.allclose(w0['c'], w2['c'])
示例#18
0
def test_fourier_interpolate(N, bounds, dtype):
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    if dtype == np.float64:
        b = basis.RealFourier(c, size=N, bounds=bounds)
    elif dtype == np.complex128:
        b = basis.ComplexFourier(c, size=N, bounds=bounds)
    x = b.local_grid(1)
    f = field.Field(dist=d, bases=(b, ), dtype=dtype)
    k = 4 * np.pi / (bounds[1] - bounds[0])
    f['g'] = 1 + np.sin(k * x + 0.1)
    results = []
    for p in [
            bounds[0], bounds[1],
            bounds[0] + (bounds[1] - bounds[0]) * np.random.rand()
    ]:
        fp = operators.Interpolate(f, c, p).evaluate()
        results.append(np.allclose(fp['g'], 1 + np.sin(k * p + 0.1)))
    assert all(results)
示例#19
0
def test_heat_1d_periodic(x_basis_class, Nx, dtype):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c, ))
    xb = x_basis_class(c, size=Nx, bounds=(0, 2 * np.pi))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb, ), dtype=dtype)
    a = field.Field(name='a', dist=d, dtype=dtype)
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.EVP([u], a)
    problem.add_equation((a * u + dx(dx(u)), 0))
    # Solver
    solver = solvers.EigenvalueSolver(problem, matrix_coupling=[True])
    solver.solve_dense(solver.subproblems[0])
    # Check solution
    k = xb.wavenumbers
    if x_basis_class is basis.RealFourier:
        k = k[1:]  # Drop one k=0 for msin
    assert np.allclose(solver.eigenvalues, k**2)
示例#20
0
def test_real_fourier_libraries_forward(N, dealias, dtype, library):
    """Tests that fast real Fourier transforms match matrix transforms."""
    c = coords.Coordinate('x')
    d = distributor.Distributor([c])
    # Matrix
    b_mat = basis.RealFourier(c,
                              size=N,
                              bounds=(0, 2 * np.pi),
                              dealias=dealias,
                              library='matrix')
    u_mat = field.Field(dist=d, bases=(b_mat, ), dtype=dtype)
    u_mat.preset_scales(dealias)
    u_mat['g'] = np.random.randn(int(np.ceil(dealias * N)))
    # Library
    b_lib = basis.RealFourier(c,
                              size=N,
                              bounds=(0, 2 * np.pi),
                              dealias=dealias,
                              library=library)
    u_lib = field.Field(dist=d, bases=(b_lib, ), dtype=dtype)
    u_lib.preset_scales(dealias)
    u_lib['g'] = u_mat['g']
    assert np.allclose(u_mat['c'], u_lib['c'])
示例#21
0
dtype = np.float64

# Parameters
radius = 1
Mmax = 31
Nmax = 31
nz = 32
Ampl = 1e-6
Re = 3162.
nu = 1./Re
zmin = 0
zmax = 16*np.pi*2*radius

# Bases
zc = coords.Coordinate('z')
c = coords.PolarCoordinates('phi', 'r')
d = distributor.Distributor((zc,c))
b = basis.DiskBasis(c, (Mmax+1, Nmax+1), radius=radius, dtype=dtype)
zb = basis.RealFourier(zc, nz, bounds=(zmin, zmax))
cb = b.S1_basis(radius=radius)

phi, r = b.local_grids((1, 1))
z = zb.local_grids((1,))

# Fields
u = field.Field(dist=d, bases=(zb, b), tensorsig=(c,),dtype=dtype)
w = field.Field(dist=d, bases=(zb, b), dtype=dtype)
p = field.Field(dist=d, bases=(zb, b), dtype=dtype)
tau_u = field.Field(dist=d, bases=(cb,), tensorsig=(c,), dtype=dtype)
tau_w = field.Field(dist=d, bases=(cb,), dtype=dtype)
示例#22
0
def main(N, alpha, method, tau):
    # Bases
    c = coords.Coordinate('x')
    d = distributor.Distributor((c,))
    xb = basis.ChebyshevT(c, size=N, bounds=(-1, 1))
    x = xb.local_grid(1)
    # Fields
    u = field.Field(name='u', dist=d, bases=(xb,), dtype=np.float64)
    ux = field.Field(name='ux', dist=d, bases=(xb,), dtype=np.float64)
    f = field.Field(name='f', dist=d, bases=(xb,), dtype=np.float64)
    t1 = field.Field(name='t1', dist=d, dtype=np.float64)
    t2 = field.Field(name='t2', dist=d, dtype=np.float64)
    pi, sin, cos = np.pi, np.sin, np.cos
    f['g'] = 64*pi**3*(4*pi*sin(4*pi*x)**2*sin(4*pi*cos(4*pi*x)) + cos(4*pi*x)*cos(4*pi*cos(4*pi*x))) + alpha*sin(4*pi*cos(4*pi*x))
    # Tau polynomials
    xb1 = xb._new_a_b(xb.a+1, xb.b+1)
    xb2 = xb._new_a_b(xb.a+2, xb.b+2)
    if tau == 0:
        # First-order classical Chebyshev tau: T[-1], dx(T[-1])
        p1 = field.Field(name='p1', dist=d, bases=(xb,), dtype=np.float64)
        p2 = field.Field(name='p2', dist=d, bases=(xb,), dtype=np.float64)
        p1['c'][-1] = 1
        p2['c'][-1] = 1
    elif tau == 1:
        # First-order ultraspherical tau: U[-1], dx(U[-1])
        p1 = field.Field(name='p1', dist=d, bases=(xb1,), dtype=np.float64)
        p2 = field.Field(name='p2', dist=d, bases=(xb1,), dtype=np.float64)
        p1['c'][-1] = 1
        p2['c'][-1] = 1
    # Problem
    dx = lambda A: operators.Differentiate(A, c)
    problem = problems.LBVP([u, ux, t1, t2])
    problem.add_equation((alpha*u - dx(ux) + t1*p1, f))
    problem.add_equation((ux - dx(u) + t2*p2, 0))
    problem.add_equation((u(x=-1), 0))
    problem.add_equation((u(x=+1), 0))
    solver = solvers.LinearBoundaryValueSolver(problem)
    # Methods
    if method == 0:
        # Condition number
        L_exp = solver.subproblems[0].L_exp
        result = np.linalg.cond(L_exp.A)
    elif method == 1:
        # Roundtrip roundoff with uniform u
        A = solver.subproblems[0].L_exp
        v = np.random.rand(A.shape[1])
        f = A * v
        u = solver.subproblem_matsolvers[solver.subproblems[0]].solve(f)
        result = np.max(np.abs(u-v))
    elif method == 2:
        # Manufactured solution
        from mpi4py_fft import fftw as mpi4py_fftw
        solver.solve()
        ue = np.sin(4*np.pi*np.cos(4*np.pi*x))
        d = mpi4py_fftw.aligned(N, fill=0)
        k = 2*(1 + np.arange((N-1)//2))
        d[::2] = (2./N)/np.hstack((1., 1.-k*k))
        w = mpi4py_fftw.aligned_like(d)
        dct = mpi4py_fftw.dctn(w, axes=(0,), type=3)
        weights = dct(d, w)
        result = np.sqrt(np.sum(weights*(u['g']-ue)**2))
    elif method == 3:
        # Roundtrip roundoff with uniform f
        A = solver.subproblems[0].L_exp
        g = np.random.rand(A.shape[0])
        v = solver.subproblem_matsolvers[solver.subproblems[0]].solve(g)
        f = A * v
        u = solver.subproblem_matsolvers[solver.subproblems[0]].solve(f)
        result = np.max(np.abs(u-v))
    return result