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
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}"
def compute_error(problem, mesh_size): mesh = problem.mesh_generator(mesh_size) u = problem.solution['u'] u_sol = Expression((ccode(u['value'][0]), ccode(u['value'][1])), degree=u['degree']) p = problem.solution['p'] p_sol = Expression(ccode(p['value']), degree=p['degree']) f = Expression( (ccode(problem.f['value'][0]), ccode(problem.f['value'][1])), degree=problem.f['degree']) W = VectorElement('Lagrange', mesh.ufl_cell(), 2) P = FiniteElement('Lagrange', mesh.ufl_cell(), 1) WP = FunctionSpace(mesh, W * P) # Get Dirichlet boundary conditions u_bcs = DirichletBC(WP.sub(0), u_sol, 'on_boundary') p_bcs = DirichletBC(WP.sub(1), p_sol, 'on_boundary') u_approx, p_approx = flow.stokes.solve(WP, bcs=[u_bcs, p_bcs], mu=problem.mu, f=f, verbose=True, tol=1.0e-12) # compute errors u_error = errornorm(u_sol, u_approx) p_error = errornorm(p_sol, p_approx) return mesh.hmax(), u_error, p_error
def transfer(self, V): fenics_bcs = list() for bc in self._bcs: if bc.component is not None: if not bc.pointwise: fenics_bcs.append( DirichletBC(V.sub(bc.component), bc.expression, bc.domain)) else: fenics_bcs.append( DirichletBC(V.sub(bc.component), bc.expression, bc.domain, method='pointwise')) else: if not bc.pointwise: fenics_bcs.append(DirichletBC(V, bc.expression, bc.domain)) else: fenics_bcs.append( DirichletBC(V, bc.expression, bc.domain, method='pointwise')) return fenics_bcs
def homogenize(bcs): b = [] for bc in bcs: b0 = DirichletBC(bc) b0.homogenize() b.append(b0) return b
def __init__(self, coarse_mesh, nref, p_coarse, p_fine): super(LaplaceEigenvalueProblem, self).__init__(coarse_mesh, nref, p_coarse, p_fine) print0("Assembling fine-mesh problem") self.dirichlet_bdry = lambda x,on_boundary: on_boundary bc = DirichletBC(self.V_fine, 0.0, self.dirichlet_bdry) u = TrialFunction(self.V_fine) v = TestFunction(self.V_fine) a = inner(grad(u), grad(v))*dx m = u*v*dx # Assemble the stiffness matrix and the mass matrix. b = v*dx # just need this to feed an argument to assemble_system assemble_system(a, b, bc, A_tensor=self.A_fine) assemble_system(m, b, bc, A_tensor=self.B_fine) # set the diagonal elements of M corresponding to boundary nodes to zero to # remove spurious eigenvalues. bc.zero(self.B_fine) print0("Assembling coarse-mesh problem") self.bc_coarse = DirichletBC(self.V_coarse, 0.0, self.dirichlet_bdry) u = TrialFunction(self.V_coarse) v = TestFunction(self.V_coarse) a = inner(grad(u), grad(v))*dx m = u*v*dx # Assemble the stiffness matrix and the mass matrix, without Dirichlet BCs. Dirichlet DOFs will be removed later. assemble(a, tensor=self.A_coarse) assemble(m, tensor=self.B_coarse)
def stokes(self): P2 = VectorElement("CG", self.mesh.ufl_cell(), 2) P1 = FiniteElement("CG", self.mesh.ufl_cell(), 1) TH = P2 * P1 VQ = FunctionSpace(self.mesh, TH) mf = self.mf self.no_slip = Constant((0., 0)) self.topflow = Expression(("-x[0] * (x[0] - 1.0) * 6.0 * m", "0.0"), m=self.U_m, degree=2) bc0 = DirichletBC(VQ.sub(0), self.topflow, mf, self.bc_dict["top"]) bc1 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["left"]) bc2 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["bottom"]) bc3 = DirichletBC(VQ.sub(0), self.no_slip, mf, self.bc_dict["right"]) # bc4 = DirichletBC(VQ.sub(1), Constant(0), mf, self.bc_dict["top"]) bcs = [bc0, bc1, bc2, bc3] vup = TestFunction(VQ) up = TrialFunction(VQ) # the solution will be in here: up_ = Function(VQ) u, p = split(up) # Trial vu, vp = split(vup) # Test u_, p_ = split(up_) # Function holding the solution F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \ - inner(vp, div(u))*dx + dot(self.g*self.rho, vu)*dx solve(lhs(F) == rhs(F), up_, bcs=bcs) self.u_.assign(project(u_, self.V)) self.p_.assign(project(p_, self.Q)) return
def __init__(self, U_m, mesh): """Function spaces and BCs""" V = VectorFunctionSpace(mesh, 'P', 2) Q = FunctionSpace(mesh, 'P', 1) self.mesh = mesh self.vu, self.vp = TestFunction(V), TestFunction(Q) # for integration self.u_, self.p_ = Function(V), Function(Q) # for the solution self.u_1, self.p_1 = Function(V), Function(Q) # for the prev. solution self.u_k, self.p_k = Function(V), Function(Q) # for the prev. solution self.u, self.p = TrialFunction(V), TrialFunction(Q) # unknown! U0_str = "4.*U_m*x[1]*(.41-x[1])/(.41*.41)" x = [0, .41 / 2] # evaluate the Expression at the center of the channel self.U_mean = np.mean(2 / 3 * eval(U0_str)) U0 = Expression((U0_str, "0"), U_m=U_m, degree=2) bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall) bc1 = DirichletBC(V, Constant((0, 0)), topandbottom) bc2 = DirichletBC(V, U0, inlet) bc3 = DirichletBC(Q, Constant(0), outlet) self.bcu = [bc0, bc1, bc2] self.bcp = [bc3] # ds is needed to compute drag and lift. ASD1 = AutoSubDomain(topandbottom) ASD2 = AutoSubDomain(cylinderwall) mf = MeshFunction("size_t", mesh, 1) mf.set_all(0) ASD1.mark(mf, 1) ASD2.mark(mf, 2) self.ds_ = ds(subdomain_data=mf, domain=mesh) return
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 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
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 __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
def ball_in_tube(): mesh = Mesh("../meshes/2d/ball-in-tube-cylindrical-coarse4.xml") V0 = FunctionSpace(mesh, "CG", 2) V1 = FunctionSpace(mesh, "B", 3) V = V0 + V1 W = MixedFunctionSpace([V, V]) P = FunctionSpace(mesh, "CG", 1) # Define mesh and boundaries. class LeftBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] < GMSH_EPS left_boundary = LeftBoundary() class RightBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] > 1.0 - GMSH_EPS right_boundary = RightBoundary() class LowerBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] < GMSH_EPS lower_boundary = LowerBoundary() class UpperBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 5.0 - GMSH_EPS class CoilBoundary(SubDomain): def inside(self, x, on_boundary): # One has to pay a little bit of attention when defining the # coil boundary; it's easy to miss the edges closest to x[0]=0. return ( on_boundary and x[1] > 1.0 - GMSH_EPS and x[1] < 2.0 + GMSH_EPS and x[0] < 1.0 - GMSH_EPS ) coil_boundary = CoilBoundary() u_bcs = [ DirichletBC(W, (0.0, 0.0), right_boundary), DirichletBC(W.sub(0), 0.0, left_boundary), DirichletBC(W, (0.0, 0.0), lower_boundary), DirichletBC(W, (0.0, 0.0), coil_boundary), ] p_bcs = [] # p_bcs = [DirichletBC(Q, 0.0, upper_boundary)] return mesh, W, P, u_bcs, p_bcs
def pinBC(membrane): bc = [] if membrane.nsd==2: bc.append(DirichletBC(membrane.V, Constant((0,0)), bd_all_1D)) elif membrane.nsd==3: # This constrains the thickness at the support but is not plane strain bc.append(DirichletBC(membrane.V.sub(1), Constant(0), bd_all)) bc.append(DirichletBC(membrane.V, Constant((0, 0, 0)), bd_x)) return bc
def get_boundary_conditions(self, use_pressure_BC, v_space, p_space): # boundary parts: 1 walls, 2 inflow, 3 outflow bc0 = DirichletBC(v_space, (0.0, 0.0, 0.0), self.facet_function, 1) # no-slip inflow = DirichletBC(v_space, self.v_in, self.facet_function, 2) bcu = [inflow, bc0] bcp = [] if use_pressure_BC: outflow = DirichletBC(p_space, 0.0, self.facet_function, 3) bcp = [outflow] return bcu, bcp
def create_dirichlet_conditions(values, boundaries, function_spaces): """Create Dirichlet boundary conditions for given boundary values, boundaries and function space.""" # Check that the size matches if len(values) != len(boundaries): error( "The number of Dirichlet values does not match the number of Dirichlet boundaries." ) if len(values) != len(function_spaces): error( "The number of Dirichlet values does not match the number of function spaces." ) if len(boundaries) != len(function_spaces): error( "The number of Dirichlet boundaries does not match the number of function spaces." ) info("Creating %d Dirichlet boundary condition(s)." % len(values)) # Create Dirichlet conditions bcs = [] for (i, value) in enumerate(values): # Get current boundary boundary = boundaries[i] function_space = function_spaces[i] # Case 0: boundary is a string if isinstance(boundary, str): boundary = CompiledSubDomain(boundary) bc = DirichletBC(function_space, value, boundary) # Case 1: boundary is a SubDomain elif isinstance(boundary, SubDomain): bc = DirichletBC(function_space, value, boundary) # Case 2: boundary is defined by a MeshFunction elif isinstance(boundary, tuple): mesh_function, index = boundary bc = DirichletBC(function_space, value, mesh_function, index) # Unhandled case else: error( "Unhandled boundary specification for boundary condition. " "Expecting a string, a SubDomain or a (MeshFunction, int) tuple." ) bcs.append(bc) return bcs
def get_boundary_conditions(self, use_pressure_BC, v_space, p_space): # boundary parts: 1 walls, 2, 4 inflow, 3, 5 outflow # Boundary conditions bc_wall = DirichletBC(v_space, (0.0, 0.0, 0.0), self.facet_function, 1) bc_cyl = DirichletBC(v_space, (0.0, 0.0, 0.0), self.facet_function, 5) inflow = DirichletBC(v_space, self.v_in, self.facet_function, 2) bcu = [inflow, bc_cyl, bc_wall] bcp = [] if use_pressure_BC: outflow = DirichletBC(p_space, 0.0, self.facet_function, 3) bcp = [outflow] return bcu, bcp
def navier_stokes_IPCS(mesh, dt, parameter): """ fenics code: weak form of the problem. """ mu, rho, nu = parameter V = VectorFunctionSpace(mesh, 'P', 2) Q = FunctionSpace(mesh, 'P', 1) bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall) bc1 = DirichletBC(V, Constant((0, 0)), topandbottom) bc2 = DirichletBC(V, U0, inlet) bc3 = DirichletBC(Q, Constant(1), outlet) bcs = [bc0, bc1, bc2, bc3] # ds is needed to compute drag and lift. Not used here. ASD1 = AutoSubDomain(topandbottom) ASD2 = AutoSubDomain(cylinderwall) mf = MeshFunction("size_t", mesh, 1) mf.set_all(0) ASD1.mark(mf, 1) ASD2.mark(mf, 2) ds_ = ds(subdomain_data=mf, domain=mesh) vu, vp = TestFunction(V), TestFunction(Q) # for integration u_, p_ = Function(V), Function(Q) # for the solution u_1, p_1 = Function(V), Function(Q) # for the prev. solution u, p = TrialFunction(V), TrialFunction(Q) # unknown! bcu = [bcs[0], bcs[1], bcs[2]] bcp = [bcs[3]] n = FacetNormal(mesh) u_mid = (u + u_1) / 2.0 F1 = rho*dot((u - u_1) / dt, vu)*dx \ + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \ + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds a1 = lhs(F1) L1 = rhs(F1) # Define variational problem for step 2 a2 = dot(nabla_grad(p), nabla_grad(vp)) * dx L2 = dot(nabla_grad(p_1), nabla_grad(vp)) * dx - ( rho / dt) * div(u_) * vp * dx # rho missing in FEniCS tutorial # Define variational problem for step 3 a3 = dot(u, vu) * dx L3 = dot(u_, vu) * dx - dt * dot(nabla_grad(p_ - p_1), vu) * dx # Assemble matrices A1 = assemble(a1) A2 = assemble(a2) A3 = assemble(a3) # Apply boundary conditions to matrices [bc.apply(A1) for bc in bcu] [bc.apply(A2) for bc in bcp] return u_, p_, u_1, p_1, L1, A1, L2, A2, L3, A3, bcu, bcp
def __init__(self, V): self.sol = Expression(sympy.printing.ccode(theta), degree=MAX_DEGREE, t=0.0, cell=triangle) self.V = V u = TrialFunction(V) v = TestFunction(V) self.M = assemble(u * v * dx) self.A = assemble(-inner(grad(u), grad(v)) * dx) self.bcs = DirichletBC(self.V, self.sol, 'on_boundary') return
def rollerBC(membrane): bc =[] if membrane.nsd==2: # bc.append(DirichletBC(membrane.V.sub(1), Constant(0), bd_all_1D)) bc.append(DirichletBC(membrane.V.sub(0), Constant(0), bd_x_mid_1D)) elif membrane.nsd==3: # This constrains the thickness at the support but is not plane strain bc.append(DirichletBC(membrane.V.sub(1), Constant(0), bd_all)) bc.append(DirichletBC(membrane.V.sub(0), Constant(0), bd_x_mid)) bc.append(DirichletBC(membrane.V.sub(2), Constant(0), bd_x)) return bc
def define_boundary_conditions(self): V = self.z.function_space() bc_clamped = [ DirichletBC(V.sub(1), Constant([0., 0.]), 'on_boundary'), DirichletBC(V.sub(2), Constant(0.), 'on_boundary') ] bc_free = [] bc_vert = [DirichletBC(V.sub(2), Constant(0.), 'on_boundary')] bc_horiz = [DirichletBC(V.sub(1), Constant([0., 0.]), 'on_boundary')] bcs = [bc_clamped, bc_free, bc_vert, bc_horiz] return bcs[self.bc_no]
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 dbcs_to_productspace(W, bcs_list): new_bcs = [] for k, bcs in enumerate(bcs_list): for bc in bcs: C = bc.function_space().component() # pylint: disable=len-as-condition if len(C) == 0: new_bcs.append(DirichletBC(W.sub(k), bc.value(), bc.domain_args[0])) else: assert len(C) == 1, "Illegal number of subspace components." new_bcs.append( DirichletBC(W.sub(k).sub(int(C[0])), bc.value(), bc.domain_args[0]) ) return new_bcs
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 cavity(): # Define mesh and boundaries. mesh = UnitSquareMesh(32, 32, "left/right") V = VectorFunctionSpace(mesh, "CG", 2) Q = FunctionSpace(mesh, "CG", 1) class LeftBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] < GMSH_EPS left_boundary = LeftBoundary() class RightBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[0] > 1.0 - GMSH_EPS right_boundary = RightBoundary() class LowerBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] < GMSH_EPS lower_boundary = LowerBoundary() class UpperBoundary(SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 1.0 - GMSH_EPS upper_boundary = UpperBoundary() # Boundary conditions for the velocity. u_bcs = [ DirichletBC(V, (0.0, 0.0), lower_boundary), DirichletBC(V, (0.0, 0.0), upper_boundary), DirichletBC(V, (0.0, 0.0), right_boundary), DirichletBC(V, (0.0, 0.0), left_boundary), ] p_bcs = [] return ( mesh, V, Q, u_bcs, p_bcs, [right_boundary], [upper_boundary, left_boundary, lower_boundary], )
def les_setup(u_, mesh, KineticEnergySGS, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving the Kinetic Energy SGS-model. """ DG = FunctionSpace(mesh, "DG", 0) CG1 = FunctionSpace(mesh, "CG", 1) dim = mesh.geometry().dim() delta = Function(DG) delta.vector().zero() delta.vector().axpy(1.0, assemble(TestFunction(DG) * dx)) delta.vector().set_local(delta.vector().array()**(1. / dim)) delta.vector().apply('insert') Ck = KineticEnergySGS["Ck"] ksgs = interpolate(Constant(1E-7), CG1) bc_ksgs = DirichletBC(CG1, 0, "on_boundary") A_mass = assemble_matrix(TrialFunction(CG1) * TestFunction(CG1) * dx) nut_form = Ck * delta * sqrt(ksgs) bcs_nut = derived_bcs(CG1, bcs['u0'], u_) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") At = Matrix() bt = Vector(nut_.vector()) ksgs_sol = KrylovSolver("bicgstab", "additive_schwarz") #ksgs_sol.parameters["preconditioner"]["structure"] = "same_nonzero_pattern" ksgs_sol.parameters["error_on_nonconvergence"] = False ksgs_sol.parameters["monitor_convergence"] = False ksgs_sol.parameters["report"] = False del NS_namespace return locals()
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 test_cmscr1d_weak_solution_zero_Dirichlet(self): print("Running test 'test_cmscr1d_weak_solution_zero_Dirichlet'") # Define temporal and spatial sample points. m, n = 10, 20 # Define mesh and function space. mesh = UnitSquareMesh(m - 1, n - 1) V = dh.create_function_space(mesh, 'default') W = dh.create_vector_function_space(mesh, 'default') # Define boundary conditions for velocity. bc = DirichletBC(W.sub(0), Constant(0), dh.DirichletBoundary()) # Create zero function. f = Function(V) # Compute velocity. v, k, res, fun, converged = cmscr1d_weak_solution(W, f, f.dx(0), f.dx(1), 1.0, 1.0, 1.0, 1.0, 1.0, bcs=bc) v = v.vector().get_local() k = k.vector().get_local() np.testing.assert_allclose(v.shape, m * n) np.testing.assert_allclose(v, np.zeros_like(v)) np.testing.assert_allclose(k.shape, m * n) np.testing.assert_allclose(k, np.zeros_like(k))
def _boundary_condition(self, *args, **kwargs): return DirichletBC( self._V, Constant( self.potential_behind_dome(self.RADIUS, *args, **kwargs)), self._boundaries, self.EXTERNAL_SURFACE)
# this option does not appear to be working at the moment: #parameters["num_threads"] = 6 mycomm = mpi_comm_world() myrank = MPI.rank(mycomm) # Domain, f-e spaces and boundary conditions: mesh = UnitSquareMesh(500,500) V = FunctionSpace(mesh, 'Lagrange', 2) # space for state and adjoint variables Vm = FunctionSpace(mesh, 'Lagrange', 1) # space for medium parameter Vme = FunctionSpace(mesh, 'Lagrange', 5) # sp for target med param # Define zero Boundary conditions: def u0_boundary(x, on_boundary): return on_boundary 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
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