def get_poisson_steps(pts, cells, tol): # Still can't initialize a mesh from points, cells filename = "mesh.xdmf" if cells.shape[1] == 3: meshio.write_points_cells(filename, pts, {"triangle": cells}) else: assert cells.shape[1] == 4 meshio.write_points_cells(filename, pts, {"tetra": cells}) mesh = Mesh() with XDMFFile(filename) as f: f.read(mesh) os.remove(filename) os.remove("mesh.h5") # build Laplace matrix with Dirichlet boundary using dolfin V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx u0 = Constant(0.0) bc = DirichletBC(V, u0, "on_boundary") f = Constant(1.0) L = f * v * dx A = assemble(a) b = assemble(L) bc.apply(A, b) # solve(A, x, b, "cg") solver = KrylovSolver("cg", "none") solver.parameters["absolute_tolerance"] = 0.0 solver.parameters["relative_tolerance"] = tol x = Function(V) x_vec = x.vector() num_steps = solver.solve(A, x_vec, b) # # convert to scipy matrix # A = as_backend_type(A).mat() # ai, aj, av = A.getValuesCSR() # A = scipy.sparse.csr_matrix( # (av, aj, ai), shape=(A.getLocalSize()[0], A.getSize()[1]) # ) # # ev = eigvals(A.todense()) # ev_max = scipy.sparse.linalg.eigs(A, k=1, which="LM")[0][0] # assert numpy.abs(ev_max.imag) < 1.0e-15 # ev_max = ev_max.real # ev_min = scipy.sparse.linalg.eigs(A, k=1, which="SM")[0][0] # assert numpy.abs(ev_min.imag) < 1.0e-15 # ev_min = ev_min.real # cond = ev_max / ev_min # solve poisson system, count num steps # b = numpy.ones(A.shape[0]) # out = pykry.gmres(A, b) # num_steps = len(out.resnorms) return num_steps
def cyclic3D(u): """ Symmetrize with respect to (xyz) cycle. """ try: nrm = np.linalg.norm(u.vector()) V = u.function_space() assert V.mesh().topology().dim() == 3 mesh1 = Mesh(V.mesh()) mesh1.coordinates()[:, :] = mesh1.coordinates()[:, [1, 2, 0]] W1 = FunctionSpace(mesh1, 'CG', 1) # testing if symmetric bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) test = interpolate(Function(W1, test.vector()), V) assert max(test.vector()) - min(test.vector()) < 1.1 v1 = interpolate(Function(W1, u.vector()), V) mesh2 = Mesh(mesh1) mesh2.coordinates()[:, :] = mesh2.coordinates()[:, [1, 2, 0]] W2 = FunctionSpace(mesh2, 'CG', 1) v2 = interpolate(Function(W2, u.vector()), V) pr = project(u+v1+v2) assert np.linalg.norm(pr.vector())/nrm > 0.01 return pr except: print "Cyclic symmetrization failed!" return u
class StreamFunction(Field): def before_first_compute(self, get): u = get("Velocity") assert len(u) == 2, "Can only compute stream function for 2D problems" V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() V = spaces.get_space(degree, 0) psi = TrialFunction(V) self.q = TestFunction(V) a = dot(grad(psi), grad(self.q)) * dx() self.bc = DirichletBC(V, Constant(0), DomainBoundary()) self.A = assemble(a) self.L = Vector() self.bc.apply(self.A) self.solver = KrylovSolver(self.A, "cg") self.psi = Function(V) def compute(self, get): u = get("Velocity") assemble(dot(u[1].dx(0) - u[0].dx(1), self.q) * dx(), tensor=self.L) self.bc.apply(self.L) self.solver.solve(self.psi.vector(), self.L) #solve(self.A, self.psi.vector(), self.L) return self.psi
class StreamFunction(Field): def before_first_compute(self, get): u = get("Velocity") assert len(u) == 2, "Can only compute stream function for 2D problems" V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() V = spaces.get_space(degree, 0) psi = TrialFunction(V) self.q = TestFunction(V) a = dot(grad(psi), grad(self.q))*dx() self.bc = DirichletBC(V, Constant(0), DomainBoundary()) self.A = assemble(a) self.L = Vector() self.bc.apply(self.A) self.solver = KrylovSolver(self.A, "cg") self.psi = Function(V) def compute(self, get): u = get("Velocity") assemble(dot(u[1].dx(0)-u[0].dx(1), self.q)*dx(), tensor=self.L) self.bc.apply(self.L) self.solver.solve(self.psi.vector(), self.L) #solve(self.A, self.psi.vector(), self.L) return self.psi
def cyclic3D(u): """ Symmetrize with respect to (xyz) cycle. """ try: nrm = np.linalg.norm(u.vector()) V = u.function_space() assert V.mesh().topology().dim() == 3 mesh1 = Mesh(V.mesh()) mesh1.coordinates()[:, :] = mesh1.coordinates()[:, [1, 2, 0]] W1 = FunctionSpace(mesh1, 'CG', 1) # testing if symmetric bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) test = interpolate(Function(W1, test.vector()), V) assert max(test.vector()) - min(test.vector()) < 1.1 v1 = interpolate(Function(W1, u.vector()), V) mesh2 = Mesh(mesh1) mesh2.coordinates()[:, :] = mesh2.coordinates()[:, [1, 2, 0]] W2 = FunctionSpace(mesh2, 'CG', 1) v2 = interpolate(Function(W2, u.vector()), V) pr = project(u + v1 + v2) assert np.linalg.norm(pr.vector()) / nrm > 0.01 return pr except: print "Cyclic symmetrization failed!" return u
def assert_solves( mesh: Mesh, diffusion: Coefficient, convection: Optional[Coefficient], reaction: Optional[Coefficient], source: Coefficient, exact: Coefficient, l2_tol: Optional[float] = 1.0e-8, h1_tol: Optional[float] = 1.0e-6, ): eafe_matrix = eafe_assemble(mesh, diffusion, convection, reaction) pw_linears = FunctionSpace(mesh, "Lagrange", 1) test_function = TestFunction(pw_linears) rhs_vector = assemble(source * test_function * dx) bc = DirichletBC(pw_linears, exact, lambda _, on_bndry: on_bndry) bc.apply(eafe_matrix, rhs_vector) solution = Function(pw_linears) solver = LUSolver(eafe_matrix, "default") solver.parameters["symmetric"] = False solver.solve(solution.vector(), rhs_vector) l2_err: float = errornorm(exact, solution, "l2", 3) assert l2_err <= l2_tol, f"L2 error too large: {l2_err} > {l2_tol}" h1_err: float = errornorm(exact, solution, "H1", 3) assert h1_err <= h1_tol, f"H1 error too large: {h1_err} > {h1_tol}"
class Heat(object): ''' u' = \\Delta u + f ''' def __init__(self, V): self.sol = Expression(sympy.printing.ccode(solution), degree=MAX_DEGREE, t=0.0, cell=triangle) self.V = V u = TrialFunction(V) v = TestFunction(V) self.M = assemble(u * v * dx) n = FacetNormal(self.V.mesh()) self.A = assemble(-inner(kappa * grad(u), grad(v / (rho * cp))) * dx + inner(kappa * grad(u), n) * v / (rho * cp) * ds) self.bcs = DirichletBC(self.V, self.sol, 'on_boundary') return def eval_alpha_M_beta_F(self, alpha, beta, u, t): # Evaluate alpha * M * u + beta * F(u, t). uvec = u.vector() v = TestFunction(self.V) f.t = t b = assemble(f * v / (rho * cp) * dx) out = Function(self.V) out.vector()[:] = \ alpha * (self.M * uvec) + beta * (self.A * uvec + b) return out def solve_alpha_M_beta_F(self, alpha, beta, b, t): # Solve alpha * M * u + beta * F(u, t) = b for u. A = alpha * self.M + beta * self.A f.t = t v = TestFunction(self.V) b2 = f / (rho * cp) rhs = assemble((b - beta * b2) * v * dx) self.bcs.apply(A, rhs) solver = \ KrylovSolver('gmres', 'ilu') if alpha < 0.0 or beta > 0.0 \ else KrylovSolver('cg', 'amg') solver.parameters['relative_tolerance'] = 1.0e-13 solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = False solver.set_operator(A) u = Function(self.V) solver.solve(u.vector(), rhs) return u
class Bratu(object): def __init__(self): self.mesh = UnitSquareMesh(40, 40, "left/right") self.V = FunctionSpace(self.mesh, "Lagrange", 1) self.bc = DirichletBC(self.V, 0.0, "on_boundary") u = TrialFunction(self.V) v = TestFunction(self.V) self.a = assemble(dot(grad(u), grad(v)) * dx) self.m = assemble(u * v * dx) def inner(self, a, b): return a.inner(self.m * b) def norm2_r(self, a): return a.inner(a) def f(self, u, lmbda): v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u out = self.a * u - lmbda * assemble(exp(ufun) * v * dx) DirichletBC(self.V, ufun, "on_boundary").apply(out) return out def df_dlmbda(self, u, lmbda): v = TestFunction(self.V) ufun = Function(self.V) ufun.vector()[:] = u out = -assemble(exp(ufun) * v * dx) self.bc.apply(out) return out def jacobian_solver(self, u, lmbda, rhs): t = TrialFunction(self.V) v = TestFunction(self.V) # from dolfin import Constant # a = assemble( # dot(grad(t), grad(v)) * dx - Constant(lmbda) * exp(u) * t * v * dx # ) ufun = Function(self.V) ufun.vector()[:] = u a = self.a - lmbda * assemble(exp(ufun) * t * v * dx) self.bc.apply(a) x = Function(self.V) # solve(a, x.vector(), rhs, "gmres", "ilu") solve(a, x.vector(), rhs) return x.vector()
def symmetrize(u, d, sym): """ Symmetrize function u. """ if len(d) == 3: # three dimensions -> cycle XYZ return cyclic3D(u) elif len(d) >= 4: # four dimensions -> rotations in 2D return rotational(u, d[-1]) nrm = np.linalg.norm(u.vector()) V = u.function_space() mesh = Mesh(V.mesh()) # test if domain is symmetric using function equal 0 inside, 1 on boundary # extrapolation will force large values if not symmetric since the flipped # domain is different bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) if len(d) == 2: # two dimensions given: swap dimensions mesh.coordinates()[:, d] = mesh.coordinates()[:, d[::-1]] else: # one dimension given: reflect mesh.coordinates()[:, d[0]] *= -1 # FIXME functionspace takes a long time to construct, maybe copy? W = FunctionSpace(mesh, 'CG', 1) try: # testing test = interpolate(Function(W, test.vector()), V) # max-min should be around 1 if domain was symmetric # may be slightly above due to boundary approximation assert max(test.vector()) - min(test.vector()) < 1.1 v = interpolate(Function(W, u.vector()), V) if sym: # symmetric pr = project(u+v) else: # antisymmetric pr = project(u-v) # small solution norm most likely means that symmetrization gives # trivial function assert np.linalg.norm(pr.vector())/nrm > 0.01 return pr except: # symmetrization failed for some reason print "Symmetrization " + str(d) + " failed!" return u
def symmetrize(u, d, sym): """ Symmetrize function u. """ if len(d) == 3: # three dimensions -> cycle XYZ return cyclic3D(u) elif len(d) >= 4: # four dimensions -> rotations in 2D return rotational(u, d[-1]) nrm = np.linalg.norm(u.vector()) V = u.function_space() mesh = Mesh(V.mesh()) # test if domain is symmetric using function equal 0 inside, 1 on boundary # extrapolation will force large values if not symmetric since the flipped # domain is different bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) if len(d) == 2: # two dimensions given: swap dimensions mesh.coordinates()[:, d] = mesh.coordinates()[:, d[::-1]] else: # one dimension given: reflect mesh.coordinates()[:, d[0]] *= -1 # FIXME functionspace takes a long time to construct, maybe copy? W = FunctionSpace(mesh, 'CG', 1) try: # testing test = interpolate(Function(W, test.vector()), V) # max-min should be around 1 if domain was symmetric # may be slightly above due to boundary approximation assert max(test.vector()) - min(test.vector()) < 1.1 v = interpolate(Function(W, u.vector()), V) if sym: # symmetric pr = project(u + v) else: # antisymmetric pr = project(u - v) # small solution norm most likely means that symmetrization gives # trivial function assert np.linalg.norm(pr.vector()) / nrm > 0.01 return pr except: # symmetrization failed for some reason print "Symmetrization " + str(d) + " failed!" return u
def solve(self, L, a, plate_potential): A = assemble(a) b = assemble(L) # print(' assembled') dirichlet_bc = DirichletBC(self.V, plate_potential, (lambda x, on_boundary: on_boundary and x[2] < self.GROUNDED_PLATE_AT)) dirichlet_bc.apply(A, b) # print(' modified') f = self.function() self.solver.solve(A, f.vector(), b) # print(' solved') return f
def dolfin_comparasion(Nx, Ny, f): from dolfin import (UnitSquareMesh, FunctionSpace, TrialFunction, TestFunction, assemble, inner, grad, dx, SpatialCoordinate, DirichletBC, Function, solve, pi, CellType, sin, cos) mesh = UnitSquareMesh.create(Nx, Ny, CellType.Type.quadrilateral) V = FunctionSpace(mesh, "CG", 1) u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx A_dol = assemble(a) x, y = SpatialCoordinate(mesh) f = eval(f) l_ = inner(f, v) * dx B_dol = assemble(l_) bc = DirichletBC(V, 0, "on_boundary") bc.apply(A_dol, B_dol) u_h = Function(V) solve(A_dol, u_h.vector(), B_dol) return u_h, assemble(u_h * dx)
def initial_solution(self, mode_number): main_boundary = self.outsides left_boundary = self.left_outsides right_boundary = self.right_outsides KK = self.K bc = DirichletBC(self.V, Constant(0.), main_boundary) bc.apply(KK) solver = standard_solver(KK, self.M) solver.solve(10) KK1 = self.K1 bc1 = DirichletBC(self.V1, Constant(0.), left_boundary) bc1.apply(KK1) solver1 = standard_solver(KK1, self.M1) solver1.solve(10) KK2 = self.K2 bc2 = DirichletBC(self.V2, Constant(0.), right_boundary) bc2.apply(KK2) solver2 = standard_solver(KK2, self.M2) solver2.solve(10) r, _, rx, _ = solver.get_eigenpair(mode_number) r1, _, rx1, _ = solver1.get_eigenpair(mode_number) r2, _, rx2, _ = solver2.get_eigenpair(mode_number) freqs = [r, r1, r2] vecs = [rx, rx1, rx2] return freqs, vecs
def _modify_linear_equation(self, x, y, z): dx_src = f'(x[0] - {x})' dy_src = f'(x[1] - {y})' dz_src = f'(x[2] - {z})' r_src2 = f'({dx_src} * {dx_src} + {dy_src} * {dy_src} + {dz_src} * {dz_src})' r_src = f'sqrt({r_src2})' conductivity = self.base_conductivity(x, y, z) minus_potential_exp = Expression(f''' {-0.25 / np.pi / conductivity} / {r_src} ''', degree=self.degree, domain=self._fm._mesh) dirichlet_bc = DirichletBC(self._fm.function_space, minus_potential_exp, (lambda x, on_boundary: on_boundary and x[2] < self.grounded_plate_edge_z)) logger.debug('Applying the "plate" Dirichlet BC') dirichlet_bc.apply(self._terms_with_unknown, self._known_terms) logger.debug('Done.')
class Heat(object): ''' u' = \\Delta u + f ''' def __init__(self, V): self.V = V u = TrialFunction(V) v = TestFunction(V) self.M = assemble(u * v * dx) self.A = assemble(-dot(grad(u), grad(v)) * dx) self.b = assemble(1.0 * v * dx) self.bcs = DirichletBC(self.V, 0.0, 'on_boundary') return # pylint: disable=unused-argument def eval_alpha_M_beta_F(self, alpha, beta, u, t): # Evaluate alpha * M * u + beta * F(u, t). uvec = u.vector() return alpha * (self.M * uvec) + beta * (self.A * uvec + self.b) def solve_alpha_M_beta_F(self, alpha, beta, b, t): # Solve alpha * M * u + beta * F(u, t) = b for u. A = alpha * self.M + beta * self.A rhs = b - beta * self.b self.bcs.apply(A, rhs) solver = KrylovSolver('gmres', 'ilu') solver.parameters['relative_tolerance'] = 1.0e-13 solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['maximum_iterations'] = 100 solver.parameters['monitor_convergence'] = True solver.set_operator(A) u = Function(self.V) solver.solve(u.vector(), rhs) return u
def solve(self): """ Find eigenvalues for transformed mesh. """ self.progress("Building mesh.") # build transformed mesh mesh = self.refineMesh() # dim = mesh.topology().dim() if self.bcLast: mesh = transform_mesh(mesh, self.transformList) Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) else: Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) mesh = transform_mesh(mesh, self.transformList) # boundary conditions computed on non-transformed mesh # copy the values to transformed mesh fun = FacetFunction("size_t", mesh, shift) fun.array()[:] = bcs.array()[:] bcs = fun ds = Measure('ds', domain=mesh, subdomain_data=bcs) V = FunctionSpace(mesh, self.method, self.deg) u = TrialFunction(V) v = TestFunction(V) self.progress("Assembling matrices.") wTop = Expression(self.wTop, degree=self.deg) wBottom = Expression(self.wBottom, degree=self.deg) # # build stiffness matrix form # s = dot(grad(u), grad(v))*wTop*dx # add Robin parts for bc in Robin: s += Constant(bc.parValue)*u*v*wTop*ds(bc.value+shift) # # build mass matrix form # if len(Steklov) > 0: m = 0 for bc in Steklov: m += Constant(bc.parValue)*u*v*wBottom*ds(bc.value+shift) else: m = u*v*wBottom*dx # assemble # if USE_EIGEN: # S, M = EigenMatrix(), EigenMatrix() # tempv = EigenVector() # else: S, M = PETScMatrix(), PETScMatrix() # tempv = PETScVector() if not np.any(bcs.array() == shift+1): # no Dirichlet parts assemble(s, tensor=S) assemble(m, tensor=M) else: # # with EIGEN we could # apply Dirichlet condition symmetrically # completely remove rows and columns # # Dirichlet parts are marked with shift+1 # # temp = Constant(0)*v*dx bc = DirichletBC(V, Constant(0.0), bcs, shift+1) # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv) # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv) assemble(s, tensor=S) bc.apply(S) assemble(m, tensor=M) # bc.zero(M) # if USE_EIGEN: # M = M.sparray() # M.eliminate_zeros() # print M.shape # indices = M.indptr[:-1] - M.indptr[1:] < 0 # M = M[indices, :].tocsc()[:, indices] # S = S.sparray()[indices, :].tocsc()[:, indices] # print M.shape # # solve the eigenvalue problem # self.progress("Solving eigenvalue problem.") eigensolver = SLEPcEigenSolver(S, M) eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["solver"] = "krylov-schur" if self.target is not None: eigensolver.parameters["spectrum"] = "target real" eigensolver.parameters["spectral_shift"] = self.target else: eigensolver.parameters["spectrum"] = "smallest magnitude" eigensolver.parameters["spectral_shift"] = -0.01 eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.solve(self.number) self.progress("Generating eigenfunctions.") if eigensolver.get_number_converged() == 0: return None eigf = [] eigv = [] if self.deg > 1: mesh = refine(mesh) W = FunctionSpace(mesh, 'CG', 1) for i in range(eigensolver.get_number_converged()): pair = eigensolver.get_eigenpair(i)[::2] eigv.append(pair[0]) u = Function(V) u.vector()[:] = pair[1] eigf.append(interpolate(u, W)) return eigv, eigf
def schwarz_algorithm(self, max_iterations, mode_number): left_robin = self.left_robin left_dirichlet = self.left_outsides right_robin = self.right_robin right_dirichlet = self.right_outsides self.build_transfer_matrices() B1 = self.B1 BO1 = self.BO1 B2 = self.B2 BO2 = self.BO2 V1 = self.V1 V2 = self.V2 VO = self.VO freqs, vecs = self.initial_solution(mode_number) r1 = freqs[1] r2 = freqs[2] M1 = self.M1 M2 = self.M2 rx1 = vecs[1] rx2 = vecs[2] if abs(rx1.max()) < abs(rx1.min()): rx1 = self.adjustment * rx1 / (rx1.min()) else: rx1 = self.adjustment * rx1 / (rx1.max()) if abs(rx2.max()) < abs(rx2.min()): rx2 = self.adjustment * rx2 / (rx2.min()) else: rx2 = self.adjustment * rx2 / (rx2.max()) iter = 0 L2_error = np.zeros((max_iterations + 1, 1)) H1_error = np.zeros((max_iterations + 1, 1)) SH_error = np.zeros((max_iterations + 1, 1)) r_left = np.zeros((max_iterations + 1, 1)) r_right = np.zeros((max_iterations + 1, 1)) u1 = Function(self.V1) u1.vector()[:] = rx1 u2 = Function(self.V2) u2.vector()[:] = rx2 L2, H1 = self.overlap_error_norms(u1, u2) L2_error[iter] = L2 H1_error[iter] = H1 SH_error[iter] = H1 - L2 r_left[iter] = r1 r_right[iter] = r2 while (iter < max_iterations): #Step 1: do f1 = du/dn2, g1 = u2 uu2 = Function(V2) if (np.absolute(rx2.max()) < np.absolute(rx2.min())): rx2 = self.adjustment * rx2 / (rx2.min()) uu2.vector()[:] = rx2 else: rx2 = self.adjustment * rx2 / (rx2.max()) uu2.vector()[:] = rx2 uu21 = Function(VO) uu21.vector()[:] = B2 * uu2.vector() g1 = Function(V1) g1.vector()[:] = BO1 * uu21.vector() du2 = Function(V2) n2 = FacetNormal(self.mesh2) du2 = assemble(inner(grad(uu2), n2) * ds) du2 = project(du2, V2) du2O = Function(VO) du2O.vector()[:] = B2 * du2.vector() f1 = Function(V1) f1.vector()[:] = BO1 * du2O.vector() #Step 2: Solve for u1 boundary = left_robin K1, _ = self.assemble_lui_stiffness(g=g1, f=f1, mesh=self.mesh1, robin_boundary=boundary) bc1 = DirichletBC(V1, Constant(0.), left_dirichlet) bc1.apply(K1) solver1 = standard_solver(K1, M1) solver1.solve(10) r1, _, rx1, _ = solver1.get_eigenpair(mode_number) #Step 3: do f1 = du1/dn1, g2 = u1 uu1 = Function(V1) if (np.absolute(rx1.max()) < np.absolute(rx1.min())): uu1.vector()[:] = self.adjustment * rx1 / (rx1.min()) else: uu1.vector()[:] = self.adjustment * rx1 / (rx1.max()) uu12 = Function(VO) uu12.vector()[:] = B1 * uu1.vector() g2 = Function(V2) g2.vector()[:] = BO2 * uu12.vector() du1 = Function(V1) n1 = FacetNormal(self.mesh1) du1 = assemble(inner(grad(uu1), n1) * ds) du1 = project(du1, V1) du12 = Function(VO) du12.vector()[:] = B1 * du1.vector() f2 = Function(V2) f2.vector()[:] = BO2 * du12.vector() #Step 4: solve for u2 boundary = right_robin K2, _ = self.assemble_lui_stiffness(g=g2, f=f2, mesh=self.mesh2, robin_boundary=boundary) bc2 = DirichletBC(V2, Constant(0.), right_dirichlet) bc2.apply(K2) solver2 = standard_solver(K2, M2) solver2.solve(10) r2, _, rx2, _ = solver2.get_eigenpair(mode_number) uu2 = Function(V2) if (np.absolute(rx2.max()) < np.absolute(rx2.min())): rx2 = self.adjustment * rx2 / (rx2.min()) uu2.vector()[:] = rx2 else: rx2 = self.adjustment * rx2 / (rx2.max()) uu2.vector()[:] = rx2 #Step 5: Calculate the L2 norm for convergence uu21.vector()[:] = B2 * uu2.vector() uu12.vector()[:] = B1 * uu1.vector() error = ((uu12 - uu21)**2) * dx L2 = assemble(error) semi_error = inner( grad(uu12) - grad(uu21), grad(uu12) - grad(uu21)) * dx H1 = L2 + assemble(semi_error) iter += 1 r_left[iter] = r1 r_right[iter] = r2 L2_error[iter] = L2 H1_error[iter] = H1 SH_error[iter] = H1 - L2 return L2_error, H1_error, SH_error, uu1, uu2, r_left, r_right
u0 = Constant("0.0") bc = DirichletBC(V, u0, u0_boundary) # Define target medium and rhs: mtrue_exp = Expression('1 + 7*(pow(pow(x[0] - 0.5,2) +' + \ ' pow(x[1] - 0.5,2),0.5) > 0.2)') #mtrue = interpolate(mtrue_exp, Vme) mtrue = interpolate(mtrue_exp, Vm) f = Expression("1.0") # Assemble weak form trial = TrialFunction(V) test = TestFunction(V) a_true = inner(mtrue*nabla_grad(trial), nabla_grad(test))*dx A_true = assemble(a_true) bc.apply(A_true) solver = PETScKrylovSolver('cg') # doesn't work with ilu preconditioner #solver = LUSolver() # doesn't work in parallel !? #solver.parameters['reuse_factorization'] = True solver.set_operator(A_true) # Assemble rhs L = f*test*dx b = assemble(L) bc.apply(b) # Solve: u_true = Function(V) """ solver.solve(u_true.vector(), b) if myrank == 0: print 'By hand:\n' print 'P{0}: max(u)={1}\n'.format(myrank, max(u_true.vector().array()))
def test_krylov_reuse_pc(): "Test preconditioner re-use with PETScKrylovSolver" # Define problem mesh = UnitSquareMesh(MPI.comm_world, 8, 8) V = FunctionSpace(mesh, ('Lagrange', 1)) bc = DirichletBC(V, Constant(0.0), lambda x, on_boundary: on_boundary) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(grad(u), grad(v)) * dx, dot(Constant(1.0), v) * dx A, P = PETScMatrix(), PETScMatrix() b = PETScVector() # Assemble linear algebra objects assemble(a, tensor=A) # noqa assemble(a, tensor=P) # noqa assemble(L, tensor=b) # noqa # Apply boundary conditions bc.apply(A) bc.apply(P) bc.apply(b) # Create Krysolv solver and set operators solver = PETScKrylovSolver("gmres", "bjacobi") solver.set_operators(A, P) # Solve x = PETScVector() num_iter_ref = solver.solve(x, b) # Change preconditioner matrix (bad matrix) and solve (PC will be # updated) a_p = u * v * dx assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter_mod = solver.solve(x, b) assert num_iter_mod > num_iter_ref # Change preconditioner matrix (good matrix) and solve (PC will be # updated) a_p = a assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_ref # Change preconditioner matrix (bad matrix) and solve (PC will not # be updated) solver.set_reuse_preconditioner(True) a_p = u * v * dx assemble(a_p, tensor=P) # noqa bc.apply(P) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_ref # Update preconditioner (bad PC, will increase iteration count) solver.set_reuse_preconditioner(False) x = PETScVector() num_iter = solver.solve(x, b) assert num_iter == num_iter_mod
def solverNeilanSalgadoZhang(P, opt): ''' This function implements the method presented in Neilan, Salgado, Zhang (2017), Chapter 4 Main characteristics: - test with piecewise second derivative of test_u - no discrete Hessian - first-order stabilization necessary ''' assert opt["HessianSpace"] == "CG", 'opt["HessianSpace"] has to be "CG"' assert opt[ "stabilityConstant1"], 'opt["stabilityConstant1"] has to be positive' gamma = P.normalizeSystem(opt) if isinstance(P.g, list): bc_V = [] for fun, dom in P.g: bc_V.append(DirichletBC(P.V, fun, dom)) else: if isinstance(P.g, Function): bc_V = DirichletBC(P.V, P.g, 'on_boundary') else: g = project(P.g, P.V) bc_V = DirichletBC(P.V, g, 'on_boundary') trial_u = TrialFunction(P.V) test_u = TestFunction(P.V) # Assemble right-hand side in each case f_h = gamma * P.f * div(grad(test_u)) * dx # Adjust load vector in case of time-dependent problem if P.isTimeDependant: f_h = gamma * P.u_np1 * div(grad(test_u)) * dx - P.dt * f_h rhs = assemble(f_h) if isinstance(bc_V, list): for bc_v in bc_V: bc_v.apply(rhs) else: bc_V.apply(rhs) repeat_setup = False if hasattr(P, 'timeDependentCoefs'): if P.timeDependentCoefs: repeat_setup = True if 'HJB' in str(type(P)): repeat_setup = True if (not P.isTimeDependant) or (P.iter == 0) or repeat_setup: print('Setup bilinear form') # Define bilinear form a_h = gamma * inner(P.a, grad(grad(trial_u))) * div(grad(test_u)) * dx \ + opt["stabilityConstant1"] * avg(P.hE)**(-1) * inner( jump(grad(trial_u), P.nE), jump(grad(test_u), P.nE)) * dS if P.hasDrift: a_h += gamma * inner(P.b, grad(trial_u)) * div(grad(test_u)) * dx if P.hasPotential: a_h += gamma * P.c * trial_u * div(grad(test_u)) * dx # Adjust system matrix in case of time-dependent problem if P.isTimeDependant: a_h = gamma * trial_u * div(grad(test_u)) * dx - P.dt * a_h S = assemble(a_h) if isinstance(bc_V, list): for bc_v in bc_V: bc_v.apply(S) else: bc_V.apply(S) P.S = S if opt['time_check']: t1 = time() solve(P.S, P.u.vector(), rhs) # tmp = assemble(inner(P.a,grad(grad(trial_u))) * div(grad(test_u)) * dx) # A = assemble(a_h) # print('Row sum: ', sum(A.array(),1).round(4)) # print('Col sum: ', sum(A.array(),0).round(4)) # print('Total sum: ', sum(sum(A.array())).round(4)) # ipdb.set_trace() # solve(a_h == f_h, P.u, bc_V, solver_parameters={'linear_solver': 'mumps'}) if opt['time_check']: print("Solve linear equation system ... %.2fs" % (time() - t1)) sys.stdout.flush() N_iter = 1 return N_iter
def test_DoGIP_vs_FEniCS(self): print( '\n== testing DoGIP vs. FEniCS for problem of weighted projection ====' ) for dim, pol_order in itertools.product([2, 3], [1, 2]): print('dim={}; pol_order={}'.format(dim, pol_order)) N = 2 # no. of elements # creating MESH, defining MATERIAL and SOURCE if dim == 2: mesh = UnitSquareMesh(N, N) m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])", degree=4) f = Expression("80*x[0]*(0.5-x[0])*(1.-x[0])*x[1]*(1.-x[1])", degree=5) elif dim == 3: mesh = UnitCubeMesh(N, N, N) m = Expression("1+10*16*x[0]*(1-x[0])*(1-x[1])*x[2]", degree=4) f = Expression("80*x[0]*(0.5-x[0])*(1.-x[0])*x[1]*(1.-x[1])", degree=5) mesh.coordinates()[:] += 0.1 * np.random.random( mesh.coordinates().shape) # mesh perturbation ## standard approach with FEniCS ############################################# V = FunctionSpace(mesh, "CG", pol_order) # original FEM space bc = DirichletBC(V, Constant(0.0), lambda x, on_boundary: on_boundary) u, v = TrialFunction(V), TestFunction(V) u_fenics = Function(V) # the vector for storing the solution solve(m * inner(grad(u), grad(v)) * dx == f * v * dx, u_fenics, bc) # solution by FEniCS ## DoGIP - double-grid integration with interpolation-projection ############# W = FunctionSpace(mesh, "DG", 2 * (pol_order - 1)) # double-grid space Wvector = VectorFunctionSpace( mesh, "DG", 2 * (pol_order - 1)) # vector variant of double-grid space w = TestFunction(W) A_dogip = assemble( m * w * dx).get_local() # diagonal matrix of material coefficients A_dogip_full = np.einsum( 'i,jk->ijk', A_dogip, np.eye(dim)) # block-diagonal mat. for non-isotropic mat. bv = assemble(f * v * dx) bc.apply(bv) b = bv.get_local() # vector of right-hand side # assembling global interpolation-projection matrix B B = get_B(V, Wvector, problem=1) # solution to DoGIP problem def Afun(x): Axd = np.einsum('...jk,...j', A_dogip_full, B.dot(x).reshape((-1, dim))) Afunx = B.T.dot(Axd.ravel()) Afunx[list(bc.get_boundary_values() )] = 0 # application of Dirichlet BC return Afunx Alinoper = linalg.LinearOperator((b.size, b.size), matvec=Afun, dtype=np.float) # system matrix x, info = linalg.cg(Alinoper, b, x0=np.zeros_like(b), tol=1e-8, maxiter=1e2) # conjugate gradients # testing the difference between DoGIP and FEniCS self.assertAlmostEqual( 0, np.linalg.norm(u_fenics.vector().get_local() - x)) print('...ok')
def forward(mu_expression, lmbda_expression, rho, Lx=10, Ly=10, t_end=1, omega_p=5, amplitude=5000, center=0, target=False): Lpml = Lx / 10 #c_p = cp(mu.vector(), lmbda.vector(), rho) max_velocity = 200 #c_p.max() stable_hx = stable_dx(max_velocity, omega_p) nx = int(Lx / stable_hx) + 1 #nx = max(nx, 60) ny = int(Ly * nx / Lx) + 1 mesh = mesh_generator(Lx, Ly, Lpml, nx, ny) used_hx = Lx / nx dt = stable_dt(used_hx, max_velocity) cfl_ct = cfl_constant(max_velocity, dt, used_hx) print(used_hx, stable_hx) print(cfl_ct) #time.sleep(10) PE = FunctionSpace(mesh, "DG", 0) mu = interpolate(mu_expression, PE) lmbda = interpolate(lmbda_expression, PE) m = 2 R = 10e-8 t = 0.0 gamma = 0.50 beta = 0.25 ff = MeshFunction("size_t", mesh, mesh.geometry().dim() - 1) Dirichlet(Lx, Ly, Lpml).mark(ff, 1) # Create function spaces VE = VectorElement("CG", mesh.ufl_cell(), 1, dim=2) TE = TensorElement("DG", mesh.ufl_cell(), 0, shape=(2, 2), symmetry=True) W = FunctionSpace(mesh, MixedElement([VE, TE])) F = FunctionSpace(mesh, "CG", 2) V = W.sub(0).collapse() M = W.sub(1).collapse() alpha_0 = Alpha_0(m, stable_hx, R, Lpml) alpha_1 = Alpha_1(alpha_0, Lx, Lpml, degree=2) alpha_2 = Alpha_2(alpha_0, Ly, Lpml, degree=2) beta_0 = Beta_0(m, max_velocity, R, Lpml) beta_1 = Beta_1(beta_0, Lx, Lpml, degree=2) beta_2 = Beta_2(beta_0, Ly, Lpml, degree=2) alpha_1 = interpolate(alpha_1, F) alpha_2 = interpolate(alpha_2, F) beta_1 = interpolate(beta_1, F) beta_2 = interpolate(beta_2, F) a_ = alpha_1 * alpha_2 b_ = alpha_1 * beta_2 + alpha_2 * beta_1 c_ = beta_1 * beta_2 Lambda_e = as_tensor([[alpha_2, 0], [0, alpha_1]]) Lambda_p = as_tensor([[beta_2, 0], [0, beta_1]]) a_ = alpha_1 * alpha_2 b_ = alpha_1 * beta_2 + alpha_2 * beta_1 c_ = beta_1 * beta_2 Lambda_e = as_tensor([[alpha_2, 0], [0, alpha_1]]) Lambda_p = as_tensor([[beta_2, 0], [0, beta_1]]) # Set up boundary condition bc = DirichletBC(W.sub(0), Constant(("0.0", "0.0")), ff, 1) # Create measure for the source term dx = Measure("dx", domain=mesh) ds = Measure("ds", domain=mesh, subdomain_data=ff) # Set up initial values u0 = Function(V) u0.set_allow_extrapolation(True) v0 = Function(V) a0 = Function(V) U0 = Function(M) V0 = Function(M) A0 = Function(M) # Test and trial functions (u, S) = TrialFunctions(W) (w, T) = TestFunctions(W) g = ModifiedRickerPulse(0, omega_p, amplitude, center) F = rho * inner(a_ * N_ddot(u, u0, a0, v0, dt, beta) \ + b_ * N_dot(u, u0, v0, a0, dt, beta, gamma) + c_ * u, w) * dx \ + inner(N_dot(S, U0, V0, A0, dt, beta, gamma).T * Lambda_e + S.T * Lambda_p, grad(w)) * dx \ - inner(g, w) * ds \ + inner(compliance(a_ * N_ddot(S, U0, A0, V0, dt, beta) + b_ * N_dot(S, U0, V0, A0, dt, beta, gamma) + c_ * S, u, mu, lmbda), T) * dx \ - 0.5 * inner(grad(u) * Lambda_p + Lambda_p * grad(u).T + grad(N_dot(u, u0, v0, a0, dt, beta, gamma)) * Lambda_e \ + Lambda_e * grad(N_dot(u, u0, v0, a0, dt, beta, gamma)).T, T) * dx \ a, L = lhs(F), rhs(F) # Assemble rhs (once) A = assemble(a) # Create GMRES Krylov solver solver = KrylovSolver(A, "gmres") # Create solution function S = Function(W) if target: xdmffile_u = XDMFFile("inversion_temporal_file/target/u.xdmf") pvd = File("inversion_temporal_file/target/u.pvd") xdmffile_u.write(u0, t) timeseries_u = TimeSeries( "inversion_temporal_file/target/u_timeseries") else: xdmffile_u = XDMFFile("inversion_temporal_file/obs/u.xdmf") xdmffile_u.write(u0, t) timeseries_u = TimeSeries("inversion_temporal_file/obs/u_timeseries") rec_counter = 0 while t < t_end - 0.5 * dt: t += float(dt) if rec_counter % 10 == 0: print( '\n\rtime: {:.3f} (Progress: {:.2f}%)'.format( t, 100 * t / t_end), ) g.t = t # Assemble rhs and apply boundary condition b = assemble(L) bc.apply(A, b) # Compute solution solver.solve(S.vector(), b) (u, U) = S.split(True) # Update previous time step update(u, u0, v0, a0, beta, gamma, dt) update(U, U0, V0, A0, beta, gamma, dt) xdmffile_u.write(u, t) pvd << (u, t) timeseries_u.store(u.vector(), t) energy = inner(u, u) * dx E = assemble(energy) print("E = ", E) print(u.vector().max())
for i, t in enumerate(trange[1:]): print('Solve problem, time step t = {}'.format(np.round(t, 4))) # Assign current time to variable t_ t_.assign(t) # Compute Ytilde, i.e. y-position of process starting in x_i,y_j # after application of convection in y-direction Ytilde = Y + by(t, X, Y) * dt[i] Vtilde = Yinterp1(vold, Ytilde, ydofs, ydiff) # Set up problem Sfull = M - dt[i] * S # Apply boundary conditions bc_Vx.apply(Sfull) # Loop over all layers in y-direction for j in range(ny + 1): y_.assign(ydofs[j]) L = assemble(L_) # This is ordinary matrix multiplication # np.max(np.abs(M*Vtilde[3,:] - M.array() @ Vtilde[3,:])) Mvtmp.vector().set_local(M * Vtilde[j, :]) Lfull = Mvtmp.vector() - dt[i] * L bc_Vx.apply(Lfull)
def solve(self): """ Find eigenvalues for transformed mesh. """ self.progress("Building mesh.") # build transformed mesh mesh = self.refineMesh() # dim = mesh.topology().dim() if self.bcLast: mesh = transform_mesh(mesh, self.transformList) Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) else: Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList) mesh = transform_mesh(mesh, self.transformList) # boundary conditions computed on non-transformed mesh # copy the values to transformed mesh fun = FacetFunction("size_t", mesh, shift) fun.array()[:] = bcs.array()[:] bcs = fun ds = Measure('ds', domain=mesh, subdomain_data=bcs) V = FunctionSpace(mesh, self.method, self.deg) u = TrialFunction(V) v = TestFunction(V) self.progress("Assembling matrices.") wTop = Expression(self.wTop) wBottom = Expression(self.wBottom) # # build stiffness matrix form # s = dot(grad(u), grad(v)) * wTop * dx # add Robin parts for bc in Robin: s += Constant(bc.parValue) * u * v * wTop * ds(bc.value + shift) # # build mass matrix form # if len(Steklov) > 0: m = 0 for bc in Steklov: m += Constant( bc.parValue) * u * v * wBottom * ds(bc.value + shift) else: m = u * v * wBottom * dx # assemble # if USE_EIGEN: # S, M = EigenMatrix(), EigenMatrix() # tempv = EigenVector() # else: S, M = PETScMatrix(), PETScMatrix() # tempv = PETScVector() if not np.any(bcs.array() == shift + 1): # no Dirichlet parts assemble(s, tensor=S) assemble(m, tensor=M) else: # # with EIGEN we could # apply Dirichlet condition symmetrically # completely remove rows and columns # # Dirichlet parts are marked with shift+1 # # temp = Constant(0)*v*dx bc = DirichletBC(V, Constant(0.0), bcs, shift + 1) # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv) # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv) assemble(s, tensor=S) bc.apply(S) assemble(m, tensor=M) # bc.zero(M) # if USE_EIGEN: # M = M.sparray() # M.eliminate_zeros() # print M.shape # indices = M.indptr[:-1] - M.indptr[1:] < 0 # M = M[indices, :].tocsc()[:, indices] # S = S.sparray()[indices, :].tocsc()[:, indices] # print M.shape # # solve the eigenvalue problem # self.progress("Solving eigenvalue problem.") eigensolver = SLEPcEigenSolver(S, M) eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["solver"] = "krylov-schur" if self.target is not None: eigensolver.parameters["spectrum"] = "target real" eigensolver.parameters["spectral_shift"] = self.target else: eigensolver.parameters["spectrum"] = "smallest magnitude" eigensolver.parameters["spectral_shift"] = -0.01 eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.solve(self.number) self.progress("Generating eigenfunctions.") if eigensolver.get_number_converged() == 0: return None eigf = [] eigv = [] if self.deg > 1: mesh = refine(mesh) W = FunctionSpace(mesh, 'CG', 1) for i in range(eigensolver.get_number_converged()): pair = eigensolver.get_eigenpair(i)[::2] eigv.append(pair[0]) u = Function(V) u.vector()[:] = pair[1] eigf.append(interpolate(u, W)) return eigv, eigf
while t < t_end - 0.5 * dt: t += float(dt) if rank == 0 and rec_counter % 10 == 0: print( '\n\rtime: {:.3f} (Progress: {:.2f}%)'.format( t, 100 * t / t_end), ) print("time taken til this point: {}".format(time.time() - t0)) for pulse in pulses: pulse.t = t g = sum(pulses) # Assemble rhs and apply boundary condition b = assemble(L) bc.apply(A, b) # Compute solution solver.solve(S.vector(), b) (u, U) = S.split(True) # Update previous time step update(u, u0, v0, a0, beta, gamma, dt) update(U, U0, V0, A0, beta, gamma, dt) pvd << (u0, t) rec_counter += 1 energy = inner(u, u) * dx E = assemble(energy) print("E = ", E)
def __call__(self, degree=3, y=0., standard_deviation=1.): V = FunctionSpace(self._mesh, "CG", degree) v = TestFunction(V) potential_trial = TrialFunction(V) potential = Function(V) dx = Measure("dx")(subdomain_data=self._subdomains) # ds = Measure("ds")(subdomain_data=self._boundaries) csd = Expression(f''' x[1] >= {self.H} ? 0 : a * exp({-0.5 / standard_deviation ** 2} * ((x[0])*(x[0]) + (x[1] - {y})*(x[1] - {y}) + (x[2])*(x[2]) )) ''', degree=degree, a=1.0) self.a = csd.a = 1.0 / assemble( csd * Measure("dx", self._mesh)) # print(assemble(csd * Measure("dx", self._mesh))) L = csd * v * dx known_terms = assemble(L) # a = (inner(grad(potential_trial), grad(v)) # * (Constant(self.SALINE_CONDUCTIVITY) * dx(self.SALINE_VOL) # + Constant(self.SLICE_CONDUCTIVITY) * (dx(self.SLICE_VOL) # + dx(self.ROI_VOL)))) a = sum( Constant(conductivity) * inner(grad(potential_trial), grad(v)) * dx(domain) for domain, conductivity in [ (self.SALINE_VOL, self.SALINE_CONDUCTIVITY), (self.SLICE_VOL, self.SLICE_CONDUCTIVITY), (self.ROI_VOL, self.SLICE_CONDUCTIVITY), ]) terms_with_unknown = assemble(a) dirchlet_bc = DirichletBC( V, Constant(2.0 * 0.25 / (self.RADIUS * np.pi * self.SALINE_CONDUCTIVITY)), # 2.0 becaue of dielectric base duplicating # the current source # slice conductivity and thickness considered # negligible self._boundaries, self.MODEL_DOME) dirchlet_bc.apply(terms_with_unknown, known_terms) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = MAX_ITER solver.parameters["absolute_tolerance"] = 1E-8 # solver.parameters["monitor_convergence"] = True start = datetime.datetime.now() try: self.iterations = solver.solve(terms_with_unknown, potential.vector(), known_terms) return potential except RuntimeError as e: self.iterations = MAX_ITER logger.warning("Solver failed: {}".format(repr(e))) return None finally: self.time = datetime.datetime.now() - start