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