FE-Project
Loading...
Searching...
No Matches
scale_element_hexahedral.F90
Go to the documentation of this file.
1!> module FElib / Element / hexahedron
2!!
3!! @par Description
4!! A module for a hexahedral finite element
5!!
6!! @author Yuta Kawai, Team SCALE
7!!
8!<
9#include "scaleFElib.h"
11
12 !-----------------------------------------------------------------------------
13 !
14 !++ used modules
15 !
16 use scale_precision
17
18 use scale_element_base, only: &
21 !-----------------------------------------------------------------------------
22 implicit none
23 private
24
25 !-----------------------------------------------------------------------------
26 !
27 !++ Public type & procedure
28 !
29
30 !> Derived type representing a hexahedral element
31 type, public, extends(elementbase3d) :: hexahedralelement
32 contains
33 procedure :: init => hexhedralelement_init
34 procedure :: final => hexhedralelement_final
35 procedure :: genintgausslegendreintrpmat => hexhedralelement_gen_intgausslegendreintrpmat
36 end type hexahedralelement
37
38 !-----------------------------------------------------------------------------
39 !
40 !++ Private procedure
41 !
42 private :: construct_element
43
44contains
45!> Initialize an object to manage a hexahedral element
46!!
47!! @param elem Object of finite element
48!! @param elemOrder_h Polynomial order with 1D horizontal direction
49!! @param elemOrder_v Polynomial order with vertical direction
50!! @param LumpedMassMatFlag Flag whether mass lumping is considered
51!OCL SERIAL
53 elem, elemOrder_h, elemOrder_v, &
54 LumpedMassMatFlag )
55 implicit none
56
57 class(hexahedralelement), intent(inout) :: elem
58 integer, intent(in) :: elemOrder_h
59 integer, intent(in) :: elemOrder_v
60 logical, intent(in) :: LumpedMassMatFlag
61
62 !-----------------------------------------------------------------------------
63
64 elem%PolyOrder_h = elemorder_h
65 elem%PolyOrder_v = elemorder_v
66 elem%Nnode_h1D = elemorder_h + 1
67 elem%Nnode_v = elemorder_v + 1
68
69 elem%Nv = 8
70 elem%Nfaces_h = 4
71 elem%Nfaces_v = 2
72 elem%Nfaces = elem%Nfaces_h + elem%Nfaces_v
73
74 elem%Nfp_h = elem%Nnode_h1D*elem%Nnode_v
75 elem%Nfp_v = elem%Nnode_h1D**2
76 elem%NfpTot = elem%Nfp_h*elem%Nfaces_h + elem%Nfp_v*elem%Nfaces_v
77
78 elem%Np = elem%Nfp_v * elem%Nnode_v
79
80 call elementbase3d_init(elem, lumpedmassmatflag)
81 call construct_element(elem)
82
83 return
84 end subroutine hexhedralelement_init
85
86!> Finalize an object to manage a hexahedral element
87!!
88!! @param elem Object of finite element
89!OCL SERIAL
90 subroutine hexhedralelement_final(elem)
91 implicit none
92
93 class(hexahedralelement), intent(inout) :: elem
94 !-----------------------------------------------------------------------------
95
96 call elementbase3d_final(elem)
97
98 return
99 end subroutine hexhedralelement_final
100
101!OCL SERIAL
102 subroutine construct_element(elem)
103
105 use scale_polynomial, only: &
109 use scale_element_base, only: &
113
114 implicit none
115
116 type(hexahedralelement), intent(inout) :: elem
117
118 integer :: nodes_ijk(elem%Nnode_h1D, elem%Nnode_h1D, elem%Nnode_v)
119
120 real(RP) :: lglPts1D_h(elem%Nnode_h1D)
121 real(RP) :: lglPts1D_v(elem%Nnode_v)
122
123 real(DP) :: intWeight_lgl1DPts_h(elem%Nnode_h1D)
124 real(DP) :: intWeight_lgl1DPts_v(elem%Nnode_v)
125
126 real(RP) :: P1D_ori_h(elem%Nnode_h1D, elem%Nnode_h1D)
127 real(RP) :: P1D_ori_v(elem%Nnode_v, elem%Nnode_v)
128 real(RP) :: DP1D_ori_h(elem%Nnode_h1D, elem%Nnode_h1D)
129 real(RP) :: DP1D_ori_v(elem%Nnode_v, elem%Nnode_v)
130 real(RP) :: DLagr1D_h(elem%Nnode_h1D, elem%Nnode_h1D)
131 real(RP) :: DLagr1D_v(elem%Nnode_v, elem%Nnode_v)
132 real(RP) :: V2D_h(elem%Nfp_h, elem%Nfp_h)
133 real(RP) :: V2D_v(elem%Nfp_v, elem%Nfp_v)
134 real(RP) :: Emat(elem%Np, elem%NfpTot)
135 real(RP) :: MassEdge_h(elem%Nfp_h, elem%Nfp_h)
136 real(RP) :: MassEdge_v(elem%Nfp_v, elem%Nfp_v)
137
138 integer :: i, j, k
139 integer :: p1, p2, p3
140 integer :: n, l, f
141 integer :: Nord
142 integer :: is, ie
143
144 integer :: f_h, f_v
145 integer :: fp, fp_h1, fp_h2, fp_v
146
147 type(quadrilateralelement) :: elem2D
148 !-----------------------------------------------------------------------------
149
150 lglpts1d_h(:) = polynomial_gengausslobattopt( elem%PolyOrder_h )
151 p1d_ori_h(:,:) = polynomial_genlegendrepoly( elem%PolyOrder_h, lglpts1d_h )
152 dp1d_ori_h(:,:) = polynomial_gendlegendrepoly( elem%PolyOrder_h, lglpts1d_h, p1d_ori_h )
153 dlagr1d_h(:,:) = polynomial_gendlagrangepoly_lglpt( elem%PolyOrder_h, lglpts1d_h )
154
155 lglpts1d_v(:) = polynomial_gengausslobattopt( elem%PolyOrder_v )
156 p1d_ori_v(:,:) = polynomial_genlegendrepoly( elem%PolyOrder_v, lglpts1d_v )
157 dp1d_ori_v(:,:) = polynomial_gendlegendrepoly( elem%PolyOrder_v, lglpts1d_v, p1d_ori_v )
158 dlagr1d_v(:,:) = polynomial_gendlagrangepoly_lglpt( elem%PolyOrder_v, lglpts1d_v )
159
160 !* Preparation
161
162 do k=1, elem%Nnode_v
163 do j=1, elem%Nnode_h1D
164 do i=1, elem%Nnode_h1D
165 nodes_ijk(i,j,k) = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
166 end do
167 end do
168 end do
169
170 ! Set the mask to extract the values at faces
171
172 elem%Fmask_h(:,1) = reshape(nodes_ijk(:,1,:), (/ elem%Nfp_h /))
173 elem%Fmask_h(:,2) = reshape(nodes_ijk(elem%Nnode_h1D,:,:), (/ elem%Nfp_h /))
174 elem%Fmask_h(:,3) = reshape(nodes_ijk(:,elem%Nnode_h1D,:), (/ elem%Nfp_h /))
175 elem%Fmask_h(:,4) = reshape(nodes_ijk(1,:,:), (/ elem%Nfp_h /))
176
177 elem%Fmask_v(:,1) = reshape(nodes_ijk(:,:,1), (/ elem%Nfp_v /))
178 elem%Fmask_v(:,2) = reshape(nodes_ijk(:,:,elem%Nnode_v), (/ elem%Nfp_v /))
179
180 !$acc update device(elem%Fmask_h, elem%Fmask_v)
181
182 !- ColMask
183
184 do j=1, elem%Nnode_h1D
185 do i=1, elem%Nnode_h1D
186 n = i + (j-1)*elem%Nnode_h1D
187 elem%Colmask(:,n) = nodes_ijk(i,j,:)
188 end do
189 end do
190 !$acc update device(elem%Colmask)
191
192 != Hslice
193
194 do k=1, elem%Nnode_v
195 elem%Hslice(:,k) = reshape(nodes_ijk(:,:,k), (/ elem%Nfp_v /))
196 end do
197 !$acc update device(elem%Hslice)
198
199 !- IndexH2Dto3D
200
201 do k=1, elem%Nnode_v
202 do j=1, elem%Nnode_h1D
203 do i=1, elem%Nnode_h1D
204 n = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
205 elem%IndexH2Dto3D(n) = nodes_ijk(i,j,1)
206 end do
207 end do
208 end do
209 !$acc update device(elem%IndexH2Dto3D)
210
211 !- IndexH2Dto3D_bnd
212
213 call elem2d%Init( elem%PolyOrder_h, .false. )
214
215 do f_h=1, 4
216 do fp_v=1, elem%Nnode_v
217 do fp_h1=1, elem%Nnode_h1D
218 fp = fp_h1 + (fp_v-1)*elem%Nnode_h1D + (f_h-1)*elem%Nfp_h
219 elem%IndexH2Dto3D_bnd(fp) = elem2d%Fmask(fp_h1,f_h)
220 end do
221 end do
222 end do
223 do f_v=1, 2
224 do fp_h2=1, elem%Nnode_h1D
225 do fp_h1=1, elem%Nnode_h1D
226 fp = fp_h1 + (fp_h2-1)*elem%Nnode_h1D &
227 + (f_v-1) * elem%Nfp_v &
228 + 4 * elem%Nnode_h1D * elem%Nnode_v
229 elem%IndexH2Dto3D_bnd(fp) = fp_h1 + (fp_h2-1)*elem%Nnode_h1D
230 end do
231 end do
232 end do
233 !$acc update device(elem%IndexH2Dto3D_bnd)
234
235 call elem2d%Final()
236
237 !- IndexZ1Dto3D
238
239 do k=1, elem%Nnode_v
240 do j=1, elem%Nnode_h1D
241 do i=1, elem%Nnode_h1D
242 n = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
243 elem%IndexZ1Dto3D(n) = k
244 end do
245 end do
246 end do
247 !$acc update device(elem%IndexZ1Dto3D)
248
249 !* Set the coordinates of LGL points, and the Vandermonde and differential matricies
250
251 elem%Dx1(:,:) = 0.0_rp
252 elem%Dx2(:,:) = 0.0_rp
253 elem%Dx3(:,:) = 0.0_rp
254
255 do k=1, elem%Nnode_v
256 do j=1, elem%Nnode_h1D
257 do i=1, elem%Nnode_h1D
258 n = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
259
260 !* Set the coordinates of LGL points
261 elem%x1(n) = lglpts1d_h(i)
262 elem%x2(n) = lglpts1d_h(j)
263 elem%x3(n) = lglpts1d_v(k)
264
265 !* Set the Vandermonde and differential matricies
266 do p3=1, elem%Nnode_v
267 do p2=1, elem%Nnode_h1D
268 do p1=1, elem%Nnode_h1D
269 l = p1 + (p2-1)*elem%Nnode_h1D + (p3-1)*elem%Nnode_h1D**2
270 elem%V(n,l) = (p1d_ori_h(i,p1)*p1d_ori_h(j,p2)*p1d_ori_v(k,p3)) &
271 * sqrt((dble(p1-1) + 0.5_dp)*(dble(p2-1) + 0.5_dp)*(dble(p3-1) + 0.5_dp))
272
273 if(p2==j .and. p3==k) elem%Dx1(n,l) = dlagr1d_h(p1,i)
274 if(p1==i .and. p3==k) elem%Dx2(n,l) = dlagr1d_h(p2,j)
275 if(p1==i .and. p2==j) elem%Dx3(n,l) = dlagr1d_v(p3,k)
276 end do
277 end do
278 end do
279 end do
280 end do
281 end do
282 elem%invV(:,:) = linalgebra_inv(elem%V)
283 !$acc update device(elem%x1, elem%x2, elem%x3, elem%V, elem%Dx1, elem%Dx2, elem%Dx3, elem%invV)
284
285 !* Set the weights at LGL points to integrate over element
286
287 intweight_lgl1dpts_h(:) = polynomial_gengausslobattoptintweight(elem%PolyOrder_h)
288 intweight_lgl1dpts_v(:) = polynomial_gengausslobattoptintweight(elem%PolyOrder_v)
289
290 do k=1, elem%Nnode_v
291 do j=1, elem%Nnode_h1D
292 do i=1, elem%Nnode_h1D
293 l = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
294 elem%IntWeight_lgl(l) = &
295 intweight_lgl1dpts_h(i) * intweight_lgl1dpts_h(j) * intweight_lgl1dpts_v(k)
296 end do
297 end do
298 end do
299 !$acc update device(elem%IntWeight_lgl)
300
301 !* Set the mass matrix
302
303 if (elem%IsLumpedMatrix()) then
304 elem%invM(:,:) = 0.0_rp
305 elem%M(:,:) = 0.0_rp
306 do k=1, elem%Nnode_v
307 do j=1, elem%Nnode_h1D
308 do i=1, elem%Nnode_h1D
309 l = i + (j-1)*elem%Nnode_h1D + (k-1)*elem%Nnode_h1D**2
310 elem%M(l,l) = elem%IntWeight_lgl(l)
311 elem%invM(l,l) = 1.0_dp/elem%IntWeight_lgl(l)
312 end do
313 end do
314 end do
315 else
316 call elementbase_construct_massmat( elem%V, elem%Np, & ! (in)
317 elem%M, elem%invM ) ! (out)
318 end if
319 !$acc update device(elem%M, elem%invM)
320
321 !* Set the stiffness matrix
322
323 call elementbase_construct_stiffmat( elem%M, elem%invM, elem%Dx1, elem%Np, & ! (in)
324 elem%Sx1 ) ! (out)
325 call elementbase_construct_stiffmat( elem%M, elem%invM, elem%Dx2, elem%Np, & ! (in)
326 elem%Sx2 ) ! (out)
327 call elementbase_construct_stiffmat( elem%M, elem%invM, elem%Dx3, elem%Np, & ! (in)
328 elem%Sx3 ) ! (out)
329 !$acc update device(elem%Sx1, elem%Sx2, elem%Sx3)
330
331 !* Set the lift matrix
332
333 do k=1, elem%Nnode_v
334 do i=1, elem%Nnode_h1D
335 n = i + (k-1)*elem%Nnode_h1D
336 do p3=1, elem%Nnode_v
337 do p1=1, elem%Nnode_h1D
338 l = p1 + (p3-1)*elem%Nnode_h1D
339 v2d_h(n,l) = p1d_ori_h(i,p1)*p1d_ori_v(k,p3) &
340 * sqrt( (dble(p1-1) + 0.5_dp)*(dble(p3-1) + 0.5_dp) )
341 end do
342 end do
343 end do
344 end do
345 do j=1, elem%Nnode_h1D
346 do i=1, elem%Nnode_h1D
347 n = i + (j-1)*elem%Nnode_h1D
348 do p2=1, elem%Nnode_h1D
349 do p1=1, elem%Nnode_h1D
350 l = p1 + (p2-1)*elem%Nnode_h1D
351 v2d_v(n,l) = p1d_ori_h(i,p1)*p1d_ori_h(j,p2) &
352 * sqrt( (dble(p1-1) + 0.5_dp)*(dble(p2-1) + 0.5_dp) )
353 end do
354 end do
355 end do
356 end do
357
358 !--
359
360 emat(:,:) = 0.0_rp
361 do f=1, elem%Nfaces_h
362 if (elem%IsLumpedMatrix()) then
363 massedge_h(:,:) = 0.0_rp
364 do k=1, elem%Nnode_v
365 do i=1, elem%Nnode_h1D
366 l = i + (k-1)*elem%Nnode_h1D
367 massedge_h(l,l) = intweight_lgl1dpts_h(i) * intweight_lgl1dpts_v(k)
368 end do
369 end do
370 else
371 call elementbase_construct_massmat( v2d_h, elem%Nfp_h, & ! (in)
372 massedge_h ) ! (out)
373 end if
374
375 is = (f-1)*elem%Nfp_h + 1
376 ie = is + elem%Nfp_h - 1
377 emat(elem%Fmask_h(:,f), is:ie) = massedge_h
378 end do
379
380 do f=1, elem%Nfaces_v
381 if (elem%IsLumpedMatrix()) then
382 massedge_v(:,:) = 0.0_rp
383 do j=1, elem%Nnode_h1D
384 do i=1, elem%Nnode_h1D
385 l = i + (j-1)*elem%Nnode_h1D
386 massedge_v(l,l) = intweight_lgl1dpts_h(i) * intweight_lgl1dpts_h(j)
387 end do
388 end do
389 else
390 call elementbase_construct_massmat( v2d_v, elem%Nfp_v, & ! (in)
391 massedge_v ) ! (out)
392 end if
393
394 is = elem%Nfaces_h*elem%Nfp_h + (f-1)*elem%Nfp_v + 1
395 ie = is + elem%Nfp_v - 1
396 emat(elem%Fmask_v(:,f), is:ie) = massedge_v
397 end do
398
399 call elementbase_construct_liftmat( elem%invM, emat, elem%Np, elem%NfpTot, & ! (in)
400 elem%Lift ) ! (out)
401 !$acc update device(elem%Lift)
402
403 return
404 end subroutine construct_element
405
406!OCL SERIAL
407 function hexhedralelement_gen_intgausslegendreintrpmat( this, IntrpPolyOrder, &
408 intw_intrp, x_intrp, y_intrp, z_intrp ) result(IntrpMat)
409
410 use scale_polynomial, only: &
414
415 implicit none
416
417 class(hexahedralelement), intent(in) :: this
418 integer, intent(in) :: IntrpPolyOrder
419 real(RP), intent(out), optional :: intw_intrp(IntrpPolyOrder**3)
420 real(RP), intent(out), optional :: x_intrp(IntrpPolyOrder**3)
421 real(RP), intent(out), optional :: y_intrp(IntrpPolyOrder**3)
422 real(RP), intent(out), optional :: z_intrp(IntrpPolyOrder**3)
423 real(RP) :: IntrpMat(IntrpPolyOrder**3,this%Np)
424
425 real(RP) :: r_int1D_i(IntrpPolyOrder)
426 real(RP) :: r_int1Dw_i(IntrpPolyOrder)
427 real(RP) :: P_int1D_ori_h(IntrpPolyOrder,this%Nnode_h1D)
428 real(RP) :: P_int1D_ori_v(IntrpPolyOrder,this%Nnode_v)
429 real(RP) :: Vint(IntrpPolyOrder**3,this%Np)
430
431 integer :: p1, p2, p3, p1_, p2_, p3_
432 integer :: n_, l_, m_
433 !-----------------------------------------------------
434
435 r_int1d_i(:) = polynomial_gengausslegendrept( intrppolyorder )
436 r_int1dw_i(:) = polynomial_gengausslegendreptintweight( intrppolyorder )
437 p_int1d_ori_h(:,:) = polynomial_genlegendrepoly( this%PolyOrder_h, r_int1d_i)
438 p_int1d_ori_v(:,:) = polynomial_genlegendrepoly( this%PolyOrder_v, r_int1d_i)
439
440 do p3_=1, intrppolyorder
441 do p2_=1, intrppolyorder
442 do p1_=1, intrppolyorder
443 n_= p1_ + (p2_-1)*intrppolyorder + (p3_-1)*intrppolyorder**2
444 if (present(intw_intrp)) intw_intrp(n_) = r_int1dw_i(p1_) * r_int1dw_i(p2_) * r_int1dw_i(p3_)
445 if (present(x_intrp)) x_intrp(n_) = r_int1d_i(p1_)
446 if (present(y_intrp)) y_intrp(n_) = r_int1d_i(p2_)
447 if (present(z_intrp)) z_intrp(n_) = r_int1d_i(p3_)
448
449 do p3=1, this%Nnode_v
450 do p2=1, this%Nnode_h1D
451 do p1=1, this%Nnode_h1D
452 l_ = p1 + (p2-1)*this%Nnode_h1D + (p3-1)*this%Nnode_h1D**2
453 vint(n_,l_) = p_int1d_ori_h(p1_,p1) * sqrt(dble(p1-1) + 0.5_dp) &
454 * p_int1d_ori_h(p2_,p2) * sqrt(dble(p2-1) + 0.5_dp) &
455 * p_int1d_ori_v(p3_,p3) * sqrt(dble(p3-1) + 0.5_dp)
456 end do
457 end do
458 end do
459 end do
460 end do
461 end do
462 intrpmat(:,:) = matmul(vint, this%invV)
463
464 return
465 end function hexhedralelement_gen_intgausslegendreintrpmat
466
module FElib / Element / Base
subroutine, public elementbase3d_init(elem, lumpedmat_flag)
Initialize an object to manage a 3D reference element.
subroutine, public elementbase_construct_massmat(v, np, massmat, invmassmat)
Construct mass matrix M^-1 = V V^T M = ( M^-1 )^-1.
subroutine, public elementbase_construct_stiffmat(massmat, invmassmat, dmat, np, stiffmat)
Construct stiffness matrix StiffMat_i = M^-1 ( M D_xi )^T.
subroutine, public elementbase_construct_liftmat(invm, emat, np, nfptot, liftmat)
Construct stiffness matrix StiffMat_i = M^-1 ( M D_xi )^T.
subroutine, public elementbase3d_final(elem)
Finalize an object to manage a 3D reference element.
module FElib / Element / hexahedron
subroutine hexhedralelement_init(elem, elemorder_h, elemorder_v, lumpedmassmatflag)
Initialize an object to manage a hexahedral element.
module FElib / Element / Quadrilateral
Module common / Linear algebra.
real(rp) function, dimension(size(a, 1), size(a, 2)), public linalgebra_inv(a)
Calculate a inversion of matrix A.
Module common / Polynomial.
real(rp) function, dimension(nord), public polynomial_gengausslegendreptintweight(nord)
A function to calculate the Gauss-Legendre (GL) weights.
real(rp) function, dimension(size(x), nord+1), public polynomial_gendlegendrepoly(nord, x, p)
A function to obtain differential values of Legendre polynomials which are evaluated at arbitrary poi...
real(rp) function, dimension(size(x), nord+1), public polynomial_genlegendrepoly(nord, x)
A function to obtain the values of Legendre polynomials which are evaluated at arbitrary points.
real(rp) function, dimension(nord+1), public polynomial_gengausslobattopt(nord)
A function to calculate the Legendre-Gauss-Lobatto (LGL) points.
real(rp) function, dimension(size(x), nord+1), public polynomial_genlagrangepoly(nord, x_lgl, x)
A function to obtain the Lagrange basis functions related to the Gauss-Legendre-Lobatto (GLL) points.
real(rp) function, dimension(nord), public polynomial_gengausslegendrept(nord)
A function to calculate the Gauss-Legendre (GL) points.
real(rp) real(rp) function, dimension(n, k), public polynomial_gendlagrangepoly_lglpt(nord, x_lgl)
Differential values of Lagrange basis functions at the GLL points.
real(rp) function, dimension(nord+1), public polynomial_gengausslobattoptintweight(nord)
A function to calculate the Gauss-Lobbato weights.
Derived type representing a 3D reference element.
Derived type representing a hexahedral element.
Derived type representing a quadrilateral element.