MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_geometry.t
Go to the documentation of this file.
1!> Module with geometry-related routines (e.g., divergence, curl)
3 use mod_comm_lib, only: mpistop
4 implicit none
5 public
6
7 integer :: coordinate=-1
8 integer, parameter :: cartesian = 0
9 integer, parameter :: cartesian_stretched= 1
10 integer, parameter :: cylindrical = 2
11 integer, parameter :: spherical = 3
12 integer, parameter :: cartesian_expansion= 4
13
14 integer :: type_curl=0
15 integer, parameter :: central=1
16 integer, parameter :: gaussbased=2
17 integer, parameter :: stokesbased=3
18
19contains
20
21 !> Set the coordinate system to be used
22 subroutine set_coordinate_system(geom)
24 character(len=*), intent(in) :: geom !< Name of the coordinate system
25
26 ! Store the geometry name
27 geometry_name = geom
28
29 select case (geom)
30 case ("Cartesian","Cartesian_1D","Cartesian_2D","Cartesian_3D")
31 ndir = ndim
33 case ("Cartesian_1D_expansion")
34 if (ndim /= 1) call mpistop("Geometry Cartesian_1D_expansion but ndim /= 1")
35 ndir = ndim
37 case ("Cartesian_1.5D")
38 if (ndim /= 1) call mpistop("Geometry Cartesian_1.5D but ndim /= 1")
40 ndir = 2
41 case ("Cartesian_1.75D")
42 if (ndim /= 1) call mpistop("Geometry Cartesian_1.75D but ndim /= 1")
44 ndir = 3
45 case ("Cartesian_2.5D")
46 if (ndim /= 2) call mpistop("Geometry Cartesian_2.5D but ndim /= 2")
48 ndir = 3
49 case ("cylindrical","cylindrical_2D","cylindrical_3D")
50 ndir = ndim
51 r_ = 1
52 z_ = 2
53 if(ndir==3) phi_ = 3
55 case ("cylindrical_2.5D")
56 if (ndim /= 2) call mpistop("Geometry cylindrical_2.5D but ndim /= 2")
57 ndir = 3
58 r_ = 1
59 z_ = 2
60 phi_ = 3
62 case ("polar","polar_2D","polar_3D")
63 ndir = ndim
64 r_ = 1
65 phi_ = 2
66 if(ndir==3) z_ = 3
68 case ("polar_1.5D")
69 if (ndim /= 1) call mpistop("Geometry polar_1.5D but ndim /= 1")
70 ndir = 2
71 r_ = 1
72 phi_ = 2
74 case ("polar_2.5D")
75 if (ndim /= 2) call mpistop("Geometry polar_2.5D but ndim /= 2")
76 ndir = 3
77 r_ = 1
78 phi_ = 2
79 z_ = 3
81 case ("spherical","spherical_2D","spherical_3D")
82 ndir = ndim
83 r_ = 1
84 if(ndir==3) phi_ = 3
85 z_ = -1
87 case ("spherical_2.5D")
88 if (ndim /= 2) &
89 call mpistop("Geometry spherical_2.5D requires ndim == 2")
90 ndir = 3
91 r_ = 1
92 phi_ = 3
93 z_ = -1
95 case default
96 call mpistop("Unknown geometry specified")
97 end select
98 end subroutine set_coordinate_system
99
100 subroutine set_pole
102
103 select case (coordinate)
104 case (spherical) {^ifthreed
105 ! For spherical grid, check whether phi-direction is periodic
106 if(periodb(ndim)) then
107 if(phi_/=3) call mpistop("phi_ should be 3 in 3D spherical coord!")
108 if(mod(ng3(1),2)/=0) &
109 call mpistop("Number of meshes in phi-direction should be even!")
110 if(abs(xprobmin2)<smalldouble) then
111 if(mype==0) write(unitterm,*) &
112 "Will apply pi-periodic conditions at northpole!"
113 poleb(1,2)=.true.
114 else
115 if(mype==0) write(unitterm,*) "There is no northpole!"
116 end if
117 if(abs(xprobmax2-dpi)<smalldouble) then
118 if(mype==0) write(unitterm,*) &
119 "Will apply pi-periodic conditions at southpole!"
120 poleb(2,2)=.true.
121 else
122 if(mype==0) write(unitterm,*) "There is no southpole!"
123 end if
124 end if}
125 case (cylindrical)
126 {
127 if (^d == phi_ .and. periodb(^d)) then
128 if(mod(ng^d(1),2)/=0) then
129 call mpistop("Number of meshes in phi-direction should be even!")
130 end if
131
132 if(abs(xprobmin1)<smalldouble) then
133 if (mype==0) then
134 write(unitterm,*) "Will apply pi-periodic conditions at r=0"
135 end if
136 poleb(1,1)=.true.
137 else
138 if (mype==0) then
139 write(unitterm,*) "There is no cylindrical axis!"
140 end if
141 end if
142 end if\}
143 end select
144
145 end subroutine set_pole
146
147 !> Deallocate geometry-related variables
148 subroutine putgridgeo(igrid)
150 integer, intent(in) :: igrid
151
152 deallocate(ps(igrid)%surfaceC,ps(igrid)%surface,ps(igrid)%dvolume,ps(igrid)%dx,&
153 psc(igrid)%dx,ps(igrid)%ds,psc(igrid)%dvolume)
154
155 end subroutine putgridgeo
156
157 !> calculate area of surfaces of cells
158 subroutine get_surface_area(s,ixG^L)
161
162 type(state) :: s
163 integer, intent(in) :: ixG^L
164
165 double precision :: x(ixG^S,ndim), xext(ixGmin1-1:ixGmax1,1), drs(ixG^S), drs_ext(ixGmin1-1:ixGmax1), dx2(ixG^S), dx3(ixG^S)
166 double precision :: exp_factor_ext(ixGmin1-1:ixGmax1),del_exp_factor_ext(ixGmin1-1:ixGmax1),exp_factor_primitive_ext(ixGmin1-1:ixGmax1)
167 double precision :: exp_factor(ixGmin1:ixGmax1),del_exp_factor(ixGmin1:ixGmax1),exp_factor_primitive(ixGmin1:ixGmax1)
168
169 select case (coordinate)
170
172 drs(ixg^s)=s%dx(ixg^s,1)
173 x(ixg^s,1)=s%x(ixg^s,1)
174 {^ifoned
175 if(associated(usr_set_surface))then
176 call usr_set_surface(ixgmin1,ixgmax1,x,drs,exp_factor,del_exp_factor,exp_factor_primitive)
177 if (any(exp_factor <= zero)) call mpistop("The area must always be strictly positive!")
178 endif
179 s%surface(ixg^s,1)=exp_factor(ixg^s)
180 xext(ixgmin1-1,1)=x(1,1)-half*drs(1)
181 xext(ixg^s,1)=x(ixg^s,1)+half*drs(ixg^s)
182 drs_ext(ixgmin1-1)=drs(1)
183 drs_ext(ixg^s)=drs(ixg^s)
184 if(associated(usr_set_surface)) call usr_set_surface(ixgmin1-1,ixgmax1,xext,drs_ext,exp_factor_ext,del_exp_factor_ext,exp_factor_primitive_ext)
185 s%surfaceC(ixgmin1-1:ixgmax1,1)=exp_factor_ext(ixgmin1-1:ixgmax1)
186 }
187
189 drs(ixg^s)=s%dx(ixg^s,1)
190 {^nooned
191 dx2(ixg^s)=s%dx(ixg^s,2)}
192 {^ifthreed
193 dx3(ixg^s)=s%dx(ixg^s,3)}
194
195 {^ifoned
196 s%surfaceC(ixg^s,1)=1.d0
197 s%surface(ixg^s,1) =1.d0
198 }
199 {^iftwod
200 s%surfaceC(ixg^s,1)=dx2(ixg^s)
201 s%surfaceC(ixg^s,2)=drs(ixg^s)
202 s%surface(ixg^s,1) =dx2(ixg^s)
203 s%surface(ixg^s,2)=drs(ixg^s)
204 }
205 {^ifthreed
206 s%surfaceC(ixg^s,1)= dx2(ixg^s)*dx3(ixg^s)
207 s%surfaceC(ixg^s,2)= drs(ixg^s)*dx3(ixg^s)
208 s%surfaceC(ixg^s,3)= drs(ixg^s)*dx2(ixg^s)
209 s%surface(ixg^s,1)=s%surfaceC(ixg^s,1)
210 s%surface(ixg^s,2)=s%surfaceC(ixg^s,2)
211 s%surface(ixg^s,3)=s%surfaceC(ixg^s,3)
212 }
213 {s%surfaceC(0^d%ixG^s,^d)=s%surfaceC(1^d%ixG^s,^d);\}
214 case (spherical)
215 x(ixg^s,1)=s%x(ixg^s,1)
216 {^nooned
217 x(ixg^s,2)=s%x(ixg^s,2)
218 }
219 drs(ixg^s)=s%dx(ixg^s,1)
220 {^nooned
221 dx2(ixg^s)=s%dx(ixg^s,2)
222 }
223 {^ifthreed
224 dx3(ixg^s)=s%dx(ixg^s,3)
225 }
226
227 s%surfaceC(ixg^s,1)=(x(ixg^s,1)+half*drs(ixg^s))**2 {^nooned &
228 *two*dabs(dsin(x(ixg^s,2)))*dsin(half*dx2(ixg^s))}{^ifthreed*dx3(ixg^s)}
229 ! change negative theta to positive to preserve positive area near pole
230
231 {^nooned
232 s%surfaceC(ixg^s,2)=x(ixg^s,1)*drs(ixg^s)&
233 *dabs(dsin(x(ixg^s,2)+half*dx2(ixg^s)))}{^ifthreed*dx3(ixg^s)}
234
235 {^ifthreed
236 s%surfaceC(ixg^s,3)=x(ixg^s,1)*drs(ixg^s)*dx2(ixg^s)
237 }
238
239 {^ifoned
240 s%surfaceC(0,1)=(x(1,1)-half*drs(1))**2
241 }
242 {^iftwod
243 s%surfaceC(0,ixgmin2:ixgmax2,1)=(x(1,ixgmin2:ixgmax2,1)-half*drs(1,&
244 ixgmin2:ixgmax2))**2*two*dabs(dsin(x(1,ixgmin2:ixgmax2,2)))*dsin(half*dx2(1,&
245 ixgmin2:ixgmax2))
246 s%surfaceC(ixgmin1:ixgmax1,0,2)=x(ixgmin1:ixgmax1,1,&
247 1)*drs(ixgmin1:ixgmax1,1)*dabs(dsin(x(ixgmin1:ixgmax1,1,&
248 2)-half*dx2(ixgmin1:ixgmax1,1)))
249 }
250 {^ifthreed
251 s%surfaceC(0,ixgmin2:ixgmax2,ixgmin3:ixgmax3,1)=(x(1,ixgmin2:ixgmax2,&
252 ixgmin3:ixgmax3,1)-half*drs(1,ixgmin2:ixgmax2,&
253 ixgmin3:ixgmax3))**2*two*dabs(dsin(x(1,ixgmin2:ixgmax2,ixgmin3:ixgmax3,&
254 2)))*dsin(half*dx2(1,ixgmin2:ixgmax2,ixgmin3:ixgmax3))*dx3(1,&
255 ixgmin2:ixgmax2,ixgmin3:ixgmax3)
256 s%surfaceC(ixgmin1:ixgmax1,0,ixgmin3:ixgmax3,2)=x(ixgmin1:ixgmax1,1,&
257 ixgmin3:ixgmax3,1)*drs(ixgmin1:ixgmax1,1,&
258 ixgmin3:ixgmax3)*dabs(dsin(x(ixgmin1:ixgmax1,1,ixgmin3:ixgmax3,&
259 2)-half*dx2(ixgmin1:ixgmax1,1,ixgmin3:ixgmax3)))*dx3(ixgmin1:ixgmax1,1,&
260 ixgmin3:ixgmax3)
261 s%surfaceC(ixgmin1:ixgmax1,ixgmin2:ixgmax2,0,3)=&
262 s%surfaceC(ixgmin1:ixgmax1,ixgmin2:ixgmax2,1,3)
263 }
264
265 s%surface(ixg^s,1)=x(ixg^s,1)**2 {^nooned &
266 *two*dabs(dsin(x(ixg^s,2)))*dsin(half*dx2(ixg^s))}{^ifthreed*dx3(ixg^s)}
267 {^nooned
268 s%surface(ixg^s,2)=x(ixg^s,1)*drs(ixg^s)&
269 *dabs(dsin(x(ixg^s,2)))}{^ifthreed*dx3(ixg^s)}
270
271 {^ifthreed
272 s%surface(ixg^s,3)=x(ixg^s,1)*drs(ixg^s)*dx2(ixg^s)}
273
274 case (cylindrical)
275 x(ixg^s,1)=s%x(ixg^s,1)
276 drs(ixg^s)=s%dx(ixg^s,1)
277 {^nooned
278 dx2(ixg^s)=s%dx(ixg^s,2)}
279 {^ifthreed
280 dx3(ixg^s)=s%dx(ixg^s,3)}
281
282 s%surfaceC(ixg^s,1)=dabs(x(ixg^s,1)+half*drs(ixg^s)){^de&*dx^de(ixg^s) }
283 ! change negative r to positive to preserve positive area near pole
284 {^nooned
285 if (z_==2) s%surfaceC(ixg^s,2)=dabs(x(ixg^s,1))*drs(ixg^s){^ifthreed*dx3(ixg^s)}
286 if (phi_==2) s%surfaceC(ixg^s,2)=drs(ixg^s){^ifthreed*dx3(ixg^s)}
287 }
288 {^ifthreed
289 if (z_==3) s%surfaceC(ixg^s,3)=dabs(x(ixg^s,1))*drs(ixg^s)*dx2(ixg^s)
290 if (phi_==3) s%surfaceC(ixg^s,3)=drs(ixg^s)*dx2(ixg^s)
291 }
292 {^ifoned
293 s%surfaceC(0,1)=dabs(x(1,1)-half*drs(1))
294 }
295 {^iftwod
296 s%surfaceC(0,ixgmin2:ixgmax2,1)=dabs(x(1,ixgmin2:ixgmax2,1)-half*drs(1,&
297 ixgmin2:ixgmax2))*dx2(1,ixgmin2:ixgmax2)
298 }
299 {^ifthreed
300 s%surfaceC(0,ixgmin2:ixgmax2,ixgmin3:ixgmax3,1)=dabs(x(1,ixgmin2:ixgmax2,&
301 ixgmin3:ixgmax3,1)-half*drs(1,ixgmin2:ixgmax2,ixgmin3:ixgmax3))*dx2(1,&
302 ixgmin2:ixgmax2,ixgmin3:ixgmax3)*dx3(1,ixgmin2:ixgmax2,&
303 ixgmin3:ixgmax3)
304 }
305 {s%surfaceC(0^de%ixG^s,^de)=s%surfaceC(1^de%ixG^s,^de);\}
306
307 s%surface(ixg^s,1)=dabs(x(ixg^s,1)){^de&*dx^de(ixg^s) }
308 {^nooned
309 if (z_==2) s%surface(ixg^s,2)=dabs(x(ixg^s,1))*drs(ixg^s){^ifthreed*dx3(ixg^s)}
310 if (phi_==2) s%surface(ixg^s,2)=drs(ixg^s){^ifthreed*dx3(ixg^s)}}
311 {^ifthreed
312 if (z_==3) s%surface(ixg^s,3)=dabs(x(ixg^s,1))*drs(ixg^s)*dx2(ixg^s)
313 if (phi_==3) s%surface(ixg^s,3)=drs(ixg^s)*dx2(ixg^s)}
314
315 case default
316 call mpistop("Sorry, coordinate unknown")
317 end select
318 end subroutine get_surface_area
319
320 !**************************************************************************
321 ! Purpose: Computes the gradient of a scalar field q(ixI^S) at cell
322 ! centers in the idir direction and outputs it in gradq(ixO^S),
323 ! which is also defined at cell **centers**. The gradient is
324 ! computed using a 2nd-order central difference scheme,
325 ! utilizing cell center values on both sides.
326 !
327 ! For uniform Cartesian coordinates, an optional input
328 ! parameter nth_in allows increasing the order of the
329 ! central difference scheme to 2*nth_in.
330 !**************************************************************************
331 subroutine gradient(q,ixI^L,ixO^L,idir,gradq,nth_in)
333 integer, intent(in) :: ixI^L, ixO^L, idir
334 integer, intent(in), optional :: nth_in
335 double precision, intent(in) :: q(ixI^S)
336 double precision, intent(inout) :: gradq(ixI^S)
337 integer :: jxO^L, hxO^L, nth
338
339 if(present(nth_in)) then
340 nth = nth_in
341 else
342 nth = 1
343 endif
344 if(nth .gt. nghostcells) then
345 call mpistop("gradient stencil too wide")
346 endif
347
348 hxo^l=ixo^l-kr(idir,^d);
349 jxo^l=ixo^l+kr(idir,^d);
350 select case(coordinate)
351 case(cartesian)
352 select case(nth)
353 case(1)
354 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))*half
355 case(2)
356 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))*2.d0/3.d0
357 hxo^l=ixo^l-2*kr(idir,^d);
358 jxo^l=ixo^l+2*kr(idir,^d);
359 gradq(ixo^s)=gradq(ixo^s)-(q(jxo^s)-q(hxo^s))/12.d0
360 case(3)
361 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))*3.d0/4.d0
362 hxo^l=ixo^l-2*kr(idir,^d);
363 jxo^l=ixo^l+2*kr(idir,^d);
364 gradq(ixo^s)=gradq(ixo^s)-(q(jxo^s)-q(hxo^s))*3.d0/20.d0
365 hxo^l=ixo^l-3*kr(idir,^d);
366 jxo^l=ixo^l+3*kr(idir,^d);
367 gradq(ixo^s)=gradq(ixo^s)+(q(jxo^s)-q(hxo^s))/60.d0
368 case default
369 call mpistop("unknown stencil gradient")
370 end select
371 gradq(ixo^s)=gradq(ixo^s)/dxlevel(idir)
373 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/(block%x(jxo^s,idir)-block%x(hxo^s,idir))
374 case(spherical)
375 select case(idir)
376 case(1)
377 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((block%x(jxo^s,1)-block%x(hxo^s,1)))
378 {^nooned
379 case(2)
380 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((block%x(jxo^s,2)-block%x(hxo^s,2))*block%x(ixo^s,1))
381 }
382 {^ifthreed
383 case(3)
384 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((block%x(jxo^s,3)-block%x(hxo^s,3))*block%x(ixo^s,1)*dsin(block%x(ixo^s,2)))
385 }
386 end select
387 case(cylindrical)
388 if(idir==phi_) then
389 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((block%x(jxo^s,phi_)-block%x(hxo^s,phi_))*block%x(ixo^s,r_))
390 else
391 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/(block%x(jxo^s,idir)-block%x(hxo^s,idir))
392 end if
393 case default
394 call mpistop('Unknown geometry')
395 end select
396 end subroutine gradient
397
398 !**************************************************************************
399 ! Purpose: Originally named as gradientS.
400 ! Computes the gradient of a scalar field q(ixI^S) at cell
401 ! centers in the idir direction and outputs it in gradq(ixO^S),
402 ! which is also defined at cell **centers**. Unlike the standard
403 ! gradient computation, this routine first reconstructs cell
404 ! face values using a slope **Limiter** and then computes the
405 ! gradient from these face values.
406 !**************************************************************************
407 subroutine gradientl(q,ixI^L,ixO^L,idir,gradq)
409 use mod_limiter
410 use mod_ppm
411 integer, intent(in) :: ixI^L, ixO^L, idir
412 double precision, intent(in) :: q(ixI^S)
413 double precision, intent(inout) :: gradq(ixI^S)
414 double precision ,dimension(ixI^S) :: qC,qL,qR,dqC,ldq,rdq
415 double precision :: x(ixI^S,1:ndim)
416 double precision :: invdx
417 integer :: hxO^L,ixC^L,jxC^L,gxC^L,hxC^L
418
419 x(ixi^s,1:ndim)=block%x(ixi^s,1:ndim)
420 invdx=1.d0/dxlevel(idir)
421 hxo^l=ixo^l-kr(idir,^d);
422 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
423 jxc^l=ixc^l+kr(idir,^d);
424 gxcmin^d=ixcmin^d-kr(idir,^d);gxcmax^d=jxcmax^d;
425 hxc^l=gxc^l+kr(idir,^d);
426 ! set the gradient limiter here
427 qr(gxc^s) = q(hxc^s)
428 ql(gxc^s) = q(gxc^s)
430 dqc(gxc^s)= qr(gxc^s)-ql(gxc^s)
431 call dwlimiter2(dqc,ixi^l,gxc^l,idir,type_gradient_limiter(block%level),ldw=ldq,rdw=rdq)
432 ql(ixc^s) = ql(ixc^s) + half*ldq(ixc^s)
433 qr(ixc^s) = qr(ixc^s) - half*rdq(jxc^s)
434 else
435 call ppmlimitervar(ixi^l,ixo^l,idir,q,q,ql,qr)
436 endif
437
438 select case(coordinate)
439 case(cartesian)
440 gradq(ixo^s)=(qr(ixo^s)-ql(hxo^s))*invdx
442 gradq(ixo^s)=(qr(ixo^s)-ql(hxo^s))/block%dx(ixo^s,idir)
443 case(spherical)
444 gradq(ixo^s)=(qr(ixo^s)-ql(hxo^s))/block%dx(ixo^s,idir)
445 select case(idir)
446 case(2)
447 gradq(ixo^s)=gradq(ixo^s)/x(ixo^s,1)
448 {^ifthreed
449 case(3)
450 gradq(ixo^s)=gradq(ixo^s)/(x(ixo^s,1)*dsin(x(ixo^s,2)))
451 }
452 end select
453 case(cylindrical)
454 gradq(ixo^s)=(qr(ixo^s)-ql(hxo^s))/block%dx(ixo^s,idir)
455 if(idir==phi_) gradq(ixo^s)=gradq(ixo^s)/x(ixo^s,1)
456 end select
457 end subroutine gradientl
458
459 !**************************************************************************
460 ! Purpose: Merged from gradientx, gradientq and gradientC.
461 ! Computes the gradient of a scalar field q(ixI^S) at cell
462 ! centers in the idir direction and outputs it in gradq(ixO^S),
463 ! which is defined at cell **Faces**. The gradient is computed
464 ! using a 2nd-order central difference scheme, utilizing
465 ! the cell center values on both sides of a given cell face.
466 !
467 ! For uniform Cartesian coordinates, an optional input
468 ! parameter nth_in allows increasing the order of the
469 ! central difference scheme to 2*nth_in.
470 !
471 ! By default, the index is shifted one position to the left.
472 ! This structure also allows the routine to be used for
473 ! one-sided difference calculations of the gradient at cell
474 ! **centers**. In such cases, the optional logical parameter pm_in
475 ! controls whether the index shifts to the left (default)
476 ! or to the right.
477 !**************************************************************************
478 subroutine gradientf(q,x,ixI^L,ixO^L,idir,gradq,nth_in,pm_in)
480 integer, intent(in) :: ixI^L, ixO^L, idir
481 double precision, intent(in) :: q(ixI^S),x(ixI^S,1:ndim)
482 double precision, intent(inout) :: gradq(ixI^S)
483 integer, intent(in), optional :: nth_in
484 logical, intent(in), optional :: pm_in
485 logical :: pm
486 integer :: nth,jxO^L,hxO^L
487
488 if(present(nth_in)) then
489 nth = nth_in
490 else
491 nth = 1
492 endif
493 if(nth .gt. nghostcells) then
494 call mpistop("gradient stencil too wide")
495 endif
496 if(present(pm_in)) then
497 pm = pm_in
498 else
499 pm = .true.
500 endif
501
502 if(pm) then
503 hxo^l=ixo^l;
504 jxo^l=ixo^l+kr(idir,^d);
505 else
506 hxo^l=ixo^l-kr(idir,^d);
507 jxo^l=ixo^l;
508 endif
509 select case(coordinate)
510 case(cartesian)
511 select case(nth)
512 case(1)
513 gradq(ixo^s)=q(jxo^s)-q(hxo^s)
514 case(2)
515 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))*27.d0/24.d0
516 if(pm) then
517 hxo^l=ixo^l-kr(idir,^d);
518 jxo^l=ixo^l+2*kr(idir,^d);
519 else
520 hxo^l=ixo^l-2*kr(idir,^d);
521 jxo^l=ixo^l+kr(idir,^d);
522 endif
523 gradq(ixo^s)=gradq(ixo^s)-(q(jxo^s)-q(hxo^s))/24.d0
524 case(3)
525 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))*225.d0/192.d0
526 if(pm) then
527 hxo^l=ixo^l-kr(idir,^d);
528 jxo^l=ixo^l+2*kr(idir,^d);
529 else
530 hxo^l=ixo^l-2*kr(idir,^d);
531 jxo^l=ixo^l+kr(idir,^d);
532 endif
533 gradq(ixo^s)=gradq(ixo^s)-(q(jxo^s)-q(hxo^s))*25.d0/384.d0
534 if(pm) then
535 hxo^l=ixo^l-2*kr(idir,^d);
536 jxo^l=ixo^l+3*kr(idir,^d);
537 else
538 hxo^l=ixo^l-3*kr(idir,^d);
539 jxo^l=ixo^l+2*kr(idir,^d);
540 endif
541 gradq(ixo^s)=gradq(ixo^s)+(q(jxo^s)-q(hxo^s))*3.0/640.d0
542 case default
543 call mpistop("unknown stencil gradient")
544 end select
545 gradq(ixo^s)=gradq(ixo^s)/dxlevel(idir)
547 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/(x(jxo^s,idir)-x(hxo^s,idir))
548 case(spherical)
549 select case(idir)
550 case(1)
551 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/(x(jxo^s,1)-x(hxo^s,1))
552 {^nooned
553 case(2)
554 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((x(jxo^s,2)-x(hxo^s,2))*x(ixo^s,1))
555 }
556 {^ifthreed
557 case(3)
558 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((x(jxo^s,3)-x(hxo^s,3))*x(ixo^s,1)*dsin(x(ixo^s,2)))
559 }
560 end select
561 case(cylindrical)
562 if(idir==phi_) then
563 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/((x(jxo^s,phi_)-x(hxo^s,phi_))*x(ixo^s,r_))
564 else
565 gradq(ixo^s)=(q(jxo^s)-q(hxo^s))/(x(jxo^s,idir)-x(hxo^s,idir))
566 end if
567 case default
568 call mpistop('Unknown geometry')
569 end select
570 end subroutine gradientf
571
572 !**************************************************************************
573 ! Purpose: Computes the divergence of a vector field qvec(ixI^S,1:ndim)
574 ! at cell centers and stores the result in q(ixO^S), which is
575 ! also defined at cell centers. The divergence is computed using
576 ! a 2nd-order central difference scheme, utilizing the vector
577 ! components at adjacent cell centers.
578 !
579 ! For uniform Cartesian coordinates, an optional input parameter
580 ! nth_in allows increasing the order of the central difference
581 ! scheme to 2*nth_in, improving the accuracy of the divergence
582 ! computation.
583 !**************************************************************************
584 subroutine divvector(qvec,ixI^L,ixO^L,divq,nth_in)
586 integer, intent(in) :: ixI^L,ixO^L
587 double precision, intent(in) :: qvec(ixI^S,1:ndir)
588 double precision, intent(inout) :: divq(ixI^S)
589 integer, intent(in), optional :: nth_in
590 double precision :: qC(ixI^S), invdx(1:ndim)
591 integer :: jxO^L, hxO^L, ixC^L, jxC^L
592 integer :: idims, gxO^L, kxO^L
593 integer :: lxO^L, fxO^L, nth
594
595 if(present(nth_in)) then
596 nth = nth_in
597 else
598 nth = 1
599 endif
600 if(nth .gt. nghostcells) then
601 call mpistop("divvector stencil too wide")
602 endif
603
604 invdx=1.d0/dxlevel
605 divq(ixo^s)=0.0d0
606 if (slab_uniform) then
607 do idims=1,ndim
608 select case(nth)
609 case(1)
610 jxo^l=ixo^l+kr(idims,^d);
611 hxo^l=ixo^l-kr(idims,^d);
612 divq(ixo^s)=divq(ixo^s)+half*(qvec(jxo^s,idims) &
613 - qvec(hxo^s,idims))*invdx(idims)
614 case(2)
615 kxo^l=ixo^l+2*kr(idims,^d);
616 jxo^l=ixo^l+kr(idims,^d);
617 hxo^l=ixo^l-kr(idims,^d);
618 gxo^l=ixo^l-2*kr(idims,^d);
619 divq(ixo^s)=divq(ixo^s)+&
620 (-qvec(kxo^s,idims)+8.d0*qvec(jxo^s,idims)-8.d0*&
621 qvec(hxo^s,idims)+qvec(gxo^s,idims))/(12.d0*dxlevel(idims))
622 case(3)
623 lxo^l=ixo^l+3*kr(idims,^d);
624 kxo^l=ixo^l+2*kr(idims,^d);
625 jxo^l=ixo^l+kr(idims,^d);
626 hxo^l=ixo^l-kr(idims,^d);
627 gxo^l=ixo^l-2*kr(idims,^d);
628 fxo^l=ixo^l-3*kr(idims,^d);
629 divq(ixo^s)=divq(ixo^s)+&
630 (-qvec(fxo^s,idims)+9.d0*qvec(gxo^s,idims)-45.d0*qvec(hxo^s,idims)&
631 +qvec(lxo^s,idims)-9.d0*qvec(kxo^s,idims)+45.d0*qvec(jxo^s,idims))&
632 /(60.d0*dxlevel(idims))
633 case default
634 call mpistop("unknown stencil in divvector")
635 end select
636 enddo
637 else
638 do idims=1,ndim
639 hxo^l=ixo^l-kr(idims,^d);
640 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
641 jxc^l=ixc^l+kr(idims,^d);
642 if(stretched_dim(idims) .and. stretch_uncentered) then
643 ! linear interpolation at cell interface along stretched dimension
644 qc(ixc^s)=block%surfaceC(ixc^s,idims)*(qvec(ixc^s,idims)+0.5d0*block%dx(ixc^s,idims)*&
645 (qvec(jxc^s,idims)-qvec(ixc^s,idims))/(block%x(jxc^s,idims)-block%x(ixc^s,idims)))
646 else
647 qc(ixc^s)=block%surfaceC(ixc^s,idims)*half*(qvec(ixc^s,idims)+qvec(jxc^s,idims))
648 end if
649 divq(ixo^s)=divq(ixo^s)+qc(ixo^s)-qc(hxo^s)
650 end do
651 divq(ixo^s)=divq(ixo^s)/block%dvolume(ixo^s)
652 end if
653 end subroutine divvector
654
655 !> Calculate divergence of a vector qvec within ixL
656 !> using limited extrapolation to cell edges
657 subroutine divvectors(qvec,ixI^L,ixO^L,divq)
659 use mod_limiter
660 use mod_ppm
661 integer, intent(in) :: ixI^L,ixO^L
662 double precision, intent(in) :: qvec(ixI^S,1:ndir)
663 double precision, intent(inout) :: divq(ixI^S)
664 double precision, dimension(ixI^S) :: qL,qR,dqC,ldq,rdq
665
666 double precision :: invdx(1:ndim)
667 integer :: hxO^L,ixC^L,jxC^L,idims,ix^L,gxC^L,hxC^L
668
669 ix^l=ixo^l^ladd2;
670
671 if (iximin^d>ixmin^d.or.iximax^d<ixmax^d|.or.) &
672 call mpistop("Error in divvectorS: Non-conforming input limits")
673
674 invdx=1.d0/dxlevel
675 divq(ixo^s)=zero
676 do idims=1,ndim
677 hxo^l=ixo^l-kr(idims,^d);
678 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
679 jxc^l=ixc^l+kr(idims,^d);
680 gxcmin^d=ixcmin^d-kr(idims,^d);gxcmax^d=jxcmax^d;
681 hxc^l=gxc^l+kr(idims,^d);
682 qr(gxc^s) = qvec(hxc^s,idims)
683 ql(gxc^s) = qvec(gxc^s,idims)
685 dqc(gxc^s)= qr(gxc^s)-ql(gxc^s)
686 call dwlimiter2(dqc,ixi^l,gxc^l,idims,type_gradient_limiter(block%level),ldw=ldq,rdw=rdq)
687 ql(ixc^s) = ql(ixc^s) + half*ldq(ixc^s)
688 qr(ixc^s) = qr(ixc^s) - half*rdq(jxc^s)
689 else
690 dqc(ixi^s)=qvec(ixi^s,idims)
691 call ppmlimitervar(ixi^l,ixo^l,idims,dqc,dqc,ql,qr)
692 endif
693
694 if (slab_uniform) then
695 divq(ixo^s)=divq(ixo^s)+half*(qr(ixo^s)-ql(hxo^s))*invdx(idims)
696 else
697 qr(ixc^s)=block%surfaceC(ixc^s,idims)*qr(ixc^s)
698 ql(ixc^s)=block%surfaceC(ixc^s,idims)*ql(ixc^s)
699 divq(ixo^s)=divq(ixo^s)+qr(ixo^s)-ql(hxo^s)
700 end if
701 end do
702 if(.not.slab_uniform) divq(ixo^s)=divq(ixo^s)/block%dvolume(ixo^s)
703 end subroutine divvectors
704
705 !**************************************************************************
706 ! Purpose: Computes the Laplacian of a scalar field q(ixI^S) at cell
707 ! centers and outputs it in laplq(ixO^S),
708 ! which is also defined at cell **centers**.
709 !
710 ! For uniform Cartesian coordinates, an optional input
711 ! parameter nth_in allows increasing the order of the
712 ! central difference scheme to 2*nth_in.
713 !**************************************************************************
714 subroutine laplacian(q,ixI^L,ixO^L,laplq,nth_in)
716 integer, intent(in) :: ixI^L, ixO^L
717 integer, intent(in), optional :: nth_in
718 double precision, intent(in) :: q(ixI^S)
719 double precision, intent(inout) :: laplq(ixI^S)
720 integer :: lxO^L, jxO^L, hxO^L, kxO^L, nth, idim
721
722 if(present(nth_in)) then
723 nth = nth_in
724 else
725 nth = 1
726 endif
727 if(nth .gt. nghostcells) then
728 call mpistop("laplacian stencil too wide")
729 endif
730
731 select case(coordinate)
732 case(cartesian)
733 select case(nth)
734 case(1)
735 laplq(ixo^s)=zero
736 do idim=1,ndim
737 jxo^l=ixo^l+kr(idim,^d);
738 hxo^l=ixo^l-kr(idim,^d);
739 laplq(ixo^s)=laplq(ixo^s)+&
740 (q(jxo^s)-2.0d0*q(ixo^s)+q(hxo^s))/dxlevel(idim)**2
741 end do
742 case(2)
743 laplq(ixo^s)=zero
744 do idim=1,ndim
745 lxo^l=ixo^l+2*kr(idim,^d);
746 jxo^l=ixo^l+kr(idim,^d);
747 hxo^l=ixo^l-kr(idim,^d);
748 kxo^l=ixo^l-2*kr(idim,^d);
749 laplq(ixo^s)=laplq(ixo^s)+&
750 (-q(lxo^s)+16.0d0*q(jxo^s)-30.0d0*q(ixo^s)+16.0d0*q(hxo^s)-q(kxo^s)) &
751 /(12.0d0 * dxlevel(idim)**2)
752 end do
753 case default
754 call mpistop("unknown stencil laplacian")
755 end select
757 call mpistop("No laplacian available")
758 case(spherical)
759 call mpistop("No laplacian available")
760 case(cylindrical)
761 call mpistop("No laplacian available")
762 case default
763 call mpistop('Unknown geometry')
764 end select
765 end subroutine laplacian
766
767 !**************************************************************************
768 ! Purpose: Computes the Laplacian of a vector field qvec(ixI^S,1:ndir) at cell
769 ! centers and outputs it in lapl_qvec(ixO^S,1:ndir),
770 ! which is also defined at cell **centers**.
771 !**************************************************************************
772 subroutine laplacian_of_vector(qvec,ixI^L,ixO^L,lapl_qvec)
774 integer, intent(in) :: ixI^L, ixO^L
775 double precision, intent(in) :: qvec(ixI^S,1:ndir)
776 double precision, intent(inout) :: lapl_qvec(ixI^S,1:ndir)
777 integer :: idir
778 double precision :: tmp(ixI^S)
779
780 do idir=1,ndir
781 call laplacian(qvec(ixi^s,idir),ixi^l,ixo^l,tmp)
782 lapl_qvec(ixo^s,idir)=tmp(ixo^s)
783 enddo
784
785 end subroutine laplacian_of_vector
786
787
788 !> Calculate curl of a vector qvec within ixL
789 !> Options to
790 !> employ standard second order CD evaluations
791 !> use Gauss theorem for non-Cartesian grids
792 !> use Stokes theorem for non-Cartesian grids
793 subroutine curlvector(qvec,ixI^L,ixO^L,curlvec,idirmin,idirmin0,ndir0,fourthorder)
795
796 integer, intent(in) :: ixI^L,ixO^L
797 integer, intent(in) :: ndir0, idirmin0
798 integer, intent(inout) :: idirmin
799 double precision, intent(in) :: qvec(ixI^S,1:ndir0)
800 double precision, intent(inout) :: curlvec(ixI^S,idirmin0:3)
801 logical, intent(in), optional :: fourthorder !< Default: false
802
803 double precision :: invdx(1:ndim)
804 double precision :: tmp(ixI^S),tmp2(ixI^S),xC(ixI^S),surface(ixI^S)
805 integer :: ixA^L,ixC^L,jxC^L,idir,jdir,kdir,hxO^L,jxO^L,kxO^L,gxO^L
806 logical :: use_4th_order
807
808 ! Calculate curl within ixL: CurlV_i=eps_ijk*d_j V_k
809 ! Curl can have components (idirmin:3)
810 ! Determine exact value of idirmin while doing the loop.
811
812 use_4th_order = .false.
813 if (present(fourthorder)) use_4th_order = fourthorder
814
815 if (use_4th_order) then
816 if (.not. slab_uniform) &
817 call mpistop("curlvector: 4th order only supported for slab geometry")
818 ! Fourth order, stencil width is two
819 ixa^l=ixo^l^ladd2;
820 else
821 ! Second order, stencil width is one
822 ixa^l=ixo^l^ladd1;
823 end if
824
825 if (iximin^d>ixamin^d.or.iximax^d<ixamax^d|.or.) &
826 call mpistop("Error in curlvector: Non-conforming input limits")
827
828 idirmin=4
829 curlvec(ixo^s,idirmin0:3)=zero
830
831 ! all non-Cartesian cases
832 select case(coordinate)
833 case(cartesian) ! Cartesian grids
834 invdx=1.d0/dxlevel
835 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
836 if(lvc(idir,jdir,kdir)/=0)then
837 if (.not. use_4th_order) then
838 ! Use second order scheme
839 jxo^l=ixo^l+kr(jdir,^d);
840 hxo^l=ixo^l-kr(jdir,^d);
841 tmp(ixo^s)=half*(qvec(jxo^s,kdir) &
842 - qvec(hxo^s,kdir))*invdx(jdir)
843 else
844 ! Use fourth order scheme
845 kxo^l=ixo^l+2*kr(jdir,^d);
846 jxo^l=ixo^l+kr(jdir,^d);
847 hxo^l=ixo^l-kr(jdir,^d);
848 gxo^l=ixo^l-2*kr(jdir,^d);
849 tmp(ixo^s)=(-qvec(kxo^s,kdir) + 8.0d0 * qvec(jxo^s,kdir) - 8.0d0 * &
850 qvec(hxo^s,kdir) + qvec(gxo^s,kdir))/(12.0d0 * dxlevel(jdir))
851 end if
852 if(lvc(idir,jdir,kdir)==1)then
853 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp(ixo^s)
854 else
855 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp(ixo^s)
856 endif
857 if(idir<idirmin)idirmin=idir
858 endif
859 enddo; enddo; enddo;
860 case(cartesian_stretched) ! stretched Cartesian grids
861 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
862 if(lvc(idir,jdir,kdir)/=0)then
863 select case(type_curl)
864 case(central)
865 tmp(ixa^s)=qvec(ixa^s,kdir)
866 hxo^l=ixo^l-kr(jdir,^d);
867 jxo^l=ixo^l+kr(jdir,^d);
868 ! second order centered differencing
869 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,jdir)-block%x(hxo^s,jdir))
870 case(gaussbased)
871 hxo^l=ixo^l-kr(jdir,^d);
872 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
873 jxc^l=ixc^l+kr(jdir,^d);
874 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
875 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
876 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
877 case(stokesbased)
878 hxo^l=ixo^l-kr(jdir,^d);
879 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
880 jxc^l=ixc^l+kr(jdir,^d);
881 if(kdir<=ndim)then
882 tmp(ixc^s)=block%ds(ixo^s,kdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
883 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
884 else
885 tmp(ixc^s)=(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
886 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
887 endif
888 if(idir<=ndim)then
889 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%surface(ixo^s,idir)
890 else ! essentially for 2.5D case, idir=3 and jdir,kdir<=2
891 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/(block%ds(ixo^s,jdir)*block%ds(ixo^s,kdir))
892 endif
893 case default
894 call mpistop('no such curl evaluator')
895 end select
896 if(lvc(idir,jdir,kdir)==1)then
897 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
898 else
899 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
900 endif
901 if(idir<idirmin)idirmin=idir
902 endif
903 enddo; enddo; enddo;
904 case(spherical) ! possibly stretched spherical grids
905 select case(type_curl)
906 case(central) ! ok for any dimensionality
907 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
908 if(lvc(idir,jdir,kdir)/=0)then
909 tmp(ixa^s)=qvec(ixa^s,kdir)
910 hxo^l=ixo^l-kr(jdir,^d);
911 jxo^l=ixo^l+kr(jdir,^d);
912 select case(jdir)
913 case(1)
914 tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1)
915 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,1)-block%x(hxo^s,1))*block%x(ixo^s,1))
916 {^nooned case(2)
917 if(idir==1) tmp(ixa^s)=tmp(ixa^s)*dsin(block%x(ixa^s,2))
918 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,2)-block%x(hxo^s,2))*block%x(ixo^s,1))
919 if(idir==1) tmp2(ixo^s)=tmp2(ixo^s)/dsin(block%x(ixo^s,2))
920 }
921 {^ifthreed case(3)
922 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,3)-block%x(hxo^s,3))*block%x(ixo^s,1)*dsin(block%x(ixo^s,2)))
923 }
924 end select
925 if(lvc(idir,jdir,kdir)==1)then
926 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
927 else
928 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
929 endif
930 if(idir<idirmin)idirmin=idir
931 endif
932 enddo; enddo; enddo;
933 case(gaussbased)
934 do idir=idirmin0,3;
935 do jdir=1,ndim; do kdir=1,ndir0
936 if(lvc(idir,jdir,kdir)/=0)then
937 hxo^l=ixo^l-kr(jdir,^d);
938 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
939 jxc^l=ixc^l+kr(jdir,^d);
940 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
941 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
942 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
943 if(lvc(idir,jdir,kdir)==1)then
944 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
945 else
946 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
947 endif
948 if(idir<idirmin)idirmin=idir
949 endif
950 enddo; enddo;
951 ! geometric terms
952 if(idir==2.and.phi_>0) curlvec(ixo^s,2)=curlvec(ixo^s,2)+qvec(ixo^s,phi_)/block%x(ixo^s,r_)
953 {^nooned
954 if(idir==phi_) curlvec(ixo^s,phi_)=curlvec(ixo^s,phi_)-qvec(ixo^s,2)/block%x(ixo^s,r_) &
955 +qvec(ixo^s,r_)*dcos(block%x(ixo^s,2))/(block%x(ixo^s,r_)*dsin(block%x(ixo^s,2)))
956 }
957 enddo;
958 case(stokesbased)
959 !if(ndim<3) call mpistop("Stokesbased for 3D spherical only")
960 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
961 if(lvc(idir,jdir,kdir)/=0)then
962 select case(idir)
963 case(1)
964 if(jdir<kdir) then
965 ! idir=1,jdir=2,kdir=3
966 !! integral along 3rd dimension
967 hxo^l=ixo^l-kr(jdir,^d);
968 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
969 jxc^l=ixc^l+kr(jdir,^d);
970 ! qvec(3) at cell interface along 2nd dimension
971 if(stretched_dim(jdir) .and. stretch_uncentered) then
972 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
973 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
974 else
975 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
976 end if
977 ! 2nd coordinate at cell interface along 2nd dimension
978 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
979 curlvec(ixo^s,idir)=(dsin(xc(ixo^s))*tmp(ixo^s)-&
980 dsin(xc(hxo^s))*tmp(hxo^s))*block%dx(ixo^s,kdir)
981 !! integral along 2nd dimension
982 hxo^l=ixo^l-kr(kdir,^d);
983 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
984 jxc^l=ixc^l+kr(kdir,^d);
985 ! qvec(2) at cell interface along 3rd dimension
986 if(stretched_dim(kdir) .and. stretch_uncentered) then
987 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
988 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
989 else
990 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
991 end if
992 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir))&
993 /block%surface(ixo^s,idir)*block%x(ixo^s,idir)
994 end if
995 case(2)
996 if(jdir<kdir) then
997 ! idir=2,jdir=1,kdir=3
998 !! integral along 1st dimension
999 hxo^l=ixo^l-kr(kdir,^d);
1000 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1001 jxc^l=ixc^l+kr(kdir,^d);
1002 ! qvec(1) at cell interface along 3rd dimension
1003 if(stretched_dim(kdir) .and. stretch_uncentered) then
1004 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1005 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1006 else
1007 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1008 end if
1009 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,1)
1010 !! integral along 3rd dimension
1011 hxo^l=ixo^l-kr(jdir,^d);
1012 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1013 jxc^l=ixc^l+kr(jdir,^d);
1014 ! qvec(3) at cell interface along 1st dimension
1015 if(stretched_dim(jdir) .and. stretch_uncentered) then
1016 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1017 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1018 else
1019 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1020 end if
1021 ! 1st coordinate at cell interface along 1st dimension
1022 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1023 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(hxo^s)*tmp(hxo^s)-xc(ixo^s)*tmp(ixo^s))*&
1024 dsin(block%x(ixo^s,idir))*block%dx(ixo^s,kdir))/block%surface(ixo^s,idir)
1025 end if
1026 case(3)
1027 if(jdir<kdir) then
1028 ! idir=3,jdir=1,kdir=2
1029 !! integral along 1st dimension
1030 hxo^l=ixo^l-kr(kdir,^d);
1031 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1032 jxc^l=ixc^l+kr(kdir,^d);
1033 ! qvec(1) at cell interface along 2nd dimension
1034 if(stretched_dim(kdir) .and. stretch_uncentered) then
1035 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1036 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1037 else
1038 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1039 end if
1040 curlvec(ixo^s,idir)=(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir)
1041 !! integral along 2nd dimension
1042 hxo^l=ixo^l-kr(jdir,^d);
1043 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1044 jxc^l=ixc^l+kr(jdir,^d);
1045 ! qvec(2) at cell interface along 1st dimension
1046 if(stretched_dim(jdir) .and. stretch_uncentered) then
1047 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1048 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1049 else
1050 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1051 end if
1052 ! 1st coordinate at cell interface along 1st dimension
1053 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1054 if(ndim==3) then
1055 surface(ixo^s)=block%surface(ixo^s,idir)
1056 else
1057 surface(ixo^s)=block%x(ixo^s,jdir)*block%dx(ixo^s,kdir)*block%dx(ixo^s,jdir)
1058 end if
1059 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(ixo^s)*tmp(ixo^s)-xc(hxo^s)*tmp(hxo^s))*block%dx(ixo^s,kdir))&
1060 /surface(ixo^s)
1061 end if
1062 end select
1063 if(idir<idirmin)idirmin=idir
1064 endif
1065 enddo; enddo; enddo;
1066 case default
1067 call mpistop('no such curl evaluator')
1068 end select
1069 case(cylindrical) ! possibly stretched cylindrical grids
1070 select case(type_curl)
1071 case(central) ! works for any dimensionality, polar/cylindrical
1072 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1073 if(lvc(idir,jdir,kdir)/=0)then
1074 tmp(ixa^s)=qvec(ixa^s,kdir)
1075 hxo^l=ixo^l-kr(jdir,^d);
1076 jxo^l=ixo^l+kr(jdir,^d);
1077 if(z_==3.or.z_==-1) then
1078 ! Case Polar_2D, Polar_2.5D or Polar_3D, i.e. R,phi,Z
1079 select case(jdir)
1080 case(1)
1081 if(idir==z_) tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1) ! R V_phi
1082 ! computes d(R V_phi)/dR or d V_Z/dR
1083 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,1)-block%x(hxo^s,1))
1084 if(idir==z_) tmp2(ixo^s)=tmp2(ixo^s)/block%x(ixo^s,1) ! (1/R)*d(R V_phi)/dR
1085 {^nooned case(2)
1086 ! handles (1/R)d V_Z/dphi or (1/R)d V_R/dphi
1087 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,2)-block%x(hxo^s,2))*block%x(ixo^s,1))
1088 }
1089 {^ifthreed case(3)
1090 ! handles d V_phi/dZ or d V_R/dZ
1091 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,3)-block%x(hxo^s,3))
1092 }
1093 end select
1094 end if
1095 if(phi_==3.or.phi_==-1) then
1096 ! Case Cylindrical_2D, Cylindrical_2.5D or Cylindrical_3D, i.e. R,Z,phi
1097 select case(jdir)
1098 case(1)
1099 if(idir==z_) tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1) ! R V_phi
1100 ! computes d(R V_phi)/dR or d V_Z/dR
1101 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,1)-block%x(hxo^s,1))
1102 if(idir==z_) tmp2(ixo^s)=tmp2(ixo^s)/block%x(ixo^s,1) ! (1/R)*d(R V_phi)/dR
1103 {^nooned case(2)
1104 ! handles d V_phi/dZ or d V_R/dZ
1105 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,2)-block%x(hxo^s,2))
1106 }
1107 {^ifthreed case(3)
1108 ! handles (1/R)d V_Z/dphi or (1/R)d V_R/dphi
1109 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,3)-block%x(hxo^s,3))*block%x(ixo^s,1))
1110 }
1111 end select
1112 end if
1113 if(lvc(idir,jdir,kdir)==1)then
1114 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1115 else
1116 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1117 endif
1118 if(idir<idirmin)idirmin=idir
1119 endif
1120 enddo; enddo; enddo;
1121 case(gaussbased) ! works for any dimensionality, polar/cylindrical
1122 if(ndim<2) call mpistop("Gaussbased for 2D, 2.5D or 3D polar or cylindrical only")
1123 do idir=idirmin0,3;
1124 do jdir=1,ndim; do kdir=1,ndir0
1125 if(lvc(idir,jdir,kdir)/=0)then
1126 hxo^l=ixo^l-kr(jdir,^d);
1127 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1128 jxc^l=ixc^l+kr(jdir,^d);
1129 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1130 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1131 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
1132 if(lvc(idir,jdir,kdir)==1)then
1133 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1134 else
1135 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1136 endif
1137 if(idir<idirmin)idirmin=idir
1138 endif
1139 enddo; enddo;
1140 ! geometric term from d e_R/d phi= e_phi for unit vectors e_R, e_phi
1141 ! but minus sign appears due to R,Z,phi ordering (?)
1142 ! note that in cylindrical 2D (RZ), phi_ is -1
1143 ! note that in polar 2D (Rphi), z_ is -1
1144 if((idir==phi_.or.(phi_==-1.and.idir==3)).and.z_>0) then
1145 ! cylindrical
1146 if( z_==2) curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-qvec(ixo^s,z_)/block%x(ixo^s,r_)
1147 ! polar
1148 if(phi_==2) curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+qvec(ixo^s,z_)/block%x(ixo^s,r_)
1149 endif
1150 enddo;
1151 case(stokesbased)
1152 if(ndim<3) call mpistop("Stokesbased for 3D cylindrical only")
1153 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1154 if(lvc(idir,jdir,kdir)/=0)then
1155 if(idir==r_) then
1156 if(jdir==phi_) then
1157 ! idir=r,jdir=phi,kdir=z
1158 !! integral along z dimension
1159 hxo^l=ixo^l-kr(jdir,^d);
1160 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1161 jxc^l=ixc^l+kr(jdir,^d);
1162 ! qvec(z) at cell interface along phi dimension
1163 if(stretched_dim(jdir) .and. stretch_uncentered) then
1164 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1165 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1166 else
1167 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1168 end if
1169 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,kdir)
1170 !! integral along phi dimension
1171 hxo^l=ixo^l-kr(kdir,^d);
1172 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1173 jxc^l=ixc^l+kr(kdir,^d);
1174 ! qvec(phi) at cell interface along z dimension
1175 if(stretched_dim(kdir) .and. stretch_uncentered) then
1176 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1177 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1178 else
1179 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1180 end if
1181 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%x(ixo^s,idir)*block%dx(ixo^s,jdir))&
1182 /block%surface(ixo^s,idir)
1183 end if
1184 else if(idir==phi_) then
1185 if(jdir<kdir) then
1186 ! idir=phi,jdir=r,kdir=z
1187 !! integral along r dimension
1188 hxo^l=ixo^l-kr(kdir,^d);
1189 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1190 jxc^l=ixc^l+kr(kdir,^d);
1191 ! qvec(r) at cell interface along z dimension
1192 if(stretched_dim(kdir) .and. stretch_uncentered) then
1193 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1194 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1195 else
1196 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1197 end if
1198 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,jdir)
1199 !! integral along z dimension
1200 hxo^l=ixo^l-kr(jdir,^d);
1201 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1202 jxc^l=ixc^l+kr(jdir,^d);
1203 ! qvec(z) at cell interface along r dimension
1204 if(stretched_dim(jdir) .and. stretch_uncentered) then
1205 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1206 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1207 else
1208 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1209 end if
1210 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,kdir))&
1211 /block%surface(ixo^s,idir)
1212 end if
1213 else ! idir==z_
1214 if(jdir<kdir) then
1215 ! idir=z,jdir=r,kdir=phi
1216 !! integral along r dimension
1217 hxo^l=ixo^l-kr(kdir,^d);
1218 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1219 jxc^l=ixc^l+kr(kdir,^d);
1220 ! qvec(r) at cell interface along phi dimension
1221 if(stretched_dim(kdir) .and. stretch_uncentered) then
1222 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1223 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1224 else
1225 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1226 end if
1227 curlvec(ixo^s,idir)=(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir)
1228 !! integral along phi dimension
1229 hxo^l=ixo^l-kr(jdir,^d);
1230 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1231 jxc^l=ixc^l+kr(jdir,^d);
1232 ! qvec(phi) at cell interface along r dimension
1233 if(stretched_dim(jdir) .and. stretch_uncentered) then
1234 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1235 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1236 else
1237 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1238 end if
1239 ! r coordinate at cell interface along r dimension
1240 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1241 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(ixo^s)*tmp(ixo^s)-xc(hxo^s)*tmp(hxo^s))*block%dx(ixo^s,kdir))&
1242 /block%surface(ixo^s,idir)
1243 end if
1244 end if
1245 if(idir<idirmin)idirmin=idir
1246 endif
1247 enddo; enddo; enddo;
1248 case default
1249 call mpistop('no such curl evaluator')
1250 end select
1251 case default
1252 call mpistop('not possible to calculate curl')
1253 end select
1254
1255 end subroutine curlvector
1256
1257 !> Calculate idim transverse components of curl of a vector qvec within ixL
1258 !> Options to
1259 !> employ standard second order CD evaluations
1260 !> use Gauss theorem for non-Cartesian grids
1261 !> use Stokes theorem for non-Cartesian grids
1262 subroutine curlvector_trans(qvec,qvecc,ixI^L,ixO^L,curlvec,idim,idirmin,idirmin0,ndir0)
1264
1265 integer, intent(in) :: ixI^L,ixO^L
1266 integer, intent(in) :: idim, ndir0, idirmin0
1267 integer, intent(inout) :: idirmin
1268 double precision, intent(in) :: qvec(ixI^S,1:ndir0),qvecc(ixI^S,1:ndir0)
1269 double precision, intent(inout) :: curlvec(ixI^S,idirmin0:3)
1270
1271 double precision :: invdx(1:ndim)
1272 double precision :: tmp(ixI^S),tmp2(ixI^S),xC(ixI^S),surface(ixI^S)
1273 integer :: ixA^L,ixC^L,jxC^L,idir,jdir,kdir,hxO^L,jxO^L
1274
1275 ! Calculate curl within ixL: CurlV_i=eps_ijk*d_j V_k
1276 ! Curl can have components (idirmin:3)
1277 ! Determine exact value of idirmin while doing the loop.
1278
1279 idirmin=4
1280 curlvec(ixo^s,idirmin0:3)=zero
1281 ! Second order, stencil width is one
1282 ixa^l=ixo^l^ladd1;
1283
1284 ! all non-Cartesian cases
1285 select case(coordinate)
1286 case(cartesian) ! Cartesian grids
1287 invdx=1.d0/dxlevel
1288 do idir=idirmin0,3
1289 do jdir=1,ndim; do kdir=1,ndir0
1290 if(lvc(idir,jdir,kdir)/=0)then
1291 if(jdir/=idim) then
1292 tmp(ixi^s)=qvec(ixi^s,kdir)
1293 hxo^l=ixo^l-kr(jdir,^d);
1294 jxo^l=ixo^l+kr(jdir,^d);
1295 else
1296 ! use two cell-center values for gradient at interface of the two cells
1297 ! because left and right neighbor interface values is unavailable at block boundary faces
1298 tmp(ixi^s)=qvecc(ixi^s,kdir)
1299 hxo^l=ixo^l;
1300 jxo^l=ixo^l+kr(jdir,^d);
1301 end if
1302 ! second order centered differencing
1303 tmp(ixo^s)=half*(tmp(jxo^s)-tmp(hxo^s))*invdx(jdir)
1304 if(lvc(idir,jdir,kdir)==1)then
1305 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp(ixo^s)
1306 else
1307 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp(ixo^s)
1308 endif
1309 if(idir<idirmin)idirmin=idir
1310 endif
1311 enddo; enddo;
1312 end do
1313 case(cartesian_stretched) ! stretched Cartesian grids
1314 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1315 if(lvc(idir,jdir,kdir)/=0)then
1316 select case(type_curl)
1317 case(central)
1318 tmp(ixi^s)=qvec(ixi^s,kdir)
1319 hxo^l=ixo^l-kr(jdir,^d);
1320 jxo^l=ixo^l+kr(jdir,^d);
1321 ! second order centered differencing
1322 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,jdir)-block%x(hxo^s,jdir))
1323 case(gaussbased)
1324 hxo^l=ixo^l-kr(jdir,^d);
1325 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1326 jxc^l=ixc^l+kr(jdir,^d);
1327 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1328 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1329 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
1330 case(stokesbased)
1331 hxo^l=ixo^l-kr(jdir,^d);
1332 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1333 jxc^l=ixc^l+kr(jdir,^d);
1334 if(kdir<=ndim)then
1335 tmp(ixc^s)=block%ds(ixo^s,kdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1336 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1337 else
1338 tmp(ixc^s)=(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1339 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1340 endif
1341 if(idir<=ndim)then
1342 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%surface(ixo^s,idir)
1343 else ! essentially for 2.5D case, idir=3 and jdir,kdir<=2
1344 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/(block%ds(ixo^s,jdir)*block%ds(ixo^s,kdir))
1345 endif
1346 case default
1347 call mpistop('no such curl evaluator')
1348 end select
1349 if(lvc(idir,jdir,kdir)==1)then
1350 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1351 else
1352 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1353 endif
1354 if(idir<idirmin)idirmin=idir
1355 endif
1356 enddo; enddo; enddo;
1357 case(spherical) ! possibly stretched spherical grids
1358 select case(type_curl)
1359 case(central) ! ok for any dimensionality
1360 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1361 if(lvc(idir,jdir,kdir)/=0)then
1362 tmp(ixi^s)=qvec(ixi^s,kdir)
1363 hxo^l=ixo^l-kr(jdir,^d);
1364 jxo^l=ixo^l+kr(jdir,^d);
1365 select case(jdir)
1366 case(1)
1367 tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1)
1368 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,1)-block%x(hxo^s,1))*block%x(ixo^s,1))
1369 {^nooned case(2)
1370 if(idir==1) tmp(ixa^s)=tmp(ixa^s)*dsin(block%x(ixa^s,2))
1371 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,2)-block%x(hxo^s,2))*block%x(ixo^s,1))
1372 if(idir==1) tmp2(ixo^s)=tmp2(ixo^s)/dsin(block%x(ixo^s,2))
1373 }
1374 {^ifthreed case(3)
1375 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,3)-block%x(hxo^s,3))*block%x(ixo^s,1)*dsin(block%x(ixo^s,2)))
1376 }
1377 end select
1378 if(lvc(idir,jdir,kdir)==1)then
1379 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1380 else
1381 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1382 endif
1383 if(idir<idirmin)idirmin=idir
1384 endif
1385 enddo; enddo; enddo;
1386 case(gaussbased)
1387 do idir=idirmin0,3;
1388 do jdir=1,ndim; do kdir=1,ndir0
1389 if(lvc(idir,jdir,kdir)/=0)then
1390 hxo^l=ixo^l-kr(jdir,^d);
1391 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1392 jxc^l=ixc^l+kr(jdir,^d);
1393 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1394 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1395 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
1396 if(lvc(idir,jdir,kdir)==1)then
1397 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1398 else
1399 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1400 endif
1401 if(idir<idirmin)idirmin=idir
1402 endif
1403 enddo; enddo;
1404 ! geometric terms
1405 if(idir==2.and.phi_>0) curlvec(ixo^s,2)=curlvec(ixo^s,2)+qvec(ixo^s,phi_)/block%x(ixo^s,r_)
1406 {^nooned
1407 if(idir==phi_) curlvec(ixo^s,phi_)=curlvec(ixo^s,phi_)-qvec(ixo^s,2)/block%x(ixo^s,r_) &
1408 +qvec(ixo^s,r_)*dcos(block%x(ixo^s,2))/(block%x(ixo^s,r_)*dsin(block%x(ixo^s,2)))
1409 }
1410 enddo;
1411 case(stokesbased)
1412 !if(ndim<3) call mpistop("Stokesbased for 3D spherical only")
1413 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1414 if(lvc(idir,jdir,kdir)/=0)then
1415 select case(idir)
1416 case(1)
1417 if(jdir<kdir) then
1418 ! idir=1,jdir=2,kdir=3
1419 !! integral along 3rd dimension
1420 hxo^l=ixo^l-kr(jdir,^d);
1421 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1422 jxc^l=ixc^l+kr(jdir,^d);
1423 ! qvec(3) at cell interface along 2nd dimension
1424 if(stretched_dim(jdir) .and. stretch_uncentered) then
1425 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1426 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1427 else
1428 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1429 end if
1430 ! 2nd coordinate at cell interface along 2nd dimension
1431 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1432 curlvec(ixo^s,idir)=(dsin(xc(ixo^s))*tmp(ixo^s)-&
1433 dsin(xc(hxo^s))*tmp(hxo^s))*block%dx(ixo^s,kdir)
1434 !! integral along 2nd dimension
1435 hxo^l=ixo^l-kr(kdir,^d);
1436 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1437 jxc^l=ixc^l+kr(kdir,^d);
1438 ! qvec(2) at cell interface along 3rd dimension
1439 if(stretched_dim(kdir) .and. stretch_uncentered) then
1440 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1441 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1442 else
1443 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1444 end if
1445 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir))&
1446 /block%surface(ixo^s,idir)*block%x(ixo^s,idir)
1447 end if
1448 case(2)
1449 if(jdir<kdir) then
1450 ! idir=2,jdir=1,kdir=3
1451 !! integral along 1st dimension
1452 hxo^l=ixo^l-kr(kdir,^d);
1453 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1454 jxc^l=ixc^l+kr(kdir,^d);
1455 ! qvec(1) at cell interface along 3rd dimension
1456 if(stretched_dim(kdir) .and. stretch_uncentered) then
1457 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1458 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1459 else
1460 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1461 end if
1462 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,1)
1463 !! integral along 3rd dimension
1464 hxo^l=ixo^l-kr(jdir,^d);
1465 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1466 jxc^l=ixc^l+kr(jdir,^d);
1467 ! qvec(3) at cell interface along 1st dimension
1468 if(stretched_dim(jdir) .and. stretch_uncentered) then
1469 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1470 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1471 else
1472 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1473 end if
1474 ! 1st coordinate at cell interface along 1st dimension
1475 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1476 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(hxo^s)*tmp(hxo^s)-xc(ixo^s)*tmp(ixo^s))*&
1477 dsin(block%x(ixo^s,idir))*block%dx(ixo^s,kdir))/block%surface(ixo^s,idir)
1478 end if
1479 case(3)
1480 if(jdir<kdir) then
1481 ! idir=3,jdir=1,kdir=2
1482 !! integral along 1st dimension
1483 hxo^l=ixo^l-kr(kdir,^d);
1484 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1485 jxc^l=ixc^l+kr(kdir,^d);
1486 ! qvec(1) at cell interface along 2nd dimension
1487 if(stretched_dim(kdir) .and. stretch_uncentered) then
1488 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1489 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1490 else
1491 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1492 end if
1493 curlvec(ixo^s,idir)=(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir)
1494 !! integral along 2nd dimension
1495 hxo^l=ixo^l-kr(jdir,^d);
1496 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1497 jxc^l=ixc^l+kr(jdir,^d);
1498 ! qvec(2) at cell interface along 1st dimension
1499 if(stretched_dim(jdir) .and. stretch_uncentered) then
1500 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1501 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1502 else
1503 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1504 end if
1505 ! 1st coordinate at cell interface along 1st dimension
1506 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1507 if(ndim==3) then
1508 surface(ixo^s)=block%surface(ixo^s,idir)
1509 else
1510 surface(ixo^s)=block%x(ixo^s,jdir)*block%dx(ixo^s,kdir)*block%dx(ixo^s,jdir)
1511 end if
1512 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(ixo^s)*tmp(ixo^s)-xc(hxo^s)*tmp(hxo^s))*block%dx(ixo^s,kdir))&
1513 /surface(ixo^s)
1514 end if
1515 end select
1516 if(idir<idirmin)idirmin=idir
1517 endif
1518 enddo; enddo; enddo;
1519 case default
1520 call mpistop('no such curl evaluator')
1521 end select
1522 case(cylindrical) ! possibly stretched cylindrical grids
1523 select case(type_curl)
1524 case(central) ! works for any dimensionality, polar/cylindrical
1525 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1526 if(lvc(idir,jdir,kdir)/=0)then
1527 tmp(ixi^s)=qvec(ixi^s,kdir)
1528 hxo^l=ixo^l-kr(jdir,^d);
1529 jxo^l=ixo^l+kr(jdir,^d);
1530 if(z_==3.or.z_==-1) then
1531 ! Case Polar_2D, Polar_2.5D or Polar_3D, i.e. R,phi,Z
1532 select case(jdir)
1533 case(1)
1534 if(idir==z_) tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1) ! R V_phi
1535 ! computes d(R V_phi)/dR or d V_Z/dR
1536 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,1)-block%x(hxo^s,1))
1537 if(idir==z_) tmp2(ixo^s)=tmp2(ixo^s)/block%x(ixo^s,1) ! (1/R)*d(R V_phi)/dR
1538 {^nooned case(2)
1539 ! handles (1/R)d V_Z/dphi or (1/R)d V_R/dphi
1540 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,2)-block%x(hxo^s,2))*block%x(ixo^s,1))
1541 }
1542 {^ifthreed case(3)
1543 ! handles d V_phi/dZ or d V_R/dZ
1544 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,3)-block%x(hxo^s,3))
1545 }
1546 end select
1547 end if
1548 if(phi_==3.or.phi_==-1) then
1549 ! Case Cylindrical_2D, Cylindrical_2.5D or Cylindrical_3D, i.e. R,Z,phi
1550 select case(jdir)
1551 case(1)
1552 if(idir==z_) tmp(ixa^s)=tmp(ixa^s)*block%x(ixa^s,1) ! R V_phi
1553 ! computes d(R V_phi)/dR or d V_Z/dR
1554 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,1)-block%x(hxo^s,1))
1555 if(idir==z_) tmp2(ixo^s)=tmp2(ixo^s)/block%x(ixo^s,1) ! (1/R)*d(R V_phi)/dR
1556 {^nooned case(2)
1557 ! handles d V_phi/dZ or d V_R/dZ
1558 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/(block%x(jxo^s,2)-block%x(hxo^s,2))
1559 }
1560 {^ifthreed case(3)
1561 ! handles (1/R)d V_Z/dphi or (1/R)d V_R/dphi
1562 tmp2(ixo^s)=(tmp(jxo^s)-tmp(hxo^s))/((block%x(jxo^s,3)-block%x(hxo^s,3))*block%x(ixo^s,1))
1563 }
1564 end select
1565 end if
1566 if(lvc(idir,jdir,kdir)==1)then
1567 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1568 else
1569 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1570 endif
1571 if(idir<idirmin)idirmin=idir
1572 endif
1573 enddo; enddo; enddo;
1574 case(gaussbased) ! works for any dimensionality, polar/cylindrical
1575 if(ndim<2) call mpistop("Gaussbased for 2D, 2.5D or 3D polar or cylindrical only")
1576 do idir=idirmin0,3;
1577 do jdir=1,ndim; do kdir=1,ndir0
1578 if(lvc(idir,jdir,kdir)/=0)then
1579 hxo^l=ixo^l-kr(jdir,^d);
1580 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1581 jxc^l=ixc^l+kr(jdir,^d);
1582 tmp(ixc^s)=block%surfaceC(ixc^s,jdir)*(qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1583 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir)))
1584 tmp2(ixo^s)=(tmp(ixo^s)-tmp(hxo^s))/block%dvolume(ixo^s)
1585 if(lvc(idir,jdir,kdir)==1)then
1586 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+tmp2(ixo^s)
1587 else
1588 curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-tmp2(ixo^s)
1589 endif
1590 if(idir<idirmin)idirmin=idir
1591 endif
1592 enddo; enddo;
1593 ! geometric term from d e_R/d phi= e_phi for unit vectors e_R, e_phi
1594 ! but minus sign appears due to R,Z,phi ordering (?)
1595 ! note that in cylindrical 2D (RZ), phi_ is -1
1596 ! note that in polar 2D (Rphi), z_ is -1
1597 if((idir==phi_.or.(phi_==-1.and.idir==3)).and.z_>0) then
1598 ! cylindrical
1599 if( z_==2) curlvec(ixo^s,idir)=curlvec(ixo^s,idir)-qvec(ixo^s,z_)/block%x(ixo^s,r_)
1600 ! polar
1601 if(phi_==2) curlvec(ixo^s,idir)=curlvec(ixo^s,idir)+qvec(ixo^s,z_)/block%x(ixo^s,r_)
1602 endif
1603 enddo;
1604 case(stokesbased)
1605 if(ndim<3) call mpistop("Stokesbased for 3D cylindrical only")
1606 do idir=idirmin0,3; do jdir=1,ndim; do kdir=1,ndir0
1607 if(lvc(idir,jdir,kdir)/=0)then
1608 if(idir==r_) then
1609 if(jdir==phi_) then
1610 ! idir=r,jdir=phi,kdir=z
1611 !! integral along z dimension
1612 hxo^l=ixo^l-kr(jdir,^d);
1613 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1614 jxc^l=ixc^l+kr(jdir,^d);
1615 ! qvec(z) at cell interface along phi dimension
1616 if(stretched_dim(jdir) .and. stretch_uncentered) then
1617 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1618 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1619 else
1620 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1621 end if
1622 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,kdir)
1623 !! integral along phi dimension
1624 hxo^l=ixo^l-kr(kdir,^d);
1625 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1626 jxc^l=ixc^l+kr(kdir,^d);
1627 ! qvec(phi) at cell interface along z dimension
1628 if(stretched_dim(kdir) .and. stretch_uncentered) then
1629 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1630 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1631 else
1632 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1633 end if
1634 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%x(ixo^s,idir)*block%dx(ixo^s,jdir))&
1635 /block%surface(ixo^s,idir)
1636 end if
1637 else if(idir==phi_) then
1638 if(jdir<kdir) then
1639 ! idir=phi,jdir=r,kdir=z
1640 !! integral along r dimension
1641 hxo^l=ixo^l-kr(kdir,^d);
1642 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1643 jxc^l=ixc^l+kr(kdir,^d);
1644 ! qvec(r) at cell interface along z dimension
1645 if(stretched_dim(kdir) .and. stretch_uncentered) then
1646 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1647 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1648 else
1649 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1650 end if
1651 curlvec(ixo^s,idir)=(tmp(ixo^s)-tmp(hxo^s))*block%dx(ixo^s,jdir)
1652 !! integral along z dimension
1653 hxo^l=ixo^l-kr(jdir,^d);
1654 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1655 jxc^l=ixc^l+kr(jdir,^d);
1656 ! qvec(z) at cell interface along r dimension
1657 if(stretched_dim(jdir) .and. stretch_uncentered) then
1658 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1659 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1660 else
1661 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1662 end if
1663 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,kdir))&
1664 /block%surface(ixo^s,idir)
1665 end if
1666 else ! idir==z_
1667 if(jdir<kdir) then
1668 ! idir=z,jdir=r,kdir=phi
1669 !! integral along r dimension
1670 hxo^l=ixo^l-kr(kdir,^d);
1671 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1672 jxc^l=ixc^l+kr(kdir,^d);
1673 ! qvec(r) at cell interface along phi dimension
1674 if(stretched_dim(kdir) .and. stretch_uncentered) then
1675 tmp(ixc^s)=qvec(ixc^s,jdir)+0.5d0*block%dx(ixc^s,kdir)*&
1676 (qvec(jxc^s,jdir)-qvec(ixc^s,jdir))/(block%x(jxc^s,kdir)-block%x(ixc^s,kdir))
1677 else
1678 tmp(ixc^s)=0.5d0*(qvec(ixc^s,jdir)+qvec(jxc^s,jdir))
1679 end if
1680 curlvec(ixo^s,idir)=(tmp(hxo^s)-tmp(ixo^s))*block%dx(ixo^s,jdir)
1681 !! integral along phi dimension
1682 hxo^l=ixo^l-kr(jdir,^d);
1683 ixcmin^d=hxomin^d;ixcmax^d=ixomax^d;
1684 jxc^l=ixc^l+kr(jdir,^d);
1685 ! qvec(phi) at cell interface along r dimension
1686 if(stretched_dim(jdir) .and. stretch_uncentered) then
1687 tmp(ixc^s)=qvec(ixc^s,kdir)+0.5d0*block%dx(ixc^s,jdir)*&
1688 (qvec(jxc^s,kdir)-qvec(ixc^s,kdir))/(block%x(jxc^s,jdir)-block%x(ixc^s,jdir))
1689 else
1690 tmp(ixc^s)=0.5d0*(qvec(ixc^s,kdir)+qvec(jxc^s,kdir))
1691 end if
1692 ! r coordinate at cell interface along r dimension
1693 xc(ixc^s)=block%x(ixc^s,jdir)+0.5d0*block%dx(ixc^s,jdir)
1694 curlvec(ixo^s,idir)=(curlvec(ixo^s,idir)+(xc(ixo^s)*tmp(ixo^s)-xc(hxo^s)*tmp(hxo^s))*block%dx(ixo^s,kdir))&
1695 /block%surface(ixo^s,idir)
1696 end if
1697 end if
1698 if(idir<idirmin)idirmin=idir
1699 endif
1700 enddo; enddo; enddo;
1701 case default
1702 call mpistop('no such curl evaluator')
1703 end select
1704 case default
1705 call mpistop('not possible to calculate curl')
1706 end select
1707
1708 end subroutine curlvector_trans
1709
1710end module mod_geometry
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 set_coordinate_system(geom)
Set the coordinate system to be used.
subroutine divvector(qvec, ixil, ixol, divq, nth_in)
integer coordinate
Definition mod_geometry.t:7
subroutine set_pole
subroutine get_surface_area(s, ixgl)
calculate area of surfaces of cells
integer, parameter spherical
integer, parameter cartesian
Definition mod_geometry.t:8
integer, parameter stokesbased
subroutine laplacian_of_vector(qvec, ixil, ixol, lapl_qvec)
integer type_curl
subroutine laplacian(q, ixil, ixol, laplq, nth_in)
integer, parameter cylindrical
integer, parameter gaussbased
integer, parameter cartesian_expansion
integer, parameter cartesian_stretched
Definition mod_geometry.t:9
subroutine curlvector(qvec, ixil, ixol, curlvec, idirmin, idirmin0, ndir0, fourthorder)
Calculate curl of a vector qvec within ixL Options to employ standard second order CD evaluations use...
subroutine gradient(q, ixil, ixol, idir, gradq, nth_in)
subroutine divvectors(qvec, ixil, ixol, divq)
Calculate divergence of a vector qvec within ixL using limited extrapolation to cell edges.
subroutine gradientf(q, x, ixil, ixol, idir, gradq, nth_in, pm_in)
integer, parameter central
subroutine gradientl(q, ixil, ixol, idir, gradq)
subroutine putgridgeo(igrid)
Deallocate geometry-related variables.
subroutine curlvector_trans(qvec, qvecc, ixil, ixol, curlvec, idim, idirmin, idirmin0, ndir0)
Calculate idim transverse components of curl of a vector qvec within ixL Options to employ standard s...
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.
character(len=std_len) geometry_name
integer, dimension(3, 3, 3) lvc
Levi-Civita tensor.
integer, dimension(3, 3) kr
Kronecker delta tensor.
logical stretch_uncentered
If true, adjust mod_geometry routines to account for grid stretching (but the flux computation will n...
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
integer ndir
Number of spatial dimensions (components) for vector variables.
logical, dimension(ndim) stretched_dim
True if a dimension is stretched.
integer, parameter unitterm
Unit for standard output.
logical, dimension(ndim) periodb
True for dimensions with periodic boundaries.
double precision, dimension(:,:), allocatable dx
spatial steps for all dimensions at all levels
integer nghostcells
Number of ghost cells surrounding a grid.
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
logical slab_uniform
uniform Cartesian geometry or not (stretched Cartesian)
integer r_
Indices for cylindrical coordinates FOR TESTS, negative value when not used:
logical, dimension(2, ndim) poleb
Indicates whether there is a pole at a boundary.
integer, dimension(:), allocatable type_gradient_limiter
Type of slope limiter used for computing gradients or divergences, when typegrad or typediv are set t...
Module with slope/flux limiters.
Definition mod_limiter.t:2
integer, parameter limiter_ppm
Definition mod_limiter.t:25
subroutine dwlimiter2(dwc, ixil, ixcl, idims, typelim, ldw, rdw)
Limit the centered dwC differences within ixC for iw in direction idim. The limiter is chosen accordi...
subroutine, public ppmlimitervar(ixil, ixl, idims, q, qct, qlc, qrc)
Definition mod_ppm.t:12
Module with all the methods that users can customize in AMRVAC.
procedure(set_surface), pointer usr_set_surface