Exemple #1
0
def test_diag_precon_nl_mixed():
    # Test PCDIAGFFT by using it
    # within the relaxation method
    # using the NONLINEAR wave equation as an example
    # we compare one iteration using just the diag PC
    # with the direct solver

    mesh = fd.PeriodicUnitSquareMesh(20, 20)
    V = fd.FunctionSpace(mesh, "BDM", 1)
    Q = fd.FunctionSpace(mesh, "DG", 0)
    W = V * Q

    x, y = fd.SpatialCoordinate(mesh)
    w0 = fd.Function(W)
    u0, p0 = w0.split()
    p0.interpolate(fd.exp(-((x - 0.5)**2 + (y - 0.5)**2) / 0.5**2))
    dt = 0.01
    theta = 0.5
    alpha = 0.001
    M = 4
    c = fd.Constant(10)
    eps = fd.Constant(0.001)

    def form_function(uu, up, vu, vp):
        return (fd.div(vu) * up + c * fd.sqrt(fd.inner(uu, uu) + eps) *
                fd.inner(uu, vu) - fd.div(uu) * vp) * fd.dx

    def form_mass(uu, up, vu, vp):
        return (fd.inner(uu, vu) + up * vp) * fd.dx

    diagfft_options = {
        'ksp_type': 'gmres',
        'pc_type': 'lu',
        'ksp_monitor': None,
        'ksp_converged_reason': None,
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }

    solver_parameters_diag = {
        'snes_monitor': None,
        'snes_converged_reason': None,
        'mat_type': 'matfree',
        'ksp_rtol': 1.0e-10,
        'ksp_max_it': 6,
        'ksp_converged_reason': None,
        'pc_type': 'python',
        'pc_python_type': 'asQ.DiagFFTPC',
    }
    for i in range(M):
        solver_parameters_diag["diagfft_" + str(i) + "_"] = diagfft_options

    PD = asQ.paradiag(form_function=form_function,
                      form_mass=form_mass,
                      W=W,
                      w0=w0,
                      dt=dt,
                      theta=theta,
                      alpha=alpha,
                      M=M,
                      solver_parameters=solver_parameters_diag,
                      circ="quasi",
                      tol=1.0e-12,
                      maxits=1)
    PD.solve(verbose=True)

    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij',
        # 'snes_monitor':None,
        # 'snes_converged_reason':None,
    }
    PDe = asQ.paradiag(form_function=form_function,
                       form_mass=form_mass,
                       W=W,
                       w0=w0,
                       dt=dt,
                       theta=theta,
                       alpha=alpha,
                       M=M,
                       solver_parameters=solver_parameters,
                       circ="quasi",
                       tol=1.0e-12,
                       maxits=1)
    PDe.solve(verbose=True)

    # define functions
    un = fd.Function(W, name='full')
    unD = fd.Function(W, name='diag')
    err = fd.Function(W, name='error')
    # write initial conditions
    un.assign(w0)
    unD.assign(w0)
    # split
    pun = fd.Function(W, name='pun')
    punD = fd.Function(W, name='punD')
    puns = pun.split()
    punDs = punD.split()

    for i in range(M):
        walls = PD.w_all.split()[2 * i:2 * i + 2]
        wallsE = PDe.w_all.split()[2 * i:2 * i + 2]
        for k in range(2):
            puns[k].assign(walls[k])
            punDs[k].assign(wallsE[k])
        err.assign(punD - pun)
        print(fd.norm(err))
        assert (fd.norm(err) < 1.0e-15)
