1 module module_multigrid
4 ! use module_f_assembly
5 use module_ndt_assembly
6 ! use module_w_assembly
9 use module_boundary_conditions
12 integer::nlevels
! number of levels
16 subroutine multigrid_setup(mg
)
18 ! set up the mg_level structure
19 ! input: mg(1)%X,Y,Z,dx,dy,dz already set
21 type(mg_type
),intent(inout
)::mg(:) ! multigrid level
27 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
28 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
29 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
30 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
31 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
32 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
33 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
34 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
! coarse grid tile
38 ! decide on the grid coarsening and compute scalars and 1D index arrays
40 mg(1)%nn
= mg(1)%nx
* mg(1)%ny
* mg(1)%nz
43 print *,'multigrid_setup received'
44 call print_mg_dims(mg
,1)
48 ! decide on coarsening
50 print *,'multigrid level ',l
,' grid size ', mg(l
)%nx
, mg(l
)%ny
, mg(l
)%nz
51 ! decide about the next level
52 call coarsening_icl(mg(l
)%cr_x
,mg(l
)%cr_y
,mg(l
)%icl_z
, &
53 mg(l
)%dx
,mg(l
)%dy
,mg(l
)%dz
, &
54 params
%A
,params
%minaspect
,params
%maxaspect
)
56 ! get horizontal coarsening lists
58 call coarsening_hzc2icl(mg(l
)%icl_x
, mg(l
)%icl_y
, &
59 mg(l
)%cr_x
,mg(l
)%cr_y
,&
62 ! update coarse mesh scalars
64 mg(l
+1)%nx
= size(mg(l
)%icl_x
)
65 mg(l
+1)%ny
= size(mg(l
)%icl_y
)
66 mg(l
+1)%nz
= size(mg(l
)%icl_z
)
67 mg(l
+1)%nn
= mg(l
+1)%nx
* mg(l
+1)%ny
* mg(l
+1)%nz
68 mg(l
+1)%dx
= mg(l
)%dx
* mg(l
)%cr_x
69 mg(l
+1)%dy
= mg(l
)%dy
* mg(l
)%cr_y
72 call print_mg_dims(mg
,l
+1)
74 if (mg(l
+1)%nn
>= mg(l
)%nn
.or
. l
== max_levels
) then
75 print *,'stopping at ',l
,' levels because coarse ndof ',mg(l
+1)%nn
, &
76 '>= fine ', mg(l
)%nn
,' or l= ',l
,' = ',max_levels
83 allocate(mg(l
+1)%dz(mg(l
+1)%nz
-1))
85 ! print *,'computing coarse dz of layer ',k
87 do m
=mg(l
)%icl_z(k
),mg(l
)%icl_z(k
+1)-1
88 ! print *,'adding fine dz ',m,' equal ',mg(l)%dz(m)
92 ! print *,'height dz of coarse layer',k,' is ',s
95 print *,nlevels
,' levels'
97 print *,'allocate grid variables'
99 call allocate_mg_level(mg(l
))
102 print *,'computing coarse grid coordinates'
104 call get_mg_dims(mg(l
), &
105 ifds
, ifde
, kfds
,kfde
, jfds
, jfde
, & ! fire grid dimensions
106 ifms
, ifme
, kfms
,kfme
, jfms
, jfme
, &
107 ifps
, ifpe
, kfps
,kfpe
, jfps
, jfpe
, & ! fire patch bounds
108 ifts
, ifte
, kfts
,kfte
, jfts
,jfte
)
109 call get_mg_dims(mg(l
+1), &
110 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
, jfcde
, & ! fire grid dimensions
111 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
, jfcme
, &
112 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
, jfcpe
, & ! fire patch bounds
113 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
)
114 call coarsening_grid(l
, &
115 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
116 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
117 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
118 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
119 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
120 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
121 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
122 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
, & ! coarse grid tile
123 mg(l
)%icl_x
, mg(l
)%icl_y
, mg(l
)%icl_z
, & ! indices of coarse grid
124 mg(l
)%X
, mg(l
)%Y
, mg(l
)%Z
, & ! fine grid coordinates
125 mg(l
+1)%X
, mg(l
+1)%Y
, mg(l
+1)%Z
) ! coarse grid coordinates
129 if(params
%debug_level
>=l
)call write_3d(mg
,l
,mg(l
)%X
,'X','v')
130 if(params
%debug_level
>=l
)call write_3d(mg
,l
,mg(l
)%Y
,'Y','v')
131 if(params
%debug_level
>=l
)call write_3d(mg
,l
,mg(l
)%Z
,'Z','v')
135 ! assemble the stiffness matrices
137 print *,'assembling the stiffness matrix on level ',l
138 call get_mg_dims(mg(l
), &
139 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
140 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
141 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
142 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
)
143 allocate(mg(l
)%Kglo(ifms
:ifme
, kfms
:kfme
, jfms
:jfme
, msize
))
145 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
146 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
147 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
148 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, &
149 params
%A
, mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
, 1, &
151 print *,'applying the boundary conditions on level ',l
152 call ndt_boundary_conditions( &
153 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
154 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
155 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
156 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, &
160 print *,'end multigrid setup'
162 end subroutine multigrid_setup
165 recursive subroutine multigrid_cycle(mg
,l
,rate
)
170 type(mg_type
),intent(inout
)::mg(:) ! multigrid levels
171 integer, intent(in
)::l
! level
172 real, intent(out
)::rate
177 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
178 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
179 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
180 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
181 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
182 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
183 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
184 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
! coarse grid tile
186 integer::it
, maxit
, nit
, nsmooth
, cycles
187 logical::coarse
,coarsest
188 real:: restol
, norm_f
, norm_res
, diftol
, siz
, reldif
, relres
, rhsiz
189 character(len
=10)::it_kind
193 call get_mg_dims(mg(l
), &
194 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
195 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
196 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
197 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
)
199 call get_mg_dims(mg(l
+1), &
200 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
201 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
202 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
203 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
) ! coarse grid tile
204 !*** temporary fix, meshes are in vertices not elements here.
205 !*** should be fixed using snode in all subroutines called from here
211 !*** temporary fix, meshes are in vertices not elements here.
212 !*** should be fixed using snode in all subroutines called from here
220 ! decide on number of iterations
221 coarsest
= l
.eq
.nlevels
222 diftol
= 0. ! default if params%check_reldif is false
225 maxit
= params
%coarsest_iter
227 if(params
%check_reldif
)diftol
= params
%diftol_coarsest
231 nsmooth
= params
%nsmooth
232 if(params
%check_reldif
)diftol
= params
%diftol_finest
234 ! some coarse level in between
235 maxit
= params
%maxit_coarse
236 nsmooth
= params
%nsmooth_coarse
237 if(params
%check_reldif
)diftol
= params
%diftol_coarse
240 mg(l
)%lambda
=0. ! initial solution 0
242 if(params
%check_relres
)then
243 norm_f
= norm2( mg(l
)%f(ifts
: ifte
, kfts
: kfte
, jfts
: jfte
)) !
244 restol
= norm_f
* params
%restol
245 print *,'starting mg cycle level ',l
,' norm_f ',norm_f
,' residual tolerance ',restol
250 coarse
= mod(it
,nsmooth
+1)==0 .and
. l
< nlevels
251 if(params
%print_level
>=l
)print *,'level=',l
,' it=',it
,' coarse=',coarse
252 if(coarse
)then ! coarse correction
253 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'cc_lambda_in')
254 it_kind
='coarse correction'
255 ! compute residual residual = f - Kglo*lambda
257 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
258 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
259 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
260 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile bounds
261 mg(l
)%Kglo
, mg(l
)%lambda
, mg(l
)%f
, mg(l
)%res
, rhsiz
, relres
)
262 if(params
%print_level
>=l
)print *,'level=',l
,' it=',it
,'mult rhsiz=',siz
,' rel res =',reldif
263 if(params
%debug_level
>=l
)call write_array(mg(l
)%res(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'cc_res')
264 ! restriction: f_coarse = R*residual
266 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
267 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
268 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
269 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile boundss
270 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
271 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
272 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
273 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
, & ! coarse grid tile
274 mg(l
+1)%f
,mg(l
)%res
, &
275 mg(l
)%cr_x
,mg(l
)%cr_y
,mg(l
)%icl_z
, &
276 mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
)
277 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%f(ifcts
: ifcte
, kfcts
: kfcte
, jfcts
:jfcte
),'cc_f_c')
278 if(params
%debug_level
>=l
)call pause
279 !if (l.eq.2) call crash('stopping here')
280 ! call self on level l+1
281 call multigrid_cycle(mg
,l
+1,rate
)
283 ! prolongation lambda = lambda + P*lambda_coarse
285 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%lambda(ifcts
: ifcte
+1, kfcts
: kfcte
+1, jfcts
:jfcte
+1),'cc_lambda_c')
287 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
288 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
289 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
290 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
291 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
292 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
293 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
294 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
, & ! coarse grid tile
295 mg(l
)%lambda
,mg(l
+1)%lambda
, &
296 mg(l
)%cr_x
,mg(l
)%cr_y
,mg(l
)%icl_z
, &
297 mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
)
299 it_kind
= 'smoothing'
300 if(coarsest
)it_kind
='coarsest'
301 if(params
%debug_level
>=l
)call write_array(mg(l
)%f(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_f_in')
302 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_lambda_in')
304 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
305 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
306 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
307 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
308 mg(l
)%Kglo
, mg(l
)%f
, mg(l
)%lambda
, siz
, reldif
)
309 if(params
%print_level
>=l
)print *,'level=',l
,' it=',it
,'sweeps siz=',siz
,' rel diff=',reldif
310 if(reldif
< diftol
)then
311 if(params
%print_level
>=l
)print *,'level ',l
,' iteration ',it
,' rel diff=',reldif
,'< diftol=',diftol
,' exiting'
314 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_lambda_out')
315 if((.not
.coarsest
.or
.it
==maxit
).and
.(params
%debug_level
>=l
))call pause
318 if(params
%check_relres
)then
320 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
321 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
322 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
323 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile bounds
324 mg(l
)%Kglo
, mg(l
)%lambda
, mg(l
)%f
, mg(l
)%res
, siz
, relres
)
325 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%res(ifcts
: ifcte
, kfcts
: kfcte
, jfcts
:jfcte
),'it_res')
326 norm_res
= norm2( mg(l
)%res(ifts
: ifte
, kfts
: kfte
, jfts
: jfte
)) ! residual norm
327 if (mod(it
,params
%nsmooth
+1)==params
%nsmooth
)then
330 if(params
%print_level
>=l
)print *,'cycle ',cycles
,' level ',l
, 'avg rate ',rate
331 rate
= (norm_res
/norm_f
)**(1d0/cycles
);
332 if(params
%print_level
>=l
)print *,'level ',l
,' iteration ',it
,' ',it_kind
,' residual ',norm_res
, &
333 ' norm_f ',norm_f
,' rate ',rate
334 if(norm_res
< restol
)exit
336 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'lambda_out')
341 end subroutine multigrid_cycle
343 end module module_multigrid