Beispiel #1
0
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    
Beispiel #2
0
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
Beispiel #3
0
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)
Beispiel #4
0
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
Beispiel #5
0
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)
Beispiel #6
0
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
Beispiel #7
0
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
Beispiel #8
0
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
Beispiel #9
0
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
Beispiel #10
0
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