def __init__(self, u_, Space, bcs=[], name="div", method={}): solver_type = method.get('solver_type', 'cg') preconditioner_type = method.get('preconditioner_type', 'default') solver_method = method.get('method', 'default') low_memory_version = method.get('low_memory_version', False) OasisFunction.__init__(self, div(u_), Space, bcs=bcs, name=name, method=solver_method, solver_type=solver_type, preconditioner_type=preconditioner_type) Source = u_[0].function_space() if not low_memory_version: self.matvec = [[A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], u_[i]] for i in range(Space.mesh().geometry().dim())] if solver_method.lower() == "gradient_matrix": from fenicstools import compiled_gradient_module DG = FunctionSpace(Space.mesh(), 'DG', 0) G = assemble(TrialFunction(DG) * self.test * dx()) dg = Function(DG) self.WGM = [] st = TrialFunction(Source) for i in range(Space.mesh().geometry().dim()): dP = assemble(st.dx(i) * TestFunction(DG) * dx) A = Matrix(G) self.WGM.append(compiled_gradient_module.compute_weighted_gradient_matrix(A, dP, dg))
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 __init__(self, V, Vm, bc, bcadj, \ RHSinput=[], ObsOp=[], UD=[], Regul=[], Data=[], plot=False, \ mycomm=None): # Define test, trial and all other functions self.trial = TrialFunction(V) self.test = TestFunction(V) self.mtrial = TrialFunction(Vm) self.mtest = TestFunction(Vm) self.rhs = Function(V) self.m = Function(Vm) self.mcopy = Function(Vm) self.srchdir = Function(Vm) self.delta_m = Function(Vm) self.MG = Function(Vm) self.Grad = Function(Vm) self.Gradnorm = 0.0 self.lenm = len(self.m.vector().array()) self.u = Function(V) self.ud = Function(V) self.diff = Function(V) self.p = Function(V) # Define weak forms to assemble A, C and E self._wkforma() self._wkformc() self._wkforme() # Store other info: self.ObsOp = ObsOp self.UD = UD self.reset() # Initialize U, C and E to [] self.Data = Data self.GN = 1.0 # GN = 0.0 => GN Hessian; = 1.0 => full Hessian # Operators and bc LinearOperator.__init__(self, self.delta_m.vector(), \ self.delta_m.vector()) self.bc = bc self.bcadj = bcadj self._assemble_solverM(Vm) self.assemble_A() self.assemble_RHS(RHSinput) self.Regul = Regul # Counters, tolerances and others self.nbPDEsolves = 0 # Updated when solve_A called self.nbfwdsolves = 0 # Counter for plots self.nbadjsolves = 0 # Counter for plots self._set_plots(plot) # MPI: self.mycomm = mycomm try: self.myrank = MPI.rank(self.mycomm) except: self.myrank = 0
def assemble_lui_stiffness(self, g, f, mesh, robin_boundary): V = FunctionSpace(mesh, "Lagrange", self.p) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) robin = MeshFunction('size_t', mesh, mesh.topology().dim() - 1) robin_boundary.mark(robin, 1) ds = Measure('ds', subdomain_data=robin) a = inner(grad(u), grad(v)) * dx b = (1 - g) * (inner(grad(u), n)) * v * ds(1) c = f * u * v * ds(1) k = lhs(a + b - c) K = PETScMatrix() assemble(k, tensor=K) return K, V
def run(): mesh = UnitSquareMesh(20, 20) V = FunctionSpace(mesh, 'Lagrange', 2) u = interpolate(Constant(2.0), V) sol = [] for ii in range(10000): #sol.append(u.copy(deepcopy=True)) #sol.append(u.vector().copy()) sol.append(u.vector().array()) test, trial = TestFunction(V), TrialFunction(V) M = assemble(inner(test, trial) * dx) m1 = np.random.randn(1000000).reshape((1000, 1000)) m2 = [] for ii in range(1000): m2.append(np.random.randn(1000))
def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__(self, os.path.join("test_eim_approximation_12_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (1., )) self.f = (1-x[0])*cos(3*pi*mu[0]*(1+x[0]))*exp(-mu[0]*(1+x[0])) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(f*g*dx)
def __init__(self, p_, Space, i=0, bcs=[], name="grad", method={}): assert len(p_.ufl_shape) == 0 assert i >= 0 and i < Space.mesh().geometry().dim() solver_type = method.get('solver_type', 'cg') preconditioner_type = method.get('preconditioner_type', 'default') solver_method = method.get('method', 'default') low_memory_version = method.get('low_memory_version', False) OasisFunction.__init__(self, p_.dx(i), Space, bcs=bcs, name=name, method=solver_method, solver_type=solver_type, preconditioner_type=preconditioner_type) self.i = i Source = p_.function_space() if not low_memory_version: self.matvec = [ A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], p_ ] if solver_method.lower() == "gradient_matrix": from fenicstools import compiled_gradient_module DG = FunctionSpace(Space.mesh(), 'DG', 0) G = assemble(TrialFunction(DG) * self.test * dx()) dg = Function(DG) dP = assemble( TrialFunction(p_.function_space()).dx(i) * TestFunction(DG) * dx()) self.WGM = compiled_gradient_module.compute_weighted_gradient_matrix( G, dP, dg)
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 _new_square_matrix(bc, val): from dolfin import TrialFunction, TestFunction from dolfin import assemble, Constant, inner, dx import numpy V = bc.function_space() u,v = TrialFunction(V),TestFunction(V) Z = assemble(Constant(0)*inner(u,v)*dx) if val != 0.0: lrange = range(*Z.local_range(0)) idx = numpy.ndarray(len(lrange), dtype=numpy.intc) idx[:] = lrange Z.ident(idx) if val != 1.0: Z *= val return Z
def test_is_zero_with_nabla(): mesh = UnitSquareMesh(4, 4) V1 = FunctionSpace(mesh, 'CG', 1) V2 = VectorFunctionSpace(mesh, 'CG', 1) v1 = TestFunction(V1) v2 = TrialFunction(V2) n = Constant([1, 1]) nn = dolfin.outer(n, n) vv = dolfin.outer(v2, v2) check_is_zero(dot(n, grad(v1)), 1) check_is_zero(dolfin.div(v2), 1) check_is_zero(dot(dolfin.div(nn), n), 0) check_is_zero(dot(dolfin.div(vv), n), 1) check_is_zero(dolfin.inner(nn, grad(v2)), 1)
def setUp(self): mesh = UnitSquareMesh(5, 5, 'crossed') self.V = FunctionSpace(mesh, 'Lagrange', 5) self.u = Function(self.V) self.uM = Function(self.V) self.uMdiag = Function(self.V) test = TestFunction(self.V) trial = TrialFunction(self.V) m = test * trial * dx self.M = assemble(m) self.solver = LUSolver() self.solver.parameters['reuse_factorization'] = True self.solver.parameters['symmetric'] = True self.solver.set_operator(self.M) self.ones = np.ones(self.V.dim())
def __init__(self, u_, Space, bcs=[], name="div", method={}): solver_type = method.get('solver_type', 'cg') preconditioner_type = method.get('preconditioner_type', 'default') solver_method = method.get('method', 'default') low_memory_version = method.get('low_memory_version', False) OasisFunction.__init__(self, div(u_), Space, bcs=bcs, name=name, method=solver_method, solver_type=solver_type, preconditioner_type=preconditioner_type) Source = u_[0].function_space() if not low_memory_version: self.matvec = [[ A_cache[(self.test * TrialFunction(Source).dx(i) * dx, ())], u_[i] ] for i in range(Space.mesh().geometry().dim())] if solver_method.lower() == "gradient_matrix": from fenicstools import compiled_gradient_module DG = FunctionSpace(Space.mesh(), 'DG', 0) G = assemble(TrialFunction(DG) * self.test * dx()) dg = Function(DG) self.WGM = [] st = TrialFunction(Source) for i in range(Space.mesh().geometry().dim()): dP = assemble(st.dx(i) * TestFunction(DG) * dx) A = Matrix(G) self.WGM.append( compiled_gradient_module.compute_weighted_gradient_matrix( A, dP, dg))
def compile_constraint_jacobian(self): """Compute first variation of constraint form. This method only has side effects. """ if self._constraint_form is None: raise NotImplementedError("Constraint form not registered.") # Fast return if first variation was already compiled. if self.__constraint_jacobian is not None: return du = TrialFunction(self.function_space) self.__constraint_jacobian = derivative(self._constraint_form, self.u, du) return
def field(self, state, x=None, lump=True, rhs_func=None): """ Returns the effective-field contribution for a given state. This method uses a projection method to retrieve the field from the RHS-form given by the :code:`form_rhs` method. It should be overriden for better performance. *Arguments* state (:class:`State`) the simulation state x (:class:`dolfin.Vector`) the vector to store the result or :code:`None` *Returns* :class:`dolfin.Function` the effective-field contribution """ # TODO set particular solver # TODO use caching for mass matrix if rhs_func is None: w = TestFunction(state.VectorFunctionSpace()) b = assemble( self.form_rhs(state, w) / Constant(Constants.gamma) * state.dx('magnetic')) else: b = rhs_func(state) # Optional mass lumping if x is None: result = Function(state.VectorFunctionSpace()) else: result = Function(state.VectorFunctionSpace(), x) if lump: A = state.M_inv_diag('magnetic') A.mult(b, result.vector()) else: w = TestFunction(state.VectorFunctionSpace()) h = TrialFunction(state.VectorFunctionSpace()) A = assemble(inner(w, h) * state.dx('magnetic')) solve(A, result.vector(), b) return result
def compute_velocity_correction( ui, p0, p1, u_bcs, rho, mu, dt, rotational_form, my_dx, tol, verbose ): """Compute the velocity correction according to .. math:: U = u_0 - \\frac{dt}{\\rho} \\nabla (p_1-p_0). """ W = ui.function_space() P = p1.function_space() u = TrialFunction(W) v = TestFunction(W) a3 = dot(u, v) * my_dx phi = Function(P) phi.assign(p1) if p0: phi -= p0 if rotational_form: r = SpatialCoordinate(W.mesh())[0] div_ui = 1 / r * (r * ui[0]).dx(0) + ui[1].dx(1) phi += mu * div_ui L3 = dot(ui, v) * my_dx - dt / rho * (phi.dx(0) * v[0] + phi.dx(1) * v[1]) * my_dx u1 = Function(W) solve( a3 == L3, u1, bcs=u_bcs, solver_parameters={ "linear_solver": "iterative", "symmetric": True, "preconditioner": "hypre_amg", "krylov_solver": { "relative_tolerance": tol, "absolute_tolerance": 0.0, "maximum_iterations": 100, "monitor_convergence": verbose, }, }, ) # u = project(ui - k/rho * grad(phi), V) # div_u = 1/r * div(r*u) r = SpatialCoordinate(W.mesh())[0] div_u1 = 1.0 / r * (r * u1[0]).dx(0) + u1[1].dx(1) info("||u||_div = {:e}".format(sqrt(assemble(div_u1 * div_u1 * my_dx)))) return u1
def generate_mesh_deformation(self): """ Generates an linear elastic mesh deformation using the steepest gradient as stress on the boundary. """ u, v = TrialFunction(self.S), TestFunction(self.S) def compute_mu(constant=True): """ Compute mu as according to arxiv paper https://arxiv.org/pdf/1509.08601.pdf """ mu_min=Constant(1) mu_max=Constant(500) if constant: return mu_max else: V = FunctionSpace(self.mesh, "CG",1) u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u),grad(v))*dx l = Constant(0)*v*dx bcs = [] for marker in self.move_dict["Fixed"]: bcs.append(DirichletBC(V, mu_min, self.mf, marker)) for marker in self.move_dict["Deform"]: bcs.append(DirichletBC(V, mu_max, self.mf, marker)) mu = Function(V) solve(a==l, mu, bcs=bcs) return mu mu = compute_mu(False) def epsilon(u): return sym(grad(u)) def sigma(u,mu=500, lmb=0): return 2*mu*epsilon(u) + lmb*tr(epsilon(u))*Identity(2) a = inner(sigma(u,mu=mu), grad(v))*dx L = inner(Constant((0,0)), v)*dx L -= self.dJ_form bcs = [] for marker in self.move_dict["Fixed"]: bcs.append(DirichletBC(self.S, Constant([0]*mesh.geometric_dimension()), self.mf, marker)) s = Function(self.S) solve(a==L, s, bcs=bcs) self.perturbation = s
def compile_objective_hessian(self): """Compute second variation of objective functional. This method only has side effects. """ # Fast return if second variation was already compiled. if self.__objective_hessian is not None: return # Make sure first variation was compiled. if self.__objective_gradient is None: self.compile_objective_gradient() du = TrialFunction(self.function_space) self.__objective_hessian = derivative(self.__objective_gradient, self.u, du) return
def __init__(self, VV): """ Input argument: VV = MixedFunctionSpace for both inversion parameters """ self.ab = Function(VV) self.abv = self.ab.vector() self.MG = Function(VV) # cost self.a, self.b = self.ab.split(deepcopy=True) self.cost = 0.5*( inner(nabla_grad(self.a), nabla_grad(self.a))*\ inner(nabla_grad(self.b), nabla_grad(self.b))*dx - \ inner(nabla_grad(self.a), nabla_grad(self.b))*\ inner(nabla_grad(self.a), nabla_grad(self.b))*dx ) # gradient testa, testb = TestFunction(VV) grada = inner( nabla_grad(testa), \ inner(nabla_grad(self.b), nabla_grad(self.b))*nabla_grad(self.a) - \ inner(nabla_grad(self.a), nabla_grad(self.b))*nabla_grad(self.b) )*dx gradb = inner( nabla_grad(testb), \ inner(nabla_grad(self.a), nabla_grad(self.a))*nabla_grad(self.b) - \ inner(nabla_grad(self.a), nabla_grad(self.b))*nabla_grad(self.a) )*dx self.grad = grada + gradb # Hessian self.ahat, self.bhat = self.ab.split(deepcopy=True) self.abhat = Function(VV) at, bt = TestFunction(VV) ah, bh = TrialFunction(VV) wkform11 = inner( nabla_grad(at), \ inner(nabla_grad(self.b), nabla_grad(self.b))*nabla_grad(ah) - \ inner(nabla_grad(ah), nabla_grad(self.b))*nabla_grad(self.b) )*dx # wkform21 = inner( nabla_grad(bt), \ 2*inner(nabla_grad(self.a), nabla_grad(ah))*nabla_grad(self.b) - \ inner(nabla_grad(self.a), nabla_grad(self.b))*nabla_grad(ah) - \ inner(nabla_grad(ah), nabla_grad(self.b))*nabla_grad(self.a) )*dx # wkform12 = inner( nabla_grad(at), \ 2*inner(nabla_grad(self.b), nabla_grad(bh))*nabla_grad(self.a) - \ inner(nabla_grad(self.a), nabla_grad(self.b))*nabla_grad(bh) - \ inner(nabla_grad(self.a), nabla_grad(bh))*nabla_grad(self.b) )*dx # wkform22 = inner( nabla_grad(bt), \ inner(nabla_grad(self.a), nabla_grad(self.a))*nabla_grad(bh) - \ inner(nabla_grad(self.a), nabla_grad(bh))*nabla_grad(self.a) )*dx # self.hessian = wkform11 + wkform21 + wkform12 + wkform22 self.precond = wkform11 + wkform22
def solve_elasticity(mesh: Mesh) -> Function: V = VectorFunctionSpace(mesh, 'P', 1) bc = DirichletBC(V, Constant((0, 0, 0)), lambda x, on_boundary: on_boundary and near(x[2], 0)) u = TrialFunction(V) v = TestFunction(V) f = Expression(('0', '0', '-rho*g'), rho=_c.rho, g=_c.g, degree=3) T = Constant((0, 0, 0)) a = inner(sigma(u), sym(nabla_grad(v))) * dx L = dot(f, v) * dx + dot(T, v) * ds u = Function(V) solve(a == L, u, bc) return u
def deformation_vector(): # n1 = VolumeNormal(multimesh.part(1)) x1 = SpatialCoordinate(multimesh.part(1)) n1 = as_vector((x1[1], x1[0])) S_sm = VectorFunctionSpace(multimesh.part(1), "CG", 1) #bcs = [DirichletBC(S_sm, Constant((0,0)), mfs[1],2), bcs = [DirichletBC(S_sm, n1, mfs[1], 1)] u, v = TrialFunction(S_sm), TestFunction(S_sm) a = inner(grad(u), grad(v)) * dx l = inner(Constant((0., 0.)), v) * dx n = Function(S_sm) solve(a == l, n, bcs=bcs) S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1) s = MultiMeshFunction(S) s.assign_part(1, n) return s
def __init__(self, N, dt): """Set up PDE problem for NxN mesh and time step dt.""" from dolfin import UnitSquareMesh, FunctionSpace, TrialFunction, \ TestFunction, Function, dx, dot, grad mesh = UnitSquareMesh(N, N) self.V = V = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(V) v = TestFunction(V) a = u * v * dx + dt * dot(grad(u), grad(v)) * dx self.a = a self.dt = dt self.mesh = mesh self.U = Function(V)
def __init__(self, energy, alpha, bcs, lb=None, ub=None): OptimisationProblem.__init__(self) self.energy = energy self.alpha = alpha self.V = self.alpha.function_space() self.denergy = derivative(self.energy, self.alpha, TestFunction(self.V)) self.ddenergy = derivative(self.denergy, self.alpha, TrialFunction(self.V)) if lb == None: lb = interpolate(Constant("0."), self.V) if ub == None: ub = interpolate(Constant("2."), self.V) self.lb = lb self.ub = ub self.bcs = bcs self.update_lb()
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 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 test_multi_ps_matrix_node_vector_fs(mesh): """Tests point source applied to a matrix with given constructor PointSource(V, source) and a vector function space when points placed at 3 vertices 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 = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * dot(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 array sums to correct value A.get_diagonal(w.vector()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2 * 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] = 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 assemble_matrices(self): V = VectorElement("Lagrange", self.mesh.ufl_cell(), self.lagrange_order, dim = 3) self._VComplex = FunctionSpace(self.mesh, V*V) u = TrialFunction(self._VComplex) (ur, ui) = split(u) v = TestFunction(self._VComplex) (vr, vi) = split(v) A_ij = None B_ij = None # construct matrices for each domain if not isinstance(self.materials, collections.Iterable): material = self.materials C = as_matrix(material.el.C) rho = material.el.rho DX = material.domain A_ij = LHS(self.q_b, C, ur, ui, vr, vi, DX) B_ij = RHS(rho, ur, ui, vr, vi, DX) else: counter = 0 # a work around for summing forms for material in self.materials: C = as_matrix(material.el.C) rho = material.el.rho DX = material.domain if counter == 0: A_ij = LHS(self.q_b, C, ur, ui, vr, vi, DX) B_ij = RHS(rho, ur, ui, vr, vi, DX) counter += 1 else: a_ij = LHS(self.q_b, C, ur, ui, vr, vi, DX) b_ij = RHS(rho, ur, ui, vr, vi, DX) A_ij += a_ij B_ij += b_ij # assemble the matrices assemble(A_ij, tensor=self._A) assemble(B_ij, tensor=self._B)
def test_krylov_reuse_pc_lu(): """Test that LU re-factorisation is only performed after set_operator(A) is called""" # Test requires PETSc version 3.5 or later. Use petsc4py to check # version number. try: from petsc4py import PETSc except ImportError: pytest.skip("petsc4py required to check PETSc version") else: if not PETSc.Sys.getVersion() >= (3, 5, 0): pytest.skip("PETSc version must be 3.5 of higher") mesh = UnitSquareMesh(MPI.comm_world, 12, 12) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = TrialFunction(V), TestFunction(V) a = Constant(1.0) * u * v * dx L = Constant(1.0) * v * dx assembler = fem.Assembler(a, L) A = assembler.assemble_matrix() b = assembler.assemble_vector() norm = 13.0 solver = PETScKrylovSolver(mesh.mpi_comm()) solver.set_options_prefix("test_lu_") PETScOptions.set("test_lu_ksp_type", "preonly") PETScOptions.set("test_lu_pc_type", "lu") solver.set_from_options() solver.set_operator(A) x = PETScVector(mesh.mpi_comm()) solver.solve(x, b) assert round(x.norm(cpp.la.Norm.l2) - norm, 10) == 0 assembler = fem.assemble.Assembler(Constant(0.5) * u * v * dx, L) assembler.assemble(A) x = PETScVector(mesh.mpi_comm()) solver.solve(x, b) assert round(x.norm(cpp.la.Norm.l2) - 2.0 * norm, 10) == 0 solver.set_operator(A) solver.solve(x, b) assert round(x.norm(cpp.la.Norm.l2) - 2.0 * norm, 10) == 0
def __init__(self, V, expression_type, basis_generation): self.V = V # Parametrized function to be interpolated mock_problem = MockProblem(V) f1 = ParametrizedExpression( mock_problem, "1/sqrt(pow(x[0]-mu[0], 2) + pow(x[1]-mu[1], 2) + 0.01)", mu=(-1., -1.), element=V.sub(1).ufl_element()) f2 = ParametrizedExpression( mock_problem, "exp( - 2*pow(x[0]-mu[0], 2) - 2*pow(x[1]-mu[1], 2) )", mu=(-1., -1.), element=V.sub(1).ufl_element()) f3 = ParametrizedExpression( mock_problem, "(1-x[0])*cos(3*pi*(pi+mu[1])*(1+x[1]))*exp(-(pi+mu[0])*(1+x[0]))", mu=(-1., -1.), element=V.sub(1).ufl_element()) # folder_prefix = os.path.join("test_eim_approximation_05_tempdir", expression_type, basis_generation) assert expression_type in ("Vector", "Matrix") if expression_type == "Vector": vq = TestFunction(V) (v, q) = split(vq) form = f1 * v[0] * dx + f2 * v[1] * dx + f3 * q * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) elif expression_type == "Matrix": up = TrialFunction(V) vq = TestFunction(V) (u, p) = split(up) (v, q) = split(vq) form = f1 * inner(grad(u), grad(v)) * dx + f2 * p * div( v) * dx + f3 * q * div(u) * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) else: # impossible to arrive here anyway thanks to the assert raise AssertionError("Invalid expression_type")
def __init__(self, truth_problem, expression_type, basis_generation): self.V = truth_problem.V1 (f0, _) = split(truth_problem._solution) # folder_prefix = os.path.join("test_eim_approximation_15_tempdir", expression_type, basis_generation) assert expression_type in ("Vector", "Matrix") if expression_type == "Vector": v = TestFunction(self.V) form = inner(f0, grad(v))*dx # Call Parent constructor EIMApproximation.__init__(self, truth_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) elif expression_type == "Matrix": u = TrialFunction(self.V) v = TestFunction(self.V) form = inner(f0, grad(u))*v*dx # Call Parent constructor EIMApproximation.__init__(self, truth_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) else: # impossible to arrive here anyway thanks to the assert raise AssertionError("Invalid expression_type")
def __init__(self, energy, alpha, bcs, lb=None, ub=None): NonlinearProblem.__init__(self) self.energy = energy self.alpha = alpha self.V = self.alpha.function_space() self.denergy = derivative(self.energy, self.alpha, TestFunction(self.V)) self.ddenergy = derivative(self.denergy, self.alpha, TrialFunction(self.V)) if lb == None: lb = interpolate(Constant("0."), self.V) if ub == None: ub = interpolate(Constant("1."), self.V) self.lb = lb self.ub = ub self.bcs = bcs self.b = PETScVector() self.A = PETScMatrix()
def test_numba_assembly(): mesh = UnitSquareMesh(MPI.comm_world, 13, 13) Q = FunctionSpace(mesh, "Lagrange", 1) u = TrialFunction(Q) v = TestFunction(Q) a = cpp.fem.Form([Q._cpp_object, Q._cpp_object]) L = cpp.fem.Form([Q._cpp_object]) sig = types.void(types.CPointer(typeof(ScalarType())), types.CPointer(types.CPointer(typeof(ScalarType()))), types.CPointer(types.double), types.intc) fnA = cfunc(sig, cache=True)(tabulate_tensor_A) a.set_cell_tabulate(0, fnA.address) fnb = cfunc(sig, cache=True)(tabulate_tensor_b) L.set_cell_tabulate(0, fnb.address) if (False): ufc_form = ffc_jit(dot(grad(u), grad(v)) * dx) ufc_form = cpp.fem.make_ufc_form(ufc_form[0]) a = cpp.fem.Form(ufc_form, [Q._cpp_object, Q._cpp_object]) ufc_form = ffc_jit(v * dx) ufc_form = cpp.fem.make_ufc_form(ufc_form[0]) L = cpp.fem.Form(ufc_form, [Q._cpp_object]) assembler = cpp.fem.Assembler([[a]], [L], []) A = PETScMatrix() b = PETScVector() assembler.assemble(A, cpp.fem.Assembler.BlockType.monolithic) assembler.assemble(b, cpp.fem.Assembler.BlockType.monolithic) Anorm = A.norm(cpp.la.Norm.frobenius) bnorm = b.norm(cpp.la.Norm.l2) print(Anorm, bnorm) assert (np.isclose(Anorm, 56.124860801609124)) assert (np.isclose(bnorm, 0.0739710713711999)) list_timings([TimingType.wall])
def main_slice_fem(mesh, subdomains, boundaries, src_pos, snk_pos): sigma_ROI = Constant(params.sigma_roi) sigma_SLICE = Constant(params.sigma_slice) sigma_SALINE = Constant(params.sigma_saline) sigma_AIR = Constant(0.) V = FunctionSpace(mesh, "CG", 2) v = TestFunction(V) u = TrialFunction(V) phi = Function(V) dx = Measure("dx")(subdomain_data=subdomains) ds = Measure("ds")(subdomain_data=boundaries) a = inner(sigma_ROI * grad(u), grad(v))*dx(params.roivol) + \ inner(sigma_SLICE * grad(u), grad(v))*dx(params.slicevol) + \ inner(sigma_SALINE * grad(u), grad(v))*dx(params.salinevol) L = Constant(0) * v * dx A = assemble(a) b = assemble(L) x_pos, y_pos, z_pos = src_pos point = Point(x_pos, y_pos, z_pos) delta = PointSource(V, point, 1.) delta.apply(b) x_pos, y_pos, z_pos = snk_pos point1 = Point(x_pos, y_pos, z_pos) delta1 = PointSource(V, point1, -1.) delta1.apply(b) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = 1000 solver.parameters["absolute_tolerance"] = 1E-8 solver.parameters["monitor_convergence"] = True info(solver.parameters, True) # set_log_level(PROGRESS) does not work in fenics 2018.1.0 solver.solve(A, phi.vector(), b) ele_pos_list = params.ele_coords vals = extract_pots(phi, ele_pos_list) # np.save(os.path.join('results', save_as), vals) return vals
def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__(self, os.path.join("test_eim_approximation_15_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u", "s", "p"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (-1., -1.)) self.f00 = 1./sqrt(pow(x[0]-mu[0], 2) + pow(x[1]-mu[1], 2) + 0.01) self.f01 = 1./sqrt(pow(x[0]-mu[0], 4) + pow(x[1]-mu[1], 4) + 0.01) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(inner(f, g)*dx) # Collapsed vector and space self.V0 = V.sub(0).collapse() self.V00 = V.sub(0).sub(0).collapse() self.V1 = V.sub(1).collapse()
def les_setup(u_, mesh, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving the Germano Dynamic LES model applying Lagrangian Averaging. """ # Create function spaces CG1 = FunctionSpace(mesh, "CG", 1) p, q = TrialFunction(CG1), TestFunction(CG1) dim = mesh.geometry().dim() # Define delta and project delta**2 to CG1 delta = pow(CellVolume(mesh), 1. / dim) delta_CG1_sq = project(delta, CG1) delta_CG1_sq.vector().set_local(delta_CG1_sq.vector().array()**2) delta_CG1_sq.vector().apply("insert") # Define nut_ Sij = sym(grad(u_)) magS = sqrt(2 * inner(Sij, Sij)) Cs = Function(CG1) nut_form = Cs**2 * delta**2 * magS # Create nut_ BCs ff = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) bcs_nut = [] for i, bc in enumerate(bcs['u0']): bc.apply(u_[0].vector()) # Need to initialize bc m = bc.markers() # Get facet indices of boundary ff.array()[m] = i + 1 bcs_nut.append(DirichletBC(CG1, Constant(0), ff, i + 1)) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") # Create functions for holding the different velocities u_CG1 = as_vector([Function(CG1) for i in range(dim)]) u_filtered = as_vector([Function(CG1) for i in range(dim)]) dummy = Function(CG1) ll = LagrangeInterpolator() # Assemble required filter matrices and functions G_under = Function(CG1, assemble(TestFunction(CG1) * dx)) G_under.vector().set_local(1. / G_under.vector().array()) G_under.vector().apply("insert") G_matr = assemble(inner(p, q) * dx) # Set up functions for Lij and Mij Lij = [Function(CG1) for i in range(dim * dim)] Mij = [Function(CG1) for i in range(dim * dim)] # Check if case is 2D or 3D and set up uiuj product pairs and # Sij forms, assemble required matrices Sijcomps = [Function(CG1) for i in range(dim * dim)] Sijfcomps = [Function(CG1) for i in range(dim * dim)] # Assemble some required matrices for solving for rate of strain terms Sijmats = [assemble_matrix(p.dx(i) * q * dx) for i in range(dim)] if dim == 3: tensdim = 6 uiuj_pairs = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)) else: tensdim = 3 uiuj_pairs = ((0, 0), (0, 1), (1, 1)) # Set up Lagrange functions JLM = Function(CG1) JLM.vector()[:] += 1E-32 JMM = Function(CG1) JMM.vector()[:] += 1 return dict(Sij=Sij, nut_form=nut_form, nut_=nut_, delta=delta, bcs_nut=bcs_nut, delta_CG1_sq=delta_CG1_sq, CG1=CG1, Cs=Cs, u_CG1=u_CG1, u_filtered=u_filtered, ll=ll, Lij=Lij, Mij=Mij, Sijcomps=Sijcomps, Sijfcomps=Sijfcomps, Sijmats=Sijmats, JLM=JLM, JMM=JMM, dim=dim, tensdim=tensdim, G_matr=G_matr, G_under=G_under, dummy=dummy, uiuj_pairs=uiuj_pairs)
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
class ObjectiveFunctional(LinearOperator): """ Provides data misfit, gradient and Hessian information for the data misfit part of a time-independent symmetric inverse problem. """ __metaclass__ = abc.ABCMeta # Instantiation def __init__(self, V, Vm, bc, bcadj, \ RHSinput=[], ObsOp=[], UD=[], Regul=[], Data=[], plot=False, \ mycomm=None): # Define test, trial and all other functions self.trial = TrialFunction(V) self.test = TestFunction(V) self.mtrial = TrialFunction(Vm) self.mtest = TestFunction(Vm) self.rhs = Function(V) self.m = Function(Vm) self.mcopy = Function(Vm) self.srchdir = Function(Vm) self.delta_m = Function(Vm) self.MG = Function(Vm) self.Grad = Function(Vm) self.Gradnorm = 0.0 self.lenm = len(self.m.vector().array()) self.u = Function(V) self.ud = Function(V) self.diff = Function(V) self.p = Function(V) # Define weak forms to assemble A, C and E self._wkforma() self._wkformc() self._wkforme() # Store other info: self.ObsOp = ObsOp self.UD = UD self.reset() # Initialize U, C and E to [] self.Data = Data self.GN = 1.0 # GN = 0.0 => GN Hessian; = 1.0 => full Hessian # Operators and bc LinearOperator.__init__(self, self.delta_m.vector(), \ self.delta_m.vector()) self.bc = bc self.bcadj = bcadj self._assemble_solverM(Vm) self.assemble_A() self.assemble_RHS(RHSinput) self.Regul = Regul # Counters, tolerances and others self.nbPDEsolves = 0 # Updated when solve_A called self.nbfwdsolves = 0 # Counter for plots self.nbadjsolves = 0 # Counter for plots self._set_plots(plot) # MPI: self.mycomm = mycomm try: self.myrank = MPI.rank(self.mycomm) except: self.myrank = 0 def copy(self): """Define a copy method""" V = self.trial.function_space() Vm = self.mtrial.function_space() newobj = self.__class__(V, Vm, self.bc, self.bcadj, [], self.ObsOp, \ self.UD, self.Regul, self.Data, False) newobj.RHS = self.RHS newobj.update_m(self.m) return newobj def mult(self, mhat, y): """mult(self, mhat, y): do y = Hessian * mhat member self.GN sets full Hessian (=1.0) or GN Hessian (=0.0)""" N = self.Nbsrc # Number of sources y[:] = np.zeros(self.lenm) for C, E in zip(self.C, self.E): # Solve for uhat C.transpmult(mhat, self.rhs.vector()) self.bcadj.apply(self.rhs.vector()) self.solve_A(self.u.vector(), -self.rhs.vector()) # Solve for phat E.transpmult(mhat, self.rhs.vector()) Etmhat = self.rhs.vector().array() self.rhs.vector().axpy(1.0, self.ObsOp.incradj(self.u)) self.bcadj.apply(self.rhs.vector()) self.solve_A(self.p.vector(), -self.rhs.vector()) # Compute Hessian*x: y.axpy(1.0/N, C * self.p.vector()) y.axpy(self.GN/N, E * self.u.vector()) y.axpy(1.0, self.Regul.hessian(mhat)) # Getters def getm(self): return self.m def getmarray(self): return self.m.vector().array() def getmcopyarray(self): return self.mcopy.vector().array() def getVm(self): return self.mtrial.function_space() def getMGarray(self): return self.MG.vector().array() def getMGvec(self): return self.MG.vector() def getGradarray(self): return self.Grad.vector().array() def getGradnorm(self): return self.Gradnorm def getsrchdirarray(self): return self.srchdir.vector().array() def getsrchdirvec(self): return self.srchdir.vector() def getsrchdirnorm(self): return np.sqrt((self.MM*self.getsrchdirvec()).inner(self.getsrchdirvec())) def getgradxdir(self): return self.gradxdir def getcost(self): return self.cost, self.misfit, self.regul def getprecond(self): Prec = PETScKrylovSolver("richardson", "amg") Prec.parameters["maximum_iterations"] = 1 Prec.parameters["error_on_nonconvergence"] = False Prec.parameters["nonzero_initial_guess"] = False Prec.set_operator(self.Regul.get_precond()) return Prec def getMass(self): return self.MM # Setters def setsrchdir(self, arr): self.srchdir.vector()[:] = arr def setgradxdir(self, valueloc): """Sum all local results for Grad . Srch_dir""" try: valueglob = MPI.sum(self.mycomm, valueloc) except: valueglob = valueloc self.gradxdir = valueglob # Solve def solvefwd(self, cost=False): """Solve fwd operators for given RHS""" self.nbfwdsolves += 1 if self.ObsOp.noise: self.noise = 0.0 if self.plot: self.plotu = PlotFenics(self.plotoutdir) self.plotu.set_varname('u{0}'.format(self.nbfwdsolves)) if cost: self.misfit = 0.0 for ii, rhs in enumerate(self.RHS): self.solve_A(self.u.vector(), rhs) if self.plot: self.plotu.plot_vtk(self.u, ii) u_obs, noiselevel = self.ObsOp.obs(self.u) self.U.append(u_obs) if self.ObsOp.noise: self.noise += noiselevel if cost: self.misfit += self.ObsOp.costfct(u_obs, self.UD[ii]) self.C.append(assemble(self.c)) if cost: self.misfit /= len(self.U) self.regul = self.Regul.cost(self.m) self.cost = self.misfit + self.regul if self.ObsOp.noise and self.myrank == 0: print 'Total noise in data misfit={:.5e}\n'.\ format(self.noise*.5/len(self.U)) self.ObsOp.noise = False # Safety if self.plot: self.plotu.gather_vtkplots() def solvefwd_cost(self): """Solve fwd operators for given RHS and compute cost fct""" self.solvefwd(True) def solveadj(self, grad=False): """Solve adj operators""" self.nbadjsolves += 1 if self.plot: self.plotp = PlotFenics(self.plotoutdir) self.plotp.set_varname('p{0}'.format(self.nbadjsolves)) self.Nbsrc = len(self.UD) if grad: self.MG.vector()[:] = np.zeros(self.lenm) for ii, C in enumerate(self.C): self.ObsOp.assemble_rhsadj(self.U[ii], self.UD[ii], \ self.rhs, self.bcadj) self.solve_A(self.p.vector(), self.rhs.vector()) if self.plot: self.plotp.plot_vtk(self.p, ii) self.E.append(assemble(self.e)) if grad: self.MG.vector().axpy(1.0/self.Nbsrc, \ C * self.p.vector()) if grad: self.MG.vector().axpy(1.0, self.Regul.grad(self.m)) self.solverM.solve(self.Grad.vector(), self.MG.vector()) self.Gradnorm = np.sqrt(self.Grad.vector().inner(self.MG.vector())) if self.plot: self.plotp.gather_vtkplots() def solveadj_constructgrad(self): """Solve adj operators and assemble gradient""" self.solveadj(True) # Assembler def assemble_A(self): """Assemble operator A(m)""" self.A = assemble(self.a) self.bc.apply(self.A) self.set_solver() def solve_A(self, b, f): """Solve system of the form A.b = f, with b and f in form to be used in solver.""" self.solver.solve(b, f) self.nbPDEsolves += 1 def assemble_RHS(self, RHSin): """Assemble RHS for fwd solve""" if RHSin == []: self.RHS = None else: self.RHS = [] for rhs in RHSin: if isinstance(rhs, Expression): L = rhs*self.test*dx b = assemble(L) self.bc.apply(b) self.RHS.append(b) else: raise WrongInstanceError("rhs should be Expression") def _assemble_solverM(self, Vm): self.MM = assemble(inner(self.mtrial, self.mtest)*dx) self.solverM = LUSolver() self.solverM.parameters['reuse_factorization'] = True self.solverM.parameters['symmetric'] = True self.solverM.set_operator(self.MM) def _set_plots(self, plot): self.plot = plot if self.plot: filename, ext = splitext(sys.argv[0]) self.plotoutdir = filename + '/Plots/' self.plotvarm = PlotFenics(self.plotoutdir) self.plotvarm.set_varname('m') def plotm(self, index): if self.plot: self.plotvarm.plot_vtk(self.m, index) def gatherm(self): if self.plot: self.plotvarm.gather_vtkplots() # Update param def update_Data(self, Data): """Update Data member""" self.Data = Data self.assemble_A() self.reset() def update_m(self, m): """Update values of parameter m""" if isinstance(m, np.ndarray): self.m.vector()[:] = m elif isinstance(m, Function): self.m.assign(m) elif isinstance(m, float): self.m.vector()[:] = m elif isinstance(m, int): self.m.vector()[:] = float(m) else: raise WrongInstanceError('Format for m not accepted') self.assemble_A() self.reset() def backup_m(self): self.mcopy.assign(self.m) def restore_m(self): self.update_m(self.mcopy) def reset(self): """Reset U, C and E""" self.U = [] self.C = [] self.E = [] def set_solver(self): """Reset solver for fwd operator""" self.solver = LUSolver() self.solver.parameters['reuse_factorization'] = True self.solver.set_operator(self.A) def addPDEcount(self, increment=1): """Increase 'nbPDEsolves' by 'increment'""" self.nbPDEsolves += increment def resetPDEsolves(self): self.nbPDEsolves = 0 # Additional methods for compatibility with CG solver: def init_vector(self, x, dim): """Initialize vector x to be compatible with parameter Does not work in dolfin 1.3.0""" self.MM.init_vector(x, 0) def init_vector130(self): """Initialize vector x to be compatible with parameter""" return Vector(Function(self.mcopy.function_space()).vector()) # Abstract methods @abc.abstractmethod def _wkforma(self): self.a = [] @abc.abstractmethod def _wkformc(self): self.c = [] @abc.abstractmethod def _wkforme(self): self.e = []
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)