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