def get_error(wh, mms=mms_data): # We look at the H1 error for velocity u3, u1, p = mms.solution u3h, u1h, ph = wh # X = ph.function_space() # bcs = DirichletBC(X, Constant(0), 'on_boundary').get_boundary_values().keys() # print np.linalg.norm(ph.vector().get_local()[bcs], np.inf) # Passing the HsNorm from preconditioner so that we don't compute # eigenvalues twice try: Hs = mms.normals.pop() except IndexError: Hs = HsNorm(ph.function_space(), s=-0.5) # e*H*e ie (e, e)_H e = interpolate(p, ph.function_space()).vector() e.axpy(-1, ph.vector()) e = np.sqrt(e.inner(Hs*e)) # On big meshes constructing the error for interpolation space # is expensive so wi reduce order then degree_rise = 1 if u3h.function_space().dim() < 2E6 else 0 # NOTE: the error is interpolated to P2 disc, or P1 disc return (H1_norm(u3, u3h, degree_rise=degree_rise), H1_norm(u1, u1h), e, L2_norm(p, ph))
def cannonical_inner_product(W, mms, params, AA): '''Inner product of alpha*H1 x beta*H1 x H-0.5''' V3, V1, Q = W # Extact Vi norms from system V3_inner = AA[0][0] V1_inner = AA[1][1] Q_inner = matrix_fromHs(HsNorm(Q, s=-0.5)) B = block_diag_mat([V3_inner, V1_inner, Q_inner]) return B
def norm(u, uh, s=s): V = uh.function_space() # I compute it as (u-uh).Hs*(u-uh) Hs = matrix_fromHs(HsNorm(V, s)) e = interpolate(u, V).vector() e.axpy(-1, uh.vector()) # u - uh # Alloc for matvec Hs_e = e.copy() Hs.mult(e, Hs_e) return sqrt(e.inner(Hs_e))
def cannonical_riesz_map(W, mms, params, AA): '''Riesz map wrt. inner product of alpha*H1 x beta*H1 x H-0.5''' V3, V1, Q = W # Extact Vi norms from system V3_inner = AA[0][0] V1_inner = AA[1][1] Q_inner = HsNorm(Q, s=-0.5) mms.normals.append(Q_inner) B = block_diag_mat([AMG(V3_inner), AMG(V1_inner), Q_inner**-1]) return B
def cannonical_riesz_map_AMG(W, mms, params): '''AMG inverse''' V1, V, Q = W kappa = Constant(params.kappa) # Outer, H1_0 u, v = TrialFunction(V1), TestFunction(V1) outer_mesh = V1.mesh() subdomains = mms.subdomains[0] # facet_f = MeshFunction('size_t', outer_mesh, outer_mesh.topology().dim() - 1, 0) [ subd.mark(facet_f, i) for i, subd in enumerate(map(CompiledSubDomain, subdomains), 1) ] bcs = [ DirichletBC(V1, Constant(0), facet_f, i) for i in range(1, 1 + len(subdomains)) ] V1_norm, _ = assemble_system( inner(grad(u), grad(v)) * dx, inner(Constant(0), v) * dx, bcs) # Inner u, v = TrialFunction(V), TestFunction(V) V_norm = assemble(inner(grad(u), grad(v)) * dx + inner(u, v) * dx) # Multiplier on the boundary # Fractional part Hs = HsNorm(Q, s=[(1, -0.5), (params.eps, 0.0)]) Hs = Hs**-1 # L2 part # epsilon = Constant(params.eps) # p, q = TrialFunction(Q), TestFunction(Q) # m = epsilon*inner(p, q)*dx # M = assemble(m) # Q_norm = mat_add(Hs, M) # return block_diag_mat([V1_norm, V_norm, Q_norm]) return block_diag_mat([AMG(V1_norm), AMG(V_norm), Hs])
def cannonical_inner_product(W, mms, params): '''H1 x H1 x H^{-1/2} cap L^2''' V1, V, Q = W kappa = Constant(params.kappa) # Outer, H1_0 u, v = TrialFunction(V1), TestFunction(V1) outer_mesh = V1.mesh() subdomains = mms.subdomains[0] # facet_f = MeshFunction('size_t', outer_mesh, outer_mesh.topology().dim() - 1, 0) [ subd.mark(facet_f, i) for i, subd in enumerate(map(CompiledSubDomain, subdomains), 1) ] bcs = [ DirichletBC(V1, Constant(0), facet_f, i) for i in range(1, 1 + len(subdomains)) ] V1_norm, _ = assemble_system( inner(grad(u), grad(v)) * dx, inner(Constant(0), v) * dx, bcs) # Inner u, v = TrialFunction(V), TestFunction(V) V_norm = assemble(inner(grad(u), grad(v)) * dx + inner(u, v) * dx) # Multiplier on the boundary # Fractional part Hs = matrix_fromHs(HsNorm(Q, s=-0.5)) # L2 part epsilon = Constant(params.eps) p, q = TrialFunction(Q), TestFunction(Q) m = epsilon * inner(p, q) * dx M = assemble(m) Q_norm = mat_add(Hs, M) return block_diag_mat([V1_norm, V_norm, Q_norm])
def get_error(wh, subdomains=subdomains, ifaces=ifaces, exact=exact, normals=mms_data.normals[0]): sigmah, uh, ph = wh print 'Mean ph', assemble(ph * dx) sigma_exact, u_exact, p_exact, I_exact = exact # Compute Hs norm on finer space Q = ph.function_space() Q = FunctionSpace(Q.mesh(), 'CG', 1) Hs = matrix_fromHs(HsNorm(Q, s=0.5)) # Use interpolated ph = interpolate(ph, Q) return (broken_norm(Hdiv_norm, subdomains[:])(sigma_exact[:], sigmah), broken_norm(L2_norm, subdomains[:])(u_exact[:], uh), L2_norm(p_exact, ph))
def get_error(wh, mms=mms_data): # We look at the H1 error for velocity u3, u1, p = mms.solution u3h, u1h, ph = wh # On a finer mesh Q = FunctionSpace(ph.function_space().mesh(), 'CG', 3) Hs = HsNorm(Q, s=-0.5) # A U = M U Lambda # Hs = M * U * Lambda^{-0.5} * (M*U).T # e*H*e ie (e, e)_H e = interpolate(p, Q).vector() e.axpy(-1, interpolate(ph, Q).vector()) e = np.sqrt(e.inner(Hs * e)) # On big meshes constructing the error for interpolation space # is expensive so wi reduce order then degree_rise = 1 if u3h.function_space().dim() < 2E6 else 0 # NOTE: the error is interpolated to P2 disc, or P1 disc return (H1_norm(u3, u3h, degree_rise=degree_rise), H1_norm(u1, u1h), e, L2_norm(p, ph))
def setup_preconditioner(W, which, eps=None): ''' This is a block diagonal preconditioner based on H1 x H-0.5 or (H1 \cap H0.5) x L2 ''' from block.algebraic.petsc import AMG from block.algebraic.petsc import LumpedInvDiag from hsmg.hseig import HsNorm V, Q = W if which == 0: print 'Using H1 x H-0.5 preconditioner' # H1 u, v = TrialFunction(V), TestFunction(V) b00 = inner(grad(u), grad(v))*dx + inner(u, v)*dx # Inverted by BoomerAMG B00 = AMG(ii_assemble(b00)) # The Q norm via spectral B11 = inverse(HsNorm(Q, s=-0.5)) # The norm is inverted exactly else: print 'Using (H1 \cap H0.5) x L2 preconditioner' bdry = Q.mesh() dxGamma = dx(domain=bdry) # Cap space u, v = TrialFunction(V), TestFunction(V) Tu, Tv = Trace(u, bdry), Trace(v, bdry) b00 = inner(grad(u), grad(v))*dx + inner(u, v)*dx + inner(Tu, Tv)*dxGamma # Inverted by BoomrAMG B00 = AMG(ii_convert(ii_assemble(b00))) # We don't have to work so hard for multiplier p, q = TrialFunction(Q), TestFunction(Q) B11 = LumpedInvDiag(ii_assemble(inner(p, q)*dx)) return block_diag_mat([B00, B11])
def cannonical_riesz_map_AMG(W, mms, params, AA): '''Approx Riesz map w.r.t to Hdiv x L2 x H^s''' V, Q, Y = W kappa1 = Constant(params.kappa) # Hdiv norm with piecewise conductivities mesh = V.mesh() cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) # Mark [ CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag) for tag, subd in enumerate(mms.subdomains[2]) ] # 0 is outside and that is where we have kappa sigma, tau = TrialFunction(V), TestFunction(V) dX = Measure('dx', subdomain_data=cell_f) V_norm = assemble((1. / kappa1) * inner(sigma, tau) * dX(0) + inner(sigma, tau) * dX(1) + inner(div(sigma), div(tau)) * dX) p, q = TrialFunction(Q), TestFunction(Q) Q_norm = assemble(inner(p, q) * dx) # Multiplier on the boundary epsilon = Constant(params.eps) # Fractional part Hs = HsNorm(Y, s=[(1, 0.5), (1. / params.eps, 0.)]) # Weight Hs = Hs**-1 # L2 part #p, q = TrialFunction(Y), TestFunction(Y) #m = (1./epsilon)*inner(p, q)*dx #M = assemble(m) #Y_norm = mat_add(Hs, M) return block_diag_mat([HypreAMS(A=V_norm, V=V), LU(Q_norm), Hs])
def cannonical_inner_product(W, mms, params): '''Inner product of Hdiv x L2 x H^s''' V, Q, Y = W kappa1 = Constant(params.kappa) # Hdiv norm with piecewise conductivities mesh = V.mesh() cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) # Mark [ CompiledSubDomain(subd, tol=1E-10).mark(cell_f, tag) for tag, subd in enumerate(mms.subdomains[2]) ] # 0 is outside and that is where we have kappa sigma, tau = TrialFunction(V), TestFunction(V) dX = Measure('dx', subdomain_data=cell_f) V_norm = assemble((1. / kappa1) * inner(sigma, tau) * dX(0) + inner(sigma, tau) * dX(1) + inner(div(sigma), div(tau)) * dX) p, q = TrialFunction(Q), TestFunction(Q) Q_norm = assemble(inner(p, q) * dx) # Multiplier on the boundary epsilon = Constant(params.eps) # Fractional part Hs = matrix_fromHs(HsNorm(Y, s=0.5)) # Weight # L2 part p, q = TrialFunction(Y), TestFunction(Y) m = (1. / epsilon) * inner(p, q) * dx M = assemble(m) Y_norm = mat_add(Hs, M) return block_diag_mat([V_norm, Q_norm, Y_norm])
def nonlinear_babuska(N, u_exact, p_exact): '''MMS for the problem''' mesh = UnitSquareMesh(N, N) bmesh = BoundaryMesh(mesh, 'exterior') V = FunctionSpace(mesh, 'CG', 1) Q = FunctionSpace(bmesh, 'CG', 1) W = (V, Q) up = ii_Function(W) u, p = up # Split v, q = list(map(TestFunction, W)) Tu, Tv = (Trace(x, bmesh) for x in (u, v)) dxGamma = Measure('dx', domain=bmesh) # Nonlinearity nl = lambda u: (Constant(2) + u)**2 f_exact = -div(nl(u) * grad(u)) g_exact = u f = interpolate(Expression(f_exact, subs={u: u_exact}, degree=1), V) h = interpolate(Expression(g_exact, subs={u: u_exact}, degree=4), Q) # The nonlinear functional F = [ inner(nl(u) * grad(u), grad(v)) * dx + inner(p, Tv) * dxGamma - inner(f, v) * dx, inner(Tu, q) * dxGamma - inner(h, q) * dxGamma ] dF = block_jacobian(F, up) # Setup H1 x H-0.5 preconditioner only once B0 = ii_derivative(inner(grad(u), grad(v)) * dx + inner(u, v) * dx, u) # The Q norm via spectral B1 = inverse(HsNorm(Q, s=-0.5)) # The norm is inverted exactly # Preconditioner B = block_diag_mat([AMG(ii_assemble(B0)), B1]) # Newton eps = 1.0 tol = 1.0E-10 niter = 0. maxiter = 25 OptDB = PETSc.Options() # Since later b gets very small making relative too much work OptDB.setValue('ksp_atol', 1E-6) OptDB.setValue('ksp_monitor_true_residual', None) dup = ii_Function(W) x_vec = as_backend_type(dup.vector()).vec() n_kspiters = [] while eps > tol and niter < maxiter: niter += 1. A, b = (ii_assemble(x) for x in (dF, F)) ksp = PETSc.KSP().create() ksp.setType('minres') ksp.setNormType(PETSc.KSP.NormType.NORM_PRECONDITIONED) ksp.setOperators(ii_PETScOperator(A)) ksp.setPC(ii_PETScPreconditioner(B, ksp)) ksp.setFromOptions() ksp.solve(as_petsc_nest(b), x_vec) niters = ksp.getIterationNumber() + 1 n_kspiters.append(niters) eps = sqrt(sum(x.norm('l2')**2 for x in dup.vectors())) print('\t%d |du| = %g | niters %d' % (niter, eps, niters)) # FIXME: Update for i in range(len(W)): up[i].vector().axpy(-1, dup[i].vector()) return up, n_kspiters