def amg_solve(N, method): # Elasticity parameters E = 1.0e9 nu = 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Stress computation def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2) # Define problem mesh = UnitSquareMesh(MPI.comm_world, N, N) V = VectorFunctionSpace(mesh, 'Lagrange', 1) bc0 = Function(V) with bc0.vector().localForm() as bc_local: bc_local.set(0.0) def boundary(x, only_boundary): return [only_boundary] * x.shape(0) bc = DirichletBC(V.sub(0), bc0, boundary) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector( (1.0, 1.0)), v) * dx # Assemble linear algebra objects A = assemble_matrix(a, [bc]) A.assemble() b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) # Create solution function u = Function(V) # Create near null space basis and orthonormalize null_space = build_nullspace(V, u.vector()) # Attached near-null space to matrix A.set_near_nullspace(null_space) # Test that basis is orthonormal assert null_space.is_orthonormal() # Create PETSC smoothed aggregation AMG preconditioner, and # create CG solver solver = PETScKrylovSolver("cg", method) # Set matrix operator solver.set_operator(A) # Compute solution and return number of iterations return solver.solve(u.vector(), b)
def fit(x0, y0, mesh, Eps, degree=1, verbose=False, solver='spsolve'): V = FunctionSpace(mesh, 'CG', degree) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) dim = mesh.geometry().dim() A = [ _assemble_eigen(+Constant(Eps[i, j]) * u.dx(i) * v.dx(j) * dx # pylint: disable=unsubscriptable-object - Constant(Eps[i, j]) * u.dx(i) * n[j] * v * ds).sparray() for i in range(dim) for j in range(dim) ] E = _build_eval_matrix(V, x0) M = sparse.vstack(A + [E]) b = numpy.concatenate([numpy.zeros(sum(a.shape[0] for a in A)), y0]) if solver == 'spsolve': MTM = M.T.dot(M) x = sparse.linalg.spsolve(MTM, M.T.dot(b)) elif solver == 'lsqr': x, istop, *_ = sparse.linalg.lsqr( M, b, show=verbose, atol=1.0e-10, btol=1.0e-10, ) assert istop == 2, \ 'sparse.linalg.lsqr not successful (error code {})'.format(istop) elif solver == 'lsmr': x, istop, *_ = sparse.linalg.lsmr( M, b, show=verbose, atol=1.0e-10, btol=1.0e-10, # min(M.shape) is the default maxiter=max(min(M.shape), 10000)) assert istop == 2, \ 'sparse.linalg.lsmr not successful (error code {})'.format(istop) else: assert solver == 'gmres', 'Unknown solver \'{}\'.'.format(solver) A = sparse.linalg.LinearOperator((M.shape[1], M.shape[1]), matvec=lambda x: M.T.dot(M.dot(x))) x, info = sparse.linalg.gmres(A, M.T.dot(b), tol=1.0e-12) assert info == 0, \ 'sparse.linalg.gmres not successful (error code {})'.format(info) u = Function(V) u.vector().set_local(x) return u
def amg_solve(N, method): # Elasticity parameters E = 1.0e9 nu = 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) # Stress computation def sigma(v): return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym( grad(v))) * Identity(2) # Define problem mesh = UnitSquareMesh(MPI.comm_world, N, N) V = VectorFunctionSpace(mesh, 'Lagrange', 1) bc0 = Function(V) bc = DirichletBC(V.sub(0), bc0, lambda x, on_boundary: on_boundary) u = TrialFunction(V) v = TestFunction(V) # Forms a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector( (1.0, 1.0)), v) * dx # Assemble linear algebra objects A, b = assemble_system(a, L, bc) # Create solution function u = Function(V) # Create near null space basis and orthonormalize null_space = build_nullspace(V, u.vector()) # Attached near-null space to matrix A.set_near_nullspace(null_space) # Test that basis is orthonormal assert null_space.is_orthonormal() # Create PETSC smoothed aggregation AMG preconditioner, and # create CG solver solver = PETScKrylovSolver("cg", method) # Set matrix operator solver.set_operator(A) # Compute solution and return number of iterations return solver.solve(u.vector(), b)
def solve(self, mesh, num=5): """ Solve for num eigenvalues based on the mesh. """ # conforming elements V = FunctionSpace(mesh, "CG", self.degree) u = TrialFunction(V) v = TestFunction(V) # weak formulation a = inner(grad(u), grad(v)) * dx b = u * v * ds A = PETScMatrix() B = PETScMatrix() A = assemble(a, tensor=A) B = assemble(b, tensor=B) # find eigenvalues eigensolver = SLEPcEigenSolver(A, B) eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["spectrum"] = "smallest real" eigensolver.parameters["spectral_shift"] = 1.0E-10 eigensolver.solve(num + 1) # extract solutions lst = [ eigensolver.get_eigenpair(i) for i in range(1, eigensolver.get_number_converged()) ] for k in range(len(lst)): u = Function(V) u.vector()[:] = lst[k][2] lst[k] = (lst[k][0], u) # pair (eigenvalue,eigenfunction) return np.array(lst)
def solve(self, mesh, num=5): """ Solve for num eigenvalues based on the mesh. """ # conforming elements V = FunctionSpace(mesh, "CG", self.degree) u = TrialFunction(V) v = TestFunction(V) # weak formulation a = inner(grad(u), grad(v)) * dx b = u * v * ds A = PETScMatrix() B = PETScMatrix() A = assemble(a, tensor=A) B = assemble(b, tensor=B) # find eigenvalues eigensolver = SLEPcEigenSolver(A, B) eigensolver.parameters["spectral_transform"] = "shift-and-invert" eigensolver.parameters["problem_type"] = "gen_hermitian" eigensolver.parameters["spectrum"] = "smallest real" eigensolver.parameters["spectral_shift"] = 1.0E-10 eigensolver.solve(num + 1) # extract solutions lst = [ eigensolver.get_eigenpair(i) for i in range( 1, eigensolver.get_number_converged())] for k in range(len(lst)): u = Function(V) u.vector()[:] = lst[k][2] lst[k] = (lst[k][0], u) # pair (eigenvalue,eigenfunction) return np.array(lst)
def cm1dvelocity(img: np.array, vel: np.array, alpha0: float, alpha1: float) -> np.array: """Computes the source for a L2-H1 mass conserving flow for a 1D image sequence and a given velocity. Takes a one-dimensional image sequence and a velocity, and returns a minimiser of the L2-H1 mass conservation functional with spatio-temporal regularisation. Args: img (np.array): A 1D image sequence of shape (m, n), where m is the number of time steps and n is the number of pixels. vel (np.array): A 1D image sequence of shape (m, n). alpha0 (float): The spatial regularisation parameter. alpha1 (float): The temporal regularisation parameter. Returns: k: A source array of shape (m, n). """ # Create mesh. [m, n] = img.shape mesh = UnitSquareMesh(m - 1, n - 1) # Define function space and functions. V = FunctionSpace(mesh, 'CG', 1) k = TrialFunction(V) w = TestFunction(V) # Convert image to function. f = Function(V) f.vector()[:] = dh.img2funvec(img) # Convert velocity to function. v = Function(V) v.vector()[:] = dh.img2funvec(vel) # Define derivatives of data. ft = Function(V) ftv = np.diff(img, axis=0) * (m - 1) ftv = np.concatenate((ftv, ftv[-1, :].reshape(1, n)), axis=0) ft.vector()[:] = dh.img2funvec(ftv) fx = Function(V) fxv = np.gradient(img, 1 / (n - 1), axis=1) fx.vector()[:] = dh.img2funvec(fxv) # Define weak formulation. A = k * w * dx + alpha0 * k.dx(1) * w.dx(1) * dx + alpha1 * k.dx(0) * w.dx( 0) * dx b = (ft + v.dx(1) * f + v * fx) * w * dx # Compute solution. k = Function(V) solve(A == b, k) # Convert back to array. k = dh.funvec2img(k.vector().get_local(), m, n) return k
def cm1dsource(img: np.array, k: np.array, alpha0: float, alpha1: float) -> np.array: """Computes the L2-H1 mass conserving flow for a 1D image sequence and a given source. Takes a one-dimensional image sequence and a source, and returns a minimiser of the L2-H1 mass conservation functional with spatio-temporal regularisation. Args: img (np.array): A 1D image sequence of shape (m, n), where m is the number of time steps and n is the number of pixels. k (np.array): A 1D image sequence of shape (m, n). alpha0 (float): The spatial regularisation parameter. alpha1 (float): The temporal regularisation parameter. Returns: v: A velocity array of shape (m, n). """ # Create mesh. [m, n] = img.shape mesh = UnitSquareMesh(m - 1, n - 1) # Define function space and functions. V = FunctionSpace(mesh, 'CG', 1) v = TrialFunction(V) w = TestFunction(V) # Convert image to function. f = Function(V) f.vector()[:] = dh.img2funvec(img) # Convert source to function. g = Function(V) g.vector()[:] = dh.img2funvec(k) # Define derivatives of data. ft = Function(V) ftv = np.diff(img, axis=0) * (m - 1) ftv = np.concatenate((ftv, ftv[-1, :].reshape(1, n)), axis=0) ft.vector()[:] = dh.img2funvec(ftv) fx = Function(V) fxv = np.gradient(img, 1 / (n - 1), axis=1) fx.vector()[:] = dh.img2funvec(fxv) ft = f.dx(0) fx = f.dx(1) # Define weak formulation. A = - (fx*v + f*v.dx(1)) * (fx*w + f*w.dx(1))*dx \ - alpha0*v.dx(1)*w.dx(1)*dx - alpha1*v.dx(0)*w.dx(0)*dx b = ft * (fx * w + f * w.dx(1)) * dx - g * (fx * w + f * w.dx(1)) * dx # Compute solution. v = Function(V) solve(A == b, v) # Convert back to array. vel = dh.funvec2img(v.vector().get_local(), m, n) return vel
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 _fit_dolfin(x0, y0, points, cells, lmbda: float, degree: int = 1, solver: str = "lsqr"): from dolfin import ( BoundingBoxTree, Cell, EigenMatrix, FacetNormal, Function, FunctionSpace, Mesh, MeshEditor, Point, TestFunction, TrialFunction, assemble, dot, ds, dx, grad, ) def _assemble_eigen(form): L = EigenMatrix() assemble(form, tensor=L) return L def _build_eval_matrix(V, points): """Build the sparse m-by-n matrix that maps a coefficient set for a function in V to the values of that function at m given points.""" # See <https://www.allanswered.com/post/lkbkm/#zxqgk> mesh = V.mesh() bbt = BoundingBoxTree() bbt.build(mesh) dofmap = V.dofmap() el = V.element() sdim = el.space_dimension() rows = [] cols = [] data = [] for i, x in enumerate(points): cell_id = bbt.compute_first_entity_collision(Point(*x)) cell = Cell(mesh, cell_id) coordinate_dofs = cell.get_vertex_coordinates() rows.append(np.full(sdim, i)) cols.append(dofmap.cell_dofs(cell_id)) v = el.evaluate_basis_all(x, coordinate_dofs, cell_id) data.append(v) rows = np.concatenate(rows) cols = np.concatenate(cols) data = np.concatenate(data) m = len(points) n = V.dim() matrix = sparse.csr_matrix((data, (rows, cols)), shape=(m, n)) return matrix editor = MeshEditor() mesh = Mesh() # Convert points, cells to dolfin mesh if cells.shape[1] == 2: editor.open(mesh, "interval", 1, 1, 1) else: # can only handle triangles for now assert cells.shape[1] == 3 # topological and geometrical dimension 2 editor.open(mesh, "triangle", 2, 2, 1) editor.init_vertices(len(points)) editor.init_cells(len(cells)) for k, point in enumerate(points): editor.add_vertex(k, point) for k, cell in enumerate(cells.astype(np.uintp)): editor.add_cell(k, cell) editor.close() V = FunctionSpace(mesh, "CG", degree) u = TrialFunction(V) v = TestFunction(V) mesh = V.mesh() n = FacetNormal(mesh) # omega = assemble(1 * dx(mesh)) A = _assemble_eigen(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds).sparray() A *= lmbda E = _build_eval_matrix(V, x0) # mass matrix M = _assemble_eigen(u * v * dx).sparray() x = _solve(A, M, E, y0, solver) u = Function(V) u.vector().set_local(x) return u
def fit(x0, y0, V, lmbda, solver, prec_dirichlet_indices=None): """We're trying to minimize sum_i w_i (f(xi) - yi)^2 + ||lmbda Delta f||^2_{L^2(Omega)} over all functions f from V with weights w_i, lmbda. The discretization of this is ||W(E(f) - y)||_2^2 + ||lmbda Delta_h f_h||^2_{M^{-1}} where E is the (small and fat) evaluation operator at coordinates x_i, Delta_h is the discretization of Delta, and M is the mass matrix. One can either try and minimize this equation with a generic method or solve the linear equation lmbda A.T M^{-1} A x + E.T E x = E.T y0 for the extremum x. Unfortunately, solving the linear equation is not straightforward. M is spd, A is nonsymmetric and rank-deficient but positive-semidefinite. So far, we simply use sparse CG, but a good idea for a preconditioner is highly welcome. """ u = TrialFunction(V) v = TestFunction(V) mesh = V.mesh() n = FacetNormal(mesh) # omega = assemble(1 * dx(mesh)) A = _assemble_eigen(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds).sparray() A *= lmbda E = _build_eval_matrix(V, x0) # mass matrix M = _assemble_eigen(u * v * dx).sparray() # Scipy implementations of both LSQR and LSMR can only be used with the standard l_2 # inner product. This is not sufficient here: We need the M inner product to make # sure that the discrete residual is an approximation to the inner product of the # continuous problem. if solver == "dense-direct": # Minv is dense, yikes! a = A.toarray() m = M.toarray() e = E.toarray() AT_Minv_A = numpy.dot(a.T, numpy.linalg.solve(m, a)) + numpy.dot( e.T, e) ET_b = numpy.dot(e.T, y0) x = numpy.linalg.solve(AT_Minv_A, ET_b) elif solver == "sparse-cg": def matvec(x): Ax = A.dot(x) return A.T.dot(sparse.linalg.spsolve(M, Ax)) + E.T.dot(E.dot(x)) lop = pykry.LinearOperator((E.shape[1], E.shape[1]), float, dot=matvec) ET_b = E.T.dot(y0) out = pykry.cg(lop, ET_b, tol=1.0e-10, maxiter=1000) x = out.xk # import matplotlib.pyplot as plt # plt.semilogy(out.resnorms) # plt.grid() # plt.show() else: def f(x): Ax = A.dot(x) Exy = E.dot(x) - y0 return numpy.dot(Ax, spsolve(M, Ax)) + numpy.dot(Exy, Exy) # Set x0 to be the average of y0 x0 = numpy.full(A.shape[0], numpy.sum(y0) / y0.shape[0]) out = scipy.optimize.minimize(f, x0, method=solver) x = out.x u = Function(V) u.vector().set_local(x) return u
def femsolve(): ''' Bilineaarinen muoto: a(u,v) = L(v) a(u,v) = (inner(grad(u), grad(v)) + u*v)*dx L(v) = f*v*dx - g*v*ds g(x) = -du/dx = -u1, x = x1 u(x0) = u0 Omega = {xeR|x0<=x<=x1} ''' from dolfin import UnitInterval, FunctionSpace, DirichletBC, TrialFunction from dolfin import TestFunction, grad, Constant, Function, solve, inner, dx, ds from dolfin import MeshFunction, assemble import dolfin # from dolfin import set_log_level, PROCESS # Create mesh and define function space mesh = UnitInterval(30) V = FunctionSpace(mesh, 'Lagrange', 2) boundaries = MeshFunction('uint', mesh, mesh.topology().dim()-1) boundaries.set_all(0) class Left(dolfin.SubDomain): def inside(self, x, on_boundary): tol = 1E-14 # tolerance for coordinate comparisons return on_boundary and abs(x[0]) < tol class Right(dolfin.SubDomain): def inside(self, x, on_boundary): return dolfin.near(x[0], 1.0) left = Left() right = Right() left.mark(boundaries, 1) right.mark(boundaries, 2) # def u0_boundary(x): # return abs(x[0]) < tol # # bc = DirichletBC(V, Constant(u0), lambda x: abs(x[0]) < tol) bcs = [DirichletBC(V, Constant(u0), boundaries, 1)] # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = (inner(grad(u), grad(v)) + u*v)*dx g = Constant(-u1) L = Constant(f)*v*dx - g*v*ds(2) # set_log_level(PROCESS) # Compute solution A = assemble(a, exterior_facet_domains=boundaries) b = assemble(L, exterior_facet_domains=boundaries) for bc in bcs: bc.apply(A, b) u = Function(V) solve(A, u.vector(), b, 'lu') coor = mesh.coordinates() u_array = u.vector().array() a = [] b = [] for i in range(mesh.num_vertices()): a.append(coor[i]) b.append(u_array[i]) print('u(%3.2f) = %0.14E'%(coor[i],u_array[i])) import numpy as np np.savez('fem',a,b)
# Improve estimate of eigenvalues for Chebyshev smoothing PETScOptions.set("mg_levels_esteig_ksp_type", "cg") PETScOptions.set("mg_levels_ksp_chebyshev_esteig_steps", 20) # Monitor solver PETScOptions.set("ksp_monitor") # Create CG Krylov solver and turn convergence monitoring on solver = PETScKrylovSolver(MPI.comm_world) solver.set_from_options() # Set matrix operator solver.set_operator(A) # Compute solution solver.solve(u.vector(), b) # Save solution to XDMF format file = XDMFFile(MPI.comm_world, "elasticity.xdmf") file.write(u) unorm = u.vector().norm() if MPI.rank(mesh.mpi_comm()) == 0: print("Solution vector norm:", unorm) # Save colored mesh partitions in VTK format if running in parallel # if MPI.size(mesh.mpi_comm()) > 1: # File("partitions.pvd") << MeshFunction("size_t", mesh, mesh.topology.dim, \ # MPI.rank(mesh.mpi_comm())) # Project and write stress field to post-processing file
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
def femsolve(): ''' Bilineaarinen muoto: a(u,v) = L(v) a(u,v) = (inner(grad(u), grad(v)) + u*v)*dx L(v) = f*v*dx - g*v*ds g(x) = -du/dx = -u1, x = x1 u(x0) = u0 Omega = {xeR|x0<=x<=x1} ''' from dolfin import UnitInterval, FunctionSpace, DirichletBC, TrialFunction from dolfin import TestFunction, grad, Constant, Function, solve, inner, dx, ds from dolfin import MeshFunction, assemble import dolfin # from dolfin import set_log_level, PROCESS # Create mesh and define function space mesh = UnitInterval(30) V = FunctionSpace(mesh, 'Lagrange', 2) boundaries = MeshFunction('uint', mesh, mesh.topology().dim() - 1) boundaries.set_all(0) class Left(dolfin.SubDomain): def inside(self, x, on_boundary): tol = 1E-14 # tolerance for coordinate comparisons return on_boundary and abs(x[0]) < tol class Right(dolfin.SubDomain): def inside(self, x, on_boundary): return dolfin.near(x[0], 1.0) left = Left() right = Right() left.mark(boundaries, 1) right.mark(boundaries, 2) # def u0_boundary(x): # return abs(x[0]) < tol # # bc = DirichletBC(V, Constant(u0), lambda x: abs(x[0]) < tol) bcs = [DirichletBC(V, Constant(u0), boundaries, 1)] # Define variational problem u = TrialFunction(V) v = TestFunction(V) a = (inner(grad(u), grad(v)) + u * v) * dx g = Constant(-u1) L = Constant(f) * v * dx - g * v * ds(2) # set_log_level(PROCESS) # Compute solution A = assemble(a, exterior_facet_domains=boundaries) b = assemble(L, exterior_facet_domains=boundaries) for bc in bcs: bc.apply(A, b) u = Function(V) solve(A, u.vector(), b, 'lu') coor = mesh.coordinates() u_array = u.vector().array() a = [] b = [] for i in range(mesh.num_vertices()): a.append(coor[i]) b.append(u_array[i]) print('u(%3.2f) = %0.14E' % (coor[i], u_array[i])) import numpy as np np.savez('fem', a, b)
def run_simulation( filepath, topology_info: int = None, top_bc: int = None, bot_bc: int = None, left_bc: int = None, right_bc: int = None, geometry: dict = None, kappa=3, #only if geometry is None show=True, save_solution=False): from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp, FunctionSpace, TrialFunction, TestFunction, DirichletBC, Constant, Measure, inner, nabla_grad, Function, solve, plot, File) mesh = Mesh() with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile: infile.read(mesh) # read the complete mesh mvc_subdo = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 1) with XDMFFile("%s_triangle.xdmf" % filepath.split('.')[0]) as infile: infile.read(mvc_subdo, "subdomains") # read the diferent subdomians subdomains = cpp.mesh.MeshFunctionSizet(mesh, mvc_subdo) mvc = MeshValueCollection("size_t", mesh, mesh.geometric_dimension() - 2) with XDMFFile("%s_line.xdmf" % filepath.split('.')[0]) as infile: infile.read(mvc, "boundary_conditions") #read the boundary conditions boundary = cpp.mesh.MeshFunctionSizet(mesh, mvc) # Define function space and basis functions V = FunctionSpace(mesh, "CG", 1) u = TrialFunction(V) v = TestFunction(V) # Boundary conditions bcs = [] for bc_id in topology_info.keys(): if bc_id[-2:] == "bc": if bot_bc is not None and bc_id[:3] == "bot": bcs.append( DirichletBC(V, Constant(bot_bc), boundary, topology_info[bc_id])) elif left_bc is not None and bc_id[:4] == "left": bcs.append( DirichletBC(V, Constant(left_bc), boundary, topology_info[bc_id])) elif top_bc is not None and bc_id[:3] == "top": bcs.append( DirichletBC(V, Constant(top_bc), boundary, topology_info[bc_id])) elif right_bc is not None and bc_id[:5] == "right": bcs.append( DirichletBC(V, Constant(right_bc), boundary, topology_info[bc_id])) else: print(bc_id + " Not assigned as boundary condition ") # raise NotImplementedError # Define new measures associated with the interior domains and # exterior boundaries dx = Measure("dx", subdomain_data=subdomains) ds = Measure("ds", subdomain_data=boundary) f = Constant(0) g = Constant(0) if geometry is not None: # run multipatch implementation (Multiple domains) a = [] L = [] for patch_id in geometry.keys(): kappa = geometry[patch_id].get("kappa") a.append( inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) * dx(topology_info[patch_id])) L.append(f * v * dx(topology_info[patch_id])) a = sum(a) L = sum(L) else: a = inner(Constant(kappa) * nabla_grad(u), nabla_grad(v)) * dx L = f * v * dx ## Redefine u as a function in function space V for the solution u = Function(V) # Solve solve(a == L, u, bcs) u.rename('u', 'Temperature') # Save solution to file in VTK format print(' [+] Output to %s_solution.pvd' % filepath.split('.')[0]) vtkfile = File('%s_solution.pvd' % filepath.split('.')[0]) vtkfile << u if show: import matplotlib matplotlib.use("Qt5Agg") # Plot solution and gradient plot(u, title="Temperature") plt.gca().view_init(azim=-90, elev=90) plt.show() dofs = V.tabulate_dof_coordinates().reshape( V.dim(), mesh.geometry().dim()) #coordinates of nodes vals = u.vector().get_local() #temperature at nodes if save_solution: from dolfin import HDF5File, MPI output_file = HDF5File(MPI.comm_world, filepath.split('.')[0] + "_solution_field.h5", "w") output_file.write(u, "solution") output_file.close() u.set_allow_extrapolation(True) return dofs, vals, mesh, u