Exemple #2
0
def test_set_para_form_mixed():
    # checks that the all-at-once system is the same as solving
    # timesteps sequentially using the mixed wave equation as an
    # example by substituting the sequential solution and evaluating
    # the residual

    mesh = fd.PeriodicUnitSquareMesh(20, 20)
    V = fd.FunctionSpace(mesh, "BDM", 1)
    Q = fd.FunctionSpace(mesh, "DG", 0)
    W = V * Q

    x, y = fd.SpatialCoordinate(mesh)
    w0 = fd.Function(W)
    u0, p0 = w0.split()
    p0.interpolate(fd.exp(-((x - 0.5)**2 + (y - 0.5)**2) / 0.5**2))
    dt = 0.01
    theta = 0.5
    alpha = 0.001
    M = 4
    solver_parameters = {
        'ksp_type': 'gmres',
        'pc_type': 'none',
        'ksp_rtol': 1.0e-8,
        'ksp_atol': 1.0e-8,
        'ksp_monitor': None
    }

    def form_function(uu, up, vu, vp):
        return (fd.div(vu) * up - fd.div(uu) * vp) * fd.dx

    def form_mass(uu, up, vu, vp):
        return (fd.inner(uu, vu) + up * vp) * fd.dx

    PD = asQ.paradiag(form_function=form_function,
                      form_mass=form_mass,
                      W=W,
                      w0=w0,
                      dt=dt,
                      theta=theta,
                      alpha=alpha,
                      M=M,
                      solver_parameters=solver_parameters,
                      circ="none")

    # sequential solver
    un = fd.Function(W)
    unp1 = fd.Function(W)

    un.assign(w0)
    v = fd.TestFunction(W)

    eqn = (1.0 / dt) * form_mass(*(fd.split(unp1)), *(fd.split(v)))
    eqn -= (1.0 / dt) * form_mass(*(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(
        (1 - theta)) * form_function(*(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(theta) * form_function(*(fd.split(unp1)),
                                              *(fd.split(v)))

    sprob = fd.NonlinearVariationalProblem(eqn, unp1)
    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }
    ssolver = fd.NonlinearVariationalSolver(
        sprob, solver_parameters=solver_parameters)

    for i in range(M):
        ssolver.solve()
        for k in range(2):
            PD.w_all.sub(2 * i + k).assign(unp1.sub(k))
        un.assign(unp1)

    Pres = fd.assemble(PD.para_form)
    for i in range(M):
        assert (dt * np.abs(Pres.sub(i).dat.data[:]).max() < 1.0e-16)
Exemple #3
0
def test_periodic(dim, inner_t, use_extension, pytestconfig):
    verbose = pytestconfig.getoption("verbose")
    """ Test template for PeriodicControlSpace."""

    if dim == 2:
        mesh = fd.PeriodicUnitSquareMesh(30, 30)
    elif dim == 3:
        mesh = fd.PeriodicUnitCubeMesh(20, 20, 20)
    else:
        raise NotImplementedError

    Q = fs.FeControlSpace(mesh)

    inner = inner_t(Q)

    # levelset test case
    V = fd.FunctionSpace(Q.mesh_m, "DG", 0)
    sigma = fd.Function(V)
    if dim == 2:
        x, y = fd.SpatialCoordinate(Q.mesh_m)
        g = fd.sin(y * np.pi)  # truncate at bdry
        f = fd.cos(2 * np.pi * x) * g
        perturbation = 0.05 * fd.sin(x * np.pi) * g**2
        sigma.interpolate(g * fd.cos(2 * np.pi * x * (1 + perturbation)))
    elif dim == 3:
        x, y, z = fd.SpatialCoordinate(Q.mesh_m)
        g = fd.sin(y * np.pi) * fd.sin(z * np.pi)  # truncate at bdry
        f = fd.cos(2 * np.pi * x) * g
        perturbation = 0.05 * fd.sin(x * np.pi) * g**2
        sigma.interpolate(g * fd.cos(2 * np.pi * x * (1 + perturbation)))
    else:
        raise NotImplementedError

    class LevelsetFct(fs.ShapeObjective):
        def __init__(self, sigma, f, *args, **kwargs):
            super().__init__(*args, **kwargs)

            self.sigma = sigma  # initial
            self.f = f  # target
            Vdet = fd.FunctionSpace(Q.mesh_r, "DG", 0)
            self.detDT = fd.Function(Vdet)

        def value_form(self):
            # volume integral
            self.detDT.interpolate(fd.det(fd.grad(self.Q.T)))
            if min(self.detDT.vector()) > 0.05:
                integrand = (self.sigma - self.f)**2
            else:
                integrand = np.nan * (self.sigma - self.f)**2
            return integrand * fd.dx(metadata={"quadrature_degree": 1})

    # if running with -v or --verbose, then export the shapes
    if verbose:
        out = fd.File("sigma.pvd")

        def cb(*args):
            out.write(sigma)
    else:
        cb = None
    J = LevelsetFct(sigma, f, Q, cb=cb)

    if use_extension == "w_ext":
        ext = fs.ElasticityExtension(Q.V_r)
    if use_extension == "w_ext_fixed_dim":
        ext = fs.ElasticityExtension(Q.V_r, fixed_dims=[0])
    else:
        ext = None

    q = fs.ControlVector(Q, inner, boundary_extension=ext)
    """
    move mesh a bit to check that we are not doing the
    taylor test in T=id
    """
    g = q.clone()
    J.gradient(g, q, None)
    q.plus(g)
    J.update(q, None, 1)
    """ Start taylor test """
    J.gradient(g, q, None)
    res = J.checkGradient(q, g, 5, 1)
    errors = [l[-1] for l in res]
    assert (errors[-1] < 0.11 * errors[-2])
    q.scale(0)
    """ End taylor test """

    # ROL parameters
    grad_tol = 1e-4
    params_dict = {
        'Step': {
            'Type': 'Trust Region'
        },
        'General': {
            'Secant': {
                'Type': 'Limited-Memory BFGS',
                'Maximum Storage': 25
            }
        },
        'Status Test': {
            'Gradient Tolerance': grad_tol,
            'Step Tolerance': 1e-10,
            'Iteration Limit': 40
        }
    }

    # assemble and solve ROL optimization problem
    params = ROL.ParameterList(params_dict, "Parameters")
    problem = ROL.OptimizationProblem(J, q)
    solver = ROL.OptimizationSolver(problem, params)
    solver.solve()

    # verify that the norm of the gradient at optimum is small enough
    state = solver.getAlgorithmState()
    assert (state.gnorm < grad_tol)
Exemple #4
0
def test_diag_precon_mixed():
    # checks that the all-at-once system is the same as solving
    # timesteps sequentially using the mixed wave equation as an
    # example by substituting the sequential solution and evaluating
    # the residual

    mesh = fd.PeriodicUnitSquareMesh(20, 20)
    V = fd.FunctionSpace(mesh, "BDM", 1)
    Q = fd.FunctionSpace(mesh, "DG", 0)
    W = V * Q

    x, y = fd.SpatialCoordinate(mesh)
    w0 = fd.Function(W)
    u0, p0 = w0.split()
    p0.interpolate(fd.exp(-((x - 0.5)**2 + (y - 0.5)**2) / 0.5**2))
    dt = 0.01
    theta = 0.5
    alpha = 0.001
    M = 4

    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }

    def form_function(uu, up, vu, vp):
        return (fd.div(vu) * up - fd.div(uu) * vp) * fd.dx

    def form_mass(uu, up, vu, vp):
        return (fd.inner(uu, vu) + up * vp) * fd.dx

    diagfft_options = {
        'ksp_type': 'gmres',
        'pc_type': 'lu',
        'ksp_monitor': None,
        'ksp_converged_reason': None,
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }

    solver_parameters_diag = {
        'snes_type': 'ksponly',
        'mat_type': 'matfree',
        'ksp_type': 'preonly',
        'ksp_rtol': 1.0e-10,
        'ksp_converged_reason': None,
        'pc_type': 'python',
        'pc_python_type': 'asQ.DiagFFTPC',
    }
    for i in range(M):
        solver_parameters_diag["diagfft_" + str(i) + "_"] = diagfft_options

    PD = asQ.paradiag(form_function=form_function,
                      form_mass=form_mass,
                      W=W,
                      w0=w0,
                      dt=dt,
                      theta=theta,
                      alpha=alpha,
                      M=M,
                      solver_parameters=solver_parameters_diag,
                      circ="picard",
                      tol=1.0e-12)
    PD.solve(verbose=True)

    # sequential solver
    un = fd.Function(W)
    unp1 = fd.Function(W)

    un.assign(w0)
    v = fd.TestFunction(W)

    eqn = form_mass(*(fd.split(unp1)), *(fd.split(v)))
    eqn -= form_mass(*(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(dt * (1 - theta)) * form_function(
        *(fd.split(un)), *(fd.split(v)))
    eqn += fd.Constant(dt * theta) * form_function(*(fd.split(unp1)),
                                                   *(fd.split(v)))

    sprob = fd.NonlinearVariationalProblem(eqn, unp1)
    solver_parameters = {
        'ksp_type': 'preonly',
        'pc_type': 'lu',
        'pc_factor_mat_solver_type': 'mumps',
        'mat_type': 'aij'
    }
    ssolver = fd.NonlinearVariationalSolver(
        sprob, solver_parameters=solver_parameters)
    ssolver.solve()

    err = fd.Function(W, name="err")
    pun = fd.Function(W, name="pun")
    puns = pun.split()
    for i in range(M):
        ssolver.solve()
        un.assign(unp1)
        walls = PD.w_all.split()[2 * i:2 * i + 2]
        for k in range(2):
            puns[k].assign(walls[k])
        err.assign(un - pun)
        assert (fd.norm(err) < 1.0e-15)
Exemple #5
0
def test_rotating_bump(scheme):
    start = 16
    finish = 3 * start
    incr = 4
    num_points = np.array(list(range(start, finish + incr, incr)))
    errors = np.zeros_like(num_points, dtype=np.float64)

    for k, nx in enumerate(num_points):
        mesh = firedrake.PeriodicUnitSquareMesh(nx, nx, diagonal='crossed')
        degree = 1
        Q = firedrake.FunctionSpace(mesh, 'DG', degree)

        # The velocity field is uniform solid-body rotation about the
        # center of a square
        x = firedrake.SpatialCoordinate(mesh)
        y = Constant((0.5, 0.5))
        w = x - y
        u = as_vector((-w[1], +w[0]))

        # There are no sources
        s = Constant(0.0)

        origin = Constant((1 / 2, 1 / 2))
        delta = Constant((1 / 6, 1 / 6))
        z_0 = Constant(origin - delta)
        r = Constant(1 / 6)
        expr_0 = max_value(0, 1 - inner(x - z_0, x - z_0) / r**2)

        θ = 4 * π / 3
        min_diameter = mesh.cell_sizes.dat.data_ro[:].min()
        max_speed = 1 / np.sqrt(2)
        # Choose a timestep that will satisfy the CFL condition
        multiplier = multipliers[scheme]
        timestep = multiplier * min_diameter / max_speed / (2 * degree + 1)
        num_steps = int(θ / timestep)
        dt = θ / num_steps

        q_0 = firedrake.project(expr_0, Q)
        equation = plumes.models.advection.make_equation(u, s)
        parameters = {
            'solver_parameters': {
                'snes_type': 'ksponly',
                'ksp_type': 'preonly',
                'pc_type': 'ilu',
                'sub_pc_type': 'bjacobi'
            }
        }
        integrator = scheme(equation, q_0, **parameters)

        for step in range(num_steps):
            integrator.step(dt)

        # Compute the exact solution
        R = as_tensor([[np.cos(θ), -np.sin(θ)], [np.sin(θ), np.cos(θ)]])
        z_1 = firedrake.dot(R, z_0 - origin) + origin
        expr_1 = max_value(0, 1 - inner(x - z_1, x - z_1) / r**2)

        q = integrator.state
        errors[k] = assemble(abs(q - expr_1) * dx) / assemble(abs(expr_1) * dx)

    slope, intercept = np.polyfit(np.log2(1 / num_points), np.log2(errors), 1)
    print(f'log(error) ~= {slope:5.3f} * log(dx) {intercept:+5.3f}')
    assert slope > degree - 0.95