FE-Project
Loading...
Searching...
No Matches
scale_element_base.F90
Go to the documentation of this file.
1!> module FElib / Element / Base
2!!
3!! @par Description
4!! A base module for finite element
5!!
6!! @author Yuta Kawai, Team SCALE
7!!
8!<
9!-------------------------------------------------------------------------------
10#include "scaleFElib.h"
12
13 !-----------------------------------------------------------------------------
14 !
15 !++ used modules
16 !
17 use scale_precision
18
19 !-----------------------------------------------------------------------------
20 implicit none
21 private
22 !-----------------------------------------------------------------------------
23 !
24 !++ Public type & procedure
25 !
26
27 !- Base
28
29 !> Derived type representing an arbitrary finite element
30 type, public :: elementbase
31 integer :: np !< Number of nodes within an element
32 integer :: nfaces !< Number of faces
33 integer :: nfptot !< Total number of nodes on faces
34 integer :: nv !< Number of vertices with an element
35 logical, private :: lumpedmatflag !< Flag whether the lumped mass matrix is used
36
37 real(rp), allocatable :: v(:,:) !< The Vandermonde matrix (V) whose size is Np x Np
38 real(rp), allocatable :: invv(:,:) !< Inversion of the Vandermonde matrix (V^-1) whose size is Np x Np
39 real(rp), allocatable :: m(:,:) !< Mass matrix (M) whose size is Np x Np
40 real(rp), allocatable :: invm(:,:) !< Inversion of the mass matrix (M^-1) whose size Np x NP
41 real(rp), allocatable :: lift(:,:) !< Lifting matrix with element boundary integrals whose size Np x NfpTot
42 real(rp), allocatable :: intweight_lgl(:) !< Weights of gaussian quadrature with the LGL nodes
43 contains
44 procedure :: islumpedmatrix => elementbase_islumpedmatrix
45 end type elementbase
49
50 !- 1D
51
52 !> Derived type representing a 1D reference element
53 type, public, extends(elementbase) :: elementbase1d
54 integer :: polyorder !< Polynomial order
55 integer :: nfp !< Number of nodes on an element face
56 integer, allocatable :: fmask(:,:) !< Array saving indices to extract nodal values on the faces
57
58 real(rp), allocatable :: x1(:) !< Array saving x1-coordinate of nodes within the reference element
59
60 real(rp), allocatable :: dx1(:,:) !< Elementwise differential matrix for the x1-coordinate direction (Dx1 = M^-1 Sx1)
61
62 real(rp), allocatable :: sx1(:,:) !< Elementwise stiffness matrix for the x1-coordinate direction
63 end type elementbase1d
64
65 public :: elementbase1d_init
66 public :: elementbase1d_final
67
68 !- 2D
69
70 !> Derived type representing a 2D reference element
71 type, public, extends(elementbase) :: elementbase2d
72 integer :: polyorder !< Polynomial order
73 integer :: nfp !< Number of nodes on an element face
74 integer, allocatable :: fmask(:,:) !< Array saving indices to extract nodal values on the faces
75
76 real(rp), allocatable :: x1(:) !< Array saving x1-coordinate of nodes within the reference element
77 real(rp), allocatable :: x2(:) !< Array saving x2-coordinate of nodes within the reference element
78
79 real(rp), allocatable :: dx1(:,:) !< Elementwise differential matrix for the x1-coordinate direction (Dx1 = M^-1 Sx1)
80 real(rp), allocatable :: dx2(:,:) !< Elementwise differential matrix for the x2-coordinate direction (Dx2 = M^-1 Sx2)
81
82 real(rp), allocatable :: sx1(:,:) !< Elementwise stiffness matrix for the x1-coordinate direction
83 real(rp), allocatable :: sx2(:,:) !< Elementwise stiffness matrix for the x2-coordinate direction
84 contains
85 procedure :: generate_l2projmat => elementbase2d_gen_l2projmat
86 procedure :: generate_interpmat => elementbase2d_gen_interpmat
87 procedure :: generate_modaltruncationmat => elementbase2d_gen_modaltruncationmat
88 end type elementbase2d
89
90 public :: elementbase2d_init
91 public :: elementbase2d_final
92
93 interface
94 function elementbase2d_genintgausslegendreintrpmat(this, IntrpPolyOrder, &
95 intw_intrp, x_intrp, y_intrp ) result(IntrpMat)
96
97 import elementbase2d
98 import rp
99 class(elementbase2d), intent(in) :: this
100 integer, intent(in) :: intrppolyorder
101 real(rp), intent(out), optional :: intw_intrp(intrppolyorder**2)
102 real(rp), intent(out), optional :: x_intrp(intrppolyorder**2)
103 real(rp), intent(out), optional :: y_intrp(intrppolyorder**2)
104 real(rp) :: intrpmat(intrppolyorder**2,this%np)
106 end interface
107
108 !- 3D
109
110 !> Derived type representing a 3D reference element
111 type, public, extends(elementbase) :: elementbase3d
112 integer :: polyorder_h !< Polynomial order with the horizontal direction
113 integer :: nnode_h1d !< Number of nodes along the horizontal coordinate
114 integer :: nfaces_h !< Number of nodes on an horizontal face of the reference element
115 integer :: nfp_h !< Number of horizontal faces of the reference element
116 integer, allocatable :: fmask_h(:,:) !< Array saving indices to extract nodal values on the horizontal faces
117
118 integer :: polyorder_v !< Polynomial order with the vertical direction
119 integer :: nnode_v !< Number of nodes along the vertical coordinate
120 integer :: nfaces_v !< Number of nodes on an vertical face of the reference element
121 integer :: nfp_v !< Number of vertical faces of the reference element
122 integer, allocatable :: fmask_v(:,:) !< Array saving indices to extract nodal values on the vertical faces
123
124 integer, allocatable :: colmask(:,:) !< Array saving indices to extract nodal values on the vertical columns
125 integer, allocatable :: hslice(:,:) !< Array saving indices to extract nodal values on the horizontal plane
126 integer, allocatable :: indexh2dto3d(:) !< Array saving indices to expand 2D horizontal nodal values into the 3D nodal values
127 integer, allocatable :: indexh2dto3d_bnd(:) !< Array saving indices to expand 2D horizontal nodal values into the 3D nodal values on element faces
128 integer, allocatable :: indexz1dto3d(:) !< Array saving indices to expand 1D vertical nodal values into the 3D nodal values
129
130 real(rp), allocatable :: x1(:) !< Array saving x1-coordinate of nodes within the reference element
131 real(rp), allocatable :: x2(:) !< Array saving x2-coordinate of nodes within the reference element
132 real(rp), allocatable :: x3(:) !< Array saving x3-coordinate of nodes within the reference element
133
134 real(rp), allocatable :: dx1(:,:) !< Elementwise differential matrix for the x1-coordinate direction (Dx1 = M^-1 Sx1)
135 real(rp), allocatable :: dx2(:,:) !< Elementwise differential matrix for the x2-coordinate direction (Dx2 = M^-1 Sx2)
136 real(rp), allocatable :: dx3(:,:) !< Elementwise differential matrix for the x3-coordinate direction (Dx3 = M^-1 Sx3)
137
138 real(rp), allocatable :: sx1(:,:) !< Elementwise stiffness matrix for the x1-coordinate direction
139 real(rp), allocatable :: sx2(:,:) !< Elementwise stiffness matrix for the x2-coordinate direction
140 real(rp), allocatable :: sx3(:,:) !< Elementwise stiffness matrix for the x3-coordinate direction
141 contains
142 procedure :: generate_l2projmat => elementbase3d_gen_l2projmat
143 procedure :: generate_interpmat => elementbase3d_gen_interpmat
144 procedure :: generate_modaltruncationmat => elementbase3d_gen_modaltruncationmat
145 end type elementbase3d
146
147 public :: elementbase3d_init
148 public :: elementbase3d_final
149
150 !-----------------------------------------------------------------------------
151 !
152 !++ Private type & procedure
153 !
154
155 private :: elementbase_init
156 private :: elementbase_final
157
158 private :: elementbase2d_gen_nodaltransfermat
159 private :: elementbase3d_gen_nodaltransfermat
160
161contains
162 !-- Base Element ------------------------------------------------------------------------------
163
164 !> Initialize a base object to manage a reference element
165!OCL SERIAL
166 subroutine elementbase_init( elem, lumpedmat_flag )
167 implicit none
168 class(elementbase), intent(inout) :: elem
169 logical, intent(in) :: lumpedmat_flag !< Flag whether mass lumping is considered
170 !-----------------------------------------------------------------------------
171
172 allocate( elem%M(elem%Np, elem%Np) )
173 allocate( elem%invM(elem%Np, elem%Np) )
174 allocate( elem%V(elem%Np, elem%Np) )
175 allocate( elem%invV(elem%Np, elem%Np) )
176 allocate( elem%Lift(elem%Np, elem%NfpTot) )
177
178 allocate( elem%IntWeight_lgl(elem%Np) )
179 !$acc enter data create( elem%M, elem%invM, elem%V, elem%invV, elem%Lift, elem%IntWeight_lgl )
180
181 elem%LumpedMatFlag = lumpedmat_flag
182 return
183 end subroutine elementbase_init
184
185 !> Finalize a base object to manage a reference element
186!OCL SERIAL
187 subroutine elementbase_final( elem )
188 implicit none
189 class(elementbase), intent(inout) :: elem
190 !-----------------------------------------------------------------------------
191 if ( allocated(elem%M) ) then
192 !$acc exit data delete( elem%M, elem%invM, elem%V, elem%invV, elem%Lift, elem%IntWeight_lgl )
193 deallocate( elem%M )
194 deallocate( elem%invM )
195 deallocate( elem%V )
196 deallocate( elem%invV )
197 deallocate( elem%Lift )
198 deallocate( elem%IntWeight_lgl )
199 end if
200
201 return
202 end subroutine elementbase_final
203
204 !> Get a flag whether the lumped mass matrix is used
205!OCL SERIAL
206 function elementbase_islumpedmatrix( elem ) result(lumpedmat_flag)
207 implicit none
208 class(elementbase), intent(in) :: elem
209 logical :: lumpedmat_flag
210 !---------------------------------------------
211
212 lumpedmat_flag = elem%LumpedMatFlag
213 return
214 end function elementbase_islumpedmatrix
215
216
217 !> Construct mass matrix
218 !! M^-1 = V V^T
219 !! M = ( M^-1 )^-1
220!OCL SERIAL
221 subroutine elementbase_construct_massmat( V, Np, &
222 MassMat, invMassMat )
224 implicit none
225 integer, intent(in) :: np
226 real(rp), intent(in) :: v(np,np)
227 real(rp), intent(out) :: massmat(np,np)
228 real(rp), intent(out), optional :: invmassmat(np,np)
229
230 real(rp) :: tmpmat(np,np)
231 real(rp) :: invm(np,np)
232 !------------------------------------
233
234 tmpmat(:,:) = transpose(v)
235 invm(:,:) = matmul( v, tmpmat )
236 massmat(:,:) = linalgebra_inv( invm )
237
238 if ( present(invmassmat) ) invmassmat(:,:) = invm(:,:)
239 return
240 end subroutine elementbase_construct_massmat
241
242 !> Construct stiffness matrix
243 !! StiffMat_i = M^-1 ( M D_xi )^T
244!OCL SERIAL
245 subroutine elementbase_construct_stiffmat( MassMat, invMassMat, DMat, Np, &
246 StiffMat )
247 implicit none
248 integer, intent(in) :: np
249 real(rp), intent(in) :: massmat(np,np)
250 real(rp), intent(in) :: invmassmat(np,np)
251 real(rp), intent(in) :: dmat(np,np)
252 real(rp), intent(out) :: stiffmat(np,np)
253
254 real(rp) :: tmpmat1(np,np)
255 real(rp) :: tmpmat2(np,np)
256 !------------------------------------
257
258 tmpmat1(:,:) = matmul( massmat, dmat )
259 tmpmat2(:,:) = transpose( tmpmat1 )
260 stiffmat(:,:) = matmul( invmassmat, tmpmat2 )
261
262 return
263 end subroutine elementbase_construct_stiffmat
264
265 !> Construct stiffness matrix
266 !! StiffMat_i = M^-1 ( M D_xi )^T
267!OCL SERIAL
268 subroutine elementbase_construct_liftmat( invM, EMat, Np, NfpTot, &
269 LiftMat )
270 implicit none
271 integer, intent(in) :: np
272 integer, intent(in) :: nfptot
273 real(rp), intent(in) :: invm(np,np)
274 real(rp), intent(in) :: emat(np,nfptot)
275 real(rp), intent(out) :: liftmat(np,nfptot)
276 !------------------------------------
277
278 liftmat(:,:) = matmul( invm, emat )
279 return
280 end subroutine elementbase_construct_liftmat
281
282 !-- 1D Element ------------------------------------------------------------------------------
283
284 !> Initialize an object to manage a 1D reference element
285 !!
286 !! @param elem Object of finite element
287 !! @param elem Flag whether mass lumping is considered
288!OCL SERIAL
289 subroutine elementbase1d_init( elem, lumpedmat_flag )
290 implicit none
291 class(elementbase1d), intent(inout) :: elem
292 logical, intent(in) :: lumpedmat_flag
293 !-----------------------------------------------------------------------------
294
295 call elementbase_init( elem, lumpedmat_flag )
296
297 !$acc enter data create( elem )
298 !$acc update device( elem%Np, elem%Nfaces, elem%NfpTot, elem%Nv )
299
300 allocate( elem%x1(elem%Np) )
301 allocate( elem%Fmask(elem%Nfp, elem%Nfaces) )
302
303 allocate( elem%Dx1(elem%Np, elem%Np) )
304 allocate( elem%Sx1(elem%Np, elem%Np) )
305 !$acc enter data create( elem%x1, elem%Dx1, elem%Sx1, elem%Fmask )
306 return
307 end subroutine elementbase1d_init
308
309!> Finalize an object to manage a 1D reference element
310!OCL SERIAL
311 subroutine elementbase1d_final( elem )
312 implicit none
313 class(elementbase1d), intent(inout) :: elem
314 !-----------------------------------------------------------------------------
315
316 if ( allocated( elem%x1 ) ) then
317 !$acc exit data delete( elem%x1, elem%Dx1, elem%Sx1, elem%Fmask )
318 !$acc exit data delete( elem )
319 deallocate( elem%x1 )
320 deallocate( elem%Dx1 )
321 deallocate( elem%Sx1 )
322 deallocate( elem%Fmask )
323 end if
324
325 call elementbase_final( elem )
326
327 return
328 end subroutine elementbase1d_final
329
330 !-- 2D Element ------------------------------------------------------------------------------
331
332 !> Initialize an object to manage a 2D reference element
333 !!
334 !! @param elem Object of finite element
335 !! @param elem Flag whether mass lumping is considered
336!OCL SERIAL
337 subroutine elementbase2d_init( elem, lumpedmat_flag )
338 implicit none
339 class(elementbase2d), intent(inout) :: elem
340 logical, intent(in) :: lumpedmat_flag
341 !-----------------------------------------------------------------------------
342
343 call elementbase_init( elem, lumpedmat_flag )
344
345 !$acc enter data create( elem )
346 !$acc update device( elem%Np, elem%Nfaces, elem%NfpTot, elem%Nv )
347
348 allocate( elem%x1(elem%Np), elem%x2(elem%Np) )
349 allocate( elem%Fmask(elem%Nfp, elem%Nfaces) )
350
351 allocate( elem%Dx1(elem%Np, elem%Np), elem%Dx2(elem%Np, elem%Np) )
352 allocate( elem%Sx1(elem%Np, elem%Np), elem%Sx2(elem%Np, elem%Np) )
353 !$acc enter data create( elem%x1, elem%x2, elem%Dx1, elem%Dx2, elem%Sx1, elem%Sx2, elem%Fmask )
354
355 return
356 end subroutine elementbase2d_init
357
358 !> Finalize an object to manage a 2D reference element
359!OCL SERIAL
360 subroutine elementbase2d_final( elem )
361 implicit none
362 class(elementbase2d), intent(inout) :: elem
363 !-----------------------------------------------------------------------------
364
365 if ( allocated( elem%x1 ) ) then
366 !$acc exit data delete( elem%x1, elem%x2, elem%Dx1, elem%Dx2, elem%Sx1, elem%Sx2, elem%Fmask )
367 !$acc exit data delete( elem )
368 deallocate( elem%x1, elem%x2 )
369 deallocate( elem%Fmask )
370
371 deallocate( elem%Dx1, elem%Dx2 )
372 deallocate( elem%Sx1, elem%Sx2 )
373 end if
374
375 call elementbase_final( elem )
376
377 return
378 end subroutine elementbase2d_final
379
380 !> Generate a projection matrix for L2 projection.
381 !! This matrix maps nodal values on elem_in to nodal values on elem. It is intended for p-restriction, i.e. elem order <= elem_in order.
382 !!
383 !! With an orthogonal Legendre modal basis, this corresponds to L2 projection onto the polynomial space represented by elem.
384 !!
385!OCL SERIAL
386 subroutine elementbase2d_gen_l2projmat( elem, &
387 elem_in, &
388 L2ProjMat )
389 implicit none
390 class(elementbase2d), intent(in) :: elem
391 class(elementbase2d), intent(in) :: elem_in
392 real(rp), intent(out) :: l2projmat(elem%np,elem_in%np)
393 !---------------------------------------------
394
395 call elementbase2d_gen_nodaltransfermat( elem, elem_in, &
396 elem%PolyOrder, &
397 l2projmat )
398 return
399 end subroutine elementbase2d_gen_l2projmat
400
401 !> Generate an interpolation matrix by p-prolongation.
402 !! This matrix maps nodal values on elem_in to nodal values on elem. It is intended for p-prolongation, i.e. elem order >= elem_in order.
403 !!
404 !! In Legendre modal space, higher modes not present in elem_in are set to zero.
405!OCL SERIAL
406 subroutine elementbase2d_gen_interpmat( elem, &
407 elem_in, &
408 InterpMat )
409 implicit none
410 class(elementbase2d), intent(in) :: elem
411 class(elementbase2d), intent(in) :: elem_in
412 real(rp), intent(out) :: interpmat(elem%np,elem_in%np)
413 !---------------------------------------------
414
415 call elementbase2d_gen_nodaltransfermat( elem, elem_in, &
416 elem_in%PolyOrder, &
417 interpmat )
418 return
419 end subroutine elementbase2d_gen_interpmat
420
421 !> Generate a nodal-to-nodal transfer matrix to remove several high modes
422!OCL SERIAL
423 subroutine elementbase2d_gen_modaltruncationmat( elem, &
424 polyOrder_tr, &
425 TruncateMat )
426 implicit none
427 class(elementbase2d), intent(in) :: elem
428 integer, intent(in) :: polyorder_tr
429 real(rp), intent(out) :: truncatemat(elem%np,elem%np)
430 !---------------------------------------------
431
432 call elementbase2d_gen_nodaltransfermat( elem, elem, &
433 polyorder_tr, &
434 truncatemat )
435 return
436 end subroutine elementbase2d_gen_modaltruncationmat
437
438 !-- 3D Element ------------------------------------------------------------------------------
439
440!> Initialize an object to manage a 3D reference element
441!!
442!! @param elem Object of finite element
443!! @param elem Flag whether mass lumping is considered
444!OCL SERIAL
445 subroutine elementbase3d_init( elem, lumpedmat_flag )
446 implicit none
447 class(elementbase3d), intent(inout) :: elem
448 logical, intent(in) :: lumpedmat_flag
449 !-----------------------------------------------------------------------------
450
451 call elementbase_init( elem, lumpedmat_flag )
452
453 !$acc enter data create( elem )
454 !$acc update device( elem%Np, elem%Nfaces, elem%NfpTot, elem%Nv )
455
456 allocate( elem%x1(elem%Np), elem%x2(elem%Np), elem%x3(elem%Np) )
457 allocate( elem%Dx1(elem%Np, elem%Np), elem%Dx2(elem%Np, elem%Np), elem%Dx3(elem%Np, elem%Np) )
458 allocate( elem%Sx1(elem%Np, elem%Np), elem%Sx2(elem%Np, elem%Np), elem%Sx3(elem%Np, elem%Np) )
459 allocate( elem%Fmask_h(elem%Nfp_h, elem%Nfaces_h), elem%Fmask_v(elem%Nfp_v, elem%Nfaces_v) )
460 allocate( elem%Colmask(elem%Nnode_v,elem%Nfp_v))
461 allocate( elem%Hslice(elem%Nfp_v,elem%Nnode_v) )
462 allocate( elem%IndexH2Dto3D(elem%Np) )
463 allocate( elem%IndexH2Dto3D_bnd(elem%NfpTot) )
464 allocate( elem%IndexZ1Dto3D(elem%Np) )
465 !$acc enter data create( elem%x1, elem%x2, elem%x3, &
466 !$acc elem%Dx1, elem%Dx2, elem%Dx3, elem%Sx1, elem%Sx2, elem%Sx3, &
467 !$acc elem%Fmask_h, elem%Fmask_v, elem%Colmask, elem%Hslice, &
468 !$acc elem%IndexH2Dto3D, elem%IndexH2Dto3D_bnd, elem%IndexZ1Dto3D )
469 return
470 end subroutine elementbase3d_init
471
472!> Finalize an object to manage a 3D reference element
473!OCL SERIAL
474 subroutine elementbase3d_final( elem )
475 implicit none
476 class(elementbase3d), intent(inout) :: elem
477 !-----------------------------------------------------------------------------
478
479 if ( allocated( elem%x1 ) ) then
480 !$acc exit data delete( elem%x1, elem%x2, elem%x3, &
481 !$acc elem%Dx1, elem%Dx2, elem%Dx3, elem%Sx1, elem%Sx2, elem%Sx3, &
482 !$acc elem%Fmask_h, elem%Fmask_v, elem%Colmask, elem%Hslice, &
483 !$acc elem%IndexH2Dto3D, elem%IndexH2Dto3D_bnd, elem%IndexZ1Dto3D )
484 !$acc exit data delete( elem )
485 deallocate( elem%x1, elem%x2, elem%x3 )
486 deallocate( elem%Dx1, elem%Dx2, elem%Dx3 )
487 deallocate( elem%Sx1, elem%Sx2, elem%Sx3 )
488 deallocate( elem%Fmask_h, elem%Fmask_v )
489 deallocate( elem%Colmask, elem%Hslice )
490 deallocate( elem%IndexH2Dto3D, elem%IndexH2Dto3D_bnd )
491 deallocate( elem%IndexZ1Dto3D )
492 end if
493
494 call elementbase_final( elem )
495
496 return
497 end subroutine elementbase3d_final
498
499 !> Generate a projection matrix for L2 projection.
500 !! This matrix maps nodal values on elem_in to nodal values on elem. It is intended for p-restriction, i.e. elem order <= elem_in order.
501 !!
502 !! With an orthogonal Legendre modal basis, this corresponds to L2 projection onto the polynomial space represented by elem.
503 !!
504!OCL SERIAL
505 subroutine elementbase3d_gen_l2projmat( elem, &
506 elem_in, &
507 L2ProjMat )
508 implicit none
509 class(elementbase3d), intent(in) :: elem
510 class(elementbase3d), intent(in) :: elem_in
511 real(rp), intent(out) :: l2projmat(elem%np,elem_in%np)
512 !---------------------------------------------
513
514 call elementbase3d_gen_nodaltransfermat( elem, elem_in, &
515 elem%PolyOrder_h, elem%PolyOrder_v, &
516 l2projmat )
517 return
518 end subroutine elementbase3d_gen_l2projmat
519
520 !> Generate an interpolation matrix by p-prolongation.
521 !! This matrix maps nodal values on elem_in to nodal values on elem. It is intended for p-prolongation, i.e. elem order >= elem_in order.
522 !!
523 !! In Legendre modal space, higher modes not present in elem_in are set to zero.
524!OCL SERIAL
525 subroutine elementbase3d_gen_interpmat( elem, &
526 elem_in, &
527 InterpMat )
528 implicit none
529
530 class(elementbase3d), intent(in) :: elem
531 class(elementbase3d), intent(in) :: elem_in
532 real(rp), intent(out) :: interpmat(elem%np,elem_in%np)
533 !---------------------------------------------
534
535 call elementbase3d_gen_nodaltransfermat( elem, elem_in, &
536 elem_in%PolyOrder_h, elem_in%PolyOrder_v, &
537 interpmat )
538 return
539 end subroutine elementbase3d_gen_interpmat
540
541 !> Generate a nodal-to-nodal transfer matrix to remove several high modes
542!OCL SERIAL
543 subroutine elementbase3d_gen_modaltruncationmat( elem, &
544 polyOrder_h_tr, polyOrder_v_tr, &
545 TruncateMat )
546 implicit none
547
548 class(elementbase3d), intent(in) :: elem
549 integer, intent(in) :: polyorder_h_tr
550 integer, intent(in) :: polyorder_v_tr
551 real(rp), intent(out) :: truncatemat(elem%np,elem%np)
552 !---------------------------------------------
553
554 call elementbase3d_gen_nodaltransfermat( elem, elem, &
555 polyorder_h_tr, polyorder_v_tr, &
556 truncatemat )
557 return
558 end subroutine elementbase3d_gen_modaltruncationmat
559
560!--- private procedures ------------------------------------------------------------------------------
561
562
563 !> Generate a nodal-to-nodal transfer matrix for 2D element.
564 !! Mat = V_elem * S * invV_elem_in
565 !! This matrix maps nodal values on elem_in to nodal values on elem.
566 !! In modal space, common modes are copied and the other modes are zero.
567 !!
568 !! If elem has lower order than elem_in, this corresponds to modal truncation, i.e. L2 projection under an orthogonal Legendre modal basis.
569 !! If elem has higher order than elem_in, this corresponds to p-prolongation by modal zero-padding.
570!OCL SERIAL
571 subroutine elementbase2d_gen_nodaltransfermat( elem, elem_in, &
572 pmax, &
573 TransferMat )
574 implicit none
575 class(elementbase2d), intent(in) :: elem !< Object to manage a reference element
576 class(elementbase2d), intent(in) :: elem_in !< Object to manage a reference element
577 integer, intent(in) :: pmax !< Maximum polynomial order of the common modes between elem and elem_in
578 real(rp), intent(out) :: transfermat(elem%np,elem_in%np) !< Nodal-to-nodal transfer matrix from elem_in to elem
579
580 integer :: p1, p2
581 integer :: p_out, p_in
582
583 real(rp) :: invv_in(elem%np,elem_in%np)
584 !---------------------------------------------
585
586 invv_in(:,:) = 0.0_rp
587 do p2=1, pmax+1
588 do p1=1, pmax+1
589 p_out = p1 + (p2-1)*(elem%PolyOrder + 1)
590 p_in = p1 + (p2-1)*(elem_in%PolyOrder + 1)
591 invv_in(p_out,:) = elem_in%invV(p_in,:)
592 end do
593 end do
594
595 transfermat(:,:) = matmul(elem%V, invv_in)
596 return
597 end subroutine elementbase2d_gen_nodaltransfermat
598
599 !> Generate a nodal-to-nodal transfer matrix for 3D element.
600 !! Mat = V_elem * S * invV_elem_in
601 !! This matrix maps nodal values on elem_in to nodal values on elem.
602 !! In modal space, common modes are copied and the other modes are zero.
603 !!
604 !! If elem has lower order than elem_in, this corresponds to modal truncation, i.e. L2 projection under an orthogonal Legendre modal basis.
605 !! If elem has higher order than elem_in, this corresponds to p-prolongation by modal zero-padding.
606!OCL SERIAL
607 subroutine elementbase3d_gen_nodaltransfermat( elem, elem_in, &
608 pmax_h, pmax_v, &
609 TransferMat )
610 implicit none
611 class(elementbase3d), intent(in) :: elem !< Object to manage a reference element
612 class(elementbase3d), intent(in) :: elem_in !< Object to manage a reference element
613 integer, intent(in) :: pmax_h !< Maximum polynomial order of the common modes between elem and elem_in
614 integer, intent(in) :: pmax_v !< Maximum polynomial order of the common modes between elem and elem_in
615 real(rp), intent(out) :: transfermat(elem%np,elem_in%np) !< Nodal-to-nodal transfer matrix from elem_in to elem
616
617 integer :: p1, p2, p3
618 integer :: p_out, p_in
619
620 real(rp) :: invv_in(elem%np,elem_in%np)
621 !---------------------------------------------
622
623 invv_in(:,:) = 0.0_rp
624 do p3=1, pmax_v+1
625 do p2=1, pmax_h+1
626 do p1=1, pmax_h+1
627 p_out = p1 + (p2-1)*(elem%PolyOrder_h + 1) + (p3-1)*(elem%PolyOrder_h + 1)**2
628 p_in = p1 + (p2-1)*(elem_in%PolyOrder_h + 1) + (p3-1)*(elem_in%PolyOrder_h + 1)**2
629 invv_in(p_out,:) = elem_in%invV(p_in,:)
630 end do
631 end do
632 end do
633
634 transfermat(:,:) = matmul(elem%V, invv_in)
635 return
636 end subroutine elementbase3d_gen_nodaltransfermat
637
638end module scale_element_base
module FElib / Element / Base
subroutine, public elementbase2d_final(elem)
Finalize an object to manage a 2D reference element.
subroutine, public elementbase3d_init(elem, lumpedmat_flag)
Initialize an object to manage a 3D reference element.
subroutine, public elementbase2d_init(elem, lumpedmat_flag)
Initialize an object to manage a 2D 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.
subroutine, public elementbase1d_init(elem, lumpedmat_flag)
Initialize an object to manage a 1D reference element.
subroutine, public elementbase1d_final(elem)
Finalize an object to manage a 1D reference element.
Module common / Linear algebra.
real(rp) function, dimension(size(a, 1), size(a, 2)), public linalgebra_inv(a)
Calculate a inversion of matrix A.
Derived type representing a 1D reference element.
Derived type representing a 2D reference element.
Derived type representing a 3D reference element.
Derived type representing an arbitrary finite element.