def mass_V0_B(T, p, bc, Bz0): el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 NbaseN = Nel + p - bc*p pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) basisN = bsp.basis_ders_on_quad_grid(T, p, pts, 0) M = np.zeros((NbaseN, 2*p + 1)) for ie in range(Nel): for il in range(p + 1): for jl in range(p + 1): value = 0. for q in range(p + 1): value += wts[ie, q] * basisN[ie, il, 0, q] * basisN[ie, jl, 0, q] * Bz0(pts[ie, q]) M[(ie + il)%NbaseN, p + jl - il] += value indices = np.indices((NbaseN, 2*p + 1)) shift = np.arange(NbaseN) - p row = indices[0].flatten() col = (indices[1] + shift[:, None])%NbaseN M = spa.csr_matrix((M.flatten(), (row, col.flatten())), shape=(NbaseN, NbaseN)) M.eliminate_zeros() return M
def GRAD(T, p, bc): el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 NbaseN = Nel + p - bc*p if bc == True: G = np.zeros((NbaseN, NbaseN)) for i in range(NbaseN): G[i, i] = -1. if i < NbaseN - 1: G[i, i + 1] = 1. G[-1, 0] = 1. return G else: G = np.zeros((NbaseN - 1, NbaseN)) for i in range(NbaseN - 1): G[i, i] = -1. G[i, i + 1] = 1. return G
def L2_prod_V1(T, p, bc, fun): t = T[1:-1] el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 NbaseN = Nel + p - bc*p NbaseD = NbaseN - (1 - bc) pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) basisD = bsp.basis_ders_on_quad_grid(t, p - 1, pts, 0, normalize=True) f_int = np.zeros(NbaseD) for ie in range(Nel): for il in range(p): value = 0. for q in range(p + 1): value += wts[ie, q]*fun(pts[ie, q])*basisD[ie, il, 0, q] f_int[(ie + il)%NbaseD] += value return f_int
def matrixAssembly_V1(p, Nbase, T, bc): """ Computes the 1d mass matrix in the space V1. Parameters ---------- p : int spline degree Nbase : int number of spline functions T : np.array knot vector bc : boolean boundary conditions (True = periodic, False = homogeneous Dirichlet, None = no boundary conditions) Returns ------- M : 2d np.array mass matrix in V1 """ t = T[1:-1] el_b = bsp.breakpoints(T, p) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) d = 0 basis = bsp.basis_ders_on_quad_grid(t, p - 1, pts, d, normalize=True) M = np.zeros((Nbase - 1, Nbase - 1)) for ie in range(ne): for il in range(p): for jl in range(p): i = ie + il j = ie + jl value_m = 0. for g in range(p + 1): value_m += wts[ie, g] * basis[ie, il, 0, g] * basis[ie, jl, 0, g] M[i, j] += value_m if bc == True: M[:p - 1, :] += M[-p + 1:, :] M[:, :p - 1] += M[:, -p + 1:] M = M[:M.shape[0] - p + 1, :M.shape[1] - p + 1] return M
def __init__(self, T, p, bc): self.p = p self.T = T self.bc = bc self.greville = bsp.greville(T, p, bc) self.breakpoints = bsp.breakpoints(T, p) self.Nbase = len(self.breakpoints) - 1 + p - bc*p self.pts_loc, self.wts_loc = np.polynomial.legendre.leggauss(p) self.interpolation_V0 = bsp.collocation_matrix(T, p, self.greville, bc) self.histopolation_V1 = histo(T, p, bc, self.greville)
def L2_prod_V1(fun, p, Nbase, T): """ Computes the L2 scalar product of the function 'fun' with the B-splines of the space V1 using a quadrature rule of order p + 1. Parameters ---------- fun : callable function for scalar product p : int spline degree Nbase : int number of spline functions T : np.array knot vector Returns ------- f_int : np.array the result of the integration with each basis function """ t = T[1:-1] el_b = bsp.breakpoints(T, p) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) d = 0 basis = bsp.basis_ders_on_quad_grid(t, p - 1, pts, d, normalize=True) f_int = np.zeros(Nbase - 1) for ie in range(ne): for il in range(p): i = ie + il value = 0. for g in range(p + 1): value += wts[ie, g] * fun(pts[ie, g]) * basis[ie, il, 0, g] f_int[i] += value return f_int
def mass_V1(T, p, bc): t = T[1:-1] el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 NbaseN = Nel + p - bc*p NbaseD = NbaseN - (1 - bc) pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) basisD = bsp.basis_ders_on_quad_grid(t, p - 1, pts, 0, normalize=True) M = np.zeros((NbaseD, 2*p + 1)) for ie in range(Nel): for il in range(p): for jl in range(p): value = 0. for q in range(p + 1): value += wts[ie, q] * basisD[ie, il, 0, q] * basisD[ie, jl, 0, q] M[(ie + il)%NbaseD, p + jl - il] += value indices = np.indices((NbaseD, 2*p + 1)) shift = np.arange(NbaseD) - p row = indices[0].flatten() col = (indices[1] + shift[:, None])%NbaseD M = spa.csr_matrix((M.flatten(), (row, col.flatten())), shape=(NbaseD, NbaseD)) M.eliminate_zeros() return M
def L2_prod_V0(T, p, bc, fun): el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 NbaseN = Nel + p - bc*p pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) basisN = bsp.basis_ders_on_quad_grid(T, p, pts, 0) f_int = np.zeros(NbaseN) for ie in range(Nel): for il in range(p + 1): value = 0. for q in range(p + 1): value += wts[ie, q] * fun(pts[ie, q]) * basisN[ie, il, 0, q] f_int[(ie + il)%NbaseN] += value return f_int
def histo(T, p, bc, grev): el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 t = T[1:-1] Nbase = Nel + p - bc*p if bc == True: pts_loc, wts_loc = np.polynomial.legendre.leggauss(p - 1) ne = Nbase D = np.zeros((ne, ne)) if p%2 != 0: grid = el_b pts, wts = bsp.quadrature_grid(grid, pts_loc, wts_loc) col_quad = bsp.collocation_matrix(t, p - 1, pts.flatten(), bc, normalize=True) for ie in range(Nel): for il in range(p): i = (ie + il)%ne for k in range(p - 1): D[ie, i] += wts[ie, k]*col_quad[ie*(p - 1) + k, i] return D else: grid = np.linspace(0., el_b[-1], 2*Nel + 1) pts, wts = bsp.quadrature_grid(grid, pts_loc, wts_loc) col_quad = bsp.collocation_matrix(t, p - 1, pts.flatten(), bc, normalize=True) for iee in range(2*Nel): for il in range(p): ie = int(iee/2) ie_grev = int(np.ceil(iee/2) - 1) i = (ie + il)%ne for k in range(p - 1): D[ie_grev, i] += wts[iee, k]*col_quad[iee*(p - 1) + k, i] return D else: ng = len(grev) col_quad = bsp.collocation_matrix(T, p, grev, bc) D = np.zeros((ng - 1, Nbase - 1)) for i in range(ng - 1): for j in range(max(i - p + 1, 1), min(i + p + 3, Nbase)): s = 0. for k in range(j): s += col_quad[i, k] - col_quad[i + 1, k] D[i, j - 1] = s return D
def matrixAssembly_V0(p, Nbase, T, bc): """ Computes the 1d mass and advection matrix in the space V0. Parameters ---------- p : int spline degree Nbase : int number of spline functions T : np.array knot vector bc : boolean boundary conditions (True = periodic, False = homogeneous Dirichlet, None = no boundary conditions) Returns ------- M : 2d np.array mass matrix in V0 D : 2d np.array advection matrix in V0 """ el_b = bsp.breakpoints(T, p) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) d = 1 basis = bsp.basis_ders_on_quad_grid(T, p, pts, d) M = np.zeros((Nbase, Nbase)) C = np.zeros((Nbase, Nbase)) for ie in range(ne): for il in range(p + 1): for jl in range(p + 1): i = ie + il j = ie + jl value_m = 0. value_c = 0. for g in range(p + 1): value_m += wts[ie, g] * basis[ie, il, 0, g] * basis[ie, jl, 0, g] value_c += wts[ie, g] * basis[ie, il, 0, g] * basis[ie, jl, 1, g] M[i, j] += value_m C[i, j] += value_c if bc == True: M[:p, :] += M[-p:, :] M[:, :p] += M[:, -p:] M = M[:M.shape[0] - p, :M.shape[1] - p] C[:p, :] += C[-p:, :] C[:, :p] += C[:, -p:] C = C[:C.shape[0] - p, :C.shape[1] - p] elif bc == False: M = M[1:-1, 1:-1] C = C[1:-1, 1:-1] return M, C
def histopolation_matrix_1d(p, Nbase, T, grev, bc): """ Computest the 1d histopolation matrix. Parameters ---------- p : int spline degree Nbase : int number of spline functions T : np.array knot vector grev : np.array greville points bc : boolean boundary conditions (True = periodic, False = homogeneous Dirichlet, None = no boundary conditions) Returns ------- D : 2d np.array histopolation matrix """ el_b = bsp.breakpoints(T, p) Nel = len(el_b) - 1 t = T[1:-1] if bc == True: pts_loc, wts_loc = np.polynomial.legendre.leggauss(p - 1) ne = Nbase - p D = np.zeros((ne, ne)) if p % 2 != 0: grid = el_b pts, wts = bsp.quadrature_grid(grid, pts_loc, wts_loc) col_quad = bsp.collocation_matrix(t, p - 1, pts.flatten(), bc, normalize=True) for ie in range(Nel): for il in range(p): i = (ie + il) % ne for k in range(p - 1): D[ie, i] += wts[ie, k] * col_quad[ie * (p - 1) + k, i] return D else: grid = np.linspace(0., el_b[-1], 2 * Nel + 1) pts, wts = bsp.quadrature_grid(grid, pts_loc, wts_loc) col_quad = bsp.collocation_matrix(t, p - 1, pts.flatten(), bc, normalize=True) for iee in range(2 * Nel): for il in range(p): ie = int(iee / 2) ie_grev = int(np.ceil(iee / 2) - 1) i = (ie + il) % ne for k in range(p - 1): D[ie_grev, i] += wts[iee, k] * col_quad[iee * (p - 1) + k, i] return D else: ng = len(grev) col_quad = bsp.collocation_matrix(T, p, grev, bc) D = np.zeros((ng - 1, Nbase - 1)) for i in range(ng - 1): for j in range(max(i - p + 1, 1), min(i + p + 3, Nbase)): s = 0. for k in range(j): s += col_quad[i, k] - col_quad[i + 1, k] D[i, j - 1] = s return D
def matrixAssembly_backgroundField(p, Nbase, T, bc, B_background_z): """ Computes the 1d mass matrix weighted with some background field in the space V0. Parameters ---------- p : int spline degree Nbase : int number of spline functions T : np.array knot vector bc : boolean boundary conditions (True = periodic, False = homogeneous Dirichlet, None = no boundary conditions) B_background_z : callable the variation of the background magnetic field in z-direction Returns ------- D : 2d np.array mass matrix in V0 """ el_b = bsp.breakpoints(T, p) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = bsp.quadrature_grid(el_b, pts_loc, wts_loc) d = 0 basis = bsp.basis_ders_on_quad_grid(T, p, pts, d) D = np.zeros((Nbase, Nbase)) for ie in range(ne): for il in range(p + 1): for jl in range(p + 1): i = ie + il j = ie + jl value_d = 0. for g in range(p + 1): value_d += wts[ie, g] * basis[ie, il, 0, g] * basis[ ie, jl, 0, g] * B_background_z(pts[ie, g]) D[i, j] += value_d if bc == True: D[:p, :] += D[-p:, :] D[:, :p] += D[:, -p:] D = D[:D.shape[0] - p, :D.shape[1] - p] elif bc == False: D = D[1:-1, 1:-1] return D