source: CIVL/examples/fortran/nek5000/core/fast3d.f

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100755
File size: 45.4 KB
Line 
1c-----------------------------------------------------------------------
2 subroutine gen_fast(df,sr,ss,st,x,y,z)
3c
4c Generate fast diagonalization matrices for each element
5c
6 include 'SIZE'
7 include 'INPUT'
8 include 'PARALLEL'
9 include 'SOLN'
10 include 'WZ'
11c
12 parameter(lxx=lx1*lx1)
13 real df(lx1*ly1*lz1,1),sr(lxx*2,1),ss(lxx*2,1),st(lxx*2,1)
14c
15 common /ctmpf/ lr(2*lx1+4),ls(2*lx1+4),lt(2*lx1+4)
16 $ , llr(lelt),lls(lelt),llt(lelt)
17 $ , lmr(lelt),lms(lelt),lmt(lelt)
18 $ , lrr(lelt),lrs(lelt),lrt(lelt)
19 real lr ,ls ,lt
20 real llr,lls,llt
21 real lmr,lms,lmt
22 real lrr,lrs,lrt
23c
24 integer lbr,rbr,lbs,rbs,lbt,rbt,e
25c
26 real x(lx1,ly1,lz1,nelv)
27 real y(lx1,ly1,lz1,nelv)
28 real z(lx1,ly1,lz1,nelv)
29 real axwt(lx2)
30
31 ierr = 0
32
33 do e=1,nelv
34c
35 if (param(44).eq.1) then
36 call get_fast_bc(lbr,rbr,lbs,rbs,lbt,rbt,e,2,ierr)
37 else
38 call get_fast_bc(lbr,rbr,lbs,rbs,lbt,rbt,e,3,ierr)
39 endif
40c
41c Set up matrices for each element.
42c
43 if (param(44).eq.1) then
44 call set_up_fast_1D_fem( sr(1,e),lr,nr ,lbr,rbr
45 $ ,llr(e),lmr(e),lrr(e),zgm2(1,1),lx2,e)
46 else
47 call set_up_fast_1D_sem( sr(1,e),lr,nr ,lbr,rbr
48 $ ,llr(e),lmr(e),lrr(e),e)
49 endif
50 if (ifaxis) then
51 xsum = vlsum(wxm2,lx2)
52 do i=1,ly2
53 yavg = vlsc2(y(1,i,1,e),wxm2,lx2)/xsum
54 axwt(i) = yavg
55 enddo
56 call set_up_fast_1D_fem_ax( ss(1,e),ls,ns ,lbs,rbs
57 $ ,lls(e),lms(e),lrs(e),zgm2(1,2),axwt,ly2,e)
58 else
59 if (param(44).eq.1) then
60 call set_up_fast_1D_fem( ss(1,e),ls,ns ,lbs,rbs
61 $ ,lls(e),lms(e),lrs(e),zgm2(1,2),ly2,e)
62 else
63 call set_up_fast_1D_sem( ss(1,e),ls,ns ,lbs,rbs
64 $ ,lls(e),lms(e),lrs(e),e)
65 endif
66 endif
67 if (if3d) then
68 if (param(44).eq.1) then
69 call set_up_fast_1D_fem( st(1,e),lt,nt ,lbt,rbt
70 $ ,llt(e),lmt(e),lrt(e),zgm2(1,3),lz2,e)
71 else
72 call set_up_fast_1D_sem( st(1,e),lt,nt ,lbt,rbt
73 $ ,llt(e),lmt(e),lrt(e),e)
74 endif
75 endif
76c
77c DIAGNOSTICS
78c
79c n12 = min(9,nr)
80c write(6,1) e,'1D lr',llr(e),lmr(e),lrr(e),(lr(k),k=1,n12)
81c write(6,1) e,'1D ls',lls(e),lms(e),lrs(e),(ls(k),k=1,n12)
82c if (if3d)
83c $ write(6,1) e,'1D lt',llt(e),lmt(e),lrt(e),(lt(k),k=1,n12)
84c 1 format(i6,1x,a5,1p12e12.4)
85c
86c
87c Set up diagonal inverse
88c
89 if (if3d) then
90 eps = 1.e-5 * (vlmax(lr(2),nr-2)
91 $ + vlmax(ls(2),ns-2) + vlmax(lt(2),nt-2))
92 l = 1
93 do k=1,nt
94 do j=1,ns
95 do i=1,nr
96 diag = lr(i) + ls(j) + lt(k)
97 if (diag.gt.eps) then
98 df(l,e) = 1.0/diag
99 else
100c write(6,3) e,'Reset Eig in gen fast:',i,j,k,l
101c $ ,eps,diag,lr(i),ls(j),lt(k)
102c 3 format(i6,1x,a21,4i5,1p5e12.4)
103 df(l,e) = 0.0
104 endif
105 l = l+1
106 enddo
107 enddo
108 enddo
109 else
110 eps = 1.e-5*(vlmax(lr(2),nr-2) + vlmax(ls(2),ns-2))
111 l = 1
112 do j=1,ns
113 do i=1,nr
114 diag = lr(i) + ls(j)
115 if (diag.gt.eps) then
116 df(l,e) = 1.0/diag
117 else
118c write(6,2) e,'Reset Eig in gen fast:',i,j,l
119c $ ,eps,diag,lr(i),ls(j)
120c 2 format(i6,1x,a21,3i5,1p4e12.4)
121 df(l,e) = 0.0
122 endif
123 l = l+1
124 enddo
125 enddo
126 endif
127c
128c Next element ....
129c
130 enddo
131
132 ierrmx = iglmax(ierr,1)
133 if (ierrmx.gt.0) then
134 if (ierr.gt.0) write(6,*) nid,ierr,' BC FAIL'
135 call exitti('E INVALID BC FOUND in genfast$',ierrmx)
136 endif
137
138
139 return
140 end
141c-----------------------------------------------------------------------
142 subroutine gen_fast_spacing(x,y,z)
143c
144c Generate fast diagonalization matrices for each element
145c
146 include 'SIZE'
147 include 'INPUT'
148 include 'PARALLEL'
149 include 'SOLN'
150 include 'WZ'
151c
152 parameter(lxx=lx1*lx1)
153c
154 common /ctmpf/ lr(2*lx1+4),ls(2*lx1+4),lt(2*lx1+4)
155 $ , llr(lelt),lls(lelt),llt(lelt)
156 $ , lmr(lelt),lms(lelt),lmt(lelt)
157 $ , lrr(lelt),lrs(lelt),lrt(lelt)
158 real lr ,ls ,lt
159 real llr,lls,llt
160 real lmr,lms,lmt
161 real lrr,lrs,lrt
162c
163 integer lbr,rbr,lbs,rbs,lbt,rbt,e
164c
165 real x(lx1,ly1,lz1,nelv)
166 real y(lx1,ly1,lz1,nelv)
167 real z(lx1,ly1,lz1,nelv)
168 real axwt(lx2)
169
170 ierr = 0
171
172 if (param(44).eq.1) then
173c __ __ __
174c Now, for each element, compute lr,ls,lt between specified planes
175c
176 n1 = lx2
177 n2 = lx2+1
178 nz0 = 1
179 nzn = 1
180 if (if3d) then
181 nz0= 0
182 nzn=n2
183 endif
184 eps = 1.e-7
185 if (wdsize.eq.8) eps = 1.e-14
186c
187c Find mean spacing between "left-most" planes
188 call plane_space2(llr,lls,llt, 0,wxm2,x,y,z,n1,n2,nz0,nzn)
189c
190c Find mean spacing between "middle" planes
191 call plane_space (lmr,lms,lmt, 1,n1,wxm2,x,y,z,n1,n2,nz0,nzn)
192c
193c Find mean spacing between "right-most" planes
194 call plane_space2(lrr,lrs,lrt,n2,wxm2,x,y,z,n1,n2,nz0,nzn)
195c
196 else
197 call load_semhat_weighted ! Fills the SEMHAT arrays
198 endif
199
200 return
201 end
202c-----------------------------------------------------------------------
203 subroutine plane_space_std(lr,ls,lt,i1,i2,w,x,y,z,nx,nxn,nz0,nzn)
204c
205c This routine now replaced by "plane_space()"
206c
207c Here, spacing is based on arithmetic mean.
208c New verision uses harmonic mean. pff 2/10/07
209c
210 include 'SIZE'
211 include 'INPUT'
212c
213 real w(1),lr(1),ls(1),lt(1)
214 real x(0:nxn,0:nxn,nz0:nzn,1)
215 real y(0:nxn,0:nxn,nz0:nzn,1)
216 real z(0:nxn,0:nxn,nz0:nzn,1)
217 real lr2,ls2,lt2
218c __ __ __
219c Now, for each element, compute lr,ls,lt between specified planes
220c
221 ny = nx
222 nz = nx
223 j1 = i1
224 k1 = i1
225 j2 = i2
226 k2 = i2
227c
228 do ie=1,nelv
229c
230 if (if3d) then
231 lr2 = 0.
232 wsum = 0.
233 do k=1,nz
234 do j=1,ny
235 weight = w(j)*w(k)
236 lr2 = lr2 + ( (x(i2,j,k,ie)-x(i1,j,k,ie))**2
237 $ + (y(i2,j,k,ie)-y(i1,j,k,ie))**2
238 $ + (z(i2,j,k,ie)-z(i1,j,k,ie))**2 )
239 $ * weight
240 wsum = wsum + weight
241 enddo
242 enddo
243 lr2 = lr2/wsum
244 lr(ie) = sqrt(lr2)
245c
246 ls2 = 0.
247 wsum = 0.
248 do k=1,nz
249 do i=1,nx
250 weight = w(i)*w(k)
251 ls2 = ls2 + ( (x(i,j2,k,ie)-x(i,j1,k,ie))**2
252 $ + (y(i,j2,k,ie)-y(i,j1,k,ie))**2
253 $ + (z(i,j2,k,ie)-z(i,j1,k,ie))**2 )
254 $ * weight
255 wsum = wsum + weight
256 enddo
257 enddo
258 ls2 = ls2/wsum
259 ls(ie) = sqrt(ls2)
260c
261 lt2 = 0.
262 wsum = 0.
263 do j=1,ny
264 do i=1,nx
265 weight = w(i)*w(j)
266 lt2 = lt2 + ( (x(i,j,k2,ie)-x(i,j,k1,ie))**2
267 $ + (y(i,j,k2,ie)-y(i,j,k1,ie))**2
268 $ + (z(i,j,k2,ie)-z(i,j,k1,ie))**2 )
269 $ * weight
270 wsum = wsum + weight
271 enddo
272 enddo
273 lt2 = lt2/wsum
274 lt(ie) = sqrt(lt2)
275c
276 else
277 lr2 = 0.
278 wsum = 0.
279 do j=1,ny
280 weight = w(j)
281 lr2 = lr2 + ( (x(i2,j,1,ie)-x(i1,j,1,ie))**2
282 $ + (y(i2,j,1,ie)-y(i1,j,1,ie))**2 )
283 $ * weight
284 wsum = wsum + weight
285 enddo
286 lr2 = lr2/wsum
287 lr(ie) = sqrt(lr2)
288c
289 ls2 = 0.
290 wsum = 0.
291 do i=1,nx
292 weight = w(i)
293 ls2 = ls2 + ( (x(i,j2,1,ie)-x(i,j1,1,ie))**2
294 $ + (y(i,j2,1,ie)-y(i,j1,1,ie))**2 )
295 $ * weight
296 wsum = wsum + weight
297 enddo
298 ls2 = ls2/wsum
299 ls(ie) = sqrt(ls2)
300c write(6,*) 'lrls',ie,lr(ie),ls(ie)
301 endif
302 enddo
303 return
304 end
305c-----------------------------------------------------------------------
306 subroutine plane_space(lr,ls,lt,i1,i2,w,x,y,z,nx,nxn,nz0,nzn)
307c
308c Here, spacing is based on harmonic mean. pff 2/10/07
309c
310c
311 include 'SIZE'
312 include 'INPUT'
313c
314 real w(1),lr(1),ls(1),lt(1)
315 real x(0:nxn,0:nxn,nz0:nzn,1)
316 real y(0:nxn,0:nxn,nz0:nzn,1)
317 real z(0:nxn,0:nxn,nz0:nzn,1)
318 real lr2,ls2,lt2
319c __ __ __
320c Now, for each element, compute lr,ls,lt between specified planes
321c
322 ny = nx
323 nz = nx
324 j1 = i1
325 k1 = i1
326 j2 = i2
327 k2 = i2
328c
329 do ie=1,nelv
330c
331 if (if3d) then
332 lr2 = 0.
333 wsum = 0.
334 do k=1,nz
335 do j=1,ny
336 weight = w(j)*w(k)
337c lr2 = lr2 + ( (x(i2,j,k,ie)-x(i1,j,k,ie))**2
338c $ + (y(i2,j,k,ie)-y(i1,j,k,ie))**2
339c $ + (z(i2,j,k,ie)-z(i1,j,k,ie))**2 )
340c $ * weight
341 lr2 = lr2 + weight /
342 $ ( (x(i2,j,k,ie)-x(i1,j,k,ie))**2
343 $ + (y(i2,j,k,ie)-y(i1,j,k,ie))**2
344 $ + (z(i2,j,k,ie)-z(i1,j,k,ie))**2 )
345 wsum = wsum + weight
346 enddo
347 enddo
348 lr2 = lr2/wsum
349 lr(ie) = 1./sqrt(lr2)
350c
351 ls2 = 0.
352 wsum = 0.
353 do k=1,nz
354 do i=1,nx
355 weight = w(i)*w(k)
356c ls2 = ls2 + ( (x(i,j2,k,ie)-x(i,j1,k,ie))**2
357c $ + (y(i,j2,k,ie)-y(i,j1,k,ie))**2
358c $ + (z(i,j2,k,ie)-z(i,j1,k,ie))**2 )
359c $ * weight
360 ls2 = ls2 + weight /
361 $ ( (x(i,j2,k,ie)-x(i,j1,k,ie))**2
362 $ + (y(i,j2,k,ie)-y(i,j1,k,ie))**2
363 $ + (z(i,j2,k,ie)-z(i,j1,k,ie))**2 )
364 wsum = wsum + weight
365 enddo
366 enddo
367 ls2 = ls2/wsum
368 ls(ie) = 1./sqrt(ls2)
369c
370 lt2 = 0.
371 wsum = 0.
372 do j=1,ny
373 do i=1,nx
374 weight = w(i)*w(j)
375c lt2 = lt2 + ( (x(i,j,k2,ie)-x(i,j,k1,ie))**2
376c $ + (y(i,j,k2,ie)-y(i,j,k1,ie))**2
377c $ + (z(i,j,k2,ie)-z(i,j,k1,ie))**2 )
378c $ * weight
379 lt2 = lt2 + weight /
380 $ ( (x(i,j,k2,ie)-x(i,j,k1,ie))**2
381 $ + (y(i,j,k2,ie)-y(i,j,k1,ie))**2
382 $ + (z(i,j,k2,ie)-z(i,j,k1,ie))**2 )
383 wsum = wsum + weight
384 enddo
385 enddo
386 lt2 = lt2/wsum
387 lt(ie) = 1./sqrt(lt2)
388c
389 else ! 2D
390 lr2 = 0.
391 wsum = 0.
392 do j=1,ny
393 weight = w(j)
394c lr2 = lr2 + ( (x(i2,j,1,ie)-x(i1,j,1,ie))**2
395c $ + (y(i2,j,1,ie)-y(i1,j,1,ie))**2 )
396c $ * weight
397 lr2 = lr2 + weight /
398 $ ( (x(i2,j,1,ie)-x(i1,j,1,ie))**2
399 $ + (y(i2,j,1,ie)-y(i1,j,1,ie))**2 )
400 wsum = wsum + weight
401 enddo
402 lr2 = lr2/wsum
403 lr(ie) = 1./sqrt(lr2)
404c
405 ls2 = 0.
406 wsum = 0.
407 do i=1,nx
408 weight = w(i)
409c ls2 = ls2 + ( (x(i,j2,1,ie)-x(i,j1,1,ie))**2
410c $ + (y(i,j2,1,ie)-y(i,j1,1,ie))**2 )
411c $ * weight
412 ls2 = ls2 + weight /
413 $ ( (x(i,j2,1,ie)-x(i,j1,1,ie))**2
414 $ + (y(i,j2,1,ie)-y(i,j1,1,ie))**2 )
415 wsum = wsum + weight
416 enddo
417 ls2 = ls2/wsum
418 ls(ie) = 1./sqrt(ls2)
419c write(6,*) 'lrls',ie,lr(ie),ls(ie)
420 endif
421 enddo
422 return
423 end
424c-----------------------------------------------------------------------
425 subroutine plane_space2(lr,ls,lt,i1,w,x,y,z,nx,nxn,nz0,nzn)
426c
427c Here, the local spacing is already given in the surface term.
428c This addition made to simplify the periodic bdry treatment.
429c
430c
431 include 'SIZE'
432 include 'INPUT'
433c
434 real w(1),lr(1),ls(1),lt(1)
435 real x(0:nxn,0:nxn,nz0:nzn,1)
436 real y(0:nxn,0:nxn,nz0:nzn,1)
437 real z(0:nxn,0:nxn,nz0:nzn,1)
438 real lr2,ls2,lt2
439c __ __ __
440c Now, for each element, compute lr,ls,lt between specified planes
441c
442 ny = nx
443 nz = nx
444 j1 = i1
445 k1 = i1
446c
447 do ie=1,nelv
448c
449 if (if3d) then
450 lr2 = 0.
451 wsum = 0.
452 do k=1,nz
453 do j=1,ny
454 weight = w(j)*w(k)
455 lr2 = lr2 + ( (x(i1,j,k,ie))**2
456 $ + (y(i1,j,k,ie))**2
457 $ + (z(i1,j,k,ie))**2 )
458 $ * weight
459 wsum = wsum + weight
460 enddo
461 enddo
462 lr2 = lr2/wsum
463 lr(ie) = sqrt(lr2)
464c
465 ls2 = 0.
466 wsum = 0.
467 do k=1,nz
468 do i=1,nx
469 weight = w(i)*w(k)
470 ls2 = ls2 + ( (x(i,j1,k,ie))**2
471 $ + (y(i,j1,k,ie))**2
472 $ + (z(i,j1,k,ie))**2 )
473 $ * weight
474 wsum = wsum + weight
475 enddo
476 enddo
477 ls2 = ls2/wsum
478 ls(ie) = sqrt(ls2)
479c
480 lt2 = 0.
481 wsum = 0.
482 do j=1,ny
483 do i=1,nx
484 weight = w(i)*w(j)
485 lt2 = lt2 + ( (x(i,j,k1,ie))**2
486 $ + (y(i,j,k1,ie))**2
487 $ + (z(i,j,k1,ie))**2 )
488 $ * weight
489 wsum = wsum + weight
490 enddo
491 enddo
492 lt2 = lt2/wsum
493 lt(ie) = sqrt(lt2)
494c write(6,1) 'lrlslt',ie,lr(ie),ls(ie),lt(ie)
495 1 format(a6,i5,1p3e12.4)
496c
497 else
498 lr2 = 0.
499 wsum = 0.
500 do j=1,ny
501 weight = w(j)
502 lr2 = lr2 + ( (x(i1,j,1,ie))**2
503 $ + (y(i1,j,1,ie))**2 )
504 $ * weight
505 wsum = wsum + weight
506 enddo
507 lr2 = lr2/wsum
508 lr(ie) = sqrt(lr2)
509c
510 ls2 = 0.
511 wsum = 0.
512 do i=1,nx
513 weight = w(i)
514 ls2 = ls2 + ( (x(i,j1,1,ie))**2
515 $ + (y(i,j1,1,ie))**2 )
516 $ * weight
517 wsum = wsum + weight
518 enddo
519 ls2 = ls2/wsum
520 ls(ie) = sqrt(ls2)
521c write(6,*) 'lrls',ie,lr(ie),ls(ie),lt(ie)
522 endif
523 enddo
524 return
525 end
526c-----------------------------------------------------------------------
527 subroutine set_up_fast_1D_fem(s,lam,n,lbc,rbc,ll,lm,lr,z,nz,e)
528 real s(1),lam(1),ll,lm,lr,z(1)
529 integer lbc,rbc,e
530c
531 parameter (m=100)
532 real dx(0:m)
533 integer icalld
534 save icalld
535 data icalld/0/
536c
537 icalld=icalld+1
538c
539 if (nz.gt.m-3) then
540 write(6,*) 'ABORT. Error in set_up_fast_1D_fem. Increase m to'
541 $ , nz
542 call exitt
543 endif
544c
545c In the present scheme, each element is viewed as a d-fold
546c tensor of (1+nz+1) arrays, even if funky bc's are applied
547c on either end of the 1D array.
548c
549 n = nz+2
550c
551c Compute spacing, dx()
552c
553 call set_up_1D_geom(dx,lbc,rbc,ll,lm,lr,z,nz)
554c
555 nn1 = n*n + 1
556 call gen_eigs_A_fem(s,s(nn1),lam,n,dx,lbc,rbc)
557c
558 return
559 end
560c-----------------------------------------------------------------------
561 subroutine set_up_1D_geom(dx,lbc,rbc,ll,lm,lr,z,nz)
562c
563 real dx(0:1),ll,lm,lr,z(2)
564 integer lbc,rbc
565c
566c
567c Set up the 1D geometry for the tensor-product based overlapping Schwarz
568c
569c Upon return:
570c
571c dx() contains the spacing required to set up the stiffness matrix.
572c
573c
574c Input:
575c
576c lbc (rbc) is 0 if the left (right) BC is Dirichlet, 1 if Neumann.
577c
578c ll is the space between the left-most Gauss point of the middle
579c element and the right-most Gauss point of the LEFT element
580c
581c lm is the space between the left-most Gauss point of the middle
582c element and the right-most Gauss point of the MIDDLE element
583c
584c lr is the space between the right-most Gauss point of the middle
585c element and the left-most Gauss point of the RIGHT element
586c
587c --- if ll (lr) is very small (0), it indicates that there is no
588c left (right) spacing, and that the left (right) BC is Neumann.
589c
590c
591c z() is the array of nz Gauss points on the interval ]-1,1[.
592c
593c Boundary conditions:
594c
595c bc = 0 -- std. Dirichlet bc applied 2 points away from interior
596c bc = 1 -- Dirichlet bc applied 1 point away from interior (outflow)
597c bc = 2 -- Neumann bc applied on interior point (W,v,V,SYM,...)
598c
599c
600c
601c Geometry:
602c
603c
604c dx0 dx1 dx2 dx3 dx5 dx5 dx6
605c
606c bl |<--ll-->|<------lm------>|<---lr--->| br
607c 0--------x-----|--x---x--------x---x--|-------x-----------0
608c
609c left elem. middle elem. right elem.
610c -1 +1
611c
612c
613c "bl" = (extrapolated) location of Gauss point lx2-1 in left elem.
614c
615c "br" = (extrapolated) location of Gauss point 2 in right elem.
616c
617c Overlapping Schwarz applied with homogeneous Dirichlet boundary
618c conditions at "bl" and "br", and with a single d.o.f. extending
619c in to each adjacent domain.
620c
621 eps = 1.e-5
622 call rone(dx,nz+3)
623c
624c Middle
625 scale = lm/(z(nz)-z(1))
626 do i=1,nz-1
627 dx(i+1) = (z(i+1)-z(i))*scale
628 enddo
629
630c Left end
631 if (lbc.eq.0) then
632 dzm0 = z(1) + 1.
633 dxm0 = scale*dzm0
634 dxln = ll - dxm0
635 scalel = dxln/dzm0
636 dx(0) = scalel*(z(2)-z(1))
637 dx(1) = ll
638 elseif (lbc.eq.1) then
639 dx(1) = ll
640 endif
641c
642c Right end
643 if (rbc.eq.0) then
644 dzm0 = z(1) + 1.
645 dxm0 = scale*dzm0
646 dxr0 = lr - dxm0
647 scaler = dxr0/dzm0
648 dx(nz+1) = lr
649 dx(nz+2) = scaler*(z(2)-z(1))
650 elseif (rbc.eq.1) then
651 dx(nz+1) = lr
652 endif
653c
654 return
655 end
656c-----------------------------------------------------------------------
657 subroutine gen_eigs_A_fem(sf,sft,atd,n,l,lbc,rbc)
658c
659c Set up Fast diagonalization solver for FEM on mesh 2
660c
661 real sf(n,n),sft(n,n),atd(1),l(0:1)
662 integer lbc,rbc
663c
664 parameter (m=100)
665 real atu(m),ad(m),au(m),c(m),bh(m),li(0:m)
666c
667 if (n.gt.m) then
668 write(6,*) 'ABORT. Error in gen_eigs_A_fem. Increase m to',n
669 call exitt
670 endif
671c
672c Get delta x's
673c
674 do i=0,n
675 li(i) = 1.0/l(i)
676 enddo
677c ^ ^
678c Fill initial arrays, A & B:
679c
680 call rzero(ad,n)
681 call rzero(au,n-1)
682 call rzero(bh,n)
683c
684 ie1 = lbc
685 ien = n-rbc
686 do ie=ie1,ien
687c
688c il,ir are the left and right endpts of element ie.
689 il = ie
690 ir = ie+1
691c
692 if (ie.gt.0) ad(il) = ad(il) + li(ie)
693 if (ie.lt.n) ad(ir) = ad(ir) + li(ie)
694 if (ie.gt.0) au(il) = - li(ie)
695 if (ie.gt.0) bh(il) = bh(il) + 0.5 * l(ie)
696 if (ie.lt.n) bh(ir) = bh(ir) + 0.5 * l(ie)
697 enddo
698c
699c Take care of bc's (using blasting)
700 bhm = vlmax(bh(2),n-2)/(n-2)
701 ahm = vlmax(ad(2),n-2)/(n-2)
702c
703 if (lbc.gt.0) then
704 au(1) = 0.
705 ad(1) = ahm
706 bh(1) = bhm
707 endif
708c
709 if (rbc.gt.0) then
710 au(n-1) = 0.
711 ad(n ) = ahm
712 bh(n ) = bhm
713 endif
714c
715c
716 do i=1,n
717 c(i) = sqrt(1.0/bh(i))
718 enddo
719c ~
720c Scale rows and columns of A by C: A = CAC
721c
722 do i=1,n
723 atd(i) = c(i)*ad(i)*c(i)
724 enddo
725c
726c Scale upper diagonal
727c
728 atu(1) = 0.
729 do i=1,n-1
730 atu(i) = c(i)*au(i)*c(i+1)
731 enddo
732c ~
733c Compute eigenvalues and eigenvectors of A
734c
735 call calcz(atd,atu,n,dmax,dmin,sf,ierr)
736 if (ierr.eq.1) then
737 nid = mynode()
738 write(6,6) nid,' czfail:',(l(k),k=0,n)
739 6 format(i5,a8,1p16e10.2)
740 call exitt
741 endif
742c
743c Sort eigenvalues and vectors
744c
745 call sort(atd,atu,n)
746 call transpose(sft,n,sf,n)
747 do j=1,n
748 call swap(sft(1,j),atu,n,au)
749 enddo
750 call transpose(sf,n,sft,n)
751c
752c Make "like" eigenvectors of same sign (for ease of diagnostics)
753c
754 do j=1,n
755 avg = vlsum(sf(1,j),n)
756 if (avg.lt.0) call chsign(sf(1,j),n)
757 enddo
758c
759c Clean up zero eigenvalue
760c
761 eps = 1.0e-6*dmax
762 do i=1,n
763c if (atd(i).lt.eps)
764c $ write(6,*) 'Reset Eig in gen_Afem:',i,n,atd(i)
765 if (atd(i).lt.eps) atd(i) = 0.0
766 enddo
767c
768c scale eigenvectors by C:
769c
770 do i=1,n
771 do j=1,n
772 sf(i,j) = sf(i,j)*c(i)
773 enddo
774 enddo
775c ^
776c Orthonormalize eigenvectors w.r.t. B inner-product
777c
778 do j=1,n
779 alpha = vlsc3(bh,sf(1,j),sf(1,j),n)
780 alpha = 1.0/sqrt(alpha)
781 call cmult(sf(1,j),alpha,n)
782 enddo
783c
784c Diagnostics
785c
786c do j=1,n
787c do i=1,n
788c sft(i,j) = vlsc3(bh,sf(1,i),sf(1,j),n)
789c enddo
790c enddo
791c
792c n8 = min(n,8)
793c do i=1,n
794c write(6,2) (sft(i,j),j=1,n8)
795c enddo
796c 2 format('Id:',1p8e12.4)
797c
798 call transpose(sft,n,sf,n)
799 return
800 end
801c-----------------------------------------------------------------------
802 subroutine get_fast_bc(lbr,rbr,lbs,rbs,lbt,rbt,e,bsym,ierr)
803 integer lbr,rbr,lbs,rbs,lbt,rbt,e,bsym
804c
805 include 'SIZE'
806 include 'INPUT'
807 include 'PARALLEL'
808 include 'TOPOL'
809 include 'TSTEP'
810c
811 integer fbc(6)
812c
813c ibc = 0 <==> Dirichlet
814c ibc = 1 <==> Dirichlet, outflow (no extension)
815c ibc = 2 <==> Neumann,
816
817
818 do iface=1,2*ldim
819 ied = eface(iface)
820 ibc = -1
821
822 if (ifmhd) call mhd_bc_dn(ibc,iface,e) ! can be overwritten by 'mvn'
823
824 if (cbc(ied,e,ifield).eq.' ') ibc = 0
825 if (cbc(ied,e,ifield).eq.'E ') ibc = 0
826 if (cbc(ied,e,ifield).eq.'msi') ibc = 0
827 if (cbc(ied,e,ifield).eq.'MSI') ibc = 0
828 if (cbc(ied,e,ifield).eq.'P ') ibc = 0
829 if (cbc(ied,e,ifield).eq.'p ') ibc = 0
830 if (cbc(ied,e,ifield).eq.'O ') ibc = 1
831 if (cbc(ied,e,ifield).eq.'ON ') ibc = 1
832 if (cbc(ied,e,ifield).eq.'o ') ibc = 1
833 if (cbc(ied,e,ifield).eq.'on ') ibc = 1
834 if (cbc(ied,e,ifield).eq.'MS ') ibc = 1
835 if (cbc(ied,e,ifield).eq.'ms ') ibc = 1
836 if (cbc(ied,e,ifield).eq.'MM ') ibc = 1
837 if (cbc(ied,e,ifield).eq.'mm ') ibc = 1
838 if (cbc(ied,e,ifield).eq.'mv ') ibc = 2
839 if (cbc(ied,e,ifield).eq.'mvn') ibc = 2
840 if (cbc(ied,e,ifield).eq.'v ') ibc = 2
841 if (cbc(ied,e,ifield).eq.'V ') ibc = 2
842 if (cbc(ied,e,ifield).eq.'W ') ibc = 2
843 if (cbc(ied,e,ifield).eq.'SYM') ibc = bsym
844 if (cbc(ied,e,ifield).eq.'SL ') ibc = 2
845 if (cbc(ied,e,ifield).eq.'sl ') ibc = 2
846 if (cbc(ied,e,ifield).eq.'SHL') ibc = 2
847 if (cbc(ied,e,ifield).eq.'shl') ibc = 2
848 if (cbc(ied,e,ifield).eq.'A ') ibc = 2
849 if (cbc(ied,e,ifield).eq.'S ') ibc = 2
850 if (cbc(ied,e,ifield).eq.'s ') ibc = 2
851 if (cbc(ied,e,ifield).eq.'J ') ibc = 0
852 if (cbc(ied,e,ifield).eq.'SP ') ibc = 0
853
854 fbc(iface) = ibc
855
856 if (ierr.eq.-1) write(6,1) ibc,ied,e,ifield,cbc(ied,e,ifield)
857 1 format(2i3,i8,i3,2x,a3,' get_fast_bc_error')
858
859 enddo
860
861 if (ierr.eq.-1) call exitti('Error A get_fast_bc$',e)
862
863 lbr = fbc(1)
864 rbr = fbc(2)
865 lbs = fbc(3)
866 rbs = fbc(4)
867 lbt = fbc(5)
868 rbt = fbc(6)
869
870 ierr = 0
871 if (ibc.lt.0) ierr = lglel(e)
872
873c write(6,6) e,lbr,rbr,lbs,rbs,(cbc(k,e,ifield),k=1,4)
874c 6 format(i5,2x,4i3,3x,4(1x,a3),' get_fast_bc')
875
876 return
877 end
878c-----------------------------------------------------------------------
879 subroutine outv(x,n,name3)
880 character*3 name3
881 real x(1)
882c
883 nn = min (n,10)
884 write(6,6) name3,(x(i),i=1,nn)
885 6 format(a3,10f12.6)
886c
887 return
888 end
889c-----------------------------------------------------------------------
890 subroutine outmat(a,m,n,name6,ie)
891 real a(m,n)
892 character*6 name6
893c
894 write(6,*)
895 write(6,*) ie,' matrix: ',name6,m,n
896 n12 = min(n,12)
897 do i=1,m
898 write(6,6) ie,name6,(a(i,j),j=1,n12)
899 enddo
900 6 format(i3,1x,a6,12f9.5)
901 write(6,*)
902 return
903 end
904c-----------------------------------------------------------------------
905 subroutine set_up_fast_1D_fem_ax
906 $ (s,lam,n,lbc,rbc,ll,lm,lr,z,y,nz,ie)
907 real s(1),lam(1),ll,lm,lr,z(1),y(1)
908 integer lbc,rbc
909c
910 parameter (m=100)
911 real dx(0:m)
912 integer icalld
913 save icalld
914 data icalld/0/
915c
916 icalld=icalld+1
917c
918 if (nz.gt.m-3) then
919 write(6,*) 'ABORT. Error in set_up_fast_1D_fem. Increase m to'
920 $ , nz
921 call exitt
922 endif
923c
924c In the present scheme, each element is viewed as a d-fold
925c tensor of (1+nz+1) arrays, even if funky bc's are applied
926c on either end of the 1D array.
927c
928 n = nz+2
929c
930c Compute spacing, dx()
931c
932 call set_up_1D_geom_ax(dx,lbc,rbc,ll,lm,lr,z,y,nz)
933c
934 nn1 = n*n + 1
935 call gen_eigs_A_fem_ax(s,s(nn1),lam,n,dx,y,lbc,rbc)
936c
937 return
938 end
939c-----------------------------------------------------------------------
940 subroutine set_up_1D_geom_ax(dx,lbc,rbc,ll,lm,lr,z,y,nz)
941c
942 real dx(0:1),ll,lm,lr,z(2),y(1)
943 integer lbc,rbc
944c
945c
946c Set up the 1D geometry for the tensor-product based overlapping Schwarz
947c
948c Upon return:
949c
950c dx() contains the spacing required to set up the stiffness matrix.
951c
952c
953c Input:
954c
955c lbc (rbc) is 0 if the left (right) BC is Dirichlet, 1 if Neumann.
956c
957c ll is the space between the left-most Gauss point of the middle
958c element and the right-most Gauss point of the LEFT element
959c
960c lm is the space between the left-most Gauss point of the middle
961c element and the right-most Gauss point of the MIDDLE element
962c
963c lr is the space between the right-most Gauss point of the middle
964c element and the left-most Gauss point of the RIGHT element
965c
966c --- if ll (lr) is very small (0), it indicates that there is no
967c left (right) spacing, and that the left (right) BC is Neumann.
968c
969c
970c z() is the array of nz Gauss points on the interval ]-1,1[.
971c
972c Boundary conditions:
973c
974c bc = 0 -- std. Dirichlet bc applied 2 points away from interior
975c bc = 1 -- Dirichlet bc applied 1 point away from interior (outflow)
976c bc = 2 -- Neumann bc applied on interior point (W,v,V,SYM,...)
977c
978c
979c
980c Geometry:
981c
982c
983c dx0 dx1 dx2 dx3 dx5 dx5 dx6
984c
985c bl |<--ll-->|<------lm------>|<---lr--->| br
986c 0--------x-----|--x---x--------x---x--|-------x-----------0
987c
988c left elem. middle elem. right elem.
989c -1 +1
990c
991c
992c "bl" = (extrapolated) location of Gauss point lx2-1 in left elem.
993c
994c "br" = (extrapolated) location of Gauss point 2 in right elem.
995c
996c Overlapping Schwarz applied with homogeneous Dirichlet boundary
997c conditions at "bl" and "br", and with a single d.o.f. extending
998c in to each adjacent domain.
999c
1000 eps = 1.e-5
1001 call rone(dx,nz+3)
1002c
1003c Middle
1004 scale = lm/(z(nz)-z(1))
1005 do i=1,nz-1
1006 dx(i+1) = (z(i+1)-z(i))*scale
1007 enddo
1008
1009c Left end
1010 if (lbc.eq.0) then
1011 dzm0 = z(1) + 1.
1012 dxm0 = scale*dzm0
1013 dxln = ll - dxm0
1014 scalel = dxln/dzm0
1015 dx(0) = scalel*(z(2)-z(1))
1016 dx(1) = ll
1017 elseif (lbc.eq.1) then
1018 dx(1) = ll
1019 endif
1020c
1021c Right end
1022 if (rbc.eq.0) then
1023 dzm0 = z(1) + 1.
1024 dxm0 = scale*dzm0
1025 dxr0 = lr - dxm0
1026 scaler = dxr0/dzm0
1027 dx(nz+1) = lr
1028 dx(nz+2) = scaler*(z(2)-z(1))
1029 elseif (rbc.eq.1) then
1030 dx(nz+1) = lr
1031 endif
1032c
1033 return
1034 end
1035c-----------------------------------------------------------------------
1036 subroutine gen_eigs_A_fem_ax(sf,sft,atd,n,l,y,lbc,rbc)
1037c
1038c Set up Fast diagonalization solver for FEM on mesh 2
1039c
1040 real sf(n,n),sft(n,n),atd(1),l(0:1),y(1)
1041 integer lbc,rbc
1042c
1043 parameter (m=100)
1044 real atu(m),ad(m),au(m),c(m),bh(m),li(0:m)
1045c
1046 if (n.gt.m) then
1047 write(6,*) 'ABORT. Error in gen_eigs_A_fem. Increase m to',n
1048 call exitt
1049 endif
1050c
1051c Get delta x's
1052c
1053 do i=0,n
1054 li(i) = 1.0/l(i)
1055 enddo
1056c ^ ^
1057c Fill initial arrays, A & B:
1058c
1059 call rzero(ad,n)
1060 call rzero(au,n-1)
1061 call rzero(bh,n)
1062c
1063 ie1 = lbc
1064 ien = n-rbc
1065 do ie=ie1,ien
1066c
1067c il,ir are the left and right endpts of element ie.
1068 il = ie
1069 ir = ie+1
1070c
1071 if (ie.gt.0) ad(il) = ad(il) + li(ie)
1072 if (ie.lt.n) ad(ir) = ad(ir) + li(ie)
1073 if (ie.gt.0) au(il) = - li(ie)
1074 if (ie.gt.0) bh(il) = bh(il) + 0.5 * l(ie)
1075 if (ie.lt.n) bh(ir) = bh(ir) + 0.5 * l(ie)
1076 enddo
1077c
1078c Take care of bc's (using blasting)
1079 bhm = vlmax(bh(2),n-2)/(n-2)
1080 ahm = vlmax(ad(2),n-2)/(n-2)
1081c
1082 if (lbc.gt.0) then
1083 au(1) = 0.
1084 ad(1) = ahm
1085 bh(1) = bhm
1086 endif
1087c
1088 if (rbc.gt.0) then
1089 au(n-1) = 0.
1090 ad(n ) = ahm
1091 bh(n ) = bhm
1092 endif
1093c
1094c
1095 do i=1,n
1096 c(i) = sqrt(1.0/bh(i))
1097 enddo
1098c ~
1099c Scale rows and columns of A by C: A = CAC
1100c
1101 do i=1,n
1102 atd(i) = c(i)*ad(i)*c(i)
1103 enddo
1104c
1105c Scale upper diagonal
1106c
1107 atu(1) = 0.
1108 do i=1,n-1
1109 atu(i) = c(i)*au(i)*c(i+1)
1110 enddo
1111c ~
1112c Compute eigenvalues and eigenvectors of A
1113c
1114 call calcz(atd,atu,n,dmax,dmin,sf,ierr)
1115 if (ierr.eq.1) then
1116 nid = mynode()
1117 write(6,6) nid,' czfail2:',(l(k),k=0,n)
1118 6 format(i5,a8,1p16e10.2)
1119 call exitt
1120 endif
1121c
1122c Sort eigenvalues and vectors
1123c
1124 call sort(atd,atu,n)
1125 call transpose(sft,n,sf,n)
1126 do j=1,n
1127 call swap(sft(1,j),atu,n,au)
1128 enddo
1129 call transpose(sf,n,sft,n)
1130c
1131c Make "like" eigenvectors of same sign (for ease of diagnostics)
1132c
1133 do j=1,n
1134 avg = vlsum(sf(1,j),n)
1135 if (avg.lt.0) call chsign(sf(1,j),n)
1136 enddo
1137c
1138c Clean up zero eigenvalue
1139c
1140 eps = 1.0e-6*dmax
1141 do i=1,n
1142c if (atd(i).lt.eps)
1143c $ write(6,*) 'Reset Eig in gen_Afm_ax:',i,n,atd(i)
1144 if (atd(i).lt.eps) atd(i) = 0.0
1145 enddo
1146c
1147c scale eigenvectors by C:
1148c
1149 do i=1,n
1150 do j=1,n
1151 sf(i,j) = sf(i,j)*c(i)
1152 enddo
1153 enddo
1154c ^
1155c Orthonormalize eigenvectors w.r.t. B inner-product
1156c
1157 do j=1,n
1158 alpha = vlsc3(bh,sf(1,j),sf(1,j),n)
1159 alpha = 1.0/sqrt(alpha)
1160 call cmult(sf(1,j),alpha,n)
1161 enddo
1162c
1163c Diagnostics
1164c
1165c do j=1,n
1166c do i=1,n
1167c sft(i,j) = vlsc3(bh,sf(1,i),sf(1,j),n)
1168c enddo
1169c enddo
1170c
1171c n8 = min(n,8)
1172c do i=1,n
1173c write(6,2) (sft(i,j),j=1,n8)
1174c enddo
1175c 2 format('Id:',1p8e12.4)
1176c
1177 call transpose(sft,n,sf,n)
1178 return
1179 end
1180c-----------------------------------------------------------------------
1181 subroutine load_semhat_weighted ! Fills the SEMHAT arrays
1182c
1183c Note that this routine performs the following matrix multiplies
1184c after getting the matrices back from semhat:
1185c
1186c dgl = bgl dgl
1187c jgl = bgl jgl
1188c
1189 include 'SIZE'
1190 include 'SEMHAT'
1191c
1192 nr = lx1-1
1193 call semhat(ah,bh,ch,dh,zh,dph,jph,bgl,zglhat,dgl,jgl,nr,wh)
1194 call do_semhat_weight(jgl,dgl,bgl,nr)
1195c
1196 return
1197 end
1198c----------------------------------------------------------------------
1199 subroutine do_semhat_weight(jgl,dgl,bgl,n)
1200 real bgl(1:n-1),jgl(1:n-1,0:n),dgl(1:n-1,0:n)
1201
1202 do j=0,n
1203 do i=1,n-1
1204 jgl(i,j)=bgl(i)*jgl(i,j)
1205 enddo
1206 enddo
1207 do j=0,n
1208 do i=1,n-1
1209 dgl(i,j)=bgl(i)*dgl(i,j)
1210 enddo
1211 enddo
1212 return
1213 end
1214c-----------------------------------------------------------------------
1215 subroutine semhat(a,b,c,d,z,dgll,jgll,bgl,zgl,dgl,jgl,n,w)
1216c
1217c Generate matrices for single element, 1D operators:
1218c
1219c a = Laplacian
1220c b = diagonal mass matrix
1221c c = convection operator b*d
1222c d = derivative matrix
1223c dgll = derivative matrix, mapping from pressure nodes to velocity
1224c jgll = interpolation matrix, mapping from pressure nodes to velocity
1225c z = GLL points
1226c
1227c zgl = GL points
1228c bgl = diagonal mass matrix on GL
1229c dgl = derivative matrix, mapping from velocity nodes to pressure
1230c jgl = interpolation matrix, mapping from velocity nodes to pressure
1231c
1232c n = polynomial degree (velocity space)
1233c w = work array of size 2*n+2
1234c
1235c Currently, this is set up for pressure nodes on the interior GLL pts.
1236c
1237c
1238 real a(0:n,0:n),b(0:n),c(0:n,0:n),d(0:n,0:n),z(0:n)
1239 real dgll(0:n,1:n-1),jgll(0:n,1:n-1)
1240c
1241 real bgl(1:n-1),zgl(1:n-1)
1242 real dgl(1:n-1,0:n),jgl(1:n-1,0:n)
1243c
1244 real w(0:2*n+1)
1245c
1246 np = n+1
1247 nm = n-1
1248 n2 = n-2
1249c
1250 call zwgll (z,b,np)
1251c
1252 do i=0,n
1253 call fd_weights_full(z(i),z,n,1,w)
1254 do j=0,n
1255 d(i,j) = w(j+np) ! Derivative matrix
1256 enddo
1257 enddo
1258
1259 if (n.eq.1) return ! No interpolation for n=1
1260
1261 do i=0,n
1262 call fd_weights_full(z(i),z(1),n2,1,w(1))
1263 do j=1,nm
1264 jgll(i,j) = w(j ) ! Interpolation matrix
1265 dgll(i,j) = w(j+nm) ! Derivative matrix
1266 enddo
1267 enddo
1268c
1269 call rzero(a,np*np)
1270 do j=0,n
1271 do i=0,n
1272 do k=0,n
1273 a(i,j) = a(i,j) + d(k,i)*b(k)*d(k,j)
1274 enddo
1275 c(i,j) = b(i)*d(i,j)
1276 enddo
1277 enddo
1278c
1279 call zwgl (zgl,bgl,nm)
1280c
1281 do i=1,n-1
1282 call fd_weights_full(zgl(i),z,n,1,w)
1283 do j=0,n
1284 jgl(i,j) = w(j ) ! Interpolation matrix
1285 dgl(i,j) = w(j+np) ! Derivative matrix
1286 enddo
1287 enddo
1288c
1289 return
1290 end
1291c-----------------------------------------------------------------------
1292 subroutine fd_weights_full(xx,x,n,m,c)
1293c
1294c This routine evaluates the derivative based on all points
1295c in the stencils. It is more memory efficient than "fd_weights"
1296c
1297c This set of routines comes from the appendix of
1298c A Practical Guide to Pseudospectral Methods, B. Fornberg
1299c Cambridge Univ. Press, 1996. (pff)
1300c
1301c Input parameters:
1302c xx -- point at wich the approximations are to be accurate
1303c x -- array of x-ordinates: x(0:n)
1304c n -- polynomial degree of interpolant (# of points := n+1)
1305c m -- highest order of derivative to be approxxmated at xi
1306c
1307c Output:
1308c c -- set of coefficients c(0:n,0:m).
1309c c(j,k) is to be applied at x(j) when
1310c the kth derivative is approxxmated by a
1311c stencil extending over x(0),x(1),...x(n).
1312c
1313c
1314 real x(0:n),c(0:n,0:m)
1315c
1316 c1 = 1.
1317 c4 = x(0) - xx
1318c
1319 do k=0,m
1320 do j=0,n
1321 c(j,k) = 0.
1322 enddo
1323 enddo
1324 c(0,0) = 1.
1325c
1326 do i=1,n
1327 mn = min(i,m)
1328 c2 = 1.
1329 c5 = c4
1330 c4 = x(i)-xx
1331 do j=0,i-1
1332 c3 = x(i)-x(j)
1333 c2 = c2*c3
1334 do k=mn,1,-1
1335 c(i,k) = c1*(k*c(i-1,k-1)-c5*c(i-1,k))/c2
1336 enddo
1337 c(i,0) = -c1*c5*c(i-1,0)/c2
1338 do k=mn,1,-1
1339 c(j,k) = (c4*c(j,k)-k*c(j,k-1))/c3
1340 enddo
1341 c(j,0) = c4*c(j,0)/c3
1342 enddo
1343 c1 = c2
1344 enddo
1345c call outmat(c,n+1,m+1,'fdw',n)
1346 return
1347 end
1348c-----------------------------------------------------------------------
1349 subroutine set_up_fast_1D_sem(s,lam,n,lbc,rbc,ll,lm,lr,ie)
1350 include 'SIZE'
1351 include 'SEMHAT'
1352c
1353 common /fast1dsem/ g(lr2),w(lr2)
1354c
1355 real g,w
1356 real s(1),lam(1),ll,lm,lr
1357 integer lbc,rbc
1358
1359 integer bb0,bb1,eb0,eb1,n,n1
1360 logical l,r
1361
1362 n=lx1-1
1363 !bcs on E are from normal vel component
1364 if(lbc.eq.2 .or. lbc.eq.3) then !wall,sym - dirichlet velocity
1365 eb0=1
1366 else !outflow,element - neumann velocity
1367 eb0=0
1368 endif
1369 if(rbc.eq.2 .or. rbc.eq.3) then !wall,sym - dirichlet velocity
1370 eb1=n-1
1371 else !outflow,element - neumann velocity
1372 eb1=n
1373 endif
1374 !bcs on B are from tangent vel component
1375 if(lbc.eq.2) then !wall - dirichlet velocity
1376 bb0=1
1377 else !outflow,element,sym - neumann velocity
1378 bb0=0
1379 endif
1380 if(rbc.eq.2) then !wall - dirichlet velocity
1381 bb1=n-1
1382 else !outflow,element,sym - neumann velocity
1383 bb1=n
1384 endif
1385c
1386 l = (lbc.eq.0)
1387 r = (rbc.eq.0)
1388c
1389c calculate E tilde operator
1390 call set_up_fast_1D_sem_op(s,eb0,eb1,l,r,ll,lm,lr,bh,dgl,0)
1391c call outmat(s,n+1,n+1,' Et ',ie)
1392c calculate B tilde operator
1393 call set_up_fast_1D_sem_op(g,bb0,bb1,l,r,ll,lm,lr,bh,jgl,1)
1394c call outmat(g,n+1,n+1,' Bt ',ie)
1395
1396 n=n+1
1397 call generalev(s,g,lam,n,w)
1398 if(.not.l) call row_zero(s,n,n,1)
1399 if(.not.r) call row_zero(s,n,n,n)
1400 call transpose(s(n*n+1),n,s,n) ! compute the transpose of s
1401
1402c call outmat (s,n,n,' S ',ie)
1403c call outmat (s(n*n+1),n,n,' St ',1)
1404c call exitt
1405 return
1406 end
1407c-----------------------------------------------------------------------
1408 subroutine set_up_fast_1D_sem_op(g,b0,b1,l,r,ll,lm,lr,bh,jgl,jscl)
1409c -1 T
1410c G = J B J
1411c
1412c gives the inexact restriction of this matrix to
1413c an element plus one node on either side
1414c
1415c g - the output matrix
1416c b0, b1 - the range for Bhat indices for the element
1417c (enforces boundary conditions)
1418c l, r - whether there is a left or right neighbor
1419c ll,lm,lr - lengths of left, middle, and right elements
1420c bh - hat matrix for B
1421c jgl - hat matrix for J (should map vel to pressure)
1422c jscl - how J scales
1423c 0: J = Jh
1424c 1: J = (L/2) Jh
1425c
1426c result is inexact because:
1427c neighbor's boundary condition at far end unknown
1428c length of neighbor's neighbor unknown
1429c (these contribs should be small for large N and
1430c elements of nearly equal size)
1431c
1432 include 'SIZE'
1433 real g(0:lx1-1,0:lx1-1)
1434 real bh(0:lx1-1),jgl(1:lx2,0:lx1-1)
1435 real ll,lm,lr
1436 integer b0,b1
1437 logical l,r
1438 integer jscl
1439c
1440 real bl(0:lx1-1),bm(0:lx1-1),br(0:lx1-1)
1441 real gl,gm,gr,gll,glm,gmm,gmr,grr
1442 real fac
1443 integer n
1444 n=lx1-1
1445c
1446c
1447c compute the scale factors for J
1448 if (jscl.eq.0) then
1449 gl=1.
1450 gm=1.
1451 gr=1.
1452 elseif (jscl.eq.1) then
1453 gl=0.5*ll
1454 gm=0.5*lm
1455 gr=0.5*lr
1456 endif
1457 gll = gl*gl
1458 glm = gl*gm
1459 gmm = gm*gm
1460 gmr = gm*gr
1461 grr = gr*gr
1462c
1463c compute the summed inverse mass matrices for
1464c the middle, left, and right elements
1465 do i=1,n-1
1466 bm(i)=2. /(lm*bh(i))
1467 enddo
1468 if (b0.eq.0) then
1469 bm(0)=0.5*lm*bh(0)
1470 if(l) bm(0)=bm(0)+0.5*ll*bh(n)
1471 bm(0)=1. /bm(0)
1472 endif
1473 if (b1.eq.n) then
1474 bm(n)=0.5*lm*bh(n)
1475 if(r) bm(n)=bm(n)+0.5*lr*bh(0)
1476 bm(n)=1. /bm(n)
1477 endif
1478c note that in computing bl for the left element,
1479c bl(0) is missing the contribution from its left neighbor
1480 if (l) then
1481 do i=0,n-1
1482 bl(i)=2. /(ll*bh(i))
1483 enddo
1484 bl(n)=bm(0)
1485 endif
1486c note that in computing br for the right element,
1487c br(n) is missing the contribution from its right neighbor
1488 if (r) then
1489 do i=1,n
1490 br(i)=2. /(lr*bh(i))
1491 enddo
1492 br(0)=bm(n)
1493 endif
1494c
1495 call rzero(g,(n+1)*(n+1))
1496 do j=1,n-1
1497 do i=1,n-1
1498 do k=b0,b1
1499 g(i,j) = g(i,j) + gmm*jgl(i,k)*bm(k)*jgl(j,k)
1500 enddo
1501 enddo
1502 enddo
1503c
1504 if (l) then
1505 do i=1,n-1
1506 g(i,0) = glm*jgl(i,0)*bm(0)*jgl(n-1,n)
1507 g(0,i) = g(i,0)
1508 enddo
1509c the following is inexact
1510c the neighbors bc's are ignored, and the contribution
1511c from the neighbor's neighbor is left out
1512c that is, bl(0) could be off as noted above
1513c or maybe i should go from 1 to n
1514 do i=0,n
1515 g(0,0) = g(0,0) + gll*jgl(n-1,i)*bl(i)*jgl(n-1,i)
1516 enddo
1517 else
1518 g(0,0)=1.
1519 endif
1520c
1521 if (r) then
1522 do i=1,n-1
1523 g(i,n) = gmr*jgl(i,n)*bm(n)*jgl(1,0)
1524 g(n,i) = g(i,n)
1525 enddo
1526c the following is inexact
1527c the neighbors bc's are ignored, and the contribution
1528c from the neighbor's neighbor is left out
1529c that is, br(n) could be off as noted above
1530c or maybe i should go from 0 to n-1
1531 do i=0,n
1532 g(n,n) = g(n,n) + grr*jgl(1,i)*br(i)*jgl(1,i)
1533 enddo
1534 else
1535 g(n,n)=1.
1536 endif
1537 return
1538 end
1539c-----------------------------------------------------------------------
1540 subroutine swap_lengths
1541
1542 include 'SIZE'
1543 include 'INPUT'
1544 include 'GEOM'
1545 include 'WZ'
1546 common /swaplengths/ l(lx1,ly1,lz1,lelv)
1547 common /ctmpf/ lr(2*lx1+4),ls(2*lx1+4),lt(2*lx1+4)
1548 $ , llr(lelt),lls(lelt),llt(lelt)
1549 $ , lmr(lelt),lms(lelt),lmt(lelt)
1550 $ , lrr(lelt),lrs(lelt),lrt(lelt)
1551 real lr ,ls ,lt
1552 real llr,lls,llt
1553 real lmr,lms,lmt
1554 real lrr,lrs,lrt
1555
1556 real l,l2d
1557 integer e
1558
1559 n2 = lx1-1
1560 nz0 = 1
1561 nzn = 1
1562 nx = lx1-2
1563 if (if3d) then
1564 nz0 = 0
1565 nzn = n2
1566 endif
1567 call plane_space(lmr,lms,lmt,0,n2,wxm1,xm1,ym1,zm1,nx,n2,nz0,nzn)
1568
1569 n=n2+1
1570 if (if3d) then
1571 do e=1,nelv
1572 do j=2,n2
1573 do k=2,n2
1574 l(1,k,j,e) = lmr(e)
1575 l(n,k,j,e) = lmr(e)
1576 l(k,1,j,e) = lms(e)
1577 l(k,n,j,e) = lms(e)
1578 l(k,j,1,e) = lmt(e)
1579 l(k,j,n,e) = lmt(e)
1580 enddo
1581 enddo
1582 enddo
1583 call dssum(l,n,n,n)
1584 do e=1,nelv
1585 llr(e) = l(1,2,2,e)-lmr(e)
1586 lrr(e) = l(n,2,2,e)-lmr(e)
1587 lls(e) = l(2,1,2,e)-lms(e)
1588 lrs(e) = l(2,n,2,e)-lms(e)
1589 llt(e) = l(2,2,1,e)-lmt(e)
1590 lrt(e) = l(2,2,n,e)-lmt(e)
1591 enddo
1592 else
1593 do e=1,nelv
1594 do j=2,n2
1595 l(1,j,1,e) = lmr(e)
1596 l(n,j,1,e) = lmr(e)
1597 l(j,1,1,e) = lms(e)
1598 l(j,n,1,e) = lms(e)
1599c call outmat(l(1,1,1,e),n,n,' L ',e)
1600 enddo
1601 enddo
1602c call outmat(l(1,1,1,25),n,n,' L ',25)
1603 call dssum(l,n,n,1)
1604c call outmat(l(1,1,1,25),n,n,' L ',25)
1605 do e=1,nelv
1606c call outmat(l(1,1,1,e),n,n,' L ',e)
1607 llr(e) = l(1,2,1,e)-lmr(e)
1608 lrr(e) = l(n,2,1,e)-lmr(e)
1609 lls(e) = l(2,1,1,e)-lms(e)
1610 lrs(e) = l(2,n,1,e)-lms(e)
1611 enddo
1612 endif
1613 return
1614 end
1615c----------------------------------------------------------------------
1616 subroutine row_zero(a,m,n,e)
1617 integer m,n,e
1618 real a(m,n)
1619 do j=1,n
1620 a(e,j)=0.
1621 enddo
1622 return
1623 end
1624c-----------------------------------------------------------------------
1625 subroutine mhd_bc_dn(ibc,face,e)
1626 integer face,e
1627c
1628c sets Neumann BC on pressure (ibc=2) for face and e(lement) except
1629c when ifield normal component has (homogeneous) Neumann
1630c boundary condition setting ibc=1 (i.e. Direchlet BC on pressure)
1631c
1632c Note: 'SYM' on a plane with r,s,t-normal is 'dnn','ndn','nnd'? bsym?
1633c
1634 include 'SIZE'
1635 include 'TOPOL'
1636 include 'INPUT'
1637 include 'TSTEP'
1638
1639 ied = eface(face) ! symmetric -> preprocessor notation
1640 nfc = face+1
1641 nfc = nfc/2 ! = 1,2,3 for face 1 & 2,3 & 4,5 & 6
1642
1643 if (indx1(cbc(ied,e,ifield),'d',1).gt.0) ibc=2
1644
1645 if (indx1(cbc(ied,e,ifield),'n',1).gt.nfc) ibc=1 ! 'n' for V_n
1646
1647 return
1648 end
1649c-----------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.