def read_fenics_solution(filepath): from dolfin import (Mesh, XDMFFile, MeshValueCollection, cpp, FunctionSpace, Function, HDF5File, MPI) 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 = Function(V) input_file = HDF5File(MPI.comm_world, filepath.split('.')[0] + "_solution_field.h5", "r") input_file.read(U, "solution") input_file.close() dofs = V.tabulate_dof_coordinates().reshape( V.dim(), mesh.geometry().dim()) # coordinates of nodes U.set_allow_extrapolation(True) return U, mesh, dofs.shape[0]
def test_tabulate_all_coordinates(mesh_factory): func, args = mesh_factory mesh = func(*args) V = FunctionSpace(mesh, ("Lagrange", 1)) W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1) W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1) W = FunctionSpace(mesh, W0 * W1) D = mesh.geometry.dim V_dofmap = V.dofmap W_dofmap = W.dofmap all_coords_V = V.tabulate_dof_coordinates() all_coords_W = W.tabulate_dof_coordinates() local_size_V = V_dofmap().index_map.size_local * V_dofmap( ).index_map.block_size local_size_W = W_dofmap().index_map.size_local * W_dofmap( ).index_map.block_size all_coords_V = all_coords_V.reshape(local_size_V, D) all_coords_W = all_coords_W.reshape(local_size_W, D) checked_V = [False] * local_size_V checked_W = [False] * local_size_W # Check that all coordinates are within the cell it should be for i in range(mesh.num_cells()): cell = MeshEntity(mesh, mesh.topology.dim, i) dofs_V = V_dofmap.cell_dofs(i) for di in dofs_V: if di >= local_size_V: continue assert cell.contains(all_coords_V[di]) checked_V[di] = True dofs_W = W_dofmap.cell_dofs(cell.index()) for di in dofs_W: if di >= local_size_W: continue assert cell.contains(all_coords_W[di]) checked_W[di] = True # Assert that all dofs have been checked by the above assert all(checked_V) assert all(checked_W)
def test_tabulate_all_coordinates(mesh_factory): func, args = mesh_factory mesh = func(*args) V = FunctionSpace(mesh, "Lagrange", 1) W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1) W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1) W = FunctionSpace(mesh, W0 * W1) D = mesh.geometry.dim V_dofmap = V.dofmap() W_dofmap = W.dofmap() all_coords_V = V.tabulate_dof_coordinates() all_coords_W = W.tabulate_dof_coordinates() local_size_V = V_dofmap.ownership_range()[1] - V_dofmap.ownership_range( )[0] local_size_W = W_dofmap.ownership_range()[1] - W_dofmap.ownership_range( )[0] all_coords_V = all_coords_V.reshape(local_size_V, D) all_coords_W = all_coords_W.reshape(local_size_W, D) checked_V = [False] * local_size_V checked_W = [False] * local_size_W # Check that all coordinates are within the cell it should be for cell in Cells(mesh): dofs_V = V_dofmap.cell_dofs(cell.index()) for di in dofs_V: if di >= local_size_V: continue assert cell.contains(Point(all_coords_V[di])) checked_V[di] = True dofs_W = W_dofmap.cell_dofs(cell.index()) for di in dofs_W: if di >= local_size_W: continue assert cell.contains(Point(all_coords_W[di])) checked_W[di] = True # Assert that all dofs have been checked by the above assert all(checked_V) assert all(checked_W)
def test_multi_ps_matrix_node(mesh): """Tests point source when given constructor PointSource(V, source) with a matrix when points placed at 3 nodes for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * u * v * dx) dim = mesh.geometry().dim() source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks matrix sums to correct value. A.get_diagonal(w.vector()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - len(point) * 10) == 0 # Check if coordinates are in portion of mesh and if so check that # diagonal components sum to the correct value. mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i - 1] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(w.vector()[j // (dim)] - 10.0) == 0.0 j += dim
def test_multi_ps_matrix_node(mesh): """Tests point source when given constructor PointSource(V, source) with a matrix when points placed at 3 nodes for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0)*u*v*dx) dim = mesh.geometry().dim() source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i-1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks matrix sums to correct value. A.get_diagonal(w.vector()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - len(point)*10) == 0 # Check if coordinates are in portion of mesh and if so check that # diagonal components sum to the correct value. mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i-1] = p j = 0 for i in range(len(mesh_coords)//(dim)): mesh_coords_check = mesh_coords[j:j+dim-1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(w.vector()[j//(dim)]-10.0) == 0.0 j += dim
def test_multi_ps_vector_node(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] dim = mesh.geometry().dim() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(point) * 10.0) == 0 # Checks values added to correct part of vector mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(b.array()[j // (dim)] - 10.0) == 0.0 j += dim
def test_multi_ps_vector_node(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] dim = mesh.geometry().dim() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0)*v*dx) source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i-1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(point)*10.0) == 0 # Checks values added to correct part of vector mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords)//(dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(b.array()[j//(dim)]-10.0) == 0.0 j += dim
def eafe_assemble( mesh: Mesh, diffusion: Coefficient, convection: Optional[Coefficient] = None, reaction: Optional[Coefficient] = None, ) -> dolfin.Matrix: """ Assembly of stiffness matrix for a generic linear elliptic equation: for `u` a continuous piecewise-linear finite element function, -div(diffusion * grad(u) + convection * u) + reaction * u = source Edge-integral quantities are approximated by a midpoint quadrature rule. :param mesh: Mesh defining finite element space :param diff: Coefficient for diffusion coefficient :param conv: [Optional] Coefficient for convection coefficient :param reac: [Optional] Coefficient for reaction coefficient :return: dolfin.Matrix pertaining to EAFE stiffness matrix """ if not issubclass(mesh.__class__, Mesh): raise TypeError( "Invalid mesh parameter: must inherit from dolfin.Mesh") logging.getLogger("FFC").setLevel(logging.WARNING) quadrature_degree = parameters["form_compiler"]["quadrature_degree"] parameters["form_compiler"]["quadrature_degree"] = 2 spatial_dim: int = mesh.topology().dim() cell_vertex_count: int = spatial_dim + 1 try: edge_advection = define_edge_advection(spatial_dim, diffusion, convection) lumped_reaction = define_mass_lumping(cell_vertex_count, reaction) except Exception as e: parameters["form_compiler"]["quadrature_degree"] = quadrature_degree raise e V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx A: dolfin.Matrix = assemble(a) mat: dolfin.PETScMatrix = as_backend_type(A).mat() A.zero() dof_map = V.dofmap() dof_coord = V.tabulate_dof_coordinates() for cell in cells(mesh): local_tensor = assemble_local(a, cell) local_to_global_map = dof_map.cell_dofs(cell.index()) cell_vertex = np.empty([cell_vertex_count, spatial_dim]) for local_dof in range(0, cell_vertex_count): dof_id = local_to_global_map[local_dof] for coord in range(0, spatial_dim): cell_vertex[local_dof, coord] = dof_coord[dof_id, coord] for vertex_id in range(0, cell_vertex_count): vertex = cell_vertex[vertex_id] local_tensor[vertex_id, vertex_id] = lumped_reaction(vertex, cell) for edge_id in range(0, cell_vertex_count): if edge_id == vertex_id: continue edge = cell_vertex[edge_id] - vertex local_tensor[vertex_id, edge_id] *= edge_advection(vertex, edge, cell) local_tensor[vertex_id, vertex_id] -= local_tensor[vertex_id, edge_id] local_to_global_list = local_to_global_map.tolist() mat.setValuesLocal( local_to_global_list, local_to_global_list, local_tensor, PETSc.InsertMode.ADD, ) A.apply("insert") mat.assemble() parameters["form_compiler"]["quadrature_degree"] = quadrature_degree return A
def solve(mesh, Eps, degree): V = FunctionSpace(mesh, "CG", degree) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) gdim = mesh.geometry().dim() A = [ _assemble_eigen( Constant(Eps[i, j]) * (u.dx(i) * v.dx(j) * dx - u.dx(i) * n[j] * v * ds) ).sparray() for j in range(gdim) for i in range(gdim) ] assert_equality = False if assert_equality: # The sum of the `A`s is exactly that: n = FacetNormal(V.mesh()) AA = _assemble_eigen( +dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx - dot(dot(as_tensor(Eps), grad(u)), n) * v * ds ).sparray() diff = AA - sum(A) assert numpy.all(abs(diff.data) < 1.0e-14) # # ATAsum = sum(a.T.dot(a) for a in A) # diff = AA.T.dot(AA) - ATAsum # # import betterspy # # betterspy.show(ATAsum) # # betterspy.show(AA.T.dot(AA)) # # betterspy.show(ATAsum - AA.T.dot(AA)) # print(diff.data) # assert numpy.all(abs(diff.data) < 1.0e-14) tol = 1.0e-10 def lower(x, on_boundary): return on_boundary and x[1] < -1.0 + tol def upper(x, on_boundary): return on_boundary and x[1] > 1.0 - tol def left(x, on_boundary): return on_boundary and abs(x[0] + 1.0) < tol def right(x, on_boundary): return on_boundary and abs(x[0] - 1.0) < tol def upper_left(x, on_boundary): return on_boundary and x[1] > +1.0 - tol and x[0] < -0.8 def lower_right(x, on_boundary): return on_boundary and x[1] < -1.0 + tol and x[0] > 0.8 bcs = [ # DirichletBC(V, Constant(0.0), lower_right), # DirichletBC(V, Constant(0.0), upper_left), DirichletBC(V, Constant(0.0), lower), DirichletBC(V, Constant(0.0), upper), # DirichletBC(V, Constant(0.0), upper_left, method='pointwise'), # DirichletBC(V, Constant(0.0), lower_left, method='pointwise'), # DirichletBC(V, Constant(0.0), lower_right, method='pointwise'), ] M = _assemble_eigen(u * v * dx).sparray() ATMinvAsum = sum( numpy.dot(a.toarray().T, numpy.linalg.solve(M.toarray(), a.toarray())) for a in A ) AA2 = _assemble_eigen( +dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx - dot(dot(as_tensor(Eps), grad(u)), n) * v * ds, # bcs=[DirichletBC(V, Constant(0.0), 'on_boundary')] # bcs=bcs # bcs=[ # DirichletBC(V, Constant(0.0), lower), # DirichletBC(V, Constant(0.0), right), # ] ).sparray() ATA2 = numpy.dot(AA2.toarray().T, numpy.linalg.solve(M.toarray(), AA2.toarray())) # Find combination of Dirichlet points: if False: # min_val = 1.0 max_val = 0.0 # min_combi = [] max_combi = [] is_updated = False it = 0 # get boundary indices d = DirichletBC(V, Constant(0.0), "on_boundary") boundary_idx = numpy.sort(list(d.get_boundary_values().keys())) # boundary_idx = numpy.arange(V.dim()) # print(boundary_idx) # pick some at random # idx = numpy.sort(numpy.random.choice(boundary_idx, size=3, replace=False)) for idx in itertools.combinations(boundary_idx, 3): it += 1 print() print(it) # Replace the rows corresponding to test functions living in one cell # (deliberately chosen as 0) by Dirichlet rows. AA3 = AA2.tolil() for k in idx: AA3[k] = 0 AA3[k, k] = 1 n = AA3.shape[0] AA3 = AA3.tocsr() ATA2 = numpy.dot( AA3.toarray().T, numpy.linalg.solve(M.toarray(), AA3.toarray()) ) vals = numpy.sort(numpy.linalg.eigvalsh(ATA2)) if vals[0] < 0.0: continue # op = sparse.linalg.LinearOperator( # (n, n), # matvec=lambda x: _spsolve(AA3, M.dot(_spsolve(AA3.T.tocsr(), x))) # ) # vals, _ = scipy.sparse.linalg.eigsh(op, k=3, which='LM') # vals = numpy.sort(1/vals[::-1]) # print(vals) print(idx) # if min_val > vals[0]: # min_val = vals[0] # min_combi = idx # is_updated = True if max_val < vals[0]: max_val = vals[0] max_combi = idx is_updated = True if is_updated: # vals, _ = scipy.sparse.linalg.eigsh(op, k=10, which='LM') # vals = numpy.sort(1/vals[::-1]) # print(vals) is_updated = False # print(min_val, min_combi) print(max_val, max_combi) # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x') meshzoo.plot2d(mesh.coordinates(), mesh.cells()) dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim)) # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or') plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob") plt.gca().set_aspect("equal") plt.title(f"smallest eigenvalue: {max_val}") plt.show() # # if True: # if abs(vals[0]) < 1.0e-8: # gdim = mesh.geometry().dim() # # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x') # X = mesh.coordinates() # meshzoo.plot2d(mesh.coordinates(), mesh.cells()) # dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim)) # plt.plot(dofs_x[idx, 0], dofs_x[idx, 1], 'or') # plt.gca().set_aspect('equal') # plt.show() meshzoo.plot2d(mesh.coordinates(), mesh.cells()) dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim)) # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or') plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob") plt.gca().set_aspect("equal") plt.title(f"final smallest eigenvalue: {max_val}") plt.show() exit(1) # Eigenvalues of the operators if True: # import betterspy # betterspy.show(sum(A), colormap="viridis") AA = _assemble_eigen( +dot(grad(u), grad(v)) * dx - dot(grad(u), n) * v * ds ).sparray() eigvals, eigvecs = scipy.sparse.linalg.eigs(AA, k=5, which="SM") assert numpy.all(numpy.abs(eigvals.imag) < 1.0e-12) eigvals = eigvals.real assert numpy.all(numpy.abs(eigvecs.imag) < 1.0e-12) eigvecs = eigvecs.real i = numpy.argsort(eigvals) print(eigvals[i]) import meshio for k in range(3): meshio.write_points_cells( f"eigval{k}.vtk", points, {"triangle": cells}, point_data={"ev": eigvecs[:, i][:, k]}, ) exit(1) # import betterspy # betterspy.show(AA, colormap="viridis") # print(numpy.sort(numpy.linalg.eigvals(AA.todense()))) exit(1) Asum = sum(A).todense() AsumT_Minv_Asum = numpy.dot(Asum.T, numpy.linalg.solve(M.toarray(), Asum)) # print(numpy.sort(numpy.linalg.eigvalsh(Asum))) print(numpy.sort(numpy.linalg.eigvalsh(AsumT_Minv_Asum))) exit(1) # eigvals, eigvecs = numpy.linalg.eigh(Asum) # i = numpy.argsort(eigvals) # print(eigvals[i]) # exit(1) # print(eigvals[:20]) # eigvals[eigvals < 1.0e-15] = 1.0e-15 # # eigvals = numpy.sort(numpy.linalg.eigvalsh(sum(A).todense())) # print(eigvals[:20]) # plt.semilogy(eigvals, ".", label="Asum") # plt.legend() # plt.grid() # plt.show() # exit(1) ATMinvAsum_eigs = numpy.sort(numpy.linalg.eigvalsh(ATMinvAsum)) print(ATMinvAsum_eigs[:20]) ATMinvAsum_eigs[ATMinvAsum_eigs < 0.0] = 1.0e-12 # ATA2_eigs = numpy.sort(numpy.linalg.eigvalsh(ATA2)) # print(ATA2_eigs[:20]) plt.semilogy(ATMinvAsum_eigs, ".", label="ATMinvAsum") # plt.semilogy(ATA2_eigs, ".", label="ATA2") plt.legend() plt.grid() plt.show() # # Preconditioned eigenvalues # # IATA_eigs = numpy.sort(scipy.linalg.eigvalsh(ATMinvAsum, ATA2)) # # plt.semilogy(IATA_eigs, ".", label="precond eigenvalues") # # plt.legend() # # plt.show() exit(1) # # Test with A only # numpy.random.seed(123) # b = numpy.random.rand(sum(a.shape[0] for a in A)) # MTM = M.T.dot(M) # MTb = M.T.dot(b) # sol = _gmres( # MTM, # # TODO linear operator # # lambda x: M.T.dot(M.dot(x)), # MTb, # M=prec # ) # plt.semilogy(sol.resnorms) # plt.show() # exit(1) n = AA2.shape[0] # define the operator def matvec(x): # M^{-1} can be computed in O(n) with CG + diagonal preconditioning # or algebraic multigrid. # return sum([a.T.dot(a.dot(x)) for a in A]) return numpy.sum([a.T.dot(_spsolve(M, a.dot(x))) for a in A], axis=0) op = sparse.linalg.LinearOperator((n, n), matvec=matvec) # pick a random solution and a consistent rhs x = numpy.random.rand(n) b = op.dot(x) linear_system = krypy.linsys.LinearSystem(op, b) print("unpreconditioned solve...") t = time.time() out = krypy.linsys.Gmres(linear_system, tol=1.0e-12, explicit_residual=True) out.xk = out.xk.reshape(b.shape) print("done.") print(" res: {}".format(out.resnorms[-1])) print( " unprec res: {}".format( numpy.linalg.norm(b - op.dot(out.xk)) / numpy.linalg.norm(b) ) ) # The error isn't useful here; only with the nullspace removed # print(' error: {}'.format(numpy.linalg.norm(out.xk - x))) print(" its: {}".format(len(out.resnorms))) print(" duration: {}s".format(time.time() - t)) # preconditioned solver ml = pyamg.smoothed_aggregation_solver(AA2) # res = [] # b = numpy.random.rand(AA2.shape[0]) # x0 = numpy.zeros(AA2.shape[1]) # x = ml.solve(b, x0, residuals=res, tol=1.0e-12) # print(res) # plt.semilogy(res) # plt.show() mlT = pyamg.smoothed_aggregation_solver(AA2.T.tocsr()) # res = [] # b = numpy.random.rand(AA2.shape[0]) # x0 = numpy.zeros(AA2.shape[1]) # x = mlT.solve(b, x0, residuals=res, tol=1.0e-12) # print(res) def prec_matvec(b): x0 = numpy.zeros(n) b1 = mlT.solve(b, x0, tol=1.0e-12) b2 = M.dot(b1) x = ml.solve(b2, x0, tol=1.0e-12) return x prec = LinearOperator((n, n), matvec=prec_matvec) # TODO assert this in a test # x = prec_matvec(b) # print(b - AA2.T.dot(AA2.dot(x))) linear_system = krypy.linsys.LinearSystem(op, b, Ml=prec) print() print("preconditioned solve...") t = time.time() try: out_prec = krypy.linsys.Gmres( linear_system, tol=1.0e-14, maxiter=1000, explicit_residual=True ) except krypy.utils.ConvergenceError: print("prec not converged!") pass out_prec.xk = out_prec.xk.reshape(b.shape) print("done.") print(" res: {}".format(out_prec.resnorms[-1])) print( " unprec res: {}".format( numpy.linalg.norm(b - op.dot(out_prec.xk)) / numpy.linalg.norm(b) ) ) print(" its: {}".format(len(out_prec.resnorms))) print(" duration: {}s".format(time.time() - t)) plt.semilogy(out.resnorms, label="original") plt.semilogy(out_prec.resnorms, label="preconditioned") plt.legend() plt.show() return out.xk
test = div(grad(psi)) S_ = gamma * inner(ax, grad(grad(phi))) * test * dx(mx) \ + stab1 * avg(hE)**(-1) * inner(jump(grad(phi), nE), jump(grad(psi), nE)) * dS(mx) \ + gamma * inner(bx, grad(phi)) * test * dx(mx) \ + gamma * c * phi * test * dx(mx) # This matrix also changes since we are testing the whole equation # with div(grad(psi)) instead of psi M_ = gamma * phi * test * dx(mx) bc_Vx = DirichletBC(Vx, g, 'on_boundary') S = assemble(S_) M = assemble(M_) # Prepare special treatment of deterministic part and time-derivative. xdofs = Vx.tabulate_dof_coordinates().flatten() ix = np.argsort(xdofs) # Since we're using the mesh in the deterministic direction # only for temporary purpose, the coordinates are fine here ydofs = Vy.tabulate_dof_coordinates().flatten() ydofs.sort() ydiff = np.diff(ydofs) assert np.all(ydiff > 0) # Create meshgrid X, Y of shape (ny+1, nx+1) X, Y = np.meshgrid(xdofs, ydofs) trange = np.linspace(T[1], T[0], nt + 1) dt = -np.diff(trange) assert np.all(dt > 0)
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