FE-Project
Loading...
Searching...
No Matches
scale_element_quadrilateral.F90
Go to the documentation of this file.
1!> module FElib / Element / Quadrilateral
2!!
3!! @par Description
4!! A module for a quadrilateral 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 !-----------------------------------------------------------------------------
23 implicit none
24 private
25
26 !-----------------------------------------------------------------------------
27 !
28 !++ Public type & procedure
29 !
30
31 !> Derived type representing a quadrilateral element
32 type, public, extends(elementbase2d) :: quadrilateralelement
33 contains
34 procedure :: init => quadrilateralelement_init
35 procedure :: final => quadrilateralelement_final
36 procedure :: genintgausslegendreintrpmat => quadrilateralelement_gen_intgausslegendreintrpmat
38
39 !-----------------------------------------------------------------------------
40 !
41 !++ Private procedure
42 !
43 private :: construct_element
44
45contains
46
47!> Initialize an object to manage a hexahedral element
48!!
49!! @param elem Object of finite element
50!! @param elemOrder Polynomial order with 1D direction
51!! @param LumpedMassMatFlag Flag whether mass lumping is considered
52!OCL SERIAL
54 elem, elemOrder, &
55 LumpedMassMatFlag )
56
57 implicit none
58
59 class(quadrilateralelement), intent(inout) :: elem
60 integer, intent(in) :: elemOrder
61 logical, intent(in) :: LumpedMassMatFlag
62
63 !-----------------------------------------------------------------------------
64
65 elem%PolyOrder = elemorder
66 elem%Nv = 4
67 elem%Np = (elemorder + 1)**2
68 elem%Nfp = elemorder + 1
69 elem%Nfaces = 4
70 elem%NfpTot = elem%Nfp*elem%Nfaces
71
72 call elementbase2d_init(elem, lumpedmassmatflag)
73 call construct_element(elem)
74
75 return
76 end subroutine quadrilateralelement_init
77
78!> Finalize an object to manage a quadrilateral element
79!!
80!! @param elem Object of finite element
81!OCL SERIAL
82 subroutine quadrilateralelement_final(elem)
83 implicit none
84
85 class(quadrilateralelement), intent(inout) :: elem
86 !-----------------------------------------------------------------------------
87
88 call elementbase2d_final(elem)
89
90 return
91 end subroutine quadrilateralelement_final
92
93!OCL SERIAL
94 subroutine construct_element(elem)
95
97 use scale_polynomial, only: &
101 use scale_element_base, only: &
104
105 implicit none
106
107 type(quadrilateralelement), intent(inout) :: elem
108
109 integer :: nodes_ij(elem%Nfp, elem%Nfp)
110
111 real(RP) :: lglPts1D(elem%Nfp)
112 real(DP) :: intWeight_lgl1DPts(elem%Nfp)
113
114 real(RP) :: P1D_ori(elem%Nfp, elem%Nfp)
115 real(RP) :: DP1D_ori(elem%Nfp, elem%Nfp)
116 real(RP) :: DLagr1D(elem%Nfp, elem%Nfp)
117 real(RP) :: V1D(elem%Nfp, elem%Nfp)
118 real(RP) :: Emat(elem%Np, elem%NfpTot)
119 real(RP) :: MassEdge(elem%Nfp, elem%Nfp)
120
121 real(RP) :: eta, etac
122 real(RP) :: filter1D(elem%Nfp), filter2D(elem%Np)
123
124 integer :: i, j
125 integer :: p1, p2
126 integer :: n, l, f
127 integer :: Nord
128 !-----------------------------------------------------------------------------
129
130 lglpts1d(:) = polynomial_gengausslobattopt( elem%PolyOrder )
131 p1d_ori(:,:) = polynomial_genlegendrepoly( elem%PolyOrder, lglpts1d )
132 dp1d_ori(:,:) = polynomial_gendlegendrepoly( elem%PolyOrder, lglpts1d, p1d_ori )
133 dlagr1d(:,:) = polynomial_gendlagrangepoly_lglpt(elem%PolyOrder, lglpts1d)
134
135 !* Preparation
136
137 do j=1, elem%Nfp
138 do i=1, elem%Nfp
139 nodes_ij(i,j) = i + (j-1)*elem%Nfp
140 end do
141 end do
142
143 ! Set the mask to extract the values at faces
144
145 elem%Fmask(:,1) = nodes_ij(:,1)
146 elem%Fmask(:,2) = nodes_ij(elem%Nfp,:)
147 elem%Fmask(:,3) = nodes_ij(:,elem%Nfp)
148 elem%Fmask(:,4) = nodes_ij(1,:)
149 !$acc update device(elem%Fmask)
150
151 !* Set the coordinates of LGL points, and the Vandermonde and differential matricies
152
153 elem%Dx1(:,:) = 0.0_rp
154 elem%Dx2(:,:) = 0.0_rp
155
156 do j=1, elem%Nfp
157 do i=1, elem%Nfp
158 n = i + (j-1)*elem%Nfp
159
160 !* Set the coordinates of LGL points
161 elem%x1(n) = lglpts1d(i)
162 elem%x2(n) = lglpts1d(j)
163
164 !* Set the Vandermonde and differential matricies
165 do p2=1, elem%Nfp
166 do p1=1, elem%Nfp
167 l = p1 + (p2-1)*elem%Nfp
168 elem%V(n,l) = (p1d_ori(i,p1)*p1d_ori(j,p2)) &
169 * sqrt((dble(p1-1) + 0.5_dp)*(dble(p2-1) + 0.5_dp))
170
171 if(p2==j) elem%Dx1(n,l) = dlagr1d(p1,i)
172 if(p1==i) elem%Dx2(n,l) = dlagr1d(p2,j)
173 end do
174 end do
175 end do
176 end do
177 elem%invV(:,:) = linalgebra_inv(elem%V)
178 !$acc update device(elem%x1, elem%x2, elem%V, elem%Dx1, elem%Dx2, elem%invV)
179
180 !* Set the weights at LGL points to integrate over element
181
182 intweight_lgl1dpts(:) = polynomial_gengausslobattoptintweight(elem%PolyOrder)
183
184 do j=1, elem%Nfp
185 do i=1, elem%Nfp
186 l = i + (j - 1)*elem%Nfp
187 elem%IntWeight_lgl(l) = &
188 intweight_lgl1dpts(i) * intweight_lgl1dpts(j)
189 end do
190 end do
191 !$acc update device(elem%IntWeight_lgl)
192
193 !* Set the mass matrix
194
195 if (elem%IsLumpedMatrix()) then
196 elem%invM(:,:) = 0.0_rp
197 elem%M(:,:) = 0.0_rp
198 do j=1, elem%Nfp
199 do i=1, elem%Nfp
200 l = i + (j - 1)*elem%Nfp
201 elem%M(l,l) = elem%IntWeight_lgl(l)
202 elem%invM(l,l) = 1.0_rp/elem%IntWeight_lgl(l)
203 end do
204 end do
205 else
206 call elementbase_construct_massmat( elem%V, elem%Np, & ! (in)
207 elem%M, elem%invM ) ! (out)
208 end if
209 !$acc update device(elem%M, elem%invM)
210
211 !* Set the stiffness matrix
212
213 call elementbase_construct_stiffmat( elem%M, elem%invM, elem%Dx1, elem%Np, & ! (in)
214 elem%Sx1 ) ! (out)
215 call elementbase_construct_stiffmat( elem%M, elem%invM, elem%Dx2, elem%Np, & ! (in)
216 elem%Sx2 ) ! (out)
217 !$acc update device(elem%Sx1, elem%Sx2)
218
219 !* Set the lift matrix
220
221 do p1=1, elem%Nfp
222 v1d(:,p1) = p1d_ori(:,p1)*sqrt(dble(p1-1) + 0.5_dp)
223 end do
224
225 emat(:,:) = 0.0_rp
226 do f=1, elem%Nfaces
227
228 if (elem%IsLumpedMatrix()) then
229 massedge = 0.0_rp
230 do l=1, elem%Nfp
231 massedge(l,l) = intweight_lgl1dpts(l)
232 end do
233 else
234 call elementbase_construct_massmat( v1d, elem%Nfp, & ! (in)
235 massedge ) ! (out)
236 end if
237
238 emat(elem%Fmask(:,f), (f-1)*elem%Nfp+1:f*elem%Nfp) = massedge
239 end do
240 call elementbase_construct_liftmat( elem%invM, emat, elem%Np, elem%NfpTot, & ! (in)
241 elem%Lift ) ! (out)
242 !$acc update device(elem%Lift)
243
244 return
245 end subroutine construct_element
246
247!OCL SERIAL
248 function quadrilateralelement_gen_intgausslegendreintrpmat( this, IntrpPolyOrder, &
249 intw_intrp, x_intrp, y_intrp ) result(IntrpMat)
250
251 use scale_polynomial, only: &
255
256 implicit none
257
258 class(quadrilateralelement), intent(in) :: this
259 integer, intent(in) :: IntrpPolyOrder
260 real(RP), intent(out), optional :: intw_intrp(IntrpPolyOrder**2)
261 real(RP), intent(out), optional :: x_intrp(IntrpPolyOrder**2)
262 real(RP), intent(out), optional :: y_intrp(IntrpPolyOrder**2)
263 real(RP) :: IntrpMat(IntrpPolyOrder**2,this%Np)
264
265 real(RP) :: r_int1D_i(IntrpPolyOrder)
266 real(RP) :: r_int1Dw_i(IntrpPolyOrder)
267 real(RP) :: P_int1D_ori(IntrpPolyOrder,this%PolyOrder+1)
268 real(RP) :: Vint(IntrpPolyOrder**2,(this%PolyOrder+1)**2)
269
270 integer :: p1, p2, p1_, p2_
271 integer :: n_, l_
272 !-----------------------------------------------------
273
274 r_int1d_i(:) = polynomial_gengausslegendrept( intrppolyorder )
275 r_int1dw_i(:) = polynomial_gengausslegendreptintweight( intrppolyorder )
276 p_int1d_ori(:,:) = polynomial_genlegendrepoly( this%PolyOrder, r_int1d_i)
277
278 do p2_=1, intrppolyorder
279 do p1_=1, intrppolyorder
280 n_= p1_ + (p2_-1)*intrppolyorder
281 if (present(intw_intrp)) intw_intrp(n_) = r_int1dw_i(p1_) * r_int1dw_i(p2_)
282 if (present(x_intrp)) x_intrp(n_) = r_int1d_i(p1_)
283 if (present(y_intrp)) y_intrp(n_) = r_int1d_i(p2_)
284
285 do p2=1, this%Nfp
286 do p1=1, this%Nfp
287 l_ = p1 + (p2-1)*this%Nfp
288 vint(n_,l_) = p_int1d_ori(p1_,p1) * sqrt(dble(p1-1) + 0.5_dp) &
289 * p_int1d_ori(p2_,p2) * sqrt(dble(p2-1) + 0.5_dp)
290 end do
291 end do
292 end do
293 end do
294 intrpmat(:,:) = matmul(vint, this%invV)
295
296 return
297 end function quadrilateralelement_gen_intgausslegendreintrpmat
298
299 !-------------------
300
module FElib / Element / Base
subroutine, public elementbase2d_final(elem)
Finalize an object to manage a 2D 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.
module FElib / Element / Quadrilateral
subroutine quadrilateralelement_init(elem, elemorder, lumpedmassmatflag)
Initialize an object to manage a hexahedral 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.
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 2D reference element.
Derived type representing a quadrilateral element.