def runTest(self): m = self.case[0].refined() if self.intorder is not None: basis = FacetBasis(m, self.case[1], intorder=self.intorder) else: basis = FacetBasis(m, self.case[1]) @LinearForm def linf(v, w): return np.sum(w.n**2, axis=0) * v b = asm(linf, basis) ones = projection(lambda x: 1.0 + x[0] * 0., basis, I=basis.get_dofs().flatten(), expand=True) self.assertAlmostEqual(b @ ones, 2 * m.p.shape[0], places=10) if self.test_integrate_volume: # by Gauss theorem this integrates to one for itr in range(m.p.shape[0]): @LinearForm def linf(v, w): return w.n[itr] * v b = asm(linf, basis) self.assertAlmostEqual(b @ m.p[itr, :], 1.0, places=5)
def test_adaptive_splitting_3d_3(): # adaptively refine one face of a cube, check that the mesh parameter h # is approximately linear w.r.t to distance from the face m = MeshTet.init_tensor(np.linspace(0, 1, 3), np.linspace(0, 1, 3), np.linspace(0, 1, 3)) for itr in range(15): m = m.refined(m.f2t[0, m.facets_satisfying(lambda x: x[0] == 0)]) @LinearForm def hproj(v, w): return w.h * v basis = Basis(m, ElementTetP1()) h = projection(hproj, basis) funh = basis.interpolator(h) xs = np.vstack(( np.linspace(0, .5, 20), np.zeros(20) + .5, np.zeros(20) + .5, )) hs = funh(xs) assert np.max(np.abs(hs - xs[0])) < 0.063
def test_matrix_element_projection(m, e): E1 = ElementVector(e) E2 = ElementVector(ElementVector(e)) basis0 = Basis(m, E1) basis1 = basis0.with_element(E2) C = linear_stress() x = basis0.interpolate(np.random.random(basis0.N)) @LinearForm def proj(v, _): return ddot(C(sym_grad(x)), v) y = projection(proj, basis1, basis0)
def runTest(self): mesh = MeshTri().refined(5) basis = CellBasis(mesh, ElementTriP1()) def fun(X): x, y = X return x**2 + y**2 x = projection(fun, basis) y = fun(mesh.p) normest = np.linalg.norm(x - y) self.assertTrue(normest < 0.011, msg="|x-y| = {}".format(normest))
def _trace_project(self, x: ndarray, elem: Element) -> ndarray: from skfem.utils import projection fbasis = FacetBasis(self.mesh, elem, facets=self.find, quadrature=(self.X, self.W)) I = fbasis.get_dofs(self.find).all() if len(I) == 0: # special case: no facet DOFs if fbasis.dofs.interior_dofs is not None: if fbasis.dofs.interior_dofs.shape[0] > 1: # no one-to-one restriction: requires interpolation raise NotImplementedError # special case: piecewise constant elem I = fbasis.dofs.interior_dofs[:, self.tind].flatten() else: raise ValueError return projection(x, fbasis, self, I=I)
# use dummy value for permittivity, uniform U in conductor K_elec_inner_conductor = asm(laplace, inner_conductor_basis) * eps0 # use dummy value for permittivity, uniform U in conductor K_elec_outer_conductor = asm(laplace, outer_conductor_basis) * eps0 # global stiffness matrix is the sum of the subdomain contributions K_elec = (K_elec_inner_insulator + K_elec_outer_insulator + K_elec_inner_conductor + K_elec_outer_conductor) # set a 1V potential difference between the conductors voltage = 1 # initialize the non-homogeneous Dirichlet conditions on the conductor surfaces U = np.zeros(K_elec.shape[0]) U[dofs['inner_conductor_outer_surface'].all()] = projection( lambda x: voltage / 2, inner_conductor_outer_surface_basis, I=dofs['inner_conductor_outer_surface']) U[dofs['outer_conductor_inner_surface'].all()] = projection( lambda x: -voltage / 2, outer_conductor_inner_surface_basis, I=dofs['outer_conductor_inner_surface']) U = solve(*condense(K_elec, x=U, D=dofs['inner_conductor_outer_surface'] | dofs['outer_conductor_inner_surface'])) # electric field energy E_elec = 0.5 * np.dot(U, K_elec * U) # energy stored in a capacitor: E = 0.5*C*U^2 # thus, C = 2*E/(U^2)
def trace( self, x: ndarray, projection: Callable[[ndarray], ndarray], target_elem: Optional[Element] = None ) -> Tuple[CellBasis, ndarray]: """Restrict solution to :math:`d-1` dimensional trace mesh. The parameter ``projection`` defines how the boundary points are projected to :math:`d-1` dimensional space. For example, >>> projection = lambda p: p[0] will keep only the `x`-coordinate in the trace mesh. Parameters ---------- x The solution vector. projection A function defining the projection of the boundary points. See above for an example. target_elem Optional finite element to project to before restriction. If not given, a piecewise constant element is used. Returns ------- CellBasis An object corresponding to the trace mesh. ndarray A projected solution vector defined on the trace mesh. """ DEFAULT_TARGET = { MeshTri: ElementTriP0, MeshQuad: ElementQuad0, MeshTet: ElementTetP0, MeshHex: ElementHex0, } meshcls = type(self.mesh) if meshcls not in DEFAULT_TARGET: raise NotImplementedError("Mesh type not supported.") if target_elem is None: target_elem = DEFAULT_TARGET[meshcls]() if type(target_elem) not in BOUNDARY_ELEMENT_MAP: raise Exception("The specified element not supported.") elemcls = BOUNDARY_ELEMENT_MAP[type(target_elem)] target_meshcls = { MeshTri: MeshLine, MeshQuad: MeshLine, MeshTet: MeshTri, MeshHex: MeshQuad, }[meshcls] assert callable(target_meshcls) # to satisfy mypy p, t = self.mesh._reix(self.mesh.facets[:, self.find]) return (CellBasis(target_meshcls(projection(p), t), elemcls()), self._trace_project(x, target_elem))