MPI-AMRVAC 3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_viscosity.t
Go to the documentation of this file.
1!> The module add viscous source terms and check time step
2!>
3!> Viscous forces in the momentum equations:
4!> d m_i/dt += - div (vc_mu * PI)
5!> !! Viscous work in the energy equation:
6!> !! de/dt += - div (v . vc_mu * PI)
7!> where the PI stress tensor is
8!> PI_i,j = - (dv_j/dx_i + dv_i/dx_j) + (2/3)*Sum_k dv_k/dx_k
9!> where vc_mu is the dynamic viscosity coefficient (g cm^-1 s^-1).
11 use mod_comm_lib, only: mpistop
12 implicit none
13
14 !> Viscosity coefficient
15 double precision, public :: vc_mu = 1.d0
16
17 !> Index of the density (in the w array)
18 integer, private, parameter :: rho_ = 1
19
20 !> Indices of the momentum density
21 integer, allocatable, private, protected :: mom(:)
22
23 !> Index of the energy density (-1 if not present)
24 integer, private, protected :: e_
25
26 !> fourth order
27 logical :: vc_4th_order = .false.
28
29 !> source split or not
30 logical :: vc_split= .false.
31
32 !> whether to compute the viscous terms as
33 !> fluxes (ie in the div on the LHS), or not (by default)
34 logical :: viscindiv= .false.
35
36
37 ! Public methods
38 public :: visc_get_flux_prim
39
40contains
41 !> Read this module"s parameters from a file
42 subroutine vc_params_read(files)
44 character(len=*), intent(in) :: files(:)
45 integer :: n
46
47 namelist /vc_list/ vc_mu, vc_4th_order, vc_split, viscindiv
48
49 do n = 1, size(files)
50 open(unitpar, file=trim(files(n)), status="old")
51 read(unitpar, vc_list, end=111)
52111 close(unitpar)
53 end do
54
55
56 end subroutine vc_params_read
57
58 !> Initialize the module
59 subroutine viscosity_init(phys_wider_stencil)
61 integer, intent(inout) :: phys_wider_stencil
62 integer :: nwx,idir
63
65
66 if(vc_split) any_source_split=.true.
67
68 ! Determine flux variables
69 nwx = 1 ! rho (density)
70
71 allocate(mom(ndir))
72 do idir = 1, ndir
73 nwx = nwx + 1
74 mom(idir) = nwx ! momentum density
75 end do
76
77 nwx = nwx + 1
78 e_ = nwx ! energy density
79
80 if (viscindiv) then
81 ! to compute the derivatives from left and right upwinded values
82 phys_wider_stencil = 1
83 end if
84
85 end subroutine viscosity_init
86
87 subroutine viscosity_add_source(qdt,ixI^L,ixO^L,wCT,w,x,&
88 energy,qsourcesplit,active)
89 ! Add viscosity source in isotropic Newtonian fluids to w within ixO
90 ! neglecting bulk viscosity
91 ! dm/dt= +div(mu*[d_j v_i+d_i v_j]-(2*mu/3)* div v * kr)
93 use mod_geometry
94
95 integer, intent(in) :: ixI^L, ixO^L
96 double precision, intent(in) :: qdt, x(ixI^S,1:ndim), wCT(ixI^S,1:nw)
97 double precision, intent(inout) :: w(ixI^S,1:nw)
98 logical, intent(in) :: energy,qsourcesplit
99 logical, intent(inout) :: active
100
101 double precision:: lambda(ixI^S,ndir,ndir),tmp(ixI^S),tmp2(ixI^S),v(ixI^S,ndir),vlambda(ixI^S,ndir)
102 integer:: ix^L,idim,idir,jdir,iw
103
104 if (viscindiv) return
105
106 if(qsourcesplit .eqv. vc_split) then
107 active = .true.
108 ! standard case, textbook viscosity
109 ! Calculating viscosity sources
110 if(.not.vc_4th_order) then
111 ! involves second derivatives, two extra layers
112 ix^l=ixo^l^ladd2;
113 if({ iximin^d>ixmin^d .or. iximax^d<ixmax^d|.or.})&
114 call mpistop("error for viscous source addition, 2 layers needed")
115 ix^l=ixo^l^ladd1;
116 else
117 ! involves second derivatives, four extra layers
118 ix^l=ixo^l^ladd4;
119 if({ iximin^d>ixmin^d .or. iximax^d<ixmax^d|.or.})&
120 call mpistop("error for viscous source addition"//&
121 "requested fourth order gradients: 4 layers needed")
122 ix^l=ixo^l^ladd2;
123 end if
124
125 ! get velocity
126 do idir=1,ndir
127 v(ixi^s,idir)=wct(ixi^s,mom(idir))/wct(ixi^s,rho_)
128 end do
129
130 ! construct lambda tensor: lambda_ij = gradv_ij + gradv_ji
131 ! initialize
132 lambda=zero
133
134 !next construct
135 do idim=1,ndim; do idir=1,ndir
136 ! Calculate velocity gradient tensor within ixL: gradv= grad v,
137 ! thus gradv_ij=d_j v_i
138 tmp(ixi^s)=v(ixi^s,idir)
139 ! Correction for Christoffel terms in non-cartesian
140 if (coordinate==cylindrical .and. idim==r_ .and. idir==phi_ ) tmp(ixi^s) = tmp(ixi^s)/x(ixi^s,1)
141 if (coordinate==spherical) then
142 if (idim==r_ .and. (idir==2 .or. idir==phi_)) then
143 tmp(ixi^s) = tmp(ixi^s)/x(ixi^s,1)
144{^nooned
145 elseif (idim==2 .and. idir==phi_) then
146 tmp(ixi^s)=tmp(ixi^s)/dsin(x(ixi^s,2))
147}
148 endif
149 endif
150 call gradient(tmp,ixi^l,ix^l,idim,tmp2)
151 ! Correction for Christoffel terms in non-cartesian
152 if (coordinate==cylindrical .and. idim==r_ .and. idir==phi_ ) tmp2(ix^s)=tmp2(ix^s)*x(ix^s,1)
153 if (coordinate==cylindrical .and. idim==phi_ .and. idir==phi_ ) tmp2(ix^s)=tmp2(ix^s)+v(ix^s,r_)/x(ix^s,1)
154 if (coordinate==spherical) then
155 if (idim==r_ .and. (idir==2 .or. idir==phi_)) then
156 tmp2(ix^s) = tmp2(ix^s)*x(ix^s,1)
157{^nooned
158 elseif (idim==2 .and. idir==phi_ ) then
159 tmp2(ix^s)=tmp2(ix^s)*dsin(x(ix^s,2))
160 elseif (idim==2 .and. idir==2 ) then
161 tmp2(ix^s)=tmp2(ix^s)+v(ix^s,r_)/x(ix^s,1)
162 elseif (idim==phi_.and. idir==phi_) then
163 tmp2(ix^s)=tmp2(ix^s)+v(ix^s,r_)/x(ix^s,1)+v(ix^s,2)/(x(ix^s,1)*dtan(x(ix^s,2)))
164}
165 endif
166 endif
167 lambda(ix^s,idim,idir)= lambda(ix^s,idim,idir)+ tmp2(ix^s)
168 lambda(ix^s,idir,idim)= lambda(ix^s,idir,idim)+ tmp2(ix^s)
169 enddo; enddo;
170
171 ! Multiply lambda with viscosity coefficient and dt
172 lambda(ix^s,1:ndir,1:ndir)=lambda(ix^s,1:ndir,1:ndir)*vc_mu*qdt
173
174 !calculate div v term through trace action separately
175 ! rq : it is safe to use the trace rather than compute the divergence
176 ! since we always retrieve the divergence (even with the
177 ! Christoffel terms)
178 tmp=0.d0
179 do idir=1,ndir
180 tmp(ix^s)=tmp(ix^s)+lambda(ix^s,idir,idir)
181 end do
182 tmp(ix^s)=tmp(ix^s)/3.d0
183
184 !substract trace from diagonal elements
185 do idir=1,ndir
186 lambda(ix^s,idir,idir)=lambda(ix^s,idir,idir)-tmp(ix^s)
187 enddo
188
189 ! dm/dt= +div(mu*[d_j v_i+d_i v_j]-(2*mu/3)* div v * kr)
190 ! hence m_j=m_j+d_i tensor_ji
191 do idir=1,ndir
192 do idim=1,ndim
193 tmp(ix^s)=lambda(ix^s,idir,idim)
194 ! Correction for divergence of a tensor
195 if (coordinate==cylindrical .and. idim==r_ .and. (idir==r_ .or. idir==z_)) tmp(ix^s) = tmp(ix^s)*x(ix^s,1)
196 if (coordinate==cylindrical .and. idim==r_ .and. idir==phi_ ) tmp(ix^s) = tmp(ix^s)*x(ix^s,1)**two
197 if (coordinate==spherical) then
198 if (idim==r_ .and. idir==r_ ) tmp(ix^s) = tmp(ix^s)*x(ix^s,1)**two
199 if (idim==r_ .and. (idir==2 .or. idir==phi_)) tmp(ix^s) = tmp(ix^s)*x(ix^s,1)**3.d0
200{^nooned
201 if (idim==2 .and. (idir==r_ .or. idir==2)) tmp(ix^s) = tmp(ix^s)*dsin(x(ix^s,2))
202 if (idim==2 .and. idir==phi_ ) tmp(ix^s) = tmp(ix^s)*dsin(x(ix^s,2))**two
203}
204 endif
205 call gradient(tmp,ixi^l,ixo^l,idim,tmp2)
206 ! Correction for divergence of a tensor
207 if (coordinate==cylindrical .and. idim==r_ .and. (idir==r_ .or. idir==z_)) tmp2(ixo^s) = tmp2(ixo^s)/x(ixo^s,1)
208 if (coordinate==cylindrical .and. idim==r_ .and. idir==phi_ ) tmp2(ixo^s) = tmp2(ixo^s)/(x(ixo^s,1)**two)
209 if (coordinate==spherical) then
210 if (idim==r_ .and. idir==r_ ) tmp2(ixo^s) = tmp2(ixo^s)/(x(ixo^s,1)**two)
211 if (idim==r_ .and. (idir==2 .or. idir==phi_)) tmp2(ixo^s) = tmp2(ixo^s)/(x(ixo^s,1)**3.d0)
212{^nooned
213 if (idim==2 .and. (idir==r_ .or. idir==2)) tmp2(ixo^s) = tmp2(ixo^s)/(dsin(x(ixo^s,2)))
214 if (idim==2 .and. idir==phi_ ) tmp2(ixo^s) = tmp2(ixo^s)/(dsin(x(ixo^s,2))**two)
215}
216 endif
217 w(ixo^s,mom(idir))=w(ixo^s,mom(idir))+tmp2(ixo^s)
218 enddo
219 ! Correction for geometrical terms in the div of a tensor
220 if (coordinate==cylindrical .and. idir==r_ ) w(ixo^s,mom(idir))=w(ixo^s,mom(idir))-lambda(ixo^s,phi_,phi_)/x(ixo^s,1)
221 if (coordinate==spherical .and. idir==r_ ) w(ixo^s,mom(idir))=w(ixo^s,mom(idir))-(lambda(ixo^s,2,2)+lambda(ixo^s,phi_,phi_))/x(ixo^s,1)
222{^nooned
223 if (coordinate==spherical .and. idir==2 ) w(ixo^s,mom(idir))=w(ixo^s,mom(idir))-lambda(ixo^s,phi_,phi_)/(x(ixo^s,1)/dtan(x(ixo^s,2)))
224}
225 end do
226
227 if(energy) then
228 ! de/dt= +div(v.dot.[mu*[d_j v_i+d_i v_j]-(2*mu/3)* div v *kr])
229 ! thus e=e+d_i v_j tensor_ji
230 vlambda=0.d0
231 do idim=1,ndim
232 do idir=1,ndir
233 vlambda(ixi^s,idim)=vlambda(ixi^s,idim)+v(ixi^s,idir)*lambda(ixi^s,idir,idim)
234 end do
235 end do
236 call divvector(vlambda,ixi^l,ixo^l,tmp2)
237 w(ixo^s,e_)=w(ixo^s,e_)+tmp2(ixo^s)
238 end if
239 end if
240
241 end subroutine viscosity_add_source
242
243 subroutine viscosity_get_dt(w,ixI^L,ixO^L,dtnew,dx^D,x)
244 ! Check diffusion time limit for dt < dtdiffpar * dx**2 / (mu/rho)
246 use mod_geometry
247
248 integer, intent(in) :: ixI^L, ixO^L
249 double precision, intent(in) :: dx^D, x(ixI^S,1:ndim)
250 double precision, intent(in) :: w(ixI^S,1:nw)
251 double precision, intent(inout) :: dtnew
252
253 double precision :: tmp(ixI^S)
254 double precision:: dtdiff_visc, dxinv2(1:ndim), max_mu
255 integer:: idim
256
257 ! Calculate the kinematic viscosity tmp=mu/rho
258 ! here vc_mu must be non-zero!!!
259
260 tmp(ixo^s)=vc_mu/w(ixo^s,rho_)
261
262 if(slab_uniform)then
263 ^d&dxinv2(^d)=one/dx^d**2;
264 do idim=1,ndim
265 dtdiff_visc=dtdiffpar/maxval(tmp(ixo^s)*dxinv2(idim))
266 ! limit the time step
267 dtnew=min(dtnew,dtdiff_visc)
268 enddo
269 else
270 do idim=1,ndim
271 max_mu=maxval(tmp(ixo^s)/block%ds(ixo^s,idim)**2)
272 dtdiff_visc=dtdiffpar/max_mu
273 ! limit the time step
274 dtnew=min(dtnew,dtdiff_visc)
275 enddo
276 endif
277
278 end subroutine viscosity_get_dt
279
280 ! viscInDiv
281 ! Get the viscous stress tensor terms in the idim direction
282 ! Beware : a priori, won't work for ndir /= ndim
283 ! Rq : we work with primitive w variables here
284 ! Rq : ixO^L is already extended by 1 unit in the direction we work on
285
286 subroutine visc_get_flux_prim(w, x, ixI^L, ixO^L, idim, f, energy)
288 use mod_geometry
289 integer, intent(in) :: ixi^l, ixo^l, idim
290 double precision, intent(in) :: w(ixi^s, 1:nw), x(ixi^s, 1:^nd)
291 double precision, intent(inout) :: f(ixi^s, nwflux)
292 logical, intent(in) :: energy
293 integer :: idir, i
294 double precision :: v(ixi^s,1:ndir)
295
296 double precision :: divergence(ixi^s)
297
298 double precision:: lambda(ixi^s,ndir) !, tmp(ixI^S) !gradV(ixI^S,ndir,ndir)
299
300 if (.not. viscindiv) return
301
302 do i=1,ndir
303 v(ixi^s,i)=w(ixi^s,i+1)
304 enddo
305 call divvector(v,ixi^l,ixo^l,divergence)
306
307 call get_crossgrad(ixi^l,ixo^l,x,w,idim,lambda)
308 lambda(ixo^s,idim) = lambda(ixo^s,idim) - (2.d0/3.d0) * divergence(ixo^s)
309
310 ! Compute the idim-th row of the viscous stress tensor
311 do idir = 1, ndir
312 f(ixo^s, mom(idir)) = f(ixo^s, mom(idir)) - vc_mu * lambda(ixo^s,idir)
313 if (energy) f(ixo^s, e_) = f(ixo^s, e_) - vc_mu * lambda(ixo^s,idir) * v(ixi^s,idir)
314 enddo
315
316 end subroutine visc_get_flux_prim
317
318 ! Compute the cross term ( d_i v_j + d_j v_i in Cartesian BUT NOT IN
319 ! CYLINDRICAL AND SPHERICAL )
320 subroutine get_crossgrad(ixI^L,ixO^L,x,w,idim,cross)
322 use mod_geometry
323 integer, intent(in) :: ixI^L, ixO^L, idim
324 double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:ndim)
325 double precision, intent(out) :: cross(ixI^S,ndir)
326
327 double precision :: tmp(ixI^S), v(ixI^S)
328 integer :: idir
329
330 if (ndir/=ndim) call mpistop("This formula are probably wrong for ndim/=ndir")
331 ! Beware also, we work w/ the angle as the 3rd component in cylindrical
332 ! and the colatitude as the 2nd one in spherical
333 cross(ixi^s,:)=zero
334 tmp(ixi^s)=zero
335 select case(coordinate)
337 call cart_cross_grad(ixi^l,ixo^l,x,w,idim,cross)
338 case (cylindrical)
339 if (idim==1) then
340 ! for rr and rz
341 call cart_cross_grad(ixi^l,ixo^l,x,w,idim,cross)
342 ! then we overwrite rth w/ the correct expression
343 {^nooned
344 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
345 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th (rq : already contains 1/r)
346 cross(ixi^s,2)=tmp(ixi^s)
347 v(ixi^s)=w(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
348 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
349 cross(ixi^s,2)=cross(ixi^s,2)+tmp(ixi^s)*x(ixi^s,1)
350 }
351 elseif (idim==2) then
352 ! thr (idem as above)
353 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
354 {^nooned
355 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
356 cross(ixi^s,1)=tmp(ixi^s)
357 v(ixi^s)=w(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
358 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
359 cross(ixi^s,1)=cross(ixi^s,1)+tmp(ixi^s)*x(ixi^s,1)
360 ! thth
361 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
362 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
363 cross(ixi^s,2)=two*tmp(ixi^s)
364 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
365 cross(ixi^s,2)=cross(ixi^s,2)+two*v(ixi^s)/x(ixi^s,1) ! + 2 vr/r
366 !thz
367 v(ixi^s)=w(ixi^s,mom(3)) ! v_z
368 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
369 }
370 cross(ixi^s,3)=tmp(ixi^s)
371 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
372 {^ifthreed
373 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_z
374 }
375 cross(ixi^s,3)=cross(ixi^s,3)+tmp(ixi^s)
376 {^ifthreed
377 elseif (idim==3) then
378 ! for zz and rz
379 call cart_cross_grad(ixi^l,ixo^l,x,w,idim,cross)
380 ! then we overwrite zth w/ the correct expression
381 !thz
382 v(ixi^s)=w(ixi^s,mom(3)) ! v_z
383 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
384 cross(ixi^s,2)=tmp(ixi^s)
385 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
386 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_z
387 cross(ixi^s,2)=cross(ixi^s,2)+tmp(ixi^s)
388 }
389 endif
390 case (spherical)
391 if (idim==1) then
392 ! rr (normal, simply 2 * dr vr)
393 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
394 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
395 cross(ixi^s,1)=two*tmp(ixi^s)
396 !rth
397 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
398 {^nooned
399 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th (rq : already contains 1/r)
400 cross(ixi^s,2)=tmp(ixi^s)
401 v(ixi^s)=w(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
402 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
403 cross(ixi^s,2)=cross(ixi^s,2)+tmp(ixi^s)*x(ixi^s,1)
404 }
405 {^ifthreed
406 !rph
407 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
408 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_phi (rq : contains 1/rsin(th))
409 cross(ixi^s,3)=tmp(ixi^s)
410 v(ixi^s)=w(ixi^s,mom(3))/x(ixi^s,1) ! v_phi / r
411 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
412 cross(ixi^s,3)=cross(ixi^s,3)+tmp(ixi^s)*x(ixi^s,1)
413 }
414 elseif (idim==2) then
415 ! thr
416 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
417 {^nooned
418 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th (rq : already contains 1/r)
419 cross(ixi^s,1)=tmp(ixi^s)
420 v(ixi^s)=w(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
421 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
422 cross(ixi^s,1)=cross(ixi^s,1)+tmp(ixi^s)*x(ixi^s,1)
423 ! thth
424 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
425 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
426 cross(ixi^s,2)=two*tmp(ixi^s)
427 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
428 cross(ixi^s,2)=cross(ixi^s,2)+two*v(ixi^s)/x(ixi^s,1) ! + 2 vr/r
429 }
430 {^ifthreed
431 !thph
432 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
433 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_phi (rq : contains 1/rsin(th))
434 cross(ixi^s,3)=tmp(ixi^s)
435 v(ixi^s)=w(ixi^s,mom(3))/dsin(x(ixi^s,2)) ! v_ph / sin(th)
436 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
437 cross(ixi^s,3)=cross(ixi^s,3)+tmp(ixi^s)*dsin(x(ixi^s,2))
438 }
439 {^ifthreed
440 elseif (idim==3) then
441 !phr
442 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
443 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_phi
444 cross(ixi^s,1)=tmp(ixi^s)
445 v(ixi^s)=w(ixi^s,mom(3))/x(ixi^s,1) ! v_phi / r
446 call gradient(v,ixi^l,ixo^l,1,tmp) ! d_r
447 cross(ixi^s,1)=cross(ixi^s,1)+tmp(ixi^s)*x(ixi^s,1)
448 !phth
449 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
450 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_phi
451 cross(ixi^s,2)=tmp(ixi^s)
452 v(ixi^s)=w(ixi^s,mom(3))/dsin(x(ixi^s,2)) ! v_ph / sin(th)
453 call gradient(v,ixi^l,ixo^l,2,tmp) ! d_th
454 cross(ixi^s,2)=cross(ixi^s,2)+tmp(ixi^s)*dsin(x(ixi^s,2))
455 !phph
456 v(ixi^s)=w(ixi^s,mom(3)) ! v_ph
457 call gradient(v,ixi^l,ixo^l,3,tmp) ! d_phi
458 cross(ixi^s,3)=two*tmp(ixi^s)
459 v(ixi^s)=w(ixi^s,mom(1)) ! v_r
460 cross(ixi^s,3)=cross(ixi^s,3)+two*v(ixi^s)/x(ixi^s,1) ! + 2 vr/r
461 v(ixi^s)=w(ixi^s,mom(2)) ! v_th
462 cross(ixi^s,3)=cross(ixi^s,3)+two*v(ixi^s)/(x(ixi^s,1)*dtan(x(ixi^s,2))) ! + 2 vth/(rtan(th))
463 }
464 endif
465 case default
466 call mpistop("Unknown geometry specified")
467 end select
468
469 end subroutine get_crossgrad
470
471 !> yields d_i v_j + d_j v_i for a given i, OK in Cartesian and for some
472 !> tensor terms in cylindrical (rr & rz) and in spherical (rr)
473 subroutine cart_cross_grad(ixI^L,ixO^L,x,w,idim,cross)
475 use mod_geometry
476 integer, intent(in) :: ixI^L, ixO^L, idim
477 double precision, intent(in) :: w(ixI^S, 1:nw), x(ixI^S, 1:^ND)
478 double precision, intent(out) :: cross(ixI^S,ndir)
479
480 double precision :: tmp(ixI^S), v(ixI^S)
481 integer :: idir
482
483 v(ixi^s)=w(ixi^s,mom(idim))
484 do idir=1,ndir
485 call gradient(v,ixi^l,ixo^l,idir,tmp)
486 cross(ixo^s,idir)=tmp(ixo^s)
487 enddo
488 do idir=1,ndir
489 v(ixi^s)=w(ixi^s,mom(idir))
490 call gradient(v,ixi^l,ixo^l,idim,tmp)
491 cross(ixo^s,idir)=cross(ixo^s,idir)+tmp(ixo^s)
492 enddo
493
494 end subroutine cart_cross_grad
495
496 subroutine visc_add_source_geom(qdt, ixI^L, ixO^L, wCT, w, x)
498 use mod_geometry
499 ! w and wCT conservative variables here
500 integer, intent(in) :: ixI^L, ixO^L
501 double precision, intent(in) :: qdt, x(ixI^S, 1:ndim)
502 double precision, intent(inout) :: wCT(ixI^S, 1:nw), w(ixI^S, 1:nw)
503 ! to change and to set as a parameter in the parfile once the possibility to
504 ! solve the equations in an angular momentum conserving form has been
505 ! implemented (change tvdlf.t eg)
506 double precision :: vv(ixI^S), divergence(ixI^S)
507 double precision :: tmp(ixI^S),tmp1(ixI^S)
508 integer :: i
509
510 if (.not. viscindiv) return
511
512 select case (coordinate)
513 case (cylindrical)
514 ! thth tensor term - - -
515 ! 1st the cross grad term
516{^nooned
517 call gradient(wct(ixi^s,mom(2)),ixi^l,ixo^l,2,tmp1) ! d_th
518 tmp(ixo^s)=two*(tmp1(ixo^s)+wct(ixo^s,mom(1))/x(ixo^s,1)) ! 2 ( d_th v_th / r + vr/r )
519 ! 2nd the divergence
520 call divvector(wct(ixi^s,mom(1:ndir)),ixi^l,ixo^l,divergence)
521 tmp(ixo^s) = tmp(ixo^s) - (2.d0/3.d0) * divergence(ixo^s)
522 ! s[mr]=-thth/radius
523 w(ixo^s,mom(1))=w(ixo^s,mom(1))-qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
524 ! rth tensor term - - -
525 call gradient(wct(ixi^s,mom(1)),ixi^l,ixo^l,2,tmp) ! d_th
526 vv(ixi^s)=wct(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
527 call gradient(vv,ixi^l,ixo^l,1,tmp1) ! d_r
528 tmp(ixo^s)=tmp(ixo^s)+tmp1(ixo^s)*x(ixo^s,1)
529 ! s[mphi]=+rth/radius
530 w(ixo^s,mom(2))=w(ixo^s,mom(2))+qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
531}
532 case (spherical)
533 ! thth tensor term - - -
534 ! 1st the cross grad term
535{^nooned
536 call gradient(wct(ixi^s,mom(2)),ixi^l,ixo^l,2,tmp1) ! d_th
537 tmp(ixo^s)=two*(tmp1(ixo^s)+wct(ixo^s,mom(1))/x(ixo^s,1)) ! 2 ( 1/r * d_th v_th + vr/r )
538 ! 2nd the divergence
539 call divvector(wct(ixi^s,mom(1:ndir)),ixi^l,ixo^l,divergence)
540 tmp(ixo^s) = tmp(ixo^s) - (2.d0/3.d0) * divergence(ixo^s)
541 ! s[mr]=-thth/radius
542 w(ixo^s,mom(1))=w(ixo^s,mom(1))-qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
543}
544 ! phiphi tensor term - - -
545 ! 1st the cross grad term
546{^ifthreed
547 call gradient(wct(ixi^s,mom(3)),ixi^l,ixo^l,3,tmp1) ! d_phi
548 tmp(ixo^s)=two*(tmp1(ixo^s)+wct(ixo^s,mom(1))/x(ixo^s,1)+wct(ixo^s,mom(2))/(x(ixo^s,1)*dtan(x(ixo^s,2)))) ! 2 ( 1/rsinth * d_ph v_ph + vr/r + vth/rtanth )
549}
550 ! 2nd the divergence
551 tmp(ixo^s) = tmp(ixo^s) - (2.d0/3.d0) * divergence(ixo^s)
552 ! s[mr]=-phiphi/radius
553 w(ixo^s,mom(1))=w(ixo^s,mom(1))-qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
554 ! s[mth]=-cotanth*phiphi/radius
555{^nooned
556 w(ixo^s,mom(2))=w(ixo^s,mom(2))-qdt*vc_mu*tmp(ixo^s)/(x(ixo^s,1)*dtan(x(ixo^s,2)))
557}
558 ! rth tensor term - - -
559 call gradient(wct(ixi^s,mom(1)),ixi^l,ixo^l,2,tmp) ! d_th (rq : already contains 1/r)
560 vv(ixi^s)=wct(ixi^s,mom(2))/x(ixi^s,1) ! v_th / r
561 call gradient(vv,ixi^l,ixo^l,1,tmp1) ! d_r
562 tmp(ixo^s)=tmp(ixo^s)+tmp1(ixo^s)*x(ixo^s,1)
563 ! s[mth]=+rth/radius
564 w(ixo^s,mom(2))=w(ixo^s,mom(2))+qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
565 ! rphi tensor term - - -
566{^ifthreed
567 call gradient(wct(ixi^s,mom(1)),ixi^l,ixo^l,3,tmp) ! d_phi (rq : contains 1/rsin(th))
568}
569 vv(ixi^s)=wct(ixi^s,mom(3))/x(ixi^s,1) ! v_phi / r
570 call gradient(vv,ixi^l,ixo^l,1,tmp1) ! d_r
571 tmp(ixo^s)=tmp(ixo^s)+tmp1(ixo^s)*x(ixo^s,1)
572 ! s[mphi]=+rphi/radius
573 w(ixo^s,mom(3))=w(ixo^s,mom(3))+qdt*vc_mu*tmp(ixo^s)/x(ixo^s,1)
574 ! phith tensor term - - -
575{^ifthreed
576 call gradient(wct(ixi^s,mom(2)),ixi^l,ixo^l,3,tmp) ! d_phi
577}
578{^nooned
579 vv(ixi^s)=wct(ixi^s,mom(3))/dsin(x(ixi^s,2)) ! v_ph / sin(th)
580 call gradient(vv,ixi^l,ixo^l,2,tmp1) ! d_th
581 tmp(ixo^s)=tmp(ixo^s)+tmp1(ixo^s)*dsin(x(ixo^s,2))
582 ! s[mphi]=+cotanth*phith/radius
583 w(ixo^s,mom(3))=w(ixo^s,mom(3))+qdt*vc_mu*tmp(ixo^s)/(x(ixo^s,1)*dtan(x(ixo^s,2)))
584}
585 end select
586
587 end subroutine visc_add_source_geom
588
589end module mod_viscosity
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
subroutine divvector(qvec, ixil, ixol, divq, nth_in)
integer coordinate
Definition mod_geometry.t:7
integer, parameter spherical
integer, parameter cartesian
Definition mod_geometry.t:8
integer, parameter cylindrical
integer, parameter cartesian_stretched
Definition mod_geometry.t:9
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
This module contains definitions of global parameters and variables and some generic functions/subrou...
type(state), pointer block
Block pointer for using one block and its previous state.
double precision dtdiffpar
For resistive MHD, the time step is also limited by the diffusion time: .
integer, parameter unitpar
file handle for IO
logical any_source_split
if any normal source term is added in split fasion
character(len=std_len), dimension(:), allocatable par_files
Which par files are used as input.
double precision, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
The module add viscous source terms and check time step.
subroutine, public visc_get_flux_prim(w, x, ixil, ixol, idim, f, energy)
subroutine get_crossgrad(ixil, ixol, x, w, idim, cross)
subroutine cart_cross_grad(ixil, ixol, x, w, idim, cross)
yields d_i v_j + d_j v_i for a given i, OK in Cartesian and for some tensor terms in cylindrical (rr ...
subroutine viscosity_add_source(qdt, ixil, ixol, wct, w, x, energy, qsourcesplit, active)
subroutine viscosity_init(phys_wider_stencil)
Initialize the module.
subroutine viscosity_get_dt(w, ixil, ixol, dtnew, dxd, x)
double precision, public vc_mu
Viscosity coefficient.
logical vc_4th_order
fourth order
logical vc_split
source split or not
subroutine visc_add_source_geom(qdt, ixil, ixol, wct, w, x)
subroutine vc_params_read(files)
Read this module"s parameters from a file.
logical viscindiv
whether to compute the viscous terms as fluxes (ie in the div on the LHS), or not (by default)