def basis_transformation(self, coordinate_mapping): """The extra 6 dofs removed here correspond to the constraints.""" V = numpy.zeros((30, 24), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) J = coordinate_mapping.jacobian_at([1 / 3, 1 / 3]) W = numpy.zeros((3, 3), dtype=object) W[0, 0] = J[1, 1] * J[1, 1] W[0, 1] = -2 * J[1, 1] * J[0, 1] W[0, 2] = J[0, 1] * J[0, 1] W[1, 0] = -1 * J[1, 1] * J[1, 0] W[1, 1] = J[1, 1] * J[0, 0] + J[0, 1] * J[1, 0] W[1, 2] = -1 * J[0, 1] * J[0, 0] W[2, 0] = J[1, 0] * J[1, 0] W[2, 1] = -2 * J[1, 0] * J[0, 0] W[2, 2] = J[0, 0] * J[0, 0] # Put into the right rows and columns. V[0:3, 0:3] = V[3:6, 3:6] = V[6:9, 6:9] = W V[9:21, 9:21] = _edge_transform(self.cell, coordinate_mapping) for i in range(21, 24): V[i, i] = Literal(1) return ListTensor(V.T)
def basis_transformation(self, coordinate_mapping): V = numpy.zeros((20, 9), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) for i in range(0, 9, 3): V[i, i] = Literal(1) V[i+2, i+2] = Literal(1) T = self.cell # This bypasses the GEM wrapper. that = numpy.array([T.compute_normalized_edge_tangent(i) for i in range(3)]) nhat = numpy.array([T.compute_normal(i) for i in range(3)]) detJ = coordinate_mapping.detJ_at([1/3, 1/3]) J = coordinate_mapping.jacobian_at([1/3, 1/3]) J_np = numpy.array([[J[0, 0], J[0, 1]], [J[1, 0], J[1, 1]]]) JTJ = J_np.T @ J_np for e in range(3): # Compute alpha and beta for the edge. Ghat_T = numpy.array([nhat[e, :], that[e, :]]) (alpha, beta) = Ghat_T @ JTJ @ that[e, :] / detJ # Stuff into the right rows and columns. idx = 3*e + 1 V[idx, idx-1] = Literal(-1) * alpha / beta V[idx, idx] = Literal(1) / beta return ListTensor(V.T)
def basis_transformation(self, coordinate_mapping): """The extra 6 dofs removed here correspond to the constraints.""" V = numpy.zeros((30, 24), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) W = _evaluation_transform(coordinate_mapping) # Put into the right rows and columns. V[0:3, 0:3] = V[3:6, 3:6] = V[6:9, 6:9] = W V[9:21, 9:21] = _edge_transform(self.cell, coordinate_mapping) # internal DOFs detJ = coordinate_mapping.detJ_at([1/3, 1/3]) V[21:24, 21:24] = W / detJ # RESCALING FOR CONDITIONING h = coordinate_mapping.cell_size() for e in range(3): eff_h = h[e] for i in range(24): V[i, 3*e] = V[i, 3*e]/(eff_h*eff_h) V[i, 1+3*e] = V[i, 1+3*e]/(eff_h*eff_h) V[i, 2+3*e] = V[i, 2+3*e]/(eff_h*eff_h) # Note: that the edge DOFs are scaled by edge lengths in FIAT implies # that they are already have the necessary rescaling to improve # conditioning. return ListTensor(V.T)
def basis_transformation(self, coordinate_mapping): Js = [ coordinate_mapping.jacobian_at(vertex) for vertex in self.cell.get_vertices() ] h = coordinate_mapping.cell_size() d = self.cell.get_dimension() numbf = self.space_dimension() M = numpy.eye(numbf, dtype=object) for multiindex in numpy.ndindex(M.shape): M[multiindex] = Literal(M[multiindex]) cur = 0 for i in range(d + 1): cur += 1 # skip the vertex J = Js[i] for j in range(d): for k in range(d): M[cur + j, cur + k] = J[j, k] / h[i] cur += d return ListTensor(M)
def basis_transformation(self, coordinate_mapping): """Note, the extra 3 dofs which are removed here correspond to the constraints.""" T = self.cell V = numpy.zeros((18, 15), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) V[:12, :12] = _edge_transform(T, coordinate_mapping) # internal dofs for i in range(12, 15): V[i, i] = Literal(1) return ListTensor(V.T)
def basis_transformation(self, coordinate_mapping): # Jacobians at edge midpoints J = coordinate_mapping.jacobian_at([1/3, 1/3]) rns = coordinate_mapping.reference_normals() pns = coordinate_mapping.physical_normals() pts = coordinate_mapping.physical_tangents() pel = coordinate_mapping.physical_edge_lengths() V = numpy.eye(6, dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) for i in range(3): V[i+3, i+3] = (rns[i, 0]*(pns[i, 0]*J[0, 0] + pns[i, 1]*J[1, 0]) + rns[i, 1]*(pns[i, 0]*J[0, 1] + pns[i, 1]*J[1, 1])) for i, c in enumerate([(1, 2), (0, 2), (0, 1)]): B12 = (rns[i, 0]*(pts[i, 0]*J[0, 0] + pts[i, 1]*J[1, 0]) + rns[i, 1]*(pts[i, 0]*J[0, 1] + pts[i, 1]*J[1, 1])) V[3+i, c[0]] = -1*B12 / pel[i] V[3+i, c[1]] = B12 / pel[i] # diagonal post-scaling to patch up conditioning h = coordinate_mapping.cell_size() for e in range(3): v0id, v1id = [i for i in range(3) if i != e] for i in range(6): V[i, 3+e] = 2*V[i, 3+e] / (h[v0id] + h[v1id]) return ListTensor(V.T)
def _slate2gem_inverse(expr, self): tensor, = expr.children if expr.diagonal: # optimise inverse on diagonal tensor by translating to # matrix which contains the reciprocal values of the diagonal tensor A, = map(self, expr.children) i, j = (Index(extent=s) for s in A.shape) return ComponentTensor( Product(Division(Literal(1), Indexed(A, (i, i))), Delta(i, j)), (i, j)) else: return Inverse(self(tensor))
def _edge_transform(T, coordinate_mapping): Vsub = numpy.zeros((12, 12), dtype=object) for multiindex in numpy.ndindex(Vsub.shape): Vsub[multiindex] = Literal(Vsub[multiindex]) for i in range(0, 12, 2): Vsub[i, i] = Literal(1) # This bypasses the GEM wrapper. that = numpy.array([T.compute_normalized_edge_tangent(i) for i in range(3)]) nhat = numpy.array([T.compute_normal(i) for i in range(3)]) detJ = coordinate_mapping.detJ_at([1/3, 1/3]) J = coordinate_mapping.jacobian_at([1/3, 1/3]) J_np = numpy.array([[J[0, 0], J[0, 1]], [J[1, 0], J[1, 1]]]) JTJ = J_np.T @ J_np for e in range(3): # Compute alpha and beta for the edge. Ghat_T = numpy.array([nhat[e, :], that[e, :]]) (alpha, beta) = Ghat_T @ JTJ @ that[e, :] / detJ # Stuff into the right rows and columns. (idx1, idx2) = (4*e + 1, 4*e + 3) Vsub[idx1, idx1-1] = Literal(-1) * alpha / beta Vsub[idx1, idx1] = Literal(1) / beta Vsub[idx2, idx2-1] = Literal(-1) * alpha / beta Vsub[idx2, idx2] = Literal(1) / beta return Vsub
def basis_transformation(self, coordinate_mapping): """Note, the extra 3 dofs which are removed here correspond to the constraints.""" T = self.cell V = numpy.zeros((18, 15), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) V[:12, :12] = _edge_transform(T, coordinate_mapping) # internal dofs W = _evaluation_transform(coordinate_mapping) detJ = coordinate_mapping.detJ_at([1/3, 1/3]) V[12:15, 12:15] = W / detJ # Note: that the edge DOFs are scaled by edge lengths in FIAT implies # that they are already have the necessary rescaling to improve # conditioning. return ListTensor(V.T)
def scalar_value(self, o): return Literal(o.value())
def _slate2gem_negative(expr, self): child, = map(self, expr.children) indices = tuple(make_indices(len(child.shape))) return ComponentTensor(Product(Literal(-1), Indexed(child, indices)), indices)
def _slate2gem_reciprocal(expr, self): child, = map(self, expr.children) indices = tuple(make_indices(len(child.shape))) return ComponentTensor(Division(Literal(1.), Indexed(child, indices)), indices)
def basis_transformation(self, coordinate_mapping): # Jacobians at edge midpoints J = coordinate_mapping.jacobian_at([1 / 3, 1 / 3]) rns = coordinate_mapping.reference_normals() pns = coordinate_mapping.physical_normals() pts = coordinate_mapping.physical_tangents() pel = coordinate_mapping.physical_edge_lengths() V = numpy.zeros((21, 21), dtype=object) for multiindex in numpy.ndindex(V.shape): V[multiindex] = Literal(V[multiindex]) for v in range(3): s = 6 * v V[s, s] = Literal(1) for i in range(2): for j in range(2): V[s + 1 + i, s + 1 + j] = J[j, i] V[s + 3, s + 3] = J[0, 0] * J[0, 0] V[s + 3, s + 4] = 2 * J[0, 0] * J[1, 0] V[s + 3, s + 5] = J[1, 0] * J[1, 0] V[s + 4, s + 3] = J[0, 0] * J[0, 1] V[s + 4, s + 4] = J[0, 0] * J[1, 1] + J[1, 0] * J[0, 1] V[s + 4, s + 5] = J[1, 0] * J[1, 1] V[s + 5, s + 3] = J[0, 1] * J[0, 1] V[s + 5, s + 4] = 2 * J[0, 1] * J[1, 1] V[s + 5, s + 5] = J[1, 1] * J[1, 1] for e in range(3): v0id, v1id = [i for i in range(3) if i != e] # nhat . J^{-T} . t foo = (rns[e, 0] * (J[0, 0] * pts[e, 0] + J[1, 0] * pts[e, 1]) + rns[e, 1] * (J[0, 1] * pts[e, 0] + J[1, 1] * pts[e, 1])) # vertex points V[18 + e, 6 * v0id] = -15 / 8 * (foo / pel[e]) V[18 + e, 6 * v1id] = 15 / 8 * (foo / pel[e]) # vertex derivatives for i in (0, 1): V[18 + e, 6 * v0id + 1 + i] = -7 / 16 * foo * pts[e, i] V[18 + e, 6 * v1id + 1 + i] = V[18 + e, 6 * v0id + 1 + i] # second derivatives tau = [ pts[e, 0] * pts[e, 0], 2 * pts[e, 0] * pts[e, 1], pts[e, 1] * pts[e, 1] ] for i in (0, 1, 2): V[18 + e, 6 * v0id + 3 + i] = -1 / 32 * (pel[e] * foo * tau[i]) V[18 + e, 6 * v1id + 3 + i] = 1 / 32 * (pel[e] * foo * tau[i]) V[18 + e, 18 + e] = (rns[e, 0] * (J[0, 0] * pns[e, 0] + J[1, 0] * pns[e, 1]) + rns[e, 1] * (J[0, 1] * pns[e, 0] + J[1, 1] * pns[e, 1])) # Patch up conditioning h = coordinate_mapping.cell_size() for v in range(3): for k in range(2): for i in range(21): V[i, 6 * v + 1 + k] = V[i, 6 * v + 1 + k] / h[v] for k in range(3): for i in range(21): V[i, 6 * v + 3 + k] = V[i, 6 * v + 3 + k] / (h[v] * h[v]) for e in range(3): v0id, v1id = [i for i in range(3) if i != e] for i in range(21): V[i, 18 + e] = 2 * V[i, 18 + e] / (h[v0id] + h[v1id]) return ListTensor(V.T)