23
23
)
24
24
25
25
26
- def divergence (mesh , quadrature_order : int = 1 , GNe : np .ndarray = None ):
26
+ def divergence (mesh , quadrature_order : int = 1 , eg : np . ndarray = None , wg : np . ndarray = None , GNeg : np .ndarray = None ):
27
27
"""Construct an FEM divergence operator such that composing div(grad(u))
28
28
computes the Laplacian of u, i.e. D @ G = L, where L is the FEM Laplacian
29
29
operator.
30
30
31
31
Args:
32
32
mesh (pbat.fem.Mesh):
33
33
quadrature_order (int, optional): Polynomial order to use for operator construction. Defaults to 1.
34
- GNe (np.ndarray, optional): Shape function gradients at quadrature points. Defaults to None.
34
+ eg (np.ndarray, optional): |#quad.pts.|x1 array of elements corresponding to quadrature points. Defaults to None.
35
+ wg (np.ndarray, optional): |#quad.pts.|x1 array of quadrature weights. Defaults to None.
36
+ GNeg (np.ndarray, optional): |#elem. nodes|x|#dims * #quad.pts.| array of shape function gradients at quadrature points. Defaults to None.
35
37
36
38
Returns:
37
39
(scipy.sparse.csc_matrix, np.ndarray):
38
40
"""
39
- G , GNe = gradient (mesh , quadrature_order = quadrature_order ,
40
- GNe = GNe , as_matrix = True )
41
- qgL = _fem .inner_product_weights (
42
- mesh , quadrature_order = quadrature_order ).flatten (order = "F" )
43
- QL = sp .sparse .diags_array ([qgL ], offsets = [0 ])
41
+ should_compute_quadrature = eg is None or wg is None or GNeg is None
42
+ G , eg , GNeg = gradient (mesh , quadrature_order = quadrature_order , as_matrix = True ) if should_compute_quadrature else gradient (
43
+ mesh , eg = eg , GNeg = GNeg , as_matrix = True )
44
+ wg = _fem .inner_product_weights (
45
+ mesh , quadrature_order = quadrature_order ).flatten (order = "F" ) if should_compute_quadrature else wg
46
+ QL = sp .sparse .diags_array (np .asarray (wg ).squeeze ())
44
47
QL = sp .sparse .kron (sp .sparse .eye_array (mesh .dims ), QL )
45
48
D = - G .T @ QL
46
- return D , GNe
49
+ return D , eg , wg , GNeg
47
50
48
51
49
- def gradient (mesh , quadrature_order : int = 1 , GNe : np .ndarray = None , as_matrix : bool = True ):
52
+ def gradient (mesh , quadrature_order : int = 1 , eg : np . ndarray = None , GNeg : np .ndarray = None , as_matrix : bool = True ):
50
53
"""Construct an FEM gradient operator
51
54
52
55
Args:
53
56
mesh (pbat.fem.Mesh):
54
57
quadrature_order (int, optional): Polynomial order to use for operator construction. Defaults to 1.
55
- GNe (np.ndarray, optional): Shape function gradients at quadrature points. Defaults to None.
58
+ eg (np.ndarray, optional): Elements corresponding to quadrature points. Defaults to None.
59
+ GNeg (np.ndarray, optional): Shape function gradients at quadrature points. Defaults to None.
56
60
as_matrix (bool, optional): Return the operator as a sparse matrix. Defaults to True.
57
61
58
62
Returns:
59
63
(scipy.sparse.csc_matrix | pbat.fem.Gradient, np.ndarray):
60
64
"""
61
- if GNe is None :
62
- GNe = _fem .shape_function_gradients (
65
+
66
+ if GNeg is None :
67
+ GNeg = _fem .shape_function_gradients (
63
68
mesh , quadrature_order = quadrature_order )
64
- G = _fem .Gradient (mesh , GNe , quadrature_order = quadrature_order )
69
+ n_quadpts_per_element = GNeg .shape [1 ] / (mesh .dims * mesh .E .shape [1 ])
70
+ eg = np .linspace (0 , mesh .E .shape [1 ]- 1 ,
71
+ num = mesh .E .shape [1 ], dtype = np .int64 )
72
+ eg = np .repeat (eg , n_quadpts_per_element )
73
+
74
+ G = _fem .Gradient (mesh , eg , GNeg )
65
75
G = G .to_matrix () if as_matrix else G
66
- return G , GNe
76
+ return G , eg , GNeg
67
77
68
78
69
79
def hyper_elastic_potential (
@@ -170,9 +180,8 @@ def mass_matrix(
170
180
if as_matrix :
171
181
M = M .to_matrix ()
172
182
if lump :
173
- lumpedm = M .sum (axis = 0 )
174
- M = sp .sparse .spdiags (lumpedm , np .array (
175
- [0 ]), m = M .shape [0 ], n = M .shape [0 ])
183
+ lumpedm = np .asarray (M .sum (axis = 0 )).squeeze ()
184
+ M = sp .sparse .diags_array (lumpedm )
176
185
return M , detJe
177
186
178
187
@@ -199,7 +208,7 @@ def load_vector(
199
208
nelems = mesh .E .shape [1 ]
200
209
wg = np .tile (mesh .quadrature_weights (quadrature_order ), nelems )
201
210
qgf = detJe .flatten (order = "F" ) * wg
202
- Qf = sp .sparse .diags_array ([ qgf ], offsets = [ 0 ] )
211
+ Qf = sp .sparse .diags_array (qgf )
203
212
Nf = _fem .shape_function_matrix (mesh , quadrature_order = quadrature_order )
204
213
if len (fe .shape ) == 1 :
205
214
fe = np .tile (fe [:, np .newaxis ], Qf .shape [0 ])
0 commit comments