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 ! allocate grid variables
99 call allocate_mg_level(mg(l
))
102 ! get 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 call get_mg_dims(mg(l
), &
138 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
139 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
140 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
141 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
)
142 allocate(mg(l
)%Kglo(ifms
:ifme
, kfms
:kfme
, jfms
:jfme
, msize
))
144 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
145 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
146 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
147 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, &
148 params
%A
, mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
, 1, &
150 call ndt_boundary_conditions( &
151 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
152 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
153 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
154 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, &
158 end subroutine multigrid_setup
161 recursive subroutine multigrid_cycle(mg
,l
,rate
)
166 type(mg_type
),intent(inout
)::mg(:) ! multigrid levels
167 integer, intent(in
)::l
! level
168 real, intent(out
)::rate
173 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
174 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
175 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
176 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
177 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
178 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
179 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
180 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
! coarse grid tile
182 integer::it
, maxit
, nit
, nsmooth
, cycles
183 logical::coarse
,coarsest
184 real:: restol
, norm_f
, norm_res
, diftol
, reldif
185 character(len
=10)::it_kind
189 call get_mg_dims(mg(l
), &
190 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
191 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, &
192 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
193 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
)
195 call get_mg_dims(mg(l
+1), &
196 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
197 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
198 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
199 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
) ! coarse grid tile
200 !*** temporary fix, meshes are in vertices not elements here.
201 !*** should be fixed using snode in all subroutines called from here
207 !*** temporary fix, meshes are in vertices not elements here.
208 !*** should be fixed using snode in all subroutines called from here
216 ! decide on number of iterations
217 coarsest
= l
.eq
.nlevels
218 diftol
= 0. ! default if params%check_reldif is false
221 maxit
= params
%coarsest_iter
223 if(params
%check_reldif
)diftol
= params
%diftol_coarsest
227 nsmooth
= params
%nsmooth
228 if(params
%check_reldif
)diftol
= params
%diftol_finest
230 ! some coarse level in between
231 maxit
= params
%maxit_coarse
232 nsmooth
= params
%nsmooth_coarse
233 if(params
%check_reldif
)diftol
= params
%diftol_coarse
236 mg(l
)%lambda
=0. ! initial solution 0
238 if(params
%check_relres
)then
239 norm_f
= norm2( mg(l
)%f(ifts
: ifte
, kfts
: kfte
, jfts
: jfte
)) !
240 restol
= norm_f
* params
%restol
241 print *,'starting mg cycle level ',l
,' norm_f ',norm_f
,' residual tolerance ',restol
246 coarse
= mod(it
,nsmooth
+1)==0 .and
. l
< nlevels
247 if(params
%print_level
>=l
)print *,'level=',l
,' it=',it
,' coarse=',coarse
248 if(coarse
)then ! coarse correction
249 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'cc_lambda_in')
250 it_kind
='coarse correction'
251 ! compute residual residual = f - Kglo*lambda
253 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
254 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
255 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
256 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile bounds
257 mg(l
)%Kglo
, mg(l
)%lambda
, mg(l
)%f
, mg(l
)%res
)
258 if(params
%debug_level
>=l
)call write_array(mg(l
)%res(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'cc_res')
259 ! restriction: f_coarse = R*residual
261 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
262 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
263 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
264 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile boundss
265 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
266 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
267 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
268 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
, & ! coarse grid tile
269 mg(l
+1)%f
,mg(l
)%res
, &
270 mg(l
)%cr_x
,mg(l
)%cr_y
,mg(l
)%icl_z
, &
271 mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
)
272 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%f(ifcts
: ifcte
, kfcts
: kfcte
, jfcts
:jfcte
),'cc_f_c')
273 if(params
%debug_level
>=l
)call pause
274 !if (l.eq.2) call crash('stopping here')
275 ! call self on level l+1
276 call multigrid_cycle(mg
,l
+1,rate
)
278 ! prolongation lambda = lambda + P*lambda_coarse
280 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%lambda(ifcts
: ifcte
+1, kfcts
: kfcte
+1, jfcts
:jfcte
+1),'cc_lambda_c')
282 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
283 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
284 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
285 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
286 ifcds
, ifcde
, kfcds
,kfcde
, jfcds
,jfcde
, & ! coarse grid domain
287 ifcms
, ifcme
, kfcms
,kfcme
, jfcms
,jfcme
, & ! coarse grid dimensions
288 ifcps
, ifcpe
, kfcps
,kfcpe
, jfcps
,jfcpe
, & ! coarse grid dimensions
289 ifcts
, ifcte
, kfcts
,kfcte
, jfcts
,jfcte
, & ! coarse grid tile
290 mg(l
)%lambda
,mg(l
+1)%lambda
, &
291 mg(l
)%cr_x
,mg(l
)%cr_y
,mg(l
)%icl_z
, &
292 mg(l
)%X
,mg(l
)%Y
,mg(l
)%Z
)
294 it_kind
= 'smoothing'
295 if(coarsest
)it_kind
='coarsest'
296 if(params
%debug_level
>=l
)call write_array(mg(l
)%f(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_f_in')
297 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_lambda_in')
299 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire grid dimensions
300 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! memory dimensions
301 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
302 ifts
, ifte
, kfts
, kfte
, jfts
, jfte
, & ! tile dimensions
303 mg(l
)%Kglo
, mg(l
)%f
, mg(l
)%lambda
, reldif
)
304 if(reldif
< diftol
)then
305 if(params
%print_level
>=l
)print *,'level ',l
,' iteration ',it
,' rel diff=',reldif
,'< diftol=',diftol
,' exiting'
308 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'sweep_lambda_out')
309 if((.not
.coarsest
.or
.it
==maxit
).and
.(params
%debug_level
>=l
))call pause
312 if(params
%check_relres
)then
314 ifds
, ifde
, kfds
, kfde
, jfds
, jfde
, & ! fire domain bounds
315 ifms
, ifme
, kfms
, kfme
, jfms
, jfme
, & ! fire memory bounds
316 ifps
, ifpe
, kfps
, kfpe
, jfps
, jfpe
, & ! fire patch bounds
317 ifts
, ifte
, kfts
, kfte
, jfts
,jfte
, & ! fire tile bounds
318 mg(l
)%Kglo
, mg(l
)%lambda
, mg(l
)%f
, mg(l
)%res
)
319 if(params
%debug_level
>=l
)call write_array(mg(l
+1)%res(ifcts
: ifcte
, kfcts
: kfcte
, jfcts
:jfcte
),'it_res')
320 norm_res
= norm2( mg(l
)%res(ifts
: ifte
, kfts
: kfte
, jfts
: jfte
)) ! residual norm
321 if (mod(it
,params
%nsmooth
+1)==params
%nsmooth
)then
324 if(params
%print_level
>=l
)print *,'cycle ',cycles
,' level ',l
, 'avg rate ',rate
325 rate
= (norm_res
/norm_f
)**(1d0/cycles
);
326 if(params
%print_level
>=l
)print *,'level ',l
,' iteration ',it
,' ',it_kind
,' residual ',norm_res
, &
327 ' norm_f ',norm_f
,' rate ',rate
328 if(norm_res
< restol
)exit
330 if(params
%debug_level
>=l
)call write_array(mg(l
)%lambda(ifts
: ifte
, kfts
: kfte
, jfts
:jfte
),'lambda_out')
335 end subroutine multigrid_cycle
337 end module module_multigrid