def assembly_mass_matrix_D(V): # ... sizes [s1, s2] = V.vector_space.starts [e1, e2] = V.vector_space.ends [p1, p2] = V.vector_space.pads # ... # ... seetings [k1, k2] = [W.quad_order for W in V.spaces] [spans_1, spans_2] = [W.spans for W in V.spaces] [basis_1, basis_2] = [W.quad_basis for W in V.spaces] [weights_1, weights_2] = [W.quad_weights for W in V.spaces] [points_1, points_2] = [W.quad_points for W in V.spaces] [V_1, V_2] = [W for W in V.spaces] # print(V.spaces[0].quad_order) # ... data structure M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): for ie2 in range(s2, e2 + 1 - p2): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] for il_1 in range(0, p1 + 1): for jl_1 in range(0, p1 + 1): for il_2 in range(0, p2 + 1): for jl_2 in range(0, p2 + 1): i1 = i_span_1 - p1 - 1 + il_1 j1 = i_span_1 - p1 - 1 + jl_1 i2 = i_span_2 - p2 - 1 + il_2 j2 = i_span_2 - p2 - 1 + jl_2 v_s = 0.0 for g1 in range(0, k1): for g2 in range(0, k2): di1_0 = coefficients_linear_combinaison( V_1, i1) * basis_1[ie1, il_1, 0, g1] di2_0 = coefficients_linear_combinaison( V_2, i2) * basis_2[ie1, il_2, 0, g1] bi_0 = di1_0 * di2_0 d_j1 = basis_1[ ie1, jl_1, 0, g1] * coefficients_linear_combinaison( V_1, j1) d_j2 = basis_2[ ie2, jl_2, 0, g2] * coefficients_linear_combinaison( V_2, j2) bj_0 = d_j1 * d_j2 wvol = weights_1[ie1, g1] * weights_2[ie2, g2] v_s = v_s + bi_0 * bj_0 * wvol M[i1, i2, j1 - i1, j2 - i2] += v_s # ... return M
def assembly_mass_V(V): # ... sizes [s1, s2] = V.vector_space.starts [e1, e2] = V.vector_space.ends [p1, p2] = V.vector_space.pads # ... # ... seetings [k1, k2] = [W.quad_order for W in V.spaces] [spans_1, spans_2] = [W.spans for W in V.spaces] [basis_1, basis_2] = [W.quad_basis for W in V.spaces] [weights_1, weights_2] = [W.quad_weights for W in V.spaces] [points_1, points_2] = [W.quad_points for W in V.spaces] # print(V.spaces[0].quad_order) # ... data structure M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): for ie2 in range(s2, e2 + 1 - p2): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] for il_1 in range(0, p1 + 1): for jl_1 in range(0, p1 + 1): for il_2 in range(0, p2 + 1): for jl_2 in range(0, p2 + 1): i1 = i_span_1 - p1 - 1 + il_1 j1 = i_span_1 - p1 - 1 + jl_1 i2 = i_span_2 - p2 - 1 + il_2 j2 = i_span_2 - p2 - 1 + jl_2 v_s = 0.0 for g1 in range(0, k1): for g2 in range(0, k2): bi_0 = basis_1[ie1, il_1, 0, g1] * basis_2[ie1, il_2, 0, g2] bj_0 = basis_1[ie1, jl_1, 0, g1] * basis_2[ie2, jl_2, 0, g2] # bj_x = basis_1[ie1, jl_1, 1, g1] * basis_2[ie2, jl_2, 0, g2] # bj_y = basis_1[ie1, jl_1, 0, g1] * basis_2[ie2, jl_2, 1, g2] wvol = weights_1[ie1, g1] * weights_2[ie2, g2] # v_s += (bi_x * bj_x + bi_y * bj_y) * wvol v_s = v_s + bi_0 * bj_0 * wvol M[i1, i2, j1 - i1, j2 - i2] += v_s # ... return M
def assemblyDSpanMassMatrix(V): """ Assembly the mass matrix of the space V Entries: -------- V: SplineSpace Output: ------- mass : StencilMatrix - the mass matrix """ # ... sizes [s1] = V.vector_space.starts [e1] = V.vector_space.ends [p1] = V.vector_space.pads k1 = V.quad_order spans_1 = V.spans basis_1 = V.quad_basis weights_1 = V.quad_weights knots_1 = V.knots # ... # ... data structure mass = StencilMatrix( V.vector_space, V.vector_space ) # ... # ... build matrices for ie1 in range(s1, e1+1-p1): i_span_1 = spans_1[ie1] for il_1 in range(0, p1+1): for jl_1 in range(0, p1+1): i1 = i_span_1 - p1 + il_1 j1 = i_span_1 - p1 + jl_1 # -- assembly D_j^p B-spline family: D_j^p = alpha * basis_w_0 alpha_j = coeffDspan(V, j1) # -- assembly D_i^p B-spline family: D_i^p = alpha * basis_w_0 alpha_i = coeffDspan(V, i1) v_m = 0.0 for g1 in range(0, k1): bi_0 = basis_1[ie1, il_1, 0, g1] bj_0 = basis_1[ie1, jl_1, 0, g1] di_0 = bi_0 * alpha_i dj_0 = bj_0 * alpha_j wvol = weights_1[ie1, g1] v_m += di_0 * dj_0 * wvol mass[i1, j1 - i1] += v_m return mass
def assemblyMassMatrix(V): """ Assembly the mass matrix of the space V Entries: -------- V: SplineSpace Output: ------- mass : StencilMatrix - the mass matrix """ # ... sizes [s1] = V.vector_space.starts [e1] = V.vector_space.ends [p1] = V.vector_space.pads k1 = V.quad_order spans_1 = V.spans basis_1 = V.quad_basis weights_1 = V.quad_weights # ... # ... data structure mass = StencilMatrix( V.vector_space, V.vector_space ) # ... # ... build matrices for ie1 in range(s1, e1+1-p1): i_span_1 = spans_1[ie1] for il_1 in range(0, p1+1): for jl_1 in range(0, p1+1): i1 = i_span_1 - p1 + il_1 j1 = i_span_1 - p1 + jl_1 v_m = 0.0 for g1 in range(0, k1): bi_0 = basis_1[ie1, il_1, 0, g1] bj_0 = basis_1[ie1, jl_1, 0, g1] wvol = weights_1[ie1, g1] v_m += bi_0 * bj_0 * wvol mass[i1, j1 - i1] += v_m # ... # ... return mass
def __init__(self, V): """ Entry: ------ V: SplineSpace used """ # ... sizes [s1] = V.vector_space.starts [e1] = V.vector_space.ends [p1] = V.vector_space.pads k1 = V.quad_order spans_1 = V.spans basis_1 = V.quad_basis weights_1 = V.quad_weights # ... # ... data structure stiffness = StencilMatrix(V.vector_space, V.vector_space) # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): i_span_1 = spans_1[ie1] for il_1 in range(0, p1 + 1): for jl_1 in range(0, p1 + 1): i1 = i_span_1 - p1 + il_1 j1 = i_span_1 - p1 + jl_1 v_s = 0.0 for g1 in range(0, k1): bi_x = basis_1[ie1, il_1, 1, g1] bj_x = basis_1[ie1, jl_1, 1, g1] wvol = weights_1[ie1, g1] v_s += (bi_x * bj_x) * wvol stiffness[i1, j1 - i1] += v_s # ... # ... self._stiff = stiffness
def assembly(V, kernel): # ... sizes [s1, s2] = V.vector_space.starts [e1, e2] = V.vector_space.ends [p1, p2] = V.vector_space.pads # ... # ... seetings [k1, k2] = [W.quad_order for W in V.spaces] [spans_1, spans_2] = [W.spans for W in V.spaces] [basis_1, basis_2] = [W.basis for W in V.spaces] [weights_1, weights_2] = [W.weights for W in V.spaces] [points_1, points_2] = [W.points for W in V.spaces] # ... # ... data structure M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... element matrix mat = zeros((p1 + 1, p2 + 1, 2 * p1 + 1, 2 * p2 + 1), order='F') # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): for ie2 in range(s2, e2 + 1 - p2): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] bs1 = basis_1[:, :, :, ie1] bs2 = basis_2[:, :, :, ie2] w1 = weights_1[:, ie1] w2 = weights_2[:, ie2] kernel(p1, p2, k1, k2, bs1, bs2, w1, w2, mat) i1 = i_span_1 - p1 - 1 i2 = i_span_2 - p2 - 1 M[i1:i1 + p1 + 1, i2:i2 + p2 + 1, :, :] += mat[:, :, :, :]
def assemble_matrix_1d(V, kernel, args=None, M=None): # ... sizes [s1] = V.vector_space.starts [e1] = V.vector_space.ends [p1] = V.vector_space.pads k1 = V.quad_order spans_1 = V.spans basis_1 = V.basis weights_1 = V.weights # ... # ... data structure if not given if M is None: M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... element matrix mat = np.zeros((p1+1,2*p1+1), order='F') # ... if args is None: _kernel = kernel else: _kernel = lambda p1, k1, bs, w, mat: kernel(p1, k1, bs, w, mat, *args) # ... build matrices for ie1 in range(s1, e1+1-p1): i_span_1 = spans_1[ie1] bs = basis_1[:, :, :, ie1] w = weights_1[:, ie1] _kernel(p1, k1, bs, w, mat) s1 = i_span_1 - p1 - 1 M._data[s1:s1+p1+1,:] += mat[:,:] # ... return M
# ... numbers of elements and degres n1 = 8 n2 = 4 p1 = 2 p2 = 1 # ... # ... Vector Spaces V = StencilVectorSpace([n1, n2], [p1, p2], [False, False]) V1 = StencilVectorSpace([n1], [p1], [False]) V2 = StencilVectorSpace([n2], [p2], [False]) # ... Inputs X0 = StencilVector(V) A = StencilMatrix(V1, V1) B = StencilMatrix(V2, V2) # ... # ... Fill in A, B and X utils.populate_1d_matrix(A, 5.) utils.populate_1d_matrix(B, 6.) utils.populate_2d_vector(X0) # ... # .. Y = kron_dot(B, A, X0) X = kron_solve(B, A, Y) print('X0 = \n', X0._data)
def assemblyMassMatrix2D(V): """ Require: -------- @V is a FemTensor V= (V1, V2) with @V1, @V2 are FemSpace Returns: -------- @M is a StencilMatrix - the mass matrix for V space """ # ... sizes [s1, s2] = V.vector_space.starts [e1, e2] = V.vector_space.ends [p1, p2] = V.vector_space.pads # ... # ... seetings [k1, k2] = [W.quad_order for W in V.spaces] [spans_1, spans_2] = [W.spans for W in V.spaces] [basis_1, basis_2] = [W.quad_basis for W in V.spaces] [weights_1, weights_2] = [W.quad_weights for W in V.spaces] [points_1, points_2] = [W.quad_points for W in V.spaces] # ... data structure M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): for ie2 in range(s2, e2 + 1 - p2): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] for il_1 in range(0, p1 + 1): for jl_1 in range(0, p1 + 1): for il_2 in range(0, p2 + 1): for jl_2 in range(0, p2 + 1): i1 = i_span_1 - p1 - 1 + il_1 j1 = i_span_1 - p1 - 1 + jl_1 i2 = i_span_2 - p2 - 1 + il_2 j2 = i_span_2 - p2 - 1 + jl_2 v_m = 0.0 for g1 in range(0, k1): for g2 in range(0, k2): bi_0 = basis_1[ie1, il_1, 0, g1] * basis_2[ie1, il_2, 0, g2] bj_0 = basis_1[ie1, jl_1, 0, g1] * basis_2[ie2, jl_2, 0, g2] wvol = weights_1[ie1, g1] * weights_2[ie2, g2] v_m = v_m + bi_0 * bj_0 * wvol M[i1, i2, j1 - i1, j2 - i2] += v_m # ... return M
def assemblyMassMatrixDspan2D(V): """ We compute the mass matrix for the span $$ D_i^{p} = \frac{p+1}{t_{i+p+1} - t_i} N_i^p $$ where $N_i^p$ are the default splines of V space Require: -------- @V is a FemTensor V= (V1, V2) with @V1, @V2 are FemSpace Returns: -------- @M is a StencilMatrix - the mass matrix for D_i^p span """ # ... sizes [s1, s2] = V.vector_space.starts [e1, e2] = V.vector_space.ends [p1, p2] = V.vector_space.pads # ... # ... seetings [k1, k2] = [W.quad_order for W in V.spaces] [spans_1, spans_2] = [W.spans for W in V.spaces] [basis_1, basis_2] = [W.quad_basis for W in V.spaces] [weights_1, weights_2] = [W.quad_weights for W in V.spaces] [points_1, points_2] = [W.quad_points for W in V.spaces] [V_1, V_2] = [W for W in V.spaces] # ... data structure M = StencilMatrix(V.vector_space, V.vector_space) # ... # ... build matrices for ie1 in range(s1, e1 + 1 - p1): for ie2 in range(s2, e2 + 1 - p2): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] for il_1 in range(0, p1 + 1): for jl_1 in range(0, p1 + 1): for il_2 in range(0, p2 + 1): for jl_2 in range(0, p2 + 1): i1 = i_span_1 - p1 - 1 + il_1 j1 = i_span_1 - p1 - 1 + jl_1 i2 = i_span_2 - p2 - 1 + il_2 j2 = i_span_2 - p2 - 1 + jl_2 v_s = 0.0 for g1 in range(0, k1): for g2 in range(0, k2): di1_0 = coefficients_linear_combinaison( V_1, i1) * basis_1[ie1, il_1, 0, g1] di2_0 = coefficients_linear_combinaison( V_2, i2) * basis_2[ie1, il_2, 0, g1] bi_0 = di1_0 * di2_0 d_j1 = basis_1[ ie1, jl_1, 0, g1] * coefficients_linear_combinaison( V_1, j1) d_j2 = basis_2[ ie2, jl_2, 0, g2] * coefficients_linear_combinaison( V_2, j2) bj_0 = d_j1 * d_j2 wvol = weights_1[ie1, g1] * weights_2[ie2, g2] v_s = v_s + bi_0 * bj_0 * wvol M[i1, i2, j1 - i1, j2 - i2] += v_s # ... return M
# ... numbers of elements and degres n1 = 8 n2 = 4 p1 = 3 p2 = 1 # ... # ... Vector Spaces V = StencilVectorSpace([n1, n2], [p1, p2], [False, False]) V1 = StencilVectorSpace([n1], [p1], [False]) V2 = StencilVectorSpace([n2], [p2], [False]) # ... Inputs Y = StencilVector(V) A = StencilMatrix(V1, V1) B = StencilMatrix(V2, V2) # ... # ... Fill in A, B and X utils.populate_1d_matrix(A, 5.) utils.populate_1d_matrix(B, 6.) utils.populate_2d_vector(Y) # ... # .. X = kron_solve(B, A, Y) X_ref = utils.kron_solve_ref(B, A, Y) print('A = \n', A.toarray())
def assemble_matrix_1d(V, kernel, args=None, M=None, fields={}): from spl.fem.vector import VectorBasicSobolevSpace # ... is_block = False if isinstance(V, VectorBasicSobolevSpace): if not (V.is_block): raise NotImplementedError('Expecting a scalar or vector space.') is_block = True # ... # ... data structure if not given if M is None: from spl.linalg.stencil import StencilVector, StencilMatrix # scalar case if not is_block: M = StencilMatrix(V.vector_space, V.vector_space) else: n_components = len(V.spaces) V = V.spaces[0] M = [] for i in range(0, n_components): line = [] for j in range(0, n_components): line.append(StencilMatrix(V.vector_space, V.vector_space)) M.append(line) # ... # ... sizes [s1] = V.vector_space.starts [e1] = V.vector_space.ends [p1] = V.vector_space.pads k1 = V.quad_order spans_1 = V.spans basis_1 = V.basis weights_1 = V.weights points_1 = V.points # ... # ... element matrix if not is_block: mat = zeros((p1 + 1, 2 * p1 + 1), order='F') else: mats = [] for i in range(0, n_components): line = [] for j in range(0, n_components): line.append(zeros((p1 + 1, 2 * p1 + 1), order='F')) mats.append(line) # ... # ... build matrices # TODO this is only for the parallel case # for ie1 in range(s1, e1+1-p1): for ie1 in range(0, V.ncells): i_span_1 = spans_1[ie1] bs = basis_1[:, :, :, ie1] w = weights_1[:, ie1] u = points_1[:, ie1] s1 = i_span_1 - p1 - 1 field_coeffs = [] for k, f in list(fields.items()): field_coeffs.append(f.coeffs[s1:s1 + p1 + 1]) if not is_block: if args is None: kernel(p1, k1, bs, u, w, mat, *field_coeffs) else: kernel(p1, k1, bs, u, w, mat, *args, *field_coeffs) else: _mats = [] for i in range(0, n_components): for j in range(0, n_components): _mats.append(mats[i][j]) if args is None: kernel(p1, k1, bs, u, w, *_mats, *field_coeffs) else: kernel(p1, k1, bs, u, w, *_mats, *args, *field_coeffs) if not is_block: M._data[s1:s1 + p1 + 1, :] += mat[:, :] else: for i in range(0, n_components): for j in range(0, n_components): _mat = mats[i][j] _M = M[i][j] _M._data[s1:s1 + p1 + 1, :] += _mat[:, :] # ... return M
def assemble_matrix_3d(V, kernel, args=None, M=None, fields={}): from spl.fem.vector import VectorBasicSobolevSpace # ... is_block = False if isinstance(V, VectorBasicSobolevSpace): if not (V.is_block): raise NotImplementedError('Expecting a scalar or vector space.') is_block = True # ... # ... data structure if not given if M is None: from spl.linalg.stencil import StencilVector, StencilMatrix # scalar case if not is_block: M = StencilMatrix(V.vector_space, V.vector_space) else: n_components = len(V.spaces) V = V.spaces[0] M = [] for i in range(0, n_components): line = [] for j in range(0, n_components): line.append(StencilMatrix(V.vector_space, V.vector_space)) M.append(line) # ... # ... sizes [s1, s2, s3] = V.vector_space.starts [e1, e2, e3] = V.vector_space.ends [p1, p2, p3] = V.vector_space.pads # ... # ... seetings [k1, k2, k3] = [W.quad_order for W in V.spaces] [spans_1, spans_2, spans_3] = [W.spans for W in V.spaces] [basis_1, basis_2, basis_3] = [W.basis for W in V.spaces] [weights_1, weights_2, weights_3] = [W.weights for W in V.spaces] [points_1, points_2, points_3] = [W.points for W in V.spaces] # ... # ... element matrix if not is_block: mat = zeros( (p1 + 1, p2 + 1, p3 + 1, 2 * p1 + 1, 2 * p2 + 1, 2 * p3 + 1), order='F') else: mats = [] for i in range(0, n_components): line = [] for j in range(0, n_components): line.append( zeros((p1 + 1, p2 + 1, p3 + 1, 2 * p1 + 1, 2 * p2 + 1, 2 * p3 + 1), order='F')) mats.append(line) # ... # ... build matrices # TODO this is only for the parallel case # for ie1 in range(s1, e1+1-p1): # for ie2 in range(s2, e2+1-p2): # for ie3 in range(s3, e3+1-p3): for ie1 in range(0, V.ncells[0]): for ie2 in range(0, V.ncells[1]): for ie3 in range(0, V.ncells[2]): i_span_1 = spans_1[ie1] i_span_2 = spans_2[ie2] i_span_3 = spans_3[ie3] bs1 = basis_1[:, :, :, ie1] bs2 = basis_2[:, :, :, ie2] bs3 = basis_3[:, :, :, ie3] w1 = weights_1[:, ie1] w2 = weights_2[:, ie2] w3 = weights_3[:, ie3] u1 = points_1[:, ie1] u2 = points_2[:, ie2] u3 = points_3[:, ie3] s1 = i_span_1 - p1 - 1 s2 = i_span_2 - p2 - 1 s3 = i_span_3 - p3 - 1 field_coeffs = [] for k, f in list(fields.items()): field_coeffs.append(f.coeffs[s1:s1 + p1 + 1, s2:s2 + p2 + 1, s3:s3 + p3 + 1]) if not is_block: if args is None: kernel(p1, p2, p3, k1, k2, k3, bs1, bs2, bs3, u1, u2, u3, w1, w2, w3, mat, *field_coeffs) else: kernel(p1, p2, p3, k1, k2, k3, bs1, bs2, bs3, u1, u2, u3, w1, w2, w3, mat, *args, *field_coeffs) else: _mats = [] for i in range(0, n_components): for j in range(0, n_components): _mats.append(mats[i][j]) if args is None: kernel(p1, p2, p3, k1, k2, k3, bs1, bs2, bs3, u1, u2, u3, w1, w2, w3, *_mats, *field_coeffs) else: kernel(p1, p2, p3, k1, k2, k3, bs1, bs2, bs3, u1, u2, u3, w1, w2, w3, *_mats, *args, *field_coeffs) if not is_block: M._data[s1:s1 + p1 + 1, s2:s2 + p2 + 1, s3:s3 + p3 + 1, :, :, :] += mat[:, :, :, :, :, :] else: for i in range(0, n_components): for j in range(0, n_components): _mat = mats[i][j] _M = M[i][j] _M._data[s1:s1 + p1 + 1, s2:s2 + p2 + 1, s3:s3 + p3 + 1, :, :, :] += _mat[:, :, :, :, :, :] # ... return M