def mass_matrix_V0_1d(p, Nbase, T, bc): """ Computes the 1d mass matrix of 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) Returns ------- mass : 2d np.array mass matrix in V0 """ if bc == True: bcon = 1 Nbase_0 = Nbase - p else: bcon = 0 Nbase_0 = Nbase el_b = inter.construct_grid_from_knots(p, Nbase, T) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p + 1) pts, wts = inter.construct_quadrature_grid(ne, p + 1, pts_loc, wts_loc, el_b) d = 0 basis = inter.eval_on_grid_splines_ders(p, Nbase, p + 1, d, T, pts) mass = np.zeros((Nbase_0, Nbase_0)) for ie in range(ne): for il in range(p + 1): for jl in range(p + 1): i = ie + il j = ie + jl value = 0. for g in range(p + 1): value += wts[g, ie] * basis[il, 0, g, ie] * basis[jl, 0, g, ie] mass[i % Nbase_0, j % Nbase_0] += value return mass[(1 - bcon):Nbase_0 - (1 - bcon), (1 - bcon):Nbase_0 - (1 - bcon)]
def PI_1_1d(fun, p, Nbase, T, bc): """ Computes the FEM coefficient of the function 'fun' projected on the space V1. Parameters ---------- fun : callable the function to be projected p : int spline degree Nbase : int number of spline functions T : np.array knot vector Returns ------- vec : np.array the FEM coefficients """ # compute greville points grev = inter.compute_greville(p, Nbase, T) # compute quadrature grid pts_loc, wts_loc = np.polynomial.legendre.leggauss(p) pts, wts = inter.construct_quadrature_grid(Nbase - 1, p, pts_loc, wts_loc, grev) # compute element boundaries to get length of domain for periodic boundary conditions el_b = inter.construct_grid_from_knots(p, Nbase, T) # assemble vector of histopolation problem at greville points rhs = integrate_1d(pts % el_b[-1], wts, fun) # assemble histopolation matrix D = histopolation_matrix_1d(p, Nbase, T, grev, bc) # apply boundary conditions if bc == True: lower = int(np.ceil(p / 2) - 1) upper = -int(np.floor(p / 2)) else: lower = 0 upper = Nbase - 1 rhs = rhs[lower:upper] # solve histopolation problem vec = np.linalg.solve(D, rhs) return vec
def L2_prod_V1_1d(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. 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 """ el_b = inter.construct_grid_from_knots(p, Nbase, T) ne = len(el_b) - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p) pts, wts = inter.construct_quadrature_grid(ne, p, pts_loc, wts_loc, el_b) t = T[1:-1] d = 0 basis = inter.eval_on_grid_splines_ders(p - 1, Nbase - 1, p, d, t, pts) 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): value += wts[g, ie] * fun(pts[g, ie]) * basis[il, 0, g, ie] f_int[i] += value * p / (t[i + p] - t[i]) return f_int
def normalization_V1_1d(p, Nbase, T): """ Computes the normalization of all basis functions of the space V1. Parameters ---------- p : int spline degree Nbase : int number of spline functions T : np.array knot vector Returns ---------- norm: np.array the integral of each basis function over the entire computational domain """ el_b = inter.construct_grid_from_knots(p, Nbase, T) Nel = len(el_b) - 1 t = T[1:-1] pts_loc, wts_loc = np.polynomial.legendre.leggauss(p - 1) pts, wts = inter.construct_quadrature_grid(Nel, p - 1, pts_loc, wts_loc, el_b) basis = inter.eval_on_grid_splines_ders(p - 1, Nbase - 1, p - 1, 0, t, pts) norm = np.zeros(Nbase - 1) for ie in range(Nel): for il in range(p): i = ie + il value = 0. for g in range(p - 1): value += wts[g, ie] * basis[il, 0, g, ie] norm[i] += value * p / (t[i + p] - t[i]) return norm
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) Returns ------- D : 2d np.array histopolation matrix """ el_b = inter.construct_grid_from_knots(p, Nbase, T) Nel = len(el_b) - 1 if bc == False: return inter.histopolation_matrix(p, Nbase, T, grev) else: if p % 2 != 0: dx = el_b[-1] / Nel ne = Nbase - 1 pts_loc, wts_loc = np.polynomial.legendre.leggauss(p - 1) pts, wts = inter.construct_quadrature_grid(ne, p - 1, pts_loc, wts_loc, grev) col_quad = inter.collocation_matrix( p - 1, ne, T[1:-1], (pts % el_b[-1]).flatten()) / dx D = np.zeros((ne, ne)) for i in range(ne): for j in range(ne): for k in range(p - 1): D[i, j] += wts[k, i] * col_quad[i + ne * k, j] lower = int(np.ceil(p / 2) - 1) upper = -int(np.floor(p / 2)) D[:, :(p - 1)] += D[:, -(p - 1):] D = D[lower:upper, :D.shape[1] - (p - 1)] return D else: dx = el_b[-1] / Nel ne = Nbase - 1 a = grev b = grev + dx / 2 c = np.vstack((a, b)).reshape((-1, ), order='F')[:-1] pts_loc, wts_loc = np.polynomial.legendre.leggauss(p - 1) pts, wts = inter.construct_quadrature_grid(2 * ne, p - 1, pts_loc, wts_loc, c) col_quad = inter.collocation_matrix( p - 1, ne, T[1:-1], (pts % el_b[-1]).flatten()) / dx D = np.zeros((ne, ne)) for il in range(2 * ne): i = int(np.floor(il / 2)) for j in range(ne): for k in range(p - 1): D[i, j] += wts[k, il] * col_quad[il + 2 * ne * k, j] lower = int(np.ceil(p / 2) - 1) upper = -int(np.floor(p / 2)) D[:, :(p - 1)] += D[:, -(p - 1):] D = D[lower:upper, :D.shape[1] - (p - 1)] return D