FE-Project
Loading...
Searching...
No Matches
scale_multigrid_solver_3d.F90
Go to the documentation of this file.
1!-------------------------------------------------------------------------------
2!> module FElib / Multigrid / Solver 3D
3!!
4!! @par Description
5!! Manage a multigrid solver for 3D domain
6!!
7!! @author Yuta Kawai, Team SCALE
8!<
9!-------------------------------------------------------------------------------
10#include "scaleFElib.h"
12
13 !-----------------------------------------------------------------------------
14 !
15 !++ used modules
16 !
17 !
18 use scale_precision
19 use scale_io
20 use scale_prc, only: prc_abort
21
22 use scale_sparsemat, only: sparsemat
23
27
34
35 use scale_meshfield_base, only: &
39
40 use scale_mesh_hierarchy_base, only: &
41 pmg_finest_level => mesh_hierarchy_pmg_finest_level, &
42 hmg_finest_level => mesh_hierarchy_hmg_finest_level, &
45 use scale_mesh_hierarchy_3d, only: &
49
54
55 !-----------------------------------------------------------------------------
56 implicit none
57 private
58
59 !-----------------------------------------------------------------------------
60 !
61 !++ Public type & procedure
62 !
63 !> Derived type for multigrid solver in 3D domain
64 type, extends(multigridsolverbase), public :: multigridsolver3d
65 type(meshhierarchy3d), pointer :: mesh_hierarchy_ptr !< Pointer to an object to manage 3D mesh hierarchy
66 class(mgsmootherbase3d), pointer :: mg_smoother_ptr !< Pointer to an object to manage 3D MG smoother
67
68 type(mgfieldset3d), allocatable :: fields_h(:) !< Array of objects to manage MG field sets for h-MG
69 type(mgfieldset3d), allocatable :: fields_p(:) !< Array of objects to manage MG field sets for p-MG
70 contains
71 procedure :: init => multigridsolver3d_init
72 procedure :: final => multigridsolver3d_final
73 procedure :: solve => multigridsolver3d_solve
74 procedure :: do_vcycle => multigridsolver3d_do_vcycle
75 !-
76 procedure :: do_hmg_vcycle => multigridsolver3d_do_hmg_vcycle
77 procedure :: operate_pmg_restriction => multigridsolver3d_operate_pmg_restriction
78 procedure :: operate_pmg_correction => multigridsolver3d_operate_pmg_correction
79 procedure :: operate_hmg_restriction => multigridsolver3d_operate_hmg_restriction
80 procedure :: operate_hmg_correction => multigridsolver3d_operate_hmg_correction
81 end type multigridsolver3d
82
83 !-----------------------------------------------------------------------------
84 !
85 !++ Public parameters & variables
86 !
87
88 !-----------------------------------------------------------------------------
89 !
90 !++ Private procedure
91 !
92
93 !-----------------------------------------------------------------------------
94 !
95 !++ Private parameters & variables
96 !
97contains
98 !> Initialize an object for multigrid solver in 3D domain
99!OCL SERIAL
100 subroutine multigridsolver3d_init( this, &
101 mesh_hierarchy, mg_smoother, &
102 aux_var_num, aux_vec_num )
104 implicit none
105 class(multigridsolver3d), intent(inout) :: this
106 class(meshhierarchy3d), intent(in), target :: mesh_hierarchy
107 class(mgsmootherbase3d), intent(in), target :: mg_smoother
108 integer, intent(in) :: aux_var_num
109 integer, intent(in) :: aux_vec_num
110
111 integer :: lev_p
112 integer :: lev_h
113 !-------------------------------------------------------------
114
115 call multigridsolverbase_init( this, mesh_hierarchy )
116
117 this%mesh_hierarchy_ptr => mesh_hierarchy
118 this%mg_smoother_ptr => mg_smoother
119
120 !- Prepare p-MG field sets
121 allocate( this%fields_p( mesh_hierarchy%NUM_pMG_LEVEL ) )
122 do lev_p=1, mesh_hierarchy%NUM_pMG_LEVEL
123 call this%fields_p(lev_p)%Init( mesh_hierarchy%p_mesh_list(lev_p)%ptr, &
124 aux_var_num, aux_vec_num, lev_p )
125 end do
126
127 !- Prepare h-MG field sets
128 allocate( this%fields_h( mesh_hierarchy%NUM_hMG_LEVEL ) )
129 do lev_h=1, mesh_hierarchy%NUM_hMG_LEVEL
130 call this%fields_h(lev_h)%Init( mesh_hierarchy%h_mesh_list(lev_h)%ptr, &
131 aux_var_num, aux_vec_num, lev_h )
132 end do
133 return
134 end subroutine multigridsolver3d_init
135
136 !> Finalize an object for multigrid solver in 3D domain
137!OCL SERIAL
138 subroutine multigridsolver3d_final(this)
140 implicit none
141 class(multigridsolver3d), intent(inout) :: this
142
143 integer :: lev_p
144 integer :: lev_h
145 !-------------------------------------------------------------
146
147 call multigridsolverbase_final( this )
148
149 if (allocated(this%fields_p) ) then
150 do lev_p=1, this%mesh_hierarchy_ptr%NUM_pMG_LEVEL
151 call this%fields_p(lev_p)%Final()
152 end do
153 end if
154 deallocate( this%fields_p )
155
156 if (allocated(this%fields_h) ) then
157 do lev_h=1, this%mesh_hierarchy_ptr%NUM_hMG_LEVEL
158 call this%fields_h(lev_h)%Final()
159 end do
160 end if
161 deallocate( this%fields_h )
162
163 return
164 end subroutine multigridsolver3d_final
165
166 !> Solve a linear system using multigrid method in 3D domain
167!OCL SERIAL
168 subroutine multigridsolver3d_solve(this, q, &
169 f )
170 implicit none
171 class(multigridsolver3d), intent(inout) :: this
172
173 class(meshfield3d), intent(inout), target :: q
174 class(meshfield3d), intent(inout) :: f
175
176 integer :: vcyc_itr
177
178 class(localmesh3d), pointer :: lmesh
179 integer :: ldomID
180 integer :: ke
181 !-------------------------------------------------------------
182
183 do ldomid=1, q%mesh%LOCAL_MESH_NUM
184 lmesh => q%mesh%lcmesh_list(ldomid)
185 do ke=lmesh%NeS, lmesh%NeE
186 this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke) = q%local(ldomid)%val(:,ke)
187 end do
188 end do
189
190 this%current_p_lev = pmg_finest_level-1
191 this%current_h_lev = hmg_finest_level-1
192
193 !-
194 do vcyc_itr=1, this%vcyc_num_max
195 log_info("MultiGridSolver3D_solve",*) "V-cycle iteration:", vcyc_itr
196
197 call this%do_Vcycle( pmg_finest_level, f, vcyc_itr )
198 if ( this%Is_converged(this%mg_smoother_ptr) ) then
199 log_info("MultiGridSolver3D_solve",*) "V-cycle converged: vcyc_itr=", vcyc_itr
200 exit
201 end if
202 end do
203
204 !-
205 do ldomid=1, q%mesh%LOCAL_MESH_NUM
206 lmesh => q%mesh%lcmesh_list(ldomid)
207 do ke=lmesh%NeS, lmesh%NeE
208 q%local(ldomid)%val(:,ke) = this%fields_p(pmg_finest_level)%dq%local(ldomid)%val(:,ke)
209 end do
210 end do
211 return
212 end subroutine multigridsolver3d_solve
213
214 !> Do a V-cycle in 3D domain
215!OCL SERIAL
216 recursive subroutine multigridsolver3d_do_vcycle( this, &
217 mg_level, f_in, vcyc_itr )
218 implicit none
219 class(multigridsolver3d), intent(inout), target :: this
220 integer, intent(in) :: mg_level
221 type(meshfield3d), intent(inout) :: f_in
222 integer, intent(in) :: vcyc_itr
223
224 logical :: invoke_hMG
225
226 class(mgfieldset3d), pointer :: fs_p
227 class(meshhierarchy3d), pointer :: mesh_hierarchy
228 !---------------------------------------------------------------------
229
230 this%current_p_lev = this%current_p_lev + 1
231
232 mesh_hierarchy => this%mesh_hierarchy_ptr
233 fs_p => this%fields_p(mg_level)
234
235 log_info("MultiGridSolver3D_do_Vcycle",*) "Start: p_level=", this%current_p_lev
236
237 !- Pre-relaxation
238 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
239 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
240 fs_p%Dx, fs_p%Dy, fs_p%Dz, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
241 this%current_p_lev, this%current_h_lev, mgsmoother_pre_id )
242
243 if ( vcyc_itr == 1 .and. this%current_p_lev == pmg_finest_level ) then
244 call this%mg_smoother_ptr%Get_initial_residual_statistics( &
245 this%history_residual_l2_initial, this%history_residual_max_initial )
246 end if
247 call this%mg_smoother_ptr%Output_residual_history()
248
249 ! if ( vcyc_itr == 1 ) call Output_tmp_data(this, fs_p, f_in, vcyc_itr, "_pre")
250
251 if ( mg_level == mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL == 0 ) then
252 ! if ( vcyc_itr == 1 ) call Output_tmp_data(this, fs_p, f_in, vcyc_itr, "_post")
253 log_info("MultiGridSolver3D_do_Vcycle",*) "End: p_level=", this%current_p_lev
254 this%current_p_lev = this%current_p_lev - 1
255 return
256 end if
257
258 !-
259 invoke_hmg = ( mg_level+1 >= mesh_hierarchy%NUM_pMG_LEVEL .and. mesh_hierarchy%NUM_hMG_LEVEL > 0 )
260
261 if ( invoke_hmg ) then
262 !- Restriction
263 call this%Operate_pMG_restriction( this%fields_h(hmg_finest_level)%f, &
264 this%fields_p(mg_level)%res, mg_level )
265
266 !- Advance node in the V-cycle
267 call this%do_hMG_Vcycle( hmg_finest_level, this%fields_h(hmg_finest_level)%f )
268
269 !- Correction
270 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
271 this%fields_h(hmg_finest_level)%dq, mg_level )
272 else
273 !- Restriction
274 call this%Operate_pMG_restriction( this%fields_p(mg_level+1)%f, &
275 this%fields_p(mg_level)%res, mg_level )
276
277 !- Advance node in the V-cycle
278 call this%do_Vcycle( mg_level+1, this%fields_p(mg_level+1)%f, vcyc_itr )
279
280 !- Correction
281 call this%Operate_pMG_correction( this%fields_p(mg_level)%dq, &
282 this%fields_p(mg_level+1)%dq, mg_level )
283 end if
284
285 !- Post-relaxation
286 call this%mg_smoother_ptr%Do_smoothing( fs_p%dq, fs_p%res, &
287 f_in, fs_p%aux_var, fs_p%var_comm_ptr, fs_p%aux_comm_ptr, &
288 fs_p%Dx, fs_p%Dy, fs_p%Dz, fs_p%Lift, mesh_hierarchy%p_mesh_list(mg_level)%ptr, &
289 this%current_p_lev, this%current_h_lev, mgsmoother_post_id )
290
291 ! if ( vcyc_itr == 1 ) call Output_tmp_data(this, fs_p, f_in, vcyc_itr, "_post")
292
293 call this%mg_smoother_ptr%Output_residual_history()
294 log_info("MultiGridSolver3D_do_Vcycle",*) "End: p_level=", this%current_p_lev
295
296 this%current_p_lev = this%current_p_lev - 1
297 return
298 end subroutine multigridsolver3d_do_vcycle
299
300!OCL SERIAL
301 recursive subroutine multigridsolver3d_do_hmg_vcycle( this, mg_level, f_in )
302 implicit none
303 class(multigridsolver3d), intent(inout), target :: this
304 integer, intent(in) :: mg_level
305 type(meshfield3d), intent(inout) :: f_in
306
307 class(meshhierarchy3d), pointer :: mesh_hierarchy
308 class(mgfieldset3d), pointer :: fs_h
309 !----------------------------------------------
310
311 mesh_hierarchy => this%mesh_hierarchy_ptr
312 fs_h => this%fields_h(mg_level)
313
314 this%current_h_lev = this%current_h_lev + 1
315
316 log_info("MultiGridSolver3D_do_hMG_Vcycle",*) "Start: h_level=", this%current_h_lev
317
318 if ( mg_level == mesh_hierarchy%NUM_hMG_LEVEL ) then
319 ! It should be replaced by a direct solver in the future
320 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
321 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
322 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
323 this%current_p_lev, this%current_h_lev, mgsmoother_pre_id )
324
325 call this%mg_smoother_ptr%Output_residual_history()
326
327 log_info("MultiGridSolver3D_do_hMG_Vcycle",*) "End: h_level=", this%current_h_lev
328 this%current_h_lev = this%current_h_lev - 1
329 return
330 end if
331
332 !- Pre-relaxation
333 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
334 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
335 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
336 this%current_p_lev, this%current_h_lev, mgsmoother_pre_id )
337
338 !- Restriction
339 call this%Operate_hMG_restriction( this%fields_h(mg_level+1)%f, &
340 this%fields_h(mg_level)%res, mg_level )
341
342 !- Advance node in the V-cycle
343 call this%do_hMG_Vcycle( mg_level+1, this%fields_h(mg_level+1)%f )
344
345 !- Correction
346 call this%Operate_hMG_correction( this%fields_h(mg_level)%dq, &
347 this%fields_h(mg_level+1)%dq, mg_level )
348
349 !- Post-relaxation
350 call this%mg_smoother_ptr%Do_smoothing( fs_h%dq, fs_h%res, &
351 f_in, fs_h%aux_var, fs_h%var_comm_ptr, fs_h%aux_comm_ptr, &
352 fs_h%Dx, fs_h%Dy, fs_h%Dz, fs_h%Lift, mesh_hierarchy%h_mesh_list(mg_level)%ptr, &
353 this%current_p_lev, this%current_h_lev, mgsmoother_post_id )
354
355 log_info("MultiGridSolver3D_do_hMG_Vcycle",*) "End: h_level=", this%current_h_lev
356 this%current_h_lev = this%current_h_lev - 1
357 return
358 end subroutine multigridsolver3d_do_hmg_vcycle
359
360!--
361!OCL SERIAL
362 subroutine multigridsolver3d_operate_pmg_restriction( this, res_c, &
363 res, p_lev )
364 implicit none
365 class(multigridsolver3d), intent(in), target :: this
366 class(meshfield3d), intent(inout) :: res_c
367 class(meshfield3d), intent(in) :: res
368 integer, intent(in) :: p_lev
369
370 class(meshhierarchy3d), pointer :: hierarchy
371 integer :: ldomID
372 class(meshbase3d), pointer :: mesh3D
373 !------------------------------------------------
374
375 if ( this%mesh_hierarchy_ptr%NUM_pMG_LEVEL < p_lev+1 ) then
376 call prc_abort()
377 end if
378
379 hierarchy => this%mesh_hierarchy_ptr
380 mesh3d => hierarchy%p_mesh_list(p_lev)%ptr
381 do ldomid=1, mesh3d%LOCAL_MESH_NUM
382 call multigridsolver3d_pmg_operation( res_c%local(ldomid)%val, &
383 res%local(ldomid)%val, &
384 hierarchy%elem3D_list(p_lev), hierarchy%elem3D_list(p_lev+1), &
385 mesh3d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_f2c, &
386 .false. )
387 end do
388 return
389 end subroutine multigridsolver3d_operate_pmg_restriction
390
391!OCL SERIAL
392 subroutine multigridsolver3d_operate_pmg_correction( this, dq, &
393 cor_c, p_lev )
394 implicit none
395 class(multigridsolver3d), intent(in), target :: this
396 class(meshfield3d), intent(inout) :: dq
397 class(meshfield3d), intent(in) :: cor_c
398 integer, intent(in) :: p_lev
399
400 class(meshhierarchy3d), pointer :: hierarchy
401
402 integer :: ldomID
403 class(meshbase3d), pointer :: mesh3D
404 !------------------------------------------------
405
406 hierarchy => this%mesh_hierarchy_ptr
407 mesh3d => hierarchy%p_mesh_list(p_lev)%ptr
408
409 do ldomid=1, mesh3d%LOCAL_MESH_NUM
410 call multigridsolver3d_pmg_operation( dq%local(ldomid)%val, &
411 cor_c%local(ldomid)%val, &
412 hierarchy%elem3D_list(p_lev+1), hierarchy%elem3D_list(p_lev), &
413 mesh3d%lcmesh_list(ldomid), hierarchy%p_level(p_lev)%pMat1D_c2f, &
414 .true. )
415 end do
416 return
417 end subroutine multigridsolver3d_operate_pmg_correction
418
419!OCL SERIAL
420 subroutine multigridsolver3d_operate_hmg_restriction( this, res_c, &
421 res, h_lev )
423 implicit none
424 class(multigridsolver3d), intent(in), target :: this
425 class(meshfield3d), intent(inout) :: res_c
426 class(meshfield3d), intent(in) :: res
427 integer, intent(in) :: h_lev
428
429 class(meshhierarchy3d), pointer :: hierarchy
430
431 integer :: ldomID
432 class(meshbase3d), pointer :: mesh3D
433 class(meshbase3d), pointer :: mesh3D_c
434 !------------------------------------------------
435
436 hierarchy => this%mesh_hierarchy_ptr
437 mesh3d => hierarchy%h_mesh_list(h_lev)%ptr
438 mesh3d_c => hierarchy%h_mesh_list(h_lev+1)%ptr
439
440 do ldomid=1, mesh3d%LOCAL_MESH_NUM
441 call multigridsolver3d_hmg_restriction_core( res_c%local(ldomid)%val, &
442 res%local(ldomid)%val, &
443 hierarchy%h_level(h_lev)%mg_local(ldomid), mesh3d%lcmesh_list(ldomid), &
444 hierarchy%elem3D_list(hierarchy%NUM_pMG_LEVEL), mesh3d_c%lcmesh_list(ldomid) )
445 end do
446 return
447 end subroutine multigridsolver3d_operate_hmg_restriction
448
449!OCL SERIAL
450 subroutine multigridsolver3d_operate_hmg_correction( this, dq, &
451 cor_c, h_lev )
453 implicit none
454 class(multigridsolver3d), intent(in), target :: this
455 class(meshfield3d), intent(inout) :: dq
456 class(meshfield3d), intent(in) :: cor_c
457 integer, intent(in) :: h_lev
458
459 integer :: ldomID
460 class(meshbase3d), pointer :: mesh3D
461 class(meshhierarchy3d), pointer :: hierarchy
462 !------------------------------------------------
463
464 hierarchy => this%mesh_hierarchy_ptr
465 mesh3d => hierarchy%h_mesh_list(h_lev)%ptr
466
467 do ldomid=1, mesh3d%LOCAL_MESH_NUM
468 call multigridsolver3d_hmg_correction_core( dq%local(ldomid)%val, &
469 cor_c%local(ldomid)%val, hierarchy%h_level(h_lev)%mg_local(ldomid), &
470 mesh3d%lcmesh_list(ldomid), mesh3d%refElem3D )
471 end do
472 return
473 end subroutine multigridsolver3d_operate_hmg_correction
474
475!-- private --------------------------------------------------------------
476
477!OCL SERIAL
478 subroutine output_tmp_data( this, fs, fin, vcyc_itr, postfix )
479 use scale_prc, only: prc_myrank
482 implicit none
483 class(multigridsolver3d), intent(in) :: this
484 class(mgfieldset3d), intent(in), target :: fs
485 class(meshfield3d), intent(in) :: fin
486 integer, intent(in) :: vcyc_itr
487 character(len=*), intent(in) :: postfix
488
489 type(file_base_meshfield) :: file
490 class(meshbase3d), pointer :: mesh
491 character(len=H_MID) :: fname
492 logical :: fileexisted
493
494 integer, parameter :: DQ_VID = 1
495 integer, parameter :: RES_VID = 2
496 integer, parameter :: FIN_VID = 3
497 !-----------------------------------------------------
498
499 select type (mesh => fs%dq%mesh)
500 type is (meshcubedom3d)
501 call file%Init(2, mesh3d=mesh)
502 end select
503
504 write(fname,'(a,i2.2,a,i2.2,a)') "tmp_plev", this%current_p_lev, "_vcyc", vcyc_itr, trim(postfix)
505 call file%Create( fname, "MG", "REAL8", fileexisted, myrank=prc_myrank )
506 call file%Def_Var( "dq", "1", "dq", dq_vid, meshbase3d_dimtypeid_xyz, "REAL8")
507 call file%Def_Var( "res", "1", "res", res_vid, meshbase3d_dimtypeid_xyz, "REAL8")
508 call file%Def_Var( "fin", "1", "fin", fin_vid, meshbase3d_dimtypeid_xyz, "REAL8")
509 call file%End_def()
510
511 call file%Write_var3D( dq_vid, fs%dq, 0.0_rp, 1.0_rp)
512 call file%Write_var3D( res_vid, fs%res, 0.0_rp, 1.0_rp)
513 call file%Write_var3D( fin_vid, fin, 0.0_rp, 1.0_rp)
514 call file%Close()
515 call file%Final()
516 return
517 end subroutine output_tmp_data
518
519!OCL SERIAL
520 subroutine multigridsolver3d_hmg_restriction_core( res_c_lc, &
521 res_lc, mg_local, lmesh, elem, lmesh_c )
522 implicit none
523 class(localmesh3d), intent(in) :: lmesh
524 class(elementbase3d), intent(in) :: elem
525 class(localmesh3d), intent(in) :: lmesh_c
526 real(RP), intent(out) :: res_c_lc(elem%Np,lmesh_c%NeA)
527 real(RP), intent(in) :: res_lc(elem%Np,lmesh%NeA)
528 class(meshhierarchylocalmgdata3d), intent(in) :: mg_local
529
530 integer :: k, ke, ke_c
531 real(RP) :: Ic2fT_lc(8,8)
532 real(RP) :: tmp_c(elem%Np)
533 real(RP) :: tmp2(elem%Np)
534 !-----------------------------------------
535
536 !$omp parallel private(ke, ke_c, tmp2, tmp_c, Ic2fT_lc)
537 !$omp do
538 do ke_c=lmesh_c%NeS, lmesh_c%NeE
539
540 tmp_c(:) = 0.0_rp
541 do k=1, 4
542 ke = mg_local%If2c_emap(k,ke_c)
543
544 tmp2(:) = matmul( elem%M, res_lc(:,ke) )
545 ic2ft_lc(:,:) = transpose( mg_local%Ic2f(:,:,ke) )
546 tmp_c(:) = tmp_c(:) + matmul( ic2ft_lc, tmp2(:) )
547 end do
548
549 res_c_lc(:,ke_c) = matmul(lmesh_c%refElem3D%invM, tmp_c(:)) * 0.25_rp
550 end do
551 !$omp end parallel
552 return
553 end subroutine multigridsolver3d_hmg_restriction_core
554
555!OCL SERIAL
556 subroutine multigridsolver3d_hmg_correction_core( dq_lc, &
557 dq_c_lc, mg_local, lmesh, elem )
558 implicit none
559 class(localmesh3d), intent(in) :: lmesh
560 class(elementbase3d), intent(in) :: elem
561 real(RP), intent(out) :: dq_lc(elem%Np,lmesh%NeA)
562 real(RP), intent(in) :: dq_c_lc(elem%Np,lmesh%NeA)
563 class(meshhierarchylocalmgdata3d), intent(in) :: mg_local
564
565 integer :: k, ke, ke_c
566 !-----------------------------------------
567
568 !$omp parallel do private(ke, ke_c)
569 do ke=lmesh%NeS, lmesh%NeE
570 ke_c = mg_local%Ic2f_emap(ke)
571 dq_lc(:,ke) = dq_lc(:,ke) + &
572 matmul( mg_local%Ic2f(:,:,ke), dq_c_lc(:,ke_c) )
573 end do
574 return
575 end subroutine multigridsolver3d_hmg_correction_core
576
577!OCL SERIAL
578 subroutine multigridsolver3d_pmg_operation( q_o, &
579 q_i, elem3D_i, elem3D_o, lcmesh, pMat1D, is_added )
580 implicit none
581 class(elementbase3d), intent(in) :: elem3D_i
582 class(elementbase3d), intent(in) :: elem3D_o
583 class(localmesh3d), intent(in) :: lcmesh
584 real(RP), intent(inout) :: q_o(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D,elem3D_o%Nnode_v,lcmesh%NeA)
585 real(RP), intent(in) :: q_i(elem3D_i%Nnode_h1D,elem3D_i%Nnode_h1D,elem3D_i%Nnode_v,lcmesh%NeA)
586 real(RP), intent(in) :: pMat1D(elem3D_o%Nnode_h1D,elem3D_i%Nnode_h1D)
587 logical, intent(in) :: is_added
588
589 integer :: ke
590
591 integer :: px, py, pz
592 integer :: pxx, pyy, pzz
593 real(RP) :: tmp1
594 real(RP) :: tmp2(elem3D_o%Nnode_h1D,elem3D_i%Nnode_h1D)
595 real(RP) :: tmp3(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D,elem3D_i%Nnode_v)
596 real(RP) :: tmp4(elem3D_o%Nnode_h1D)
597 real(RP) :: tmp_h(elem3D_o%Nnode_h1D,elem3D_o%Nnode_h1D)
598
599 real(RP) :: mat_tr(elem3D_i%Nnode_h1D,elem3D_o%Nnode_h1D)
600 !-------------------------------------------
601
602 mat_tr(:,:) = transpose(pmat1d)
603
604 !$omp parallel do private(tmp1, tmp2, tmp3, tmp4, tmp_h)
605 do ke=lcmesh%NeS, lcmesh%NeE
606
607 do pz=1, elem3d_i%Nnode_v
608 do py=1, elem3d_i%Nnode_h1D
609 do pxx=1, elem3d_o%Nnode_h1D
610 tmp1 = 0.0_rp
611 do px=1, elem3d_i%Nnode_h1D
612 tmp1 = tmp1 + mat_tr(px,pxx) * q_i(px,py,pz,ke)
613 end do
614 tmp2(pxx,py) = tmp1
615 end do
616 end do
617
618 do pyy=1, elem3d_o%Nnode_h1D
619 tmp4(:) = 0.0_rp
620 do py=1, elem3d_i%Nnode_h1D
621 do px=1, elem3d_o%Nnode_h1D
622 tmp4(px) = tmp4(px) + mat_tr(py,pyy) * tmp2(px,py)
623 end do
624 end do
625 tmp3(:,pyy,pz) = tmp4(:)
626 end do
627 end do
628
629 if ( is_added ) then
630 do pzz=1, elem3d_o%Nnode_v
631 tmp_h(:,:) = 0.0_rp
632 do pz=1, elem3d_i%Nnode_v
633 do py=1, elem3d_o%Nnode_h1D
634 do px=1, elem3d_o%Nnode_h1D
635 tmp_h(px,py) = tmp_h(px,py) + mat_tr(pz,pzz) * tmp3(px,py,pz)
636 end do
637 end do
638 end do
639 q_o(:,:,pzz,ke) = q_o(:,:,pzz,ke) + tmp_h(:,:)
640 end do
641 else
642 do pzz=1, elem3d_o%Nnode_v
643 tmp_h(:,:) = 0.0_rp
644 do pz=1, elem3d_i%Nnode_v
645 do py=1, elem3d_o%Nnode_h1D
646 do px=1, elem3d_o%Nnode_h1D
647 tmp_h(px,py) = tmp_h(px,py) + mat_tr(pz,pzz) * tmp3(px,py,pz)
648 end do
649 end do
650 end do
651 q_o(:,:,pzz,ke) = tmp_h(:,:)
652 end do
653 end if
654 end do
655 return
656 end subroutine multigridsolver3d_pmg_operation
module FElib / Element / Base
module FElib / Element / hexahedron
module FElib / Element / Quadrilateral
module FElib / Mesh / Local 3D
module FElib / Mesh / Base 3D
integer, public meshbase3d_dimtypeid_xyz
module FElib / Mesh / Cubic 3D domain
module FElib / Mesh / 3D domain
module FElib / Mesh / Hierarchy base
integer, parameter, public mesh_hierarchy_type_pmg
Type ID of mesh hierarchy: p-MG.
integer, parameter, public mesh_hierarchy_hmg_finest_level
Finest level index in h-MG.
integer, parameter, public mesh_hierarchy_type_hmg
Type ID of mesh hierarchy: h-MG.
integer, parameter, public mesh_hierarchy_pmg_finest_level
Finest level index in p-MG.
module FElib / Mesh / Rectangle 2D domain
module FElib / Data / base
module FElib / Data / Communication 3D cubic domain
module FElib / Data / Communication 2D rectangle domain
module FElib / Multigrid / Field set base
module FElib / Multigrid / Smoother base
integer, parameter, public mgsmoother_pre_id
ID to represent pre-smoothing.
integer, parameter, public mgsmoother_post_id
ID to represent post-smoothing.
module FElib / Multigrid / Solver 3D
subroutine multigridsolver3d_init(this, mesh_hierarchy, mg_smoother, aux_var_num, aux_vec_num)
Initialize an object for multigrid solver in 3D domain.
module FElib / Multigrid / Solver base
subroutine, public multigridsolverbase_final(this)
Finalize a base object for multigrid solver.
subroutine, public multigridsolverbase_init(this, mesh_hierarchy)
Initialize a base object for multigrid solver.
Module common / sparsemat.
Derived type representing a 3D reference element.
Derived type representing a hexahedral element.
Derived type representing a quadrilateral element.
Derived type to manage file output with MeshField data.
Derived type to manage a local 3D computational domain.
Derived type to manage a computational mesh (base type for 3D domain)
Derived type to manage a cubic 3D computational domain.
Derived type for mesh hierarchy in 3D domain.
Derived type to represent mesh hierarchy level in 3D domain.
Derived type to manage 3D local mesh data for multigrid.
Derived type to manage a rectangular 2D computational domain.
Derived type representing a field with 2D mesh.
Derived type representing a field with 3D mesh.
Base derived type to manage data communication with 3D cubic domain.
Base derived type to manage data communication with 2D rectangle domain.
Derived type for multigrid solver in 3D domain.
Derived type to manage a sparse matrix.