def inject(self, weights): """map weights on curve to d2 form on sphere""" brush = np.zeros(self.complex.shape, np.float) #brush is d2; it s a conserved quantity util.scatter( self.raveled_indices, self.baries*weights[:,None], brush) return self.complex.boundify(brush)
def metric(self): """ calc metric properties and hodges; nicely vectorized """ topology = self.topology #metrics MP0 = np.ones (topology.P0) MP1 = np.zeros(topology.P1) MP2 = np.zeros(topology.P2) MD0 = np.ones (topology.D0) MD1 = np.zeros(topology.D1) MD2 = np.zeros(topology.D2) #precomputations EVP = util.gather(topology.EVi, self.primal) FEVP = util.gather(topology.FEi, EVP) #[faces, e3, v2, c3] FEM = util.normalize(FEVP.sum(axis=2)) FEV = util.gather(topology.FEi, topology.EVi) #calculate areas; devectorization over e makes things a little more elegant, by avoiding superfluous stacking for e in xrange(3): areas = triangle_area_from_corners(FEVP[:,e,0,:], FEVP[:,e,1,:], self.dual) MP2 += areas #add contribution to primal face util.scatter( #add contributions divided over left and right dual face FEV[:,e,:], #get both verts of each edge np.repeat(areas/2, 2), #half of domain area for both verts MD2) #calc edge lengths MP1 += edge_length(EVP[:,0,:], EVP[:,1,:]) for e in xrange(3): util.scatter( topology.FEi[:,e], edge_length(FEM[:,e,:], self.dual), MD1) #hodge operators self.D2P0 = MD2 / MP0 self.P0D2 = MP0 / MD2 self.D1P1 = MD1 / MP1 self.P1D1 = MP1 / MD1 self.D0P2 = MD0 / MP2 self.P2D0 = MP2 / MD0