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)
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)
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)
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)
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