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 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 create_space(ne, p, order=None, xmin=0., xmax=1.): grid = np.linspace(xmin, xmax, ne+1) knots = make_knots(grid, p, periodic=False) spans = elements_spans(knots, p) # In[6]: nelements = len(grid) - 1 nbasis = len(knots) - p - 1 # we need the value a B-Spline and its first derivative nderiv = 1 # create the gauss-legendre rule, on [-1, 1] if order is None: order = p u, w = gauss_legendre( order ) # for each element on the grid, we create a local quadrature grid points, weights = quadrature_grid( grid, u, w ) # for each element and a quadrature points, # we compute the non-vanishing B-Splines basis = basis_ders_on_quad_grid( knots, p, points, nderiv ) return SplineSpace(knots=knots, degree=p, nelements=nelements, nbasis=nbasis, points=points, weights=weights, spans=spans, basis=basis)
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 create_mapping(V, kind='square', **kwargs): if kind == 'square': srf = make_square(**kwargs) else: raise NotImplementedError('{} not implemented'.format(kind)) (X1, V2), (V1, X2) = V.spaces T1, T2 = srf.knots p1, p2 = srf.degree # ... we will evaluate the bsplines associated to the mapping on the # quadrature grid used for the approximation. # notice that the mapping/space must fulfill a compatibility constraint. nderiv = 1 basis_1 = basis_ders_on_quad_grid( T1, p1, V1.points, nderiv ) basis_2 = basis_ders_on_quad_grid( T2, p2, V2.points, nderiv ) basis = (basis_1, basis_2) # ... # ... we compute the spans with respect to the elements of the space and not # the mapping spans_1 = np.zeros( V1.nelements, dtype=int ) for ie in range(V1.nelements): xx = V1.points[ie,:] spans_1[ie] = find_span( T1, p1, xx[0] ) spans_2 = np.zeros( V2.nelements, dtype=int ) for ie in range(V2.nelements): xx = V2.points[ie,:] spans_2[ie] = find_span( T2, p2, xx[0] ) spans = (spans_1, spans_2) # ... return SplineMapping(degree=srf.degree, coeffs=srf.points, spans=spans, basis=basis)
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 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 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