source: trunk/SOURCES/conserv-mass-adv-diff_sept2009_mod.f90 @ 10

Last change on this file since 10 was 4, checked in by dumas, 10 years ago

initial import GRISLI trunk

File size: 15.0 KB
Line 
1!> \file conserv-mass-adv-diff_sept2009_mod.f90
2!! Module qui calcule l evolution de l epaisseur en resolvant
3!! une equation d'advection diffusion
4!<
5
6!> \namespace equat_adv_diff_2D_vect
7!!  Calcule l evolution de l epaisseur en resolvant
8!!  une equation d'advection diffusion
9!! @note Version avec :  call resol_adv_diff_2D_vect (Dmx,Dmy,advmx,advmy,H_p,i_Hp,bilmass,vieuxH,H)
10!! @note - le terme vecteur est passe en dummy parametres
11!! l epaisseur peut etre imposee   
12!! \author CatRitz
13!! \date june 2009
14!! @note  Used modules:
15!! @note  - use module3D_phy
16!! @note  - use reso_adv_diff_2D
17!! @todo essayer dans le futur la methode de Richard dUX/dx = H dU/dx + U dH/dx
18!<
19module equat_adv_diff_2D_vect                          ! Cat nouvelle mouture juin 2009
20use module3D_phy
21use reso_adv_diff_2D_vect
22use prescribe_H
23
24implicit none
25
26real, dimension(nx,ny) :: advmx           !< partie advective en x
27real, dimension(nx,ny) :: advmy           !< partie advective en y
28real, dimension(nx,ny) :: dmx             !< partie advective en x
29real, dimension(nx,ny) :: dmy             !< partie advective en y
30real, dimension(nx,ny) :: VieuxH          !< ancienne valeur de H
31real, dimension(nx,ny) :: bilmass         !< bilan de masse pour la colonne
32logical, dimension(nx,ny) :: zonemx       !< pour separer advection-diffusion
33logical,  dimension(nx,ny) :: zonemy      !< pour separer advection-diffusion
34real :: adv_frac                          !< fraction du flux traitee en advection
35integer :: itesti
36integer :: itour
37
38
39contains
40
41!> SUBROUTINE: init_icethick
42!! Definition et initialisation des parametres qui gerent la repartition advection diffusion
43!! @return adv_frac
44
45subroutine init_icethick
46
47implicit none
48
49namelist/mass_conserv/adv_frac,V_limit 
50
51
52rewind(num_param)        ! pour revenir au debut du fichier param_list.dat
53read(num_param,mass_conserv)
54
55
56write(num_rep_42,*)'! Conservation de la masse avec equation advection-diffusion '
57write(num_rep_42,mass_conserv)
58write(num_rep_42,*)'! la repartition depend de adv_frac'
59write(num_rep_42,*)'! >1  -> advection seule'
60write(num_rep_42,*)'! 0   -> diffusion seule'
61write(num_rep_42,*)'! 0<*<1   -> fraction de l advection'
62write(num_rep_42,*)'! -1 -> zones diffusion + zones advection'
63write(num_rep_42,*)'! V_limit depend de la calotte : '
64write(num_rep_42,*)'! typiquement 3000 m/an en Antarctique, 10000 m/an au Groenland'
65write(num_rep_42,*)'!___________________________________________________________' 
66
67
68call init_reso_adv_diff_2D     
69call init_prescribe_H        ! initialize grounding line mask
70
71Dx1=1./Dx
72itour=0
73
74end subroutine init_icethick
75
76!------------------------------------------------------------------
77!> SUBROUTINE: icethick3
78!! Routine pour le calcule de l'epaisseur de glace
79!<
80subroutine icethick3
81
82implicit none
83real,dimension(nx,ny) :: Dminx,Dminy
84real,dimension(nx,ny) :: Uxdiff,Uydiff           ! vitesse due a la diffusion
85integer :: it1,it2,it3
86
87real aux                                         ! pour le calcul du critere
88real maxdia                                      ! sur le pas de temps
89integer imaxdia,jmaxdia
90
91
92if (itracebug.eq.1) call tracebug(" Entree dans routine icethick")
93
94! Copie de H sur vieuxH       
95! --------------------
96where (mk0(:,:).eq.0)
97   vieuxH(:,:)=0.
98elsewhere (i_Hp(:,:).eq.1)                 ! previous prescribed thickness
99   vieuxH(:,:)=Hp(:,:)                     ! H may have been changed by calving
100elsewhere
101   vieuxH(:,:)=H(:,:)
102end where
103
104! mk0 est le masque à ne jamais dépasser
105! mk0=0  ->  pas de glace
106! mk0=-1 ->  on garde la même epaisseur
107! pour l'Antarctique masque mko=1 partout
108
109
110Maxdia = -1.0
111imaxdia=0
112jmaxdia=0
113
114! attention limitation !
115uxbar(:,:)=max(uxbar(:,:),-V_limit)
116uxbar(:,:)=min(uxbar(:,:),V_limit)
117uybar(:,:)=max(uybar(:,:),-V_limit)
118uybar(:,:)=min(uybar(:,:),V_limit)
119
120! le pas de temps est choisi pour rendre la matrice advective diagonale dominante
121do i=2,nx-1
122   do j=2,ny-1
123      aux = (abs(uxbar(i,j)) + abs(uxbar(i+1,j))) &
124           + (abs(uybar(i,j)) + abs(uybar(i,j+1)))
125      aux=aux*dx1*0.5
126      if (aux.gt.maxdia) then
127         maxdia=aux
128         imaxdia=i
129         jmaxdia=j
130      endif
131   end do
132end do
133
134
135if (maxdia.ge.(testdiag/dtmax)) then
136   dt = testdiag/Maxdia
137   dt=max(dt,dtmin)
138else
139   dt = dtmax
140end if
141
142! next_time ajuste le pas de temps pour faciliter la synchronisation
143! avec le pas de temps long (dtt)
144
145 call next_time(time,dt,dtt,dtmax,dtmin,isynchro,itracebug,num_tracebug)
146
147
148! calcul diffusivite - vitesse
149!-----------------------------------------------------------------
150
151Uxdiff(:,:)=diffmx(:,:)*(-sdx(:,:))   ! vitesse qui peut s'exprimer en terme diffusif
152Uydiff(:,:)=diffmy(:,:)*(-sdy(:,:))   ! dans les where qui suivent elle est limitee a uxbar
153                                      ! pour eviter des problemes dans le cas 0< adv_frac <1
154dmx(:,:)=diffmx(:,:)
155dmy(:,:)=diffmy(:,:)
156
157! schema amont pour la diffusion en x
158where (Uxbar(:,:).ge.0.)
159  dmx(:,:)=diffmx(:,:)*eoshift(H(:,:),shift=-1,boundary=0.,dim=1)
160  uxdiff(:,:)=min(uxdiff(:,:),uxbar(:,:))       ! pour tenir compte limitation utot
161elsewhere
162  dmx(:,:)=diffmx(:,:)*H(:,:)
163  uxdiff(:,:)=max(uxdiff(:,:),uxbar(:,:))       ! pour tenir compte limitation utot
164end where
165
166
167
168! schema amont pour la diffusion en y
169where (uybar(:,:).ge.0.)
170  dmy(:,:)=diffmy(:,:)*eoshift(H(:,:),shift=-1,boundary=0.,dim=2)
171  uydiff(:,:)=min(uydiff(:,:),uybar(:,:))       ! pour tenir compte limitation utot
172elsewhere
173  dmy(:,:)=dmy(:,:)*H(:,:)
174  uydiff(:,:)=max(uydiff(:,:),uybar(:,:))       ! pour tenir compte limitation utot
175end where
176
177
178
179! tests pour la répartition advection - diffusion
180!------------------------------------------------
181
182if (adv_frac.gt.1.) then ! advection seulement
183   advmx(:,:)=Uxbar(:,:)
184   advmy(:,:)=Uybar(:,:)
185   Dmx(:,:)=0.
186   Dmy(:,:)=0.
187
188else if (abs(adv_frac).lt.1.e-8) then   ! diffusion seulement
189   advmx(:,:)=0.
190   advmy(:,:)=0.
191
192   ! D reste la valeur au dessus)
193
194else if ((adv_frac.ge.1.e-8).and.(adv_frac.le.1.)) then        ! advection-diffusion)
195
196! selon x --------------------------------
197
198! advection = adv_frac* tout ce qui n'est pas diffusion
199! diffusion = ce qui peut être exprime en diffusion
200!             + une partie (1-adv_frac) de l'advection
201
202   where ((abs(sdx(:,:)).gt.1.e-8).and.(Hmx(:,:).gt.2.))      ! cas general
203       advmx(:,:)=(Uxbar(:,:)-Uxdiff(:,:))                   ! tout ce qui n'est pas diffusion
204       advmx(:,:)=advmx(:,:)*adv_frac                         ! la fraction adv_frac du precedent
205       Dminx(:,:)=-(Uxbar(:,:)-advmx(:,:))/sdx(:,:)          ! ce qui reste exprime en diffusivite
206                                                            ! a multiplier par H
207
208! schema amont pour la diffusivite
209       where (uxbar(:,:).ge.0.)
210          dmx(:,:)=dminx(:,:)*eoshift(H(:,:),shift=-1,boundary=0.,dim=1)
211       elsewhere
212          dmx(:,:)=dminx(:,:)*H(:,:)
213       end where
214
215
216   elsewhere   ! zones trop plates ou trop fines
217      Dmx(:,:)=0.
218      advmx(:,:)=Uxbar(:,:)
219   end where
220
221
222! selon y --------------------------------
223
224! advection = adv_frac* tout ce qui n'est pas diffusion
225! diffusion = ce qui peut être exprime en diffusion
226!             + une partie (1-adv_frac) de l'advection
227
228   where ((abs(sdy(:,:)).gt.1.e-8).and.(Hmy(:,:).gt.2.))      ! cas general
229       advmy(:,:)=(Uybar(:,:)-Uydiff(:,:))                    ! tout ce qui n'est pas diffusion
230       advmy(:,:)=advmy(:,:)*adv_frac                         ! la fraction adv_frac du precedent
231       Dminy(:,:)=-(Uybar(:,:)-advmy(:,:))/sdy(:,:)          ! ce qui reste exprime en diffusivite
232                                                            ! a multiplier par H
233
234! schema amont pour la diffusivite
235       where (uybar(:,:).ge.0.)
236          dmy(:,:)=dminy(:,:)*eoshift(H(:,:),shift=-1,boundary=0.,dim=2)
237       elsewhere
238          dmy(:,:)=dminy(:,:)*H(:,:)
239       end where
240
241
242
243   elsewhere   ! zones trop plates ou trop fines
244      Dmy(:,:)=0.
245      advmy(:,:)=Uybar(:,:)
246   end where
247
248
249else if (adv_frac.lt.0) then                  ! diffusif dans zones SIA, advectif ailleurs
250
251   zonemx(:,:)=flgzmx(:,:)
252   zonemy(:,:)=flgzmy(:,:)
253
254! selon x --------------
255   where (zonemx(:,:))
256    advmx(:,:)=Uxbar(:,:)
257    Dmx(:,:)=0.
258   elsewhere
259    advmx(:,:)=0.
260   end where
261
262! selon y --------------
263   where (zonemy(:,:))
264    advmy(:,:)=Uybar(:,:)
265    Dmy(:,:)=0.
266   elsewhere
267    advmy(:,:)=0.
268   end where
269
270end if
271
272
273where (flot(:,:) )
274   tabtest(:,:)=1.
275elsewhere
276   tabtest(:,:)=0.
277end where
278
279!------------------------------------------------------------------detect
280!!$ tabtest(:,:)=dmx(:,:)
281!!$
282!!$call detect_assym(nx,ny,0,41,1,0,1,0,tabtest,itesti)
283!!$
284!!$if (itesti.gt.0) then
285!!$   write(6,*) 'asymetrie sur dmx avant resol pour time=',time,itesti
286!!$   stop
287!!$else
288!!$   write(6,*) ' pas d asymetrie sur dmx avant resol pour time=',time,itesti
289!!$end if
290!----------------------------------------------------------- fin detect 
291
292
293!------------------------------------------------------------------detect
294!!$ tabtest(:,:)=dmy(:,:)
295!!$
296!!$call detect_assym(nx,ny,0,41,1,0,1,1,tabtest,itesti)
297!!$
298!!$if (itesti.gt.0) then
299!!$   write(6,*) 'asymetrie sur dmy avant resol pour time=',time,itesti
300!!$   stop
301!!$else
302!!$   write(6,*) ' pas d asymetrie sur dmy avant resol pour time=',time,itesti
303!!$end if
304!----------------------------------------------------------- fin detect 
305
306!------------------------------------------------------------------detect
307!!$ tabtest(:,:)=advmx(:,:)
308!!$
309!!$call detect_assym(nx,ny,0,41,1,0,1,0,tabtest,itesti)
310!!$
311!!$if (itesti.gt.0) then
312!!$   write(6,*) 'asymetrie sur advmx avant resol pour time=',time,itesti
313!!$   stop
314!!$else
315!!$   write(6,*) ' pas d asymetrie sur advdmx avant resol pour time=',time,itesti
316!!$end if
317!----------------------------------------------------------- fin detect 
318
319!------------------------------------------------------------------detect
320!!$ tabtest(:,:)=advmy(:,:)
321!!$
322!!$call detect_assym(nx,ny,0,41,1,0,-1,1,tabtest,itesti)
323!!$
324!!$if (itesti.gt.0) then
325!!$   write(6,*) 'asymetrie sur advmy avant resol pour time=',time,itesti
326!!$   stop
327!!$else
328!!$   write(6,*) ' pas d asymetrie sur advmy avant resol pour time=',time,itesti
329!!$end if
330!----------------------------------------------------------- fin detect 
331
332! nouveau calcul de dt
333aux=maxval( (abs(advmx(:,:))+abs(advmy(:,:)))/dx+(abs(dmx(:,:))+abs(dmy(:,:)))/dx/dx)
334
335! write(166,*) 'critere pour dt',time-dt,testdiag/aux,dt
336
337
338if (aux.gt.1.e-20) then
339   if (testdiag/aux.lt.dt) then
340      time=time-dt
341      dt=testdiag/aux*4.
342if (itracebug.eq.1) call tracebug("aux tres petit,deuxieme appel a next_time dt*4")
343      call next_time(time,dt,dtt,dtmax,dtmin,isynchro,itracebug,num_tracebug)
344   end if
345end if
346
347
348timemax=time
349
350! etait avant dans step
351if (time.lt.TGROUNDED) then
352   MARINE=.false.
353else
354   MARINE=.true.
355endif
356! fin vient de step
357
358! les variables dtdx et dtdx2 sont globales
359 Dtdx2=Dt/(Dx**2)
360 dtdx=dt/dx
361
362
363if (geoplace(1:5).eq.'mism3') then       ! pas de flux sur les limites laterales
364   dmy(:,2)       = 0.
365   dmy(:,3)       = 0.
366   dmy(:,ny-1)    = 0.
367   dmy(:,ny)      = 0.
368   advmy(:,2)     = 0.
369   advmy(:,3)     = 0.
370   advmy(:,ny-1)  = 0.
371   advmy(:,ny)    = 0.
372   uybar(:,2)     = 0
373   uybar(:,3)     = 0
374   uybar(:,ny-1)  = 0
375   uybar(:,ny)    = 0   
376end if
377
378
379debug_3D(:,:,45)=dmx(:,:)
380debug_3D(:,:,46)=dmy(:,:)
381debug_3D(:,:,47)=advmx(:,:)
382debug_3D(:,:,48)=advmy(:,:)
383
384
385bilmass(:,:)=bm(:,:)-bmelt(:,:)                       ! surface and bottom mass balance
386
387! diverses precription de l'epaisseur en fonction de l'objectif
388!-------------------------------------------------------------------
389
390
391  call prescribe_fixed_points            ! ceux qui sont fixes pour tout le run (bords de grille, regions)
392
393
394   
395
396
397 if ((igrdline.eq.1)) then               ! present grounding line
398
399!    if ((time.lt.time_gl(1)).or.(nt.lt.2)) then      ATTENTION test seulement si version prescribe-H_mod.f90
400       call prescribe_present_H_gl       ! prescribe present thickness at the grounding line
401!    else
402!       call prescribe_retreat
403!    endif
404 end if
405
406 if ((igrdline.eq.2)) then               ! paleo grounding line
407    call prescribe_paleo_gl_shelf
408 end if
409
410 if ((igrdline.eq.3)) then 
411!    where (flot(:,:))
412!       mk_gr(:,:) = 0
413!    elsewhere
414!       mk_gr(:,:) = 1
415!    end where
416    if (itracebug.eq.1) call tracebug(" avant time_step_recul")
417    call time_step_recul                 ! version prescribe-H-i2s_mod.f90 avec use proto_recul_mod
418    if (itracebug.eq.1) call tracebug(" apres time_step_recul")
419!    call prescr_ice2sea_retreat         ! version prescribe-H_mod.f90
420 endif
421
422
423!if (time.ge.t_break) then                ! action sur les ice shelves
424!   call melt_ice_shelves                 ! ATTENTION version prescribe-H_mod.f90
425!   call break_all_ice_shelves
426!end if
427
428
429!!$! impose une variation d'épaisseur d'apres une carte a un temps donne (a affiner plus tard pour des runs transient)
430!!$if (time.eq.t_break) then
431!!$   call lect_prescribed_deltaH
432!!$else if (time.gt.t_break) then
433!!$   call prescribe_deltaH
434!!$end if
435!!$
436!!$if (time.eq.t_break) then                            ! si appele apres lect_prescribed_deltaH, cumule les effets
437!!$   call break_all_ice_shelves
438!!$end if
439
440debug_3D(:,:,87)=S(:,:)-debug_3D(:,:,88)
441
442debug_3D(:,:,86)=Hp(:,:)
443debug_3D(:,:,85)=i_Hp(:,:)
444
445!!$where (i_hp(:,:).eq.1)
446!!$   vieuxh(:,:)=Hp(:,:)
447!!$endwhere
448
449
450! Appel a la routine de resolution resol_adv_diff_2D_vect
451!------------------------------------------------------------
452! On ecrit les vitesses sous la forme
453! Ux = -Dmx * sdx + advmx
454
455! Dmx, Dmy sont les termes diffusifs de la vitesse
456! advmx, advmy sont les termes advectifs.
457! la repartition entre les deux depend de adv_frac.
458
459! i_Hp est un tableau des points ou l'epaisseur est imposee a la valeur Hp
460! bilmass est le bilan de masse (surface et fond)
461! vieuxH est la precedente valeur de H
462! H est le retour de la nouvelle valeur.
463
464
465call resol_adv_diff_2D_vect (Dmx,Dmy,advmx,advmy,Hp,i_Hp,bilmass,vieuxH,H)
466
467! remise à 0 des epaisseurs negatives, on garde la difference dans ablbord
468where (H(:,:).lt.0.)
469   ablbord(:,:)=H(:,:)/dt
470elsewhere
471   ablbord(:,:)=0.
472endwhere
473
474H(:,:)=max(H(:,:),0.)       ! pas d'epaisseur negative
475
476
477! calcul du masque "ice"
478where (flot(:,:))        ! points flottants, sera éventuellement réévalué dans flottab
479   H(:,:)=max(H(:,:),1.) ! dans la partie marine l'épaisseur mini est 1 m
480   where(H(:,:).gt.1.)
481      ice(:,:)=1
482   elsewhere
483      ice(:,:)=0
484   endwhere
485elsewhere                ! points posés
486   where(H(:,:).gt.0.)
487      ice(:,:)=1
488   elsewhere
489      ice(:,:)=0
490   endwhere
491endwhere
492
493
494! eventuellement retirer apres spinup ou avoir un cas serac
495Hdot(:,:)=(H(:,:)-vieuxH(:,:))/dt
496
497if (igrdline.ne.3) then
498   Hdot(:,:)=min(Hdot(:,:),10.)
499   Hdot(:,:)=max(Hdot(:,:),-10.)
500endif
501
502where (i_hp(:,:).ne.1)
503   H(:,:)=vieuxH(:,:)+Hdot(:,:)*dt
504end where
505
506
507
508! si mk0=-1, on garde l'epaisseur precedente
509! en attendant un masque plus propre
510
511where(mk0(:,:).eq.-1)
512   H(:,:)=vieuxH(:,:)
513   Hdot(:,:)=0.
514end where
515
516
517
518!calul de l'ablation sur les bords (pourrait n'être appelé que pour les sorties courtes)
519if (isynchro.eq.1) call ablation_bord
520
521
522if (itracebug.eq.1)  call tracebug(' Fin routine icethick') !, maxval(H) ',maxval(H(:,:))
523
524
525end subroutine icethick3
526
527end module equat_adv_diff_2D_vect
Note: See TracBrowser for help on using the repository browser.