def __init__(self, mesh, FuncSpace_dict, beta_map=Constant(1e-6), ds=ds): """ Instantiate FormsPDEMap Parameters ---------- mesh: dolfin.Mesh Dolfin Mesh FuncSpace_dict: dict Dictionary containing the function space definitions. Following keys are required: - FuncSpace_local: function space for local variable - FuncSpace_lambda: function space for Lagrange multiplier - FuncSpace_bar: function space for control variable beta_map: dolfin.Constant, optional Penalty/Regularizatio term to establish coupling between local unknown and control. Defaults to Constant(1e-6) ds: dolfin.Measure, optional ds Measure of mesh """ self.W = FuncSpace_dict["FuncSpace_local"] self.T = FuncSpace_dict["FuncSpace_lambda"] self.Wbar = FuncSpace_dict["FuncSpace_bar"] self.n = FacetNormal(mesh) self.beta_map = beta_map self.ds = ds self.gdim = mesh.geometry().dim()
def solve(self, dt): self.u = Function(self.V0) self.w = TestFunction(self.V0) self.du = TrialFunction(self.V0) x = SpatialCoordinate(self.mesh0) L = inner( self.S(), self.eps(self.w) )*dx(degree=4)\ - inner( self.b, self.w )*dx(degree=4)\ - inner( self.h, self.w )*ds(degree=4)\ + inner( 1e-6*self.u, self.w )*ds(degree=4)\ - inner( min_value(x[2]+self.ut[2]+self.u[2], 0) * Constant((0,0,-1.0)), self.w )*ds(degree=4) a = derivative(L, self.u, self.du) problem = NonlinearVariationalProblem(L, self.u, bcs=[], J=a) solver = NonlinearVariationalSolver(problem) solver.solve() self.ut.vector()[:] = self.ut.vector()[:] + self.u.vector()[:] ALE.move(self.mesh, Function(self.V, self.u.vector())) self.v.vector()[:] = self.u.vector()[:] / dt self.n = FacetNormal(self.mesh)
def create_coupling_neumann_boundary_condition(self, test_functions, function_space=None, boundary_marker=None): """Creates the coupling Neumann boundary conditions using create_coupling_boundary_condition() method. :return: expression in form of integral: g*v*ds. (see e.g. p. 83ff Langtangen, Hans Petter, and Anders Logg. "Solving PDEs in Python The FEniCS Tutorial Volume I." (2016).) """ if not function_space: self._function_space = test_functions.function_space() else: self._function_space = function_space self._create_coupling_boundary_condition() if not boundary_marker: # there is only 1 Neumann-BC which is at the coupling boundary -> integration over whole boundary if self._coupling_bc_expression.is_scalar_valued(): return test_functions * self._coupling_bc_expression * dolfin.ds # this term has to be added to weak form to add a Neumann BC (see e.g. p. 83ff Langtangen, Hans Petter, and Anders Logg. "Solving PDEs in Python The FEniCS Tutorial Volume I." (2016).) elif self._coupling_bc_expression.is_vector_valued(): n = FacetNormal(self._mesh_fenics) return -test_functions * dot( n, self._coupling_bc_expression) * dolfin.ds else: raise Exception("invalid!") else: # For multiple Neumann BCs integration should only be performed over the respective domain. # TODO: fix the problem here raise Exception("Boundary markers are not implemented yet") return dot(self._coupling_bc_expression, test_functions) * self.dss(boundary_marker)
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, u_k, vu = domain.u, domain.u_1, domain.u_k, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho*inner((u-u_1)/dt, vu) * dx convection = dot(div(rho*outer(u_k, u)), vu) * dx convection = rho*dot(dot(u_k, nabla_grad(u)), vu) * dx pressure = (inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds) diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # good # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx # + dot(mu * (grad(u) + grad(u).T)*n, vu)*ds) # very slow! # F_impl = acceleration + convection + pressure + diffusion # dot(u_1, nabla_grad(u_1)) works # dot(u, nabla_grad(u_1)) does not change! u_mid = (u + u_1) / 2.0 F_impl = 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 self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def __init__(self, domain): rho, mu, dt, g = domain.rho, domain.mu, domain.dt, domain.g u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds body_force = dot(g*rho, vu)*dx \ + dot(Constant((0.0, 0.0)), vu) * ds # diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu))*dx # + dot(mu * (grad(u_1) + grad(u_1).T)*n, vu)*ds) # just fine # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # just fine # just fine, but horribly slow in combination with ??? -> not reproducable diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu)) * dx + dot(mu * (grad(u) + grad(u).T) * n, vu) * ds) # convection = rho*dot(dot(u, nabla_grad(u_1)), vu) * dx # no vortices convection = rho * dot(dot(u_1, nabla_grad(u)), vu) * dx # stabilization = -gamma*psi_p*p_1 # convection = dot(div(rho * outer(u_1, u_1)), vu) * dx # not stable! # convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx # just fine F_impl = -acceleration - convection + diffusion + pressure + body_force self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def _rhs(self, degree, y): base_potential = Expression(f''' 0.25 / ({np.pi * self.BASE_CONDUCTIVITY}) / sqrt((x[0])*(x[0]) + (x[1] - {y})*(x[1] - {y}) + (x[2])*(x[2])) ''', degree=degree, domain=self._mesh) n = FacetNormal(self._mesh) return -sum( (inner((Constant(c - self.BASE_CONDUCTIVITY) * grad(base_potential)), grad(self._v)) * self._dx(x) for x, c in self.CONDUCTIVITY.items() if c != self.BASE_CONDUCTIVITY), # # Eq. 20 at Piastra et al 2018 # sum((Constant(self.BASE_CONDUCTIVITY) # * inner(n, grad(self._base_potential)) # * self._v # * self._ds(s)) # for s in self.SURFACE_CONDUCTIVITY) # Eq. 19 at Piastra et al 2018 sum((Constant(c) * inner(n, grad(base_potential)) * self._v * self._ds(s)) for s, c in self.SURFACE_CONDUCTIVITY.items()))
def update_multimesh(self, step): move_norm = [] hmins = [] move_max = [] for i in range(1, self.N): s_move = self.deformation[i - 1].copy(True) s_move.vector()[:] *= step # Approximate geodesic distance dDeform = Measure("ds", subdomain_data=self.mfs[i]) n_i = FacetNormal(self.multimesh.part(i)) geo_dist_i = inner(s_move, s_move)*\ dDeform(self.move_dict[i]["Deform"]) move_norm.append(assemble(geo_dist_i)) # move_max.append(project(sqrt(s_move[0]**2 + s_move[1]**2), # FunctionSpace(self.multimesh.part(i),"CG",1) # ).vector().max()) # hmins.append(self.multimesh.part(i).hmin()) ALE.move(self.multimesh.part(i), s_move) # Compute L2 norm of movement self.move_norm = sqrt(sum(move_norm)) # self.move_max = max(move_max) # print(hmins, move_max) self.multimesh.build() for key in self.cover_points.keys(): self.multimesh.auto_cover(key, self.cover_points[key])
def facet_normal(self): """ Returns symbolic outward unit normal to the boundary facets. :returns: unit normal vector :rtype: :py:class:`ufl.geometry.FacetNormal` """ return FacetNormal(self._mesh)
def __init__(self, mesh, FuncSpace_dict, beta_map=Constant(1E-6), ds=ds): self.W = FuncSpace_dict['FuncSpace_local'] self.T = FuncSpace_dict['FuncSpace_lambda'] self.Wbar = FuncSpace_dict['FuncSpace_bar'] self.n = FacetNormal(mesh) self.beta_map = beta_map self.ds = ds self.gdim = mesh.geometry().dim()
def __init__(self, mesh, FuncSpaces_L, FuncSpaces_G, alpha, beta_stab=Constant(0.0), ds=ds): self.mixedL = FuncSpaces_L self.mixedG = FuncSpaces_G self.n = FacetNormal(mesh) self.beta_stab = beta_stab self.alpha = alpha self.he = CellDiameter(mesh) self.ds = ds self.gdim = mesh.geometry().dim()
def fit(x0, y0, mesh, Eps, degree=1, verbose=False, solver='spsolve'): V = FunctionSpace(mesh, 'CG', degree) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) dim = mesh.geometry().dim() A = [ _assemble_eigen(+Constant(Eps[i, j]) * u.dx(i) * v.dx(j) * dx # pylint: disable=unsubscriptable-object - Constant(Eps[i, j]) * u.dx(i) * n[j] * v * ds).sparray() for i in range(dim) for j in range(dim) ] E = _build_eval_matrix(V, x0) M = sparse.vstack(A + [E]) b = numpy.concatenate([numpy.zeros(sum(a.shape[0] for a in A)), y0]) if solver == 'spsolve': MTM = M.T.dot(M) x = sparse.linalg.spsolve(MTM, M.T.dot(b)) elif solver == 'lsqr': x, istop, *_ = sparse.linalg.lsqr( M, b, show=verbose, atol=1.0e-10, btol=1.0e-10, ) assert istop == 2, \ 'sparse.linalg.lsqr not successful (error code {})'.format(istop) elif solver == 'lsmr': x, istop, *_ = sparse.linalg.lsmr( M, b, show=verbose, atol=1.0e-10, btol=1.0e-10, # min(M.shape) is the default maxiter=max(min(M.shape), 10000)) assert istop == 2, \ 'sparse.linalg.lsmr not successful (error code {})'.format(istop) else: assert solver == 'gmres', 'Unknown solver \'{}\'.'.format(solver) A = sparse.linalg.LinearOperator((M.shape[1], M.shape[1]), matvec=lambda x: M.T.dot(M.dot(x))) x, info = sparse.linalg.gmres(A, M.T.dot(b), tol=1.0e-12) assert info == 0, \ 'sparse.linalg.gmres not successful (error code {})'.format(info) u = Function(V) u.vector().set_local(x) return u
def 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 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 __init__(self, domain): rho, mu, dt = domain.rho, domain.mu, domain.dt u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu)) * dx + dot(mu * (grad(u_1) + grad(u_1).T) * n, vu) * ds) pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx F_impl = -acceleration - convection + diffusion + pressure self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def set_form(self, form): """ This function is called by simulator.set_form to set up the equations for the electric field. This function will add the poisson equation to the variational form. Args: form: A FEniCS variational form. """ # gather some variables v, d = self.simulator.v_phi, self.simulator.d_phi psi = self.simulator.psi sigma = interpolate(Constant(0), self.simulator.geometry.V) b = interpolate(Constant(0), self.simulator.geometry.V) # calculate sigma and b (used in boundary condition) for ion in self.simulator.ion_list: sigma += (1. / psi) * ion.z**2 * ion.D * ion.c b += ion.z * ion.D * ion.c # boundary condition g = inner( nabla_grad(b) / sigma, FacetNormal(self.simulator.geometry.mesh)) # gather constants F = Constant(self.simulator.F) eps = Constant(self.simulator.epsilon) rho = Function(self.simulator.geometry.V) # calculate rho for ion in self.simulator.ion_list: rho += F * ion.z * ion.c_new self.rho = rho # update variational form form += (inner(nabla_grad(self.phi_new), nabla_grad(v)) + self.dummy_new * v + self.phi_new * d - rho * v / eps) * dx form += g * v * ds v, d = self.simulator.v_phi_ps, self.simulator.d_phi_ps form += (inner(nabla_grad(self.phi_ps_new), nabla_grad(v)) + self.phi_ps_new * d + v * self.dummy_ps_new) * dx return form
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 __init__(self, domain): rho, mu, dt = domain.rho, domain.mu, domain.dt u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.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) A1 = assemble(a1) [bc.apply(A1) for bc in domain.bcu] self.a1, self.L1, self.A1 = a1, L1, A1 self.domain = domain return
def generate_H1_deformation(self): self.deformation = [] for i in range(1, self.N): S_i = VectorFunctionSpace(self.multimesh.part(i), "CG", 1) u_i, v_i = TrialFunction(S_i), TestFunction(S_i) d_free = Measure("ds", domain=self.multimesh.part(i), subdomain_data=self.mfs[i], subdomain_id=self.move_dict[i]["Deform"]) plot(-self.integrand_list[i - 1]) plt.show() a_i = inner(u_i, v_i) * dx + 0.01 * inner(grad(u_i), grad(v_i)) * dx n_i = FacetNormal(self.multimesh.part(i)) l_i = inner(v_i, -self.integrand_list[i - 1]) * d_free s_i = Function(S_i) solve(a_i == l_i, s_i) plot(s_i) plt.show() self.deformation.append(s_i)
def __init__(self, mesh, FuncSpaces_L, FuncSpaces_G, alpha, h_d=[ Expression(('0.0', '0.0'), degree=3), Expression(('0.0', '0.0'), degree=3) ], beta_stab=Constant(0.), ds=ds): self.mixedL = FuncSpaces_L self.mixedG = FuncSpaces_G self.n = FacetNormal(mesh) self.beta_stab = beta_stab self.alpha = alpha self.he = CellDiameter(mesh) self.h_d = h_d self.ds = ds self.gdim = mesh.geometry().dim()
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.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) A1 = assemble(a1) [bc.apply(A1) for bc in domain.bcu] self.a1, self.L1, self.A1 = a1, L1, A1 self.domain = domain return
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu n = FacetNormal(domain.mesh) acceleration = rho*inner((u-u_1)/dt, vu) * dx convection = dot(div(rho*outer(u_1, u)), vu) * dx diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu))*dx + dot(mu * (grad(u_1) + grad(u_1).T)*n, vu)*ds) pressure = inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds # int. by parts # TODO: what is better? # convection = rho*dot(dot(u_1, nabla_grad(u_k)), vu) * dx # diffusion = (mu*inner(grad(u_1), grad(vu))*dx # - mu*dot(nabla_grad(u_1)*n, vu)*ds) # int. by parts F_impl = - acceleration - convection + diffusion + pressure self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def adaptive(self, mesh, eigv, eigf): """Refine mesh based on residual errors.""" fraction = 0.1 C = FunctionSpace(mesh, "DG", 0) # constants on triangles w = TestFunction(C) h = CellSize(mesh) n = FacetNormal(mesh) marker = CellFunction("bool", mesh) print len(marker) indicators = np.zeros(len(marker)) for e, u in zip(eigv, eigf): errform = avg(h) * jump(grad(u), n) ** 2 * avg(w) * dS \ + h * (inner(grad(u), n) - Constant(e) * u) ** 2 * w * ds if self.degree > 1: errform += h**2 * div(grad(u))**2 * w * dx indicators[:] += assemble(errform).array() # errors for each cell print "Residual error: ", sqrt(sum(indicators) / len(eigv)) cutoff = sorted(indicators, reverse=True)[int(len(indicators) * fraction) - 1] marker.array()[:] = indicators > cutoff # mark worst errors mesh = refine(mesh, marker) return mesh
def solve(self): """ Solves the stokes equation with the current multimesh """ (u, p) = TrialFunctions(self.VQ) (v, q) = TestFunctions(self.VQ) n = FacetNormal(self.multimesh) h = 2.0 * Circumradius(self.multimesh) alpha = Constant(6.0) tensor_jump = lambda u: outer(u("+"), n("+")) + outer(u("-"), n("-")) a_s = inner(grad(u), grad(v)) * dX a_IP = - inner(avg(grad(u)), tensor_jump(v))*dI\ - inner(avg(grad(v)), tensor_jump(u))*dI\ + alpha/avg(h) * inner(jump(u), jump(v))*dI a_O = inner(jump(grad(u)), jump(grad(v))) * dO b_s = -div(u) * q * dX - div(v) * p * dX b_IP = jump(u, n) * avg(q) * dI + jump(v, n) * avg(p) * dI l_s = inner(self.f, v) * dX s_C = h*h*inner(-div(grad(u)) + grad(p), -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(-div(grad(u("+"))) + grad(p("+")), -div(grad(v("+"))) + grad(q("+")))*dO l_C = h*h*inner(self.f, -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(self.f("+"), -div(grad(v("+"))) - grad(q("+")))*dO a = a_s + a_IP + a_O + b_s + b_IP + s_C l = l_s + l_C A = assemble_multimesh(a) L = assemble_multimesh(l) [bc.apply(A, L) for bc in self.bcs] self.VQ.lock_inactive_dofs(A, L) solve(A, self.w.vector(), L, "mumps") self.splitMMF()
def __init__(self, domain): rho, mu, dt, g = domain.rho, domain.mu, domain.dt, domain.g u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu)) * dx + dot(mu * (grad(u_1) + grad(u_1).T) * n, vu) * ds) body_force = dot(g*rho, vu)*dx \ + dot(Constant((0.0, 0.0)), vu) * ds # diffusion = (mu*inner(grad(u_1), grad(vu))*dx # - mu*dot(nabla_grad(u_1)*n, vu)*ds) # int. by parts pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds # int. by parts # TODO: what is better? # convection = dot(div(rho*outer(u_1, u_1)), vu) * dx # not stable! convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx F_impl = -acceleration - convection + diffusion + pressure + body_force self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
def before_first_compute(self, get): u = get("Velocity") V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() if degree <= 1: Q = spaces.get_grad_space(V, shape=(spaces.d, )) else: if degree > 2: cbc_warning( "Unable to handle higher order WSS space. Using CG1.") Q = spaces.get_space(1, 1) Q_boundary = spaces.get_space(Q.ufl_element().degree(), 1, boundary=True) self.v = TestFunction(Q) self.tau = Function(Q, name="WSS_full") self.tau_boundary = Function(Q_boundary, name="WSS") local_dofmapping = mesh_to_boundarymesh_dofmap(spaces.BoundaryMesh, Q, Q_boundary) self._keys = np.array(local_dofmapping.keys(), dtype=np.intc) self._values = np.array(local_dofmapping.values(), dtype=np.intc) self._temp_array = np.zeros(len(self._keys), dtype=np.float_) Mb = assemble( inner(TestFunction(Q_boundary), TrialFunction(Q_boundary)) * dx) self.solver = create_solver("gmres", "jacobi") self.solver.set_operator(Mb) self.b = Function(Q_boundary).vector() self._n = FacetNormal(V.mesh())
def test_local_assembler_on_facet_integrals2(): mesh = UnitSquareMesh(MPI.comm_world, 4, 4) Vu = VectorFunctionSpace(mesh, 'DG', 1) Vv = FunctionSpace(mesh, 'DGT', 1) u = TrialFunction(Vu) v = TestFunction(Vv) n = FacetNormal(mesh) # Define form a = dot(u, n) * v * ds for R in '+-': a += dot(u(R), n(R)) * v(R) * dS # Compile form. This is collective a = Form(a) # Get global cell 0. This will return a cell only on one of the # processes c = get_cell_at(mesh, 1 / 6, 1 / 12, 0) if c: A_e = assemble_local(a, c) A_correct = numpy.array([[0, 1 / 12, 1 / 24, 0, 0, 0], [0, 1 / 24, 1 / 12, 0, 0, 0], [-1 / 12, 0, -1 / 24, 1 / 12, 0, 1 / 24], [-1 / 24, 0, -1 / 12, 1 / 24, 0, 1 / 12], [0, 0, 0, -1 / 12, -1 / 24, 0], [0, 0, 0, -1 / 24, -1 / 12, 0]]) error = ((A_e - A_correct)**2).sum()**0.5 error = float(error) # MPI.max does strange things to numpy.float64 else: error = 0.0 error = MPI.max(MPI.comm_world, float(error)) assert error < 1e-16
def __init__(self, mesh0=UnitCubeMesh(8, 8, 8), params={}): parameters['form_compiler']['representation'] = 'uflacs' parameters['form_compiler']['optimize'] = True parameters['form_compiler']['quadrature_degree'] = 4 self.mesh0 = Mesh(mesh0) self.mesh = Mesh(mesh0) if not 'C1' in params: params['C1'] = 100 self.params = params self.b = Constant((0.0, 0.0, 0.0)) self.h = Constant((0.0, 0.0, 0.0)) self.C0 = FunctionSpace(self.mesh0, "Lagrange", 2) self.V0 = VectorFunctionSpace(self.mesh0, "Lagrange", 1) self.W0 = TensorFunctionSpace(self.mesh0, "Lagrange", 1) self.C = FunctionSpace(self.mesh, "Lagrange", 2) self.V = VectorFunctionSpace(self.mesh, "Lagrange", 1) self.W = TensorFunctionSpace(self.mesh, "Lagrange", 1) self.G = project(Identity(3), self.W0) self.ut = Function(self.V0) self.du = TestFunction(self.V0) self.w = TrialFunction(self.V0) self.n0 = FacetNormal(self.mesh0) self.v = Function(self.V) self.t = 0.0
def _setup_dg1_projection_2D(self, w, incompressibility_flux_type, D12, use_bcs): """ Implement the projection where the result is BDM embeded in a DG1 function """ sim = self.simulation k = 1 gdim = 2 mesh = w[0].function_space().mesh() V = VectorFunctionSpace(mesh, 'DG', k) W = FunctionSpace(mesh, 'DGT', k) n = FacetNormal(mesh) v1 = TestFunction(W) u = TrialFunction(V) # The same fluxes that are used in the incompressibility equation if incompressibility_flux_type == 'central': u_hat_dS = dolfin.avg(w) elif incompressibility_flux_type == 'upwind': w_nU = (dot(w, n) + abs(dot(w, n))) / 2.0 switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0) u_hat_dS = switch * w('+') + (1 - switch) * w('-') if D12 is not None: u_hat_dS += dolfin.Constant([D12, D12]) * dolfin.jump(w, n) # Equation 1 - flux through the sides a = L = 0 for R in '+-': a += dot(u(R), n(R)) * v1(R) * dS L += dot(u_hat_dS, n(R)) * v1(R) * dS # Eq. 1 cont. - flux through external boundaries a += dot(u, n) * v1 * ds if use_bcs: for d in range(gdim): dirichlet_bcs = sim.data['dirichlet_bcs']['u%d' % d] neumann_bcs = sim.data['neumann_bcs'].get('u%d' % d, []) robin_bcs = sim.data['robin_bcs'].get('u%d' % d, []) outlet_bcs = sim.data['outlet_bcs'] for dbc in dirichlet_bcs: u_bc = dbc.func() L += u_bc * n[d] * v1 * dbc.ds() for nbc in neumann_bcs + robin_bcs + outlet_bcs: if nbc.enforce_zero_flux: pass # L += 0 else: L += w[d] * n[d] * v1 * nbc.ds() for sbc in sim.data['slip_bcs'].get('u', []): pass # L += 0 else: L += dot(w, n) * v1 * ds # Equation 2 - internal shape : empty for DG1 # Equation 3 - BDM Phi : empty for DG1 return a, L, V
for k, cell in enumerate(cells): editor.add_cell(k, cell) editor.close() return mesh mesh = UnitSquareMesh(200, 200) # mesh = create_dolfin_mesh(*meshzoo.triangle(1500, corners=[[0, 0], [1, 0], [0, 1]])) V = FunctionSpace(mesh, "CG", 1) u = TrialFunction(V) v = TestFunction(V) n = FacetNormal(mesh) # A = assemble(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds) A = assemble(dot(grad(u), grad(v)) * dx - dot(n, grad(u)) * v * ds) M = assemble(u * v * dx) f = Expression("sin(pi * x[0]) * sin(pi * x[1])", element=V.ufl_element()) x = project(f, V) Ax = A * x.vector() Minv_Ax = Function(V).vector() solve(M, Minv_Ax, Ax) val = Ax.inner(Minv_Ax) print(val)
def _setup_projection_nedelec(self, w, incompressibility_flux_type, D12, use_bcs, pdeg, gdim): """ Implement the BDM-like projection using Nedelec elements in the test function """ sim = self.simulation k = pdeg mesh = w[0].function_space().mesh() V = VectorFunctionSpace(mesh, 'DG', k) n = FacetNormal(mesh) # The mixed function space of the projection test functions e1 = FiniteElement('DGT', mesh.ufl_cell(), k) e2 = FiniteElement('N1curl', mesh.ufl_cell(), k - 1) em = MixedElement([e1, e2]) W = FunctionSpace(mesh, em) v1, v2 = TestFunctions(W) u = TrialFunction(V) # The same fluxes that are used in the incompressibility equation if incompressibility_flux_type == 'central': u_hat_dS = dolfin.avg(w) elif incompressibility_flux_type == 'upwind': w_nU = (dot(w, n) + abs(dot(w, n))) / 2.0 switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0) u_hat_dS = switch * w('+') + (1 - switch) * w('-') if D12 is not None: u_hat_dS += dolfin.Constant([D12] * gdim) * dolfin.jump(w, n) # Equation 1 - flux through the sides a = L = 0 for R in '+-': a += dot(u(R), n(R)) * v1(R) * dS L += dot(u_hat_dS, n(R)) * v1(R) * dS # Eq. 1 cont. - flux through external boundaries a += dot(u, n) * v1 * ds if use_bcs: for d in range(gdim): dirichlet_bcs = sim.data['dirichlet_bcs'].get('u%d' % d, []) neumann_bcs = sim.data['neumann_bcs'].get('u%d' % d, []) robin_bcs = sim.data['robin_bcs'].get('u%d' % d, []) outlet_bcs = sim.data['outlet_bcs'] for dbc in dirichlet_bcs: u_bc = dbc.func() L += u_bc * n[d] * v1 * dbc.ds() for nbc in neumann_bcs + robin_bcs + outlet_bcs: if nbc.enforce_zero_flux: pass # L += 0 else: L += w[d] * n[d] * v1 * nbc.ds() for sbc in sim.data['slip_bcs'].get('u', []): pass # L += 0 else: L += dot(w, n) * v1 * ds # Equation 2 - internal shape using 'Nedelec 1st kind H(curl)' elements a += dot(u, v2) * dx L += dot(w, v2) * dx return a, L, V