source: CIVL/examples/fortran/nek5000/core/navier8.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: 59.1 KB
Line 
1c-----------------------------------------------------------------------
2c
3 subroutine set_vert(glo_num,ngv,nx,nel,vertex,ifcenter)
4c
5c Given global array, vertex, pointing to hex vertices, set up
6c a new array of global pointers for an nx^ldim set of elements.
7c
8 include 'SIZE'
9 include 'INPUT'
10c
11 integer*8 glo_num(1),ngv
12 integer vertex(1),nx
13 logical ifcenter
14
15 if (if3d) then
16 call setvert3d(glo_num,ngv,nx,nel,vertex,ifcenter)
17 else
18 call setvert2d(glo_num,ngv,nx,nel,vertex,ifcenter)
19 endif
20
21c Check for single-element periodicity 'p' bc
22 nz = 1
23 if (if3d) nz = nx
24 call check_p_bc(glo_num,nx,nx,nz,nel)
25
26 if(nio.eq.0 .and. loglevel.gt.2)
27 $ write(6,*) 'call usrsetvert'
28 call usrsetvert(glo_num,nel,nx,nx,nz)
29 if(nio.eq.0 .and. loglevel.gt.2)
30 $ write(6,'(A,/)') ' done :: usrsetvert'
31
32 return
33 end
34c
35c-----------------------------------------------------------------------
36c
37 subroutine crs_solve_l2(uf,vf)
38c
39c Given an input vector v, this generates the H1 coarse-grid solution
40c
41 include 'SIZE'
42 include 'DOMAIN'
43 include 'ESOLV'
44 include 'GEOM'
45 include 'PARALLEL'
46 include 'SOLN'
47 include 'INPUT'
48 include 'TSTEP'
49 real uf(1),vf(1)
50 common /scrpre/ uc(lcr*lelt),w(2*lx1*ly1*lz1)
51
52 call map_f_to_c_l2_bilin(uf,vf,w)
53 call fgslib_crs_solve(xxth(ifield),uc,uf)
54 call map_c_to_f_l2_bilin(uf,uc,w)
55
56 return
57 end
58c
59c-----------------------------------------------------------------------
60c subroutine test_h1_crs
61c include 'SIZE'
62c include 'DOMAIN'
63c common /scrxxt/ x(lcr*lelv),b(lcr*lelv)
64c common /nekmpi/ mid,mp,nekcomm,nekgroup,nekreal
65c real x,b
66c ntot=nelv*nxyz_c
67c do i=1,12
68c call rzero(b,ntot)
69c if(mp.eq.1) then
70c b(i)=1
71c else if(mid.eq.0) then
72c if(i.gt.8) b(i-8)=1
73c else
74c if(i.le.8) b(i)=1
75c endif
76c call hsmg_coarse_solve(x,b)
77c print *, 'Column ',i,':',(x(j),j=1,ntot)
78c enddo
79c return
80c end
81c-----------------------------------------------------------------------
82c
83 subroutine set_up_h1_crs
84
85 include 'SIZE'
86 include 'GEOM'
87 include 'DOMAIN'
88 include 'INPUT'
89 include 'PARALLEL'
90 include 'TSTEP'
91 common /nekmpi/ mid,mp,nekcomm,nekgroup,nekreal
92
93 common /ivrtx/ vertex ((2**ldim)*lelt)
94 integer vertex
95
96 integer gs_handle
97 integer null_space,e
98
99 character*3 cb
100 common /scrxxt/ cmlt(lcr,lelv),mask(lcr,lelv)
101 common /scrxxti/ ia(lcr,lcr,lelv), ja(lcr,lcr,lelv)
102 real mask
103 integer ia,ja
104 real z
105
106 integer key(2),aa(2)
107 common /scrch/ iwork(2,lx1*ly1*lz1*lelv)
108 common /scrns/ w(7*lx1*ly1*lz1*lelv)
109 common /vptsol/ a(27*lx1*ly1*lz1*lelv)
110 integer w
111 real wr(1)
112 equivalence (wr,w)
113
114 common /scrvhx/ h1(lx1*ly1*lz1*lelv),h2(lx1*ly1*lz1*lelv)
115 common /scrmgx/ w1(lx1*ly1*lz1*lelv),w2(lx1*ly1*lz1*lelv)
116
117 integer*8 ngv
118 character*132 amgfile_c
119 character*1 fname1(132)
120 equivalence (fname1,amgfile_c)
121 integer nnamg
122
123 t0 = dnekclock()
124
125c nxc is order of coarse grid space + 1, nxc=2, linear, 3=quad,etc.
126c nxc=param(82)
127c if (nxc.gt.lxc) then
128c nxc=lxc
129c write(6,*) 'WARNING :: coarse grid space too large',nxc,lxc
130c endif
131c if (nxc.lt.2) nxc=2
132
133 nxc = 2
134 nx_crs = nxc
135
136 if(nio.eq.0) write(6,*) 'setup h1 coarse grid, nx_crs=', nx_crs
137
138 ncr = nxc**ldim
139 nxyz_c = ncr
140c
141c Set SEM_to_GLOB
142c
143 call get_vertex
144 call set_vert(se_to_gcrs,ngv,nxc,nelv,vertex,.true.)
145
146c Set mask
147 z=0
148 ntot=nelv*nxyz_c
149 nzc=1
150 if (if3d) nzc=nxc
151 call rone(mask,ntot)
152 call rone(cmlt,ntot)
153 nfaces=2*ldim
154c ifield=1 !c? avo: set in set_overlap through 'TSTEP'?
155
156 if (ifield.eq.1) then
157 do ie=1,nelv
158 do iface=1,nfaces
159 cb=cbc(iface,ie,ifield)
160 if (cb.eq.'o ' .or. cb.eq.'on ' .or.
161 $ cb.eq.'O ' .or. cb.eq.'ON ' .or. cb.eq.'MM ' .or.
162 $ cb.eq.'mm ' .or. cb.eq.'ms ' .or. cb.eq.'MS ')
163 $ call facev(mask,ie,iface,z,nxc,nxc,nzc) ! 'S* ' & 's* ' ?avo?
164 enddo
165 enddo
166 elseif (ifield.eq.ifldmhd) then ! no ifmhd ?avo?
167 do ie=1,nelv
168 do iface=1,nfaces
169 cb=cbc(iface,ie,ifield)
170 if (cb.eq.'ndd' .or. cb.eq.'dnd' .or. cb.eq.'ddn')
171 $ call facev(mask,ie,iface,z,nxc,nxc,nzc)
172 enddo
173 enddo
174 endif
175
176c Set global index of dirichlet nodes to zero; xxt will ignore them
177
178 call fgslib_gs_setup(gs_handle,se_to_gcrs,ntot,nekcomm,mp)
179 call fgslib_gs_op (gs_handle,mask,1,2,0) ! "*"
180 call fgslib_gs_op (gs_handle,cmlt,1,1,0) ! "+"
181 call fgslib_gs_free (gs_handle)
182 call set_jl_crs_mask(ntot,mask,se_to_gcrs)
183
184 call invcol1(cmlt,ntot)
185
186c Setup local SEM-based Neumann operators (for now, just full...)
187
188c if (param(51).eq.1) then ! old coarse grid
189c nxyz1=lx1*ly1*lz1
190c lda = 27*nxyz1*lelt
191c ldw = 7*nxyz1*lelt
192c call get_local_crs(a,lda,nxc,h1,h2,w,ldw)
193c else
194c NOTE: a(),h1,...,w2() must all be large enough
195 n = lx1*ly1*lz1*nelv
196 call rone (h1,n)
197 call rzero(h2,n)
198 call get_local_crs_galerkin(a,ncr,nxc,h1,h2,w1,w2)
199c endif
200
201 call set_mat_ij(ia,ja,ncr,nelv)
202 null_space=0
203 if (ifield.eq.1) then
204 if (ifvcor) null_space=1
205 elseif (ifield.eq.ifldmhd) then
206 if (ifbcor) null_space=1
207 endif
208
209 nz=ncr*ncr*nelv
210 isolver = param(40)
211
212 call blank(fname1,132)
213 lamgn = ltrunc(amgfile,len(amgfile))
214 call chcopy(fname1,amgfile,lamgn)
215 call chcopy(fname1(lamgn+1),char(0),1)
216
217 ierr = 0
218 call fgslib_crs_setup(xxth(ifield),isolver,nekcomm,mp,ntot,
219 $ se_to_gcrs,nz,ia,ja,a, null_space, crs_param,
220 $ amgfile_c,ierr)
221 ierr = iglmax(ierr,1)
222 if (ifneknek) ierr = iglmax_ms(ierr,1)
223 if (ierr.eq.1) then
224 call exitt
225 endif
226
227 t0 = dnekclock()-t0
228 if (nio.eq.0) then
229 write(6,*) 'done :: setup h1 coarse grid ',t0, ' sec'
230 write(6,*) ' '
231 endif
232
233 return
234 end
235c
236c-----------------------------------------------------------------------
237 subroutine set_jl_crs_mask(n, mask, se_to_gcrs)
238 real mask(1)
239 integer*8 se_to_gcrs(1)
240 do i=1,n
241 if(mask(i).lt.0.1) se_to_gcrs(i)=0
242 enddo
243 return
244 end
245c-----------------------------------------------------------------------
246 subroutine set_mat_ij(ia,ja,n,ne)
247 integer n,ne
248 integer ia(n,n,ne), ja(n,n,ne)
249c
250 integer i,j,ie
251 do ie=1,ne
252 do j=1,n
253 do i=1,n
254 ia(i,j,ie)=(ie-1)*n+i-1
255 ja(i,j,ie)=(ie-1)*n+j-1
256 enddo
257 enddo
258 enddo
259 return
260 end
261c-----------------------------------------------------------------------
262 subroutine irank_vec(ind,nn,a,m,n,key,nkey,aa)
263c
264c Compute rank of each unique entry a(1,i)
265c
266c Output: ind(i) i=1,...,n (global) rank of entry a(*,i)
267c nn = max(rank)
268c a(j,i) is destroyed
269c
270c Input: a(j,i) j=1,...,m; i=1,...,n
271c m : leading dim. of v (ldv must be .ge. m)
272c key : sort key
273c nkey :
274c
275c Although not mandatory, this ranking procedure is probably
276c most effectively employed when the keys are pre-sorted. Thus,
277c the option is provided to sort vi() prior to the ranking.
278c
279c
280 integer ind(n),a(m,n)
281 integer key(nkey),aa(m)
282 logical iftuple_ianeb,a_ne_b
283c
284 if (m.eq.1) then
285c
286 write(6,*)
287 $ 'WARNING: For single key, not clear that rank is unique!'
288 call irank(a,ind,n)
289 return
290 endif
291c
292c
293 nk = min(nkey,m)
294 call ituple_sort(a,m,n,key,nk,ind,aa)
295c
296c Find unique a's
297c
298 nn=1
299c
300 call icopy(aa,a,m)
301 a(1,1) = nn
302 a(2,1)=ind(1)
303c
304 do i=2,n
305 a_ne_b = iftuple_ianeb(aa,a(1,i),key,nk)
306 if (a_ne_b) then
307 call icopy(aa,a(1,i),m)
308 nn = nn+1
309 endif
310 a(1,i) = nn
311 a(2,i) = ind(i)
312 enddo
313c
314c Set ind() to rank
315c
316 do i=1,n
317 iold=a(2,i)
318 ind(iold) = a(1,i)
319 enddo
320c
321 return
322 end
323c
324c-----------------------------------------------------------------------
325c
326 subroutine ituple_sort(a,lda,n,key,nkey,ind,aa)
327C
328C Use Heap Sort (p 231 Num. Rec., 1st Ed.)
329C
330 integer a(lda,n),aa(lda)
331 integer ind(1),key(nkey)
332 logical iftuple_ialtb
333C
334 dO 10 j=1,n
335 ind(j)=j
336 10 continue
337C
338 if (n.le.1) return
339 L=n/2+1
340 ir=n
341 100 continue
342 if (l.gt.1) then
343 l=l-1
344c aa = a (l)
345 call icopy(aa,a(1,l),lda)
346 ii = ind(l)
347 else
348c aa = a(ir)
349 call icopy(aa,a(1,ir),lda)
350 ii = ind(ir)
351c a(ir) = a( 1)
352 call icopy(a(1,ir),a(1,1),lda)
353 ind(ir) = ind( 1)
354 ir=ir-1
355 if (ir.eq.1) then
356c a(1) = aa
357 call icopy(a(1,1),aa,lda)
358 ind(1) = ii
359 return
360 endif
361 endif
362 i=l
363 j=l+l
364 200 continue
365 if (j.le.ir) then
366 if (j.lt.ir) then
367 if (iftuple_ialtb(a(1,j),a(1,j+1),key,nkey)) j=j+1
368 endif
369 if (iftuple_ialtb(aa,a(1,j),key,nkey)) then
370c a(i) = a(j)
371 call icopy(a(1,i),a(1,j),lda)
372 ind(i) = ind(j)
373 i=j
374 j=j+j
375 else
376 j=ir+1
377 endif
378 GOTO 200
379 endif
380c a(i) = aa
381 call icopy(a(1,i),aa,lda)
382 ind(i) = ii
383 GOTO 100
384 end
385c
386c-----------------------------------------------------------------------
387c
388 subroutine tuple_sort(a,lda,n,key,nkey,ind,aa)
389C
390C Use Heap Sort (p 231 Num. Rec., 1st Ed.)
391C
392 real a(lda,n),aa(lda)
393 integer ind(1),key(nkey)
394 logical iftuple_altb
395C
396 dO 10 j=1,n
397 ind(j)=j
398 10 continue
399C
400 if (n.le.1) return
401 L=n/2+1
402 ir=n
403 100 continue
404 if (l.gt.1) then
405 l=l-1
406c aa = a (l)
407 call copy(aa,a(1,l),lda)
408 ii = ind(l)
409 else
410c aa = a(ir)
411 call copy(aa,a(1,ir),lda)
412 ii = ind(ir)
413c a(ir) = a( 1)
414 call copy(a(1,ir),a(1,1),lda)
415 ind(ir) = ind( 1)
416 ir=ir-1
417 if (ir.eq.1) then
418c a(1) = aa
419 call copy(a(1,1),aa,lda)
420 ind(1) = ii
421 return
422 endif
423 endif
424 i=l
425 j=l+l
426 200 continue
427 if (j.le.ir) then
428 if (j.lt.ir) then
429c if ( a(j).lt.a(j+1) ) j=j+1
430 if (iftuple_altb(a(1,j),a(1,j+1),key,nkey)) j=j+1
431 endif
432c if (aa.lt.a(j)) then
433 if (iftuple_altb(aa,a(1,j),key,nkey)) then
434c a(i) = a(j)
435 call copy(a(1,i),a(1,j),lda)
436 ind(i) = ind(j)
437 i=j
438 j=j+j
439 else
440 j=ir+1
441 endif
442 GOTO 200
443 endif
444c a(i) = aa
445 call copy(a(1,i),aa,lda)
446 ind(i) = ii
447 GOTO 100
448 end
449c
450c-----------------------------------------------------------------------
451c
452 logical function iftuple_ialtb(a,b,key,nkey)
453 integer a(1),b(1)
454 integer key(nkey)
455c
456 do i=1,nkey
457 k=key(i)
458 if (a(k).lt.b(k)) then
459 iftuple_ialtb = .true.
460 return
461 elseif (a(k).gt.b(k)) then
462 iftuple_ialtb = .false.
463 return
464 endif
465 enddo
466 iftuple_ialtb = .false.
467 return
468 end
469c
470c-----------------------------------------------------------------------
471c
472 logical function iftuple_altb(a,b,key,nkey)
473 real a(1),b(1)
474 integer key(nkey)
475c
476 do i=1,nkey
477 k=key(i)
478 if (a(k).lt.b(k)) then
479 iftuple_altb = .true.
480 return
481 elseif (a(k).gt.b(k)) then
482 iftuple_altb = .false.
483 return
484 endif
485 enddo
486 iftuple_altb = .false.
487 return
488 end
489c
490c-----------------------------------------------------------------------
491c
492 logical function iftuple_ianeb(a,b,key,nkey)
493 integer a(1),b(1)
494 integer key(nkey)
495c
496 do i=1,nkey
497 k=key(i)
498 if (a(k).ne.b(k)) then
499 iftuple_ianeb = .true.
500 return
501 endif
502 enddo
503 iftuple_ianeb = .false.
504 return
505 end
506c
507c-----------------------------------------------------------------------
508c
509 subroutine get_local_crs(a,lda,nxc,h1,h2,w,ldw)
510c
511c This routine generates Nelv submatrices of order nxc^ldim.
512c
513 include 'SIZE'
514 include 'GEOM'
515 include 'INPUT'
516 include 'TSTEP'
517 include 'DOMAIN'
518 include 'PARALLEL'
519c
520c
521c Generate local triangular matrix
522c
523 real a(1),h1(1),h2(1),w(ldw)
524c
525 parameter (lcrd=lx1**ldim)
526 common /ctmp1/ x(lcrd),y(lcrd),z(lcrd)
527c
528c
529 ncrs_loc = nxc**ldim
530 n2 = ncrs_loc*ncrs_loc
531c
532c Required storage for a:
533 nda = n2*nelv
534 if (nda.gt.lda) then
535 write(6,*)nid,'ERROR: increase storage get_local_crs:',nda,lda
536 call exitt
537 endif
538c
539c
540 l = 1
541 do ie=1,nelv
542c
543 call map_m_to_n(x,nxc,xm1(1,1,1,ie),lx1,if3d,w,ldw)
544 call map_m_to_n(y,nxc,ym1(1,1,1,ie),lx1,if3d,w,ldw)
545 if (if3d) call map_m_to_n(z,nxc,zm1(1,1,1,ie),lx1,if3d,w,ldw)
546c.later. call map_m_to_n(hl1,nxc,h1(1,1,1,ie),lx1,if3d,w,ldw)
547c.later. call map_m_to_n(hl2,nxc,h2(1,1,1,ie),lx1,if3d,w,ldw)
548c
549 call a_crs_enriched(a(l),h1,h2,x,y,z,nxc,if3d,ie)
550 l=l+n2
551c
552 enddo
553c
554 return
555 end
556c
557c-----------------------------------------------------------------------
558c
559 subroutine a_crs_enriched(a,h1,h2,x1,y1,z1,nxc,if3d,ie)
560c
561c This sets up a matrix for a single array of tensor-product
562c gridpoints (e.g., an array defined by SEM-GLL vertices)
563c
564c For example, suppose ldim=3.
565c
566c Then, there would be ncrs_loc := nxc^3 dofs for this matrix,
567c
568c and the matrix size would be (ncrs_loc x ncrs_loc).
569c
570c
571c
572 include 'SIZE'
573c
574 real a(1),h1(1),h2(1)
575 real x1(nxc,nxc,1),y1(nxc,nxc,1),z1(nxc,nxc,1)
576 logical if3d
577c
578 parameter (ldm2=2**ldim)
579 real a_loc(ldm2,ldm2)
580 real x(8),y(8),z(8)
581c
582 ncrs_loc = nxc**ldim
583 n2 = ncrs_loc*ncrs_loc
584 call rzero(a,n2)
585c
586 nyc=nxc
587 nzc=2
588 if (if3d) nzc=nxc
589 nz =0
590 if (if3d) nz=1
591c
592c Here, we march across sub-cubes
593c
594 do kz=1,nzc-1
595 do ky=1,nyc-1
596 do kx=1,nxc-1
597 k = 0
598 do iz=0,nz
599 do iy=0,1
600 do ix=0,1
601 k = k+1
602 x(k) = x1(kx+ix,ky+iy,kz+iz)
603 y(k) = y1(kx+ix,ky+iy,kz+iz)
604 z(k) = z1(kx+ix,ky+iy,kz+iz)
605 enddo
606 enddo
607 enddo
608 if (if3d) then
609 call a_crs_3d(a_loc,h1,h2,x,y,z,ie)
610 else
611 call a_crs_2d(a_loc,h1,h2,x,y,ie)
612 endif
613c call outmat(a_loc,ldm2,ldm2,'A_loc ',ie)
614c
615c Assemble:
616c
617 j = 0
618 do jz=0,nz
619 do jy=0,1
620 do jx=0,1
621 j = j+1
622 ja = (kx+jx) + nxc*(ky+jy-1) + nxc*nyc*(kz+jz-1)
623c
624 i = 0
625 do iz=0,nz
626 do iy=0,1
627 do ix=0,1
628 i = i+1
629 ia = (kx+ix) + nxc*(ky+iy-1) + nxc*nyc*(kz+iz-1)
630c
631 ija = ia + ncrs_loc*(ja-1)
632 a(ija) = a(ija) + a_loc(i,j)
633c
634 enddo
635 enddo
636 enddo
637c
638 enddo
639 enddo
640 enddo
641 enddo
642 enddo
643 enddo
644c
645 return
646 end
647c
648c-----------------------------------------------------------------------
649c
650 subroutine a_crs_3d(a,h1,h2,xc,yc,zc,ie)
651c
652c Generate stiffness matrix for 3D coarse grid problem.
653c
654c This is done by using two tetrahedrizations of each
655c hexahedral subdomain (element) such that each of the
656c 6 panels (faces) on the sides of an element has a big X.
657c
658c
659 real a(0:7,0:7),h1(0:7),h2(0:7)
660 real xc(0:7),yc(0:7),zc(0:7)
661c
662 real a_loc(4,4)
663 real xt(4),yt(4),zt(4)
664c
665 integer vertex(4,5,2)
666 save vertex
667 data vertex / 000 , 001 , 010 , 100
668 $ , 000 , 001 , 011 , 101
669 $ , 011 , 010 , 000 , 110
670 $ , 011 , 010 , 001 , 111
671 $ , 000 , 110 , 101 , 011
672c
673 $ , 101 , 100 , 110 , 000
674 $ , 101 , 100 , 111 , 001
675 $ , 110 , 111 , 100 , 010
676 $ , 110 , 111 , 101 , 011
677 $ , 111 , 001 , 100 , 010 /
678c
679 integer icalld
680 save icalld
681 data icalld/0/
682c
683 if (icalld.eq.0) then
684 do i=1,40
685 call bindec(vertex(i,1,1))
686 enddo
687 endif
688 icalld=icalld+1
689c
690 call rzero(a,64)
691 do k=1,10
692 do iv=1,4
693 xt(iv) = xc(vertex(iv,k,1))
694 yt(iv) = yc(vertex(iv,k,1))
695 zt(iv) = zc(vertex(iv,k,1))
696 enddo
697 call get_local_A_tet(a_loc,xt,yt,zt,k,ie)
698 do j=1,4
699 jj = vertex(j,k,1)
700 do i=1,4
701 ii = vertex(i,k,1)
702 a(ii,jj) = a(ii,jj) + 0.5*a_loc(i,j)
703 enddo
704 enddo
705 enddo
706 return
707 end
708c
709c-----------------------------------------------------------------------
710c
711 subroutine bindec(bin_in)
712 integer bin_in,d,b,b2
713c
714 keep = bin_in
715 d = bin_in
716 b2 = 1
717 b = 0
718 do l=1,12
719 b = b + b2*mod(d,10)
720 d = d/10
721 b2 = b2*2
722 if (d.eq.0) goto 1
723 enddo
724 1 continue
725 bin_in = b
726 return
727 end
728c
729c-----------------------------------------------------------------------
730 subroutine get_local_A_tet(a,x,y,z,kt,ie)
731c
732c Generate local tetrahedral matrix
733c
734c
735 real a(4,4), g(4,4)
736 real x(4),y(4),z(4)
737c
738 11 continue
739 x23 = x(2) - x(3)
740 y23 = y(2) - y(3)
741 z23 = z(2) - z(3)
742 x34 = x(3) - x(4)
743 y34 = y(3) - y(4)
744 z34 = z(3) - z(4)
745 x41 = x(4) - x(1)
746 y41 = y(4) - y(1)
747 z41 = z(4) - z(1)
748 x12 = x(1) - x(2)
749 y12 = y(1) - y(2)
750 z12 = z(1) - z(2)
751c
752 xy234 = x34*y23 - x23*y34
753 xy341 = x34*y41 - x41*y34
754 xy412 = x12*y41 - x41*y12
755 xy123 = x12*y23 - x23*y12
756 xz234 = x23*z34 - x34*z23
757 xz341 = x41*z34 - x34*z41
758 xz412 = x41*z12 - x12*z41
759 xz123 = x23*z12 - x12*z23
760 yz234 = y34*z23 - y23*z34
761 yz341 = y34*z41 - y41*z34
762 yz412 = y12*z41 - y41*z12
763 yz123 = y12*z23 - y23*z12
764c
765 g(1,1) = -(x(2)*yz234 + y(2)*xz234 + z(2)*xy234)
766 g(2,1) = -(x(3)*yz341 + y(3)*xz341 + z(3)*xy341)
767 g(3,1) = -(x(4)*yz412 + y(4)*xz412 + z(4)*xy412)
768 g(4,1) = -(x(1)*yz123 + y(1)*xz123 + z(1)*xy123)
769 g(1,2) = yz234
770 g(2,2) = yz341
771 g(3,2) = yz412
772 g(4,2) = yz123
773 g(1,3) = xz234
774 g(2,3) = xz341
775 g(3,3) = xz412
776 g(4,3) = xz123
777 g(1,4) = xy234
778 g(2,4) = xy341
779 g(3,4) = xy412
780 g(4,4) = xy123
781c
782c vol36 = 1/(36*volume) = 1/(6*determinant)
783c
784 det = x(1)*yz234 + x(2)*yz341 + x(3)*yz412 + x(4)*yz123
785 vol36 = 1.0/(6.0*det)
786 if (vol36.lt.0) then
787 write(6,*) 'Error: tetrahedron not right-handed',ie
788 write(6,1) 'x',(x(k),k=1,4)
789 write(6,1) 'y',(y(k),k=1,4)
790 write(6,1) 'z',(z(k),k=1,4)
791 1 format(a1,1p4e15.5)
792
793c call exitt ! Option 1
794
795 xx = x(1) ! Option 2
796 x(1) = x(2) ! -- this is the option that
797 x(2) = xx ! actually works. 11/25/07
798
799 xx = y(1)
800 y(1) = y(2)
801 y(2) = xx
802
803 xx = z(1)
804 z(1) = z(2)
805 z(2) = xx
806
807 goto 11
808
809c call rzero(a,16) ! Option 3
810c return
811
812c vol36 = abs(vol36) ! Option 4
813
814 endif
815c
816 do j=1,4
817 do i=1,4
818 a(i,j)=vol36*(g(i,2)*g(j,2)+g(i,3)*g(j,3)+g(i,4)*g(j,4))
819 enddo
820 enddo
821c
822 return
823 end
824c
825c-----------------------------------------------------------------------
826c
827 subroutine a_crs_2d(a,h1,h2,x,y,ie)
828c
829 include 'SIZE'
830 include 'GEOM'
831 include 'INPUT'
832 include 'TSTEP'
833 include 'DOMAIN'
834 include 'PARALLEL'
835c
836c Generate local triangle-based stiffnes matrix for quad
837c
838 real a(4,4),h1(1),h2(1)
839 real x(1),y(1)
840c
841c Triangle to Square pointers
842c
843 integer elem(3,2)
844 save elem
845 data elem / 1,2,4 , 1,4,3 /
846c
847 real a_loc(3,3)
848c
849c
850 call rzero(a,16)
851c
852 do i=1,2
853 j1 = elem(1,i)
854 j2 = elem(2,i)
855 j3 = elem(3,i)
856 x1=x(j1)
857 y1=y(j1)
858 x2=x(j2)
859 y2=y(j2)
860 x3=x(j3)
861 y3=y(j3)
862c
863 y23=y2-y3
864 y31=y3-y1
865 y12=y1-y2
866c
867 x32=x3-x2
868 x13=x1-x3
869 x21=x2-x1
870c
871c area4 = 1/(4*area)
872 area4 = 0.50/(x21*y31 - y12*x13)
873c
874 a_loc(1, 1) = area4*( y23*y23+x32*x32 )
875 a_loc(1, 2) = area4*( y23*y31+x32*x13 )
876 a_loc(1, 3) = area4*( y23*y12+x32*x21 )
877c
878 a_loc(2, 1) = area4*( y31*y23+x13*x32 )
879 a_loc(2, 2) = area4*( y31*y31+x13*x13 )
880 a_loc(2, 3) = area4*( y31*y12+x13*x21 )
881c
882 a_loc(3, 1) = area4*( y12*y23+x21*x32 )
883 a_loc(3, 2) = area4*( y12*y31+x21*x13 )
884 a_loc(3, 3) = area4*( y12*y12+x21*x21 )
885c
886c Store in "4 x 4" format
887c
888 do il=1,3
889 iv = elem(il,i)
890 do jl=1,3
891 jv = elem(jl,i)
892 a(iv,jv) = a(iv,jv) + a_loc(il,jl)
893 enddo
894 enddo
895 enddo
896c
897 return
898 end
899c
900c-----------------------------------------------------------------------
901c
902 subroutine map_m_to_n(a,na,b,nb,if3d,w,ldw)
903c
904c Input: b
905c Output: a
906c
907 real a(1),b(1),w(1)
908 logical if3d
909c
910 parameter(lx=50)
911 real za(lx),zb(lx)
912c
913 real iba(lx*lx),ibat(lx*lx)
914 save iba,ibat
915c
916 integer nao,nbo
917 save nao,nbo
918 data nao,nbo / -9, -9/
919c
920 if (na.gt.lx.or.nb.gt.lx) then
921 write(6,*)'ERROR: increase lx in map_m_to_n to max:',na,nb
922 call exitt
923 endif
924c
925 if (na.ne.nao .or. nb.ne.nbo) then
926 nao = na
927 nbo = nb
928 call zwgll(za,w,na)
929 call zwgll(zb,w,nb)
930 call igllm(iba,ibat,zb,za,nb,na,nb,na)
931 endif
932c
933 call specmpn(a,na,b,nb,iba,ibat,if3d,w,ldw)
934c
935 return
936 end
937c
938c-----------------------------------------------------------------------
939c
940 subroutine specmpn(b,nb,a,na,ba,ab,if3d,w,ldw)
941C
942C - Spectral interpolation from A to B via tensor products
943C - scratch arrays: w(na*na*nb + nb*nb*na)
944C
945C 5/3/00 -- this routine replaces specmp in navier1.f, which
946c has a potential memory problem
947C
948C
949 logical if3d
950c
951 real b(nb,nb,nb),a(na,na,na)
952 real w(ldw)
953c
954 ltest = na*nb
955 if (if3d) ltest = na*na*nb + nb*na*na
956 if (ldw.lt.ltest) then
957 write(6,*) 'ERROR specmp:',ldw,ltest,if3d
958 call exitt
959 endif
960c
961 if (if3d) then
962 nab = na*nb
963 nbb = nb*nb
964 call mxm(ba,nb,a,na,w,na*na)
965 k=1
966 l=na*na*nb + 1
967 do iz=1,na
968 call mxm(w(k),nb,ab,na,w(l),nb)
969 k=k+nab
970 l=l+nbb
971 enddo
972 l=na*na*nb + 1
973 call mxm(w(l),nbb,ab,na,b,nb)
974 else
975 call mxm(ba,nb,a,na,w,na)
976 call mxm(w,nb,ab,na,b,nb)
977 endif
978 return
979 end
980c
981c-----------------------------------------------------------------------
982c
983 subroutine irank(A,IND,N)
984C
985C Use Heap Sort (p 233 Num. Rec.), 5/26/93 pff.
986C
987 integer A(1),IND(1)
988C
989 if (n.le.1) return
990 DO 10 J=1,N
991 IND(j)=j
992 10 continue
993C
994 if (n.eq.1) return
995 L=n/2+1
996 ir=n
997 100 continue
998 IF (l.gt.1) THEN
999 l=l-1
1000 indx=ind(l)
1001 q=a(indx)
1002 ELSE
1003 indx=ind(ir)
1004 q=a(indx)
1005 ind(ir)=ind(1)
1006 ir=ir-1
1007 if (ir.eq.1) then
1008 ind(1)=indx
1009 return
1010 endif
1011 ENDIF
1012 i=l
1013 j=l+l
1014 200 continue
1015 IF (J.le.IR) THEN
1016 IF (J.lt.IR) THEN
1017 IF ( A(IND(j)).lt.A(IND(j+1)) ) j=j+1
1018 ENDIF
1019 IF (q.lt.A(IND(j))) THEN
1020 IND(I)=IND(J)
1021 I=J
1022 J=J+J
1023 ELSE
1024 J=IR+1
1025 ENDIF
1026 GOTO 200
1027 ENDIF
1028 IND(I)=INDX
1029 GOTO 100
1030 END
1031c-----------------------------------------------------------------------
1032 subroutine iranku(r,input,n,w,ind)
1033c
1034c Return the rank of each input value, and the maximum rank.
1035c
1036c OUTPUT: r(k) = rank of each entry, k=1,..,n
1037c maxr = max( r )
1038c w(i) = sorted & compressed list of input values
1039c
1040 integer r(1),input(1),ind(1),w(1)
1041c
1042 call icopy(r,input,n)
1043 call isort(r,ind,n)
1044c
1045 maxr = 1
1046 rlast = r(1)
1047 do i=1,n
1048c Bump rank only when r_i changes
1049 if (r(i).ne.rlast) then
1050 rlast = r(i)
1051 maxr = maxr + 1
1052 endif
1053 r(i) = maxr
1054 enddo
1055 call iunswap(r,ind,n,w)
1056c
1057 return
1058 end
1059c
1060c-----------------------------------------------------------------------
1061c
1062 subroutine ifacev_redef(a,ie,iface,val,nx,ny,nz)
1063C
1064C Assign the value VAL to face(IFACE,IE) of array A.
1065C IFACE is the input in the pre-processor ordering scheme.
1066C
1067 include 'SIZE'
1068 integer a(nx,ny,nz,lelt),val
1069 call facind (kx1,kx2,ky1,ky2,kz1,kz2,nx,ny,nz,iface)
1070 do 100 iz=kz1,kz2
1071 do 100 iy=ky1,ky2
1072 do 100 ix=kx1,kx2
1073 a(ix,iy,iz,ie)=val
1074 100 continue
1075 return
1076 end
1077c
1078c-----------------------------------------------------------------------
1079 subroutine map_c_to_f_l2_bilin(uf,uc,w)
1080c
1081c H1 Iterpolation operator: linear --> spectral GLL mesh
1082c
1083 include 'SIZE'
1084 include 'DOMAIN'
1085 include 'INPUT'
1086c
1087 parameter (lxyz = lx2*ly2*lz2)
1088 real uc(nxyz_c,lelt),uf(lxyz,lelt),w(1)
1089
1090 ltot22 = 2*lx2*ly2*lz2
1091 nx_crs = 2 ! bilinear only
1092
1093 do ie=1,nelv
1094 call maph1_to_l2(uf(1,ie),lx2,uc(1,ie),nx_crs,if3d,w,ltot22)
1095 enddo
1096c
1097 return
1098 end
1099c
1100c-----------------------------------------------------------------------
1101c
1102 subroutine map_f_to_c_l2_bilin(uc,uf,w)
1103
1104c TRANSPOSE of L2 Iterpolation operator: T
1105c (linear --> spectral GLL mesh)
1106
1107 include 'SIZE'
1108 include 'DOMAIN'
1109 include 'INPUT'
1110
1111 parameter (lxyz = lx2*ly2*lz2)
1112 real uc(nxyz_c,lelt),uf(lxyz,lelt),w(1)
1113
1114 ltot22 = 2*lx2*ly2*lz2
1115 nx_crs = 2 ! bilinear only
1116
1117 do ie=1,nelv
1118 call maph1_to_l2t(uc(1,ie),nx_crs,uf(1,ie),lx2,if3d,w,ltot22)
1119 enddo
1120c
1121 return
1122 end
1123c
1124c-----------------------------------------------------------------------
1125c
1126 subroutine maph1_to_l2(a,na,b,nb,if3d,w,ldw)
1127c
1128c Input: b
1129c Output: a
1130c
1131 real a(1),b(1),w(1)
1132 logical if3d
1133c
1134 parameter(lx=50)
1135 real za(lx),zb(lx)
1136c
1137 real iba(lx*lx),ibat(lx*lx)
1138 save iba,ibat
1139c
1140 integer nao,nbo
1141 save nao,nbo
1142 data nao,nbo / -9, -9/
1143c
1144c
1145 if (na.gt.lx.or.nb.gt.lx) then
1146 write(6,*)'ERROR: increase lx in maph1_to_l2 to max:',na,nb
1147 call exitt
1148 endif
1149c
1150 if (na.ne.nao .or. nb.ne.nbo) then
1151 nao = na
1152 nbo = nb
1153 call zwgl (za,w,na)
1154 call zwgll(zb,w,nb)
1155 call igllm(iba,ibat,zb,za,nb,na,nb,na)
1156 endif
1157c
1158 call specmpn(a,na,b,nb,iba,ibat,if3d,w,ldw)
1159c
1160 return
1161 end
1162c
1163c-----------------------------------------------------------------------
1164c
1165 subroutine maph1_to_l2t(b,nb,a,na,if3d,w,ldw)
1166c
1167c Input: a
1168c Output: b
1169c
1170 real a(1),b(1),w(1)
1171 logical if3d
1172c
1173 parameter(lx=50)
1174 real za(lx),zb(lx)
1175c
1176 real iba(lx*lx),ibat(lx*lx)
1177 save iba,ibat
1178c
1179 integer nao,nbo
1180 save nao,nbo
1181 data nao,nbo / -9, -9/
1182c
1183c
1184 if (na.gt.lx.or.nb.gt.lx) then
1185 write(6,*)'ERROR: increase lx in maph1_to_l2 to max:',na,nb
1186 call exitt
1187 endif
1188c
1189 if (na.ne.nao .or. nb.ne.nbo) then
1190 nao = na
1191 nbo = nb
1192 call zwgl (za,w,na)
1193 call zwgll(zb,w,nb)
1194 call igllm(iba,ibat,zb,za,nb,na,nb,na)
1195 endif
1196c
1197 call specmpn(b,nb,a,na,ibat,iba,if3d,w,ldw)
1198c
1199 return
1200 end
1201c
1202c-----------------------------------------------------------------------
1203 subroutine irank_vec_tally(ind,nn,a,m,n,key,nkey,key2,aa)
1204c
1205c Compute rank of each unique entry a(1,i)
1206c
1207c Output: ind(i) i=1,...,n (global) rank of entry a(*,i)
1208c nn = max(rank)
1209c a(j,i) is destroyed
1210c a(1,i) tally of preceding structure values
1211c
1212c Input: a(j,i) j=1,...,m; i=1,...,n
1213c m : leading dim. of v (ldv must be .ge. m)
1214c key : sort key
1215c nkey :
1216c
1217c Although not mandatory, this ranking procedure is probably
1218c most effectively employed when the keys are pre-sorted. Thus,
1219c the option is provided to sort vi() prior to the ranking.
1220c
1221c
1222 integer ind(n),a(m,n)
1223 integer key(nkey),key2(0:3),aa(m)
1224 logical iftuple_ianeb,a_ne_b
1225c
1226c
1227 nk = min(nkey,m)
1228 call ituple_sort(a,m,n,key,nk,ind,aa)
1229c do i=1,n
1230c write(6,*) i,' sort:',(a(k,i),k=1,3)
1231c enddo
1232c
1233c
1234c Find unique a's
1235c
1236 call icopy(aa,a,m)
1237 nn=1
1238 mm=0
1239c
1240 a(1,1) = nn
1241 a(2,1)=ind(1)
1242 a(3,1)=mm
1243c
1244 do i=2,n
1245 a_ne_b = iftuple_ianeb(aa,a(1,i),key,nk)
1246 if (a_ne_b) then ! new structure
1247 ms = aa(3) ! structure type
1248 if (aa(2).eq.0) ms = aa(2) ! structure type
1249 mm = mm+key2(ms) ! n dofs
1250 call icopy(aa,a(1,i),m)
1251 nn = nn+1
1252 endif
1253 a(1,i) = nn
1254 a(2,i) = ind(i)
1255 a(3,i) = mm
1256 enddo
1257 ms = aa(3)
1258 if (aa(2).eq.0) ms = aa(2) ! structure type
1259 nn = mm+key2(ms)
1260c
1261c Set ind() to rank
1262c
1263 do i=1,n
1264 iold=a(2,i)
1265 ind(iold) = a(1,i)
1266 enddo
1267c
1268c Set a1() to number of preceding dofs
1269c
1270 do i=1,n
1271 iold=a(2,i)
1272 a(1,iold) = a(3,i)
1273 enddo
1274c
1275 return
1276 end
1277c
1278c-----------------------------------------------------------------------
1279c
1280 subroutine out_se1(se2crs,nx,name)
1281c
1282 include 'SIZE'
1283 integer se2crs(nx,nx,1)
1284 character*4 name
1285c
1286 write(6,*)
1287 write(6,*) 'out_se',nx,name
1288 do ie=nelv-1,1,-2
1289 write(6,*)
1290 do j=nx,1,-1
1291 if(nx.eq.4) then
1292 write(6,4) name,((se2crs(i,j,k+ie),i=1,nx),k=0,1)
1293 elseif(nx.eq.3) then
1294 write(6,3) name,((se2crs(i,j,k+ie),i=1,nx),k=0,1)
1295 else
1296 write(6,2) name,((se2crs(i,j,k+ie),i=1,nx),k=0,1)
1297 endif
1298 enddo
1299 enddo
1300c
1301 4 format(a4,5x,2(4i5,3x))
1302 3 format(a4,5x,2(3i5,3x))
1303 2 format(a4,5x,2(2i5,3x))
1304c
1305 return
1306 end
1307c
1308c-----------------------------------------------------------------------
1309c
1310 subroutine out_se0(se2crs,nx,nel,name)
1311c
1312 include 'SIZE'
1313 integer se2crs(nx,nx,1)
1314 character*4 name
1315c
1316 write(6,*)
1317 write(6,*) 'out_se',nx,name,nel
1318 do ie=nel-3,1,-4
1319 write(6,*)
1320 do j=nx,1,-1
1321 if(nx.eq.4) then
1322 write(6,4) name,((se2crs(i,j,k+ie),i=1,nx),k=0,3)
1323 elseif(nx.eq.3) then
1324 write(6,3) name,((se2crs(i,j,k+ie),i=1,nx),k=0,3)
1325 else
1326 write(6,2) name,((se2crs(i,j,k+ie),i=1,nx),k=0,3)
1327 endif
1328 enddo
1329 enddo
1330c
1331 4 format(a4,5x,4(4i5,3x))
1332 3 format(a4,5x,4(3i5,3x))
1333 2 format(a4,5x,4(2i5,3x))
1334c
1335 return
1336 end
1337c
1338c-----------------------------------------------------------------------
1339c
1340 subroutine crs_solve_h1(uf,vf)
1341c
1342c Given an input vector v, this generates the H1 coarse-grid solution
1343c
1344 include 'SIZE'
1345 include 'DOMAIN'
1346 include 'INPUT'
1347 include 'GEOM'
1348 include 'SOLN'
1349 include 'PARALLEL'
1350 include 'CTIMER'
1351 include 'TSTEP'
1352
1353 real uf(1),vf(1)
1354 common /scrpre/ uc(lcr*lelt)
1355 common /scrpr2/ vc(lcr*lelt)
1356 common /scrxxt/ cmlt(lcr,lelv),mask(lcr,lelv)
1357
1358 integer icalld1
1359 save icalld1
1360 data icalld1 /0/
1361
1362
1363 if (icalld1.eq.0) then ! timer info
1364 ncrsl=0
1365 tcrsl=0.0
1366 icalld1=1
1367 endif
1368 ncrsl = ncrsl + 1
1369
1370 ntot = nelv*lx1*ly1*lz1
1371 call col3(uf,vf,vmult,ntot)
1372
1373 call map_f_to_c_h1_bilin(vc,uf) ! additive Schwarz
1374
1375#ifdef TIMER
1376 etime1=dnekclock()
1377#endif
1378 call fgslib_crs_solve(xxth(ifield),uc,vc)
1379#ifdef TIMER
1380 tcrsl=tcrsl+dnekclock()-etime1
1381#endif
1382
1383 call map_c_to_f_h1_bilin(uf,uc)
1384
1385
1386 return
1387 end
1388c-----------------------------------------------------------------------
1389 subroutine set_h1_basis_bilin
1390c
1391 include 'SIZE'
1392 include 'DOMAIN'
1393 include 'WZ'
1394c
1395 do ix=1,lx1
1396 h1_basis(ix) = 0.5*(1.0-zgm1(ix,1))
1397 h1_basis(ix+lx1) = 0.5*(1.0+zgm1(ix,1))
1398 enddo
1399 call transpose(h1_basist,2,h1_basis,lx1)
1400c
1401 return
1402 end
1403c
1404c-----------------------------------------------------------------------
1405c
1406 subroutine map_c_to_f_h1_bilin(uf,uc)
1407c
1408c H1 Iterpolation operator: linear --> spectral GLL mesh
1409c
1410 include 'SIZE'
1411 include 'INPUT'
1412 include 'DOMAIN'
1413c
1414 parameter (lxyz = lx1*ly1*lz1)
1415 real uc(2,2,ldim-1,lelt),uf(lxyz,lelt)
1416 parameter (l2 = ldim-1)
1417 common /ctmp0/ w(lx1,lx1,2),v(lx1,2,l2,lelt)
1418c
1419 integer icalld
1420 save icalld
1421 data icalld/0/
1422 if (icalld.eq.0) then
1423 icalld=icalld+1
1424 call set_h1_basis_bilin
1425 endif
1426c
1427c
1428 n2 = 2
1429 if (if3d) then
1430c
1431 n31 = n2*n2*nelv
1432 n13 = lx1*lx1
1433c
1434 call mxm(h1_basis,lx1,uc,n2,v,n31)
1435 do ie=1,nelv
1436 do iz=1,n2
1437 call mxm(v(1,1,iz,ie),lx1,h1_basist,n2,w(1,1,iz),lx1)
1438 enddo
1439 call mxm(w,n13,h1_basist,n2,uf(1,ie),lx1)
1440 enddo
1441c
1442 else
1443c
1444 n31 = 2*nelv
1445 call mxm(h1_basis,lx1,uc,n2,v,n31)
1446 do ie=1,nelv
1447 call mxm(v(1,1,1,ie),lx1,h1_basist,n2,uf(1,ie),lx1)
1448 enddo
1449 endif
1450 return
1451 end
1452c
1453c-----------------------------------------------------------------------
1454c
1455 subroutine map_f_to_c_h1_bilin(uc,uf)
1456c
1457c TRANSPOSE of H1 Iterpolation operator: T
1458c (linear --> spectral GLL mesh)
1459c
1460 include 'SIZE'
1461 include 'DOMAIN'
1462 include 'INPUT'
1463c
1464 parameter (lxyz = lx1*ly1*lz1)
1465 real uc(lcr,lelt),uf(lx1,ly1,lz1,lelt)
1466 common /ctmp0/ w(2,2,lx1),v(2,ly1,lz1,lelt)
1467c
1468 integer icalld
1469 save icalld
1470 data icalld/0/
1471 if (icalld.eq.0) then
1472 icalld=icalld+1
1473 call set_h1_basis_bilin
1474 endif
1475c
1476 n2 = 2
1477 if (if3d) then
1478 n31 = ly1*lz1*nelv
1479 n13 = n2*n2
1480 call mxm(h1_basist,n2,uf,lx1,v,n31)
1481 do ie=1,nelv
1482 do iz=1,lz1
1483 call mxm(v(1,1,iz,ie),n2,h1_basis,lx1,w(1,1,iz),n2)
1484 enddo
1485 call mxm(w,n13,h1_basis,lx1,uc(1,ie),n2)
1486 enddo
1487 else
1488 n31 = ly1*nelv
1489 call mxm(h1_basist,n2,uf,lx1,v,n31)
1490 do ie=1,nelv
1491 call mxm(v(1,1,1,ie),n2,h1_basis,lx1,uc(1,ie),n2)
1492 enddo
1493 endif
1494
1495 return
1496 end
1497c-----------------------------------------------------------------------
1498 subroutine get_local_crs_galerkin(a,ncl,nxc,h1,h2,w1,w2)
1499
1500c This routine generates Nelv submatrices of order ncl using
1501c Galerkin projection
1502
1503 include 'SIZE'
1504
1505 real a(ncl,ncl,1),h1(1),h2(1)
1506 real w1(lx1*ly1*lz1,nelv),w2(lx1*ly1*lz1,nelv)
1507
1508 parameter (lcrd=lx1**ldim)
1509 common /ctmp1z/ b(lcrd,8)
1510
1511 integer e
1512
1513 do j=1,ncl
1514 call gen_crs_basis(b(1,j),j) ! bi- or tri-linear interpolant
1515 enddo
1516
1517 isd = 1
1518 imsh = 1
1519
1520 nxyz = lx1*ly1*lz1
1521 do j = 1,ncl
1522 do e = 1,nelv
1523 call copy(w1(1,e),b(1,j),nxyz)
1524 enddo
1525
1526 call axhelm (w2,w1,h1,h2,imsh,isd) ! A^e * bj
1527
1528 do e = 1,nelv
1529 do i = 1,ncl
1530 a(i,j,e) = vlsc2(b(1,i),w2(1,e),nxyz) ! bi^T * A^e * bj
1531 enddo
1532 enddo
1533
1534 enddo
1535
1536 return
1537 end
1538c-----------------------------------------------------------------------
1539 subroutine gen_crs_basis(b,j) ! bi- tri-linear
1540
1541 include 'SIZE'
1542 real b(lx1,ly1,lz1)
1543
1544 real z0(lx1),z1(lx1)
1545 real zr(lx1),zs(lx1),zt(lx1)
1546
1547 integer p,q,r
1548
1549 call zwgll(zr,zs,lx1)
1550
1551 do i=1,lx1
1552 z0(i) = .5*(1-zr(i)) ! 1-->0
1553 z1(i) = .5*(1+zr(i)) ! 0-->1
1554 enddo
1555
1556 call copy(zr,z0,lx1)
1557 call copy(zs,z0,lx1)
1558 call copy(zt,z0,lx1)
1559
1560 if (mod(j,2).eq.0) call copy(zr,z1,lx1)
1561 if (j.eq.3.or.j.eq.4.or.j.eq.7.or.j.eq.8) call copy(zs,z1,lx1)
1562 if (j.gt.4) call copy(zt,z1,lx1)
1563
1564 if (ldim.eq.3) then
1565 do r=1,lx1
1566 do q=1,lx1
1567 do p=1,lx1
1568 b(p,q,r) = zr(p)*zs(q)*zt(r)
1569 enddo
1570 enddo
1571 enddo
1572 else
1573 do q=1,lx1
1574 do p=1,lx1
1575 b(p,q,1) = zr(p)*zs(q)
1576 enddo
1577 enddo
1578 endif
1579
1580 return
1581 end
1582c-----------------------------------------------------------------------
1583 subroutine gen_crs_basis2(b,j) ! bi- tri-quadratic
1584
1585 include 'SIZE'
1586 real b(lx1,ly1,lz1)
1587
1588 real z0(lx1),z1(lx1),z2(lx1)
1589 real zr(lx1),zs(lx1),zt(lx1)
1590
1591 integer p,q,r
1592
1593 call zwgll(zr,zs,lx1)
1594
1595 do i=1,lx1
1596 z0(i) = .5*(zr(i)-1)*zr(i) ! 1-->0 ! Lagrangian, ordered
1597 z1(i) = 4.*(1+zr(i))*(1-zr(i)) ! lexicographically
1598 z2(i) = .5*(zr(i)+1)*zr(i) ! 0-->1 !
1599 enddo
1600
1601 call copy(zr,z0,lx1)
1602 call copy(zs,z0,lx1)
1603 call copy(zt,z0,lx1)
1604
1605 if (mod(j,2).eq.0) call copy(zr,z1,lx1)
1606 if (j.eq.3.or.j.eq.4.or.j.eq.7.or.j.eq.8) call copy(zs,z1,lx1)
1607 if (j.gt.4) call copy(zt,z1,lx1)
1608
1609 if (ldim.eq.3) then
1610 do r=1,lx1
1611 do q=1,lx1
1612 do p=1,lx1
1613 b(p,q,r) = zr(p)*zs(q)*zt(r)
1614 enddo
1615 enddo
1616 enddo
1617 else
1618 do q=1,lx1
1619 do p=1,lx1
1620 b(p,q,1) = zr(p)*zs(q)
1621 enddo
1622 enddo
1623 endif
1624
1625 return
1626 end
1627c-----------------------------------------------------------------------
1628 subroutine get_vertex
1629 include 'SIZE'
1630 include 'TOTAL'
1631
1632 common /ivrtx/ vertex ((2**ldim)*lelt)
1633 integer vertex
1634
1635 call get_vert
1636
1637 return
1638 end
1639c-----------------------------------------------------------------------
1640c-----------------------------------------------------------------------
1641 subroutine irank_vecn(ind,nn,a,m,n,key,nkey,aa)
1642c
1643c Compute rank of each unique entry a(1,i)
1644c
1645c Output: ind(i) i=1,...,n (global) rank of entry a(*,i)
1646c nn = max(rank)
1647c a(j,i) is permuted
1648c
1649c Input: a(j,i) j=1,...,m; i=1,...,n
1650c m : leading dim. of v (ldv must be .ge. m)
1651c key : sort key
1652c nkey :
1653c
1654c Although not mandatory, this ranking procedure is probably
1655c most effectively employed when the keys are pre-sorted. Thus,
1656c the option is provided to sort vi() prior to the ranking.
1657c
1658c
1659 integer ind(n),a(m,n)
1660 integer key(nkey),aa(m)
1661 logical iftuple_ianeb,a_ne_b
1662
1663 nk = min(nkey,m)
1664 call ituple_sort(a,m,n,key,nk,ind,aa)
1665
1666c Find unique a's
1667 call icopy(aa,a,m)
1668 nn = 1
1669 ind(1) = nn
1670c
1671 do i=2,n
1672 a_ne_b = iftuple_ianeb(aa,a(1,i),key,nk)
1673 if (a_ne_b) then
1674 call icopy(aa,a(1,i),m)
1675 nn = nn+1
1676 endif
1677 ind(i) = nn ! set ind() to rank
1678 enddo
1679
1680 return
1681 end
1682c-----------------------------------------------------------------------
1683 subroutine gbtuple_rank(tuple,m,n,nmax,cr_h,nid,np,ind)
1684c
1685c Return a unique rank for each matched tuple set. Global. Balanced.
1686c
1687c tuple is destroyed.
1688c
1689c By "balanced" we mean that none of the tuple entries is likely to
1690c be much more uniquely populated than any other, so that any of
1691c the tuples can serve as an initial (parallel) sort key
1692c
1693c First two slots in tuple(:,i) assumed empty
1694c
1695 integer ind(nmax),tuple(m,nmax),cr_h
1696
1697 parameter (mmax=40)
1698 integer key(mmax),wtuple(mmax)
1699
1700 if (m.gt.mmax) then
1701 write(6,*) nid,m,mmax,' gbtuple_rank fail'
1702 call exitt
1703 endif
1704
1705 do i=1,n
1706 tuple(1,i) = mod(tuple(3,i),np) ! destination processor
1707 tuple(2,i) = i ! return location
1708 enddo
1709
1710 ni= n
1711 ky=1 ! Assumes crystal_new already called
1712 call fgslib_crystal_ituple_transfer(cr_h, tuple,m,ni,nmax, ky)
1713
1714 nimx = iglmax(ni,1)
1715 if (ni.gt.nmax) write(6,*) ni,nmax,n,'cr_xfer problem, A'
1716 if (nimx.gt.nmax) call exitt
1717
1718 nkey = m-2
1719 do k=1,nkey
1720 key(k) = k+2
1721 enddo
1722
1723 call irank_vecn(ind,nu,tuple,m,ni,key,nkey,wtuple)! tuple re-ordered,
1724 ! but contents same
1725
1726 nu_tot = igl_running_sum(nu) ! running sum over P processors
1727 nu_prior = nu_tot - nu
1728
1729 do i=1,ni
1730 tuple(3,i) = ind(i) + nu_prior ! global ranking
1731 enddo
1732
1733 call fgslib_crystal_ituple_transfer(cr_h, tuple,m,ni,nmax, ky)
1734
1735 nk = 1 ! restore to original order, local rank: 2; global: 3
1736 ky = 2
1737 call ituple_sort(tuple,m,n,ky,nk,ind,wtuple)
1738
1739
1740 return
1741 end
1742c-----------------------------------------------------------------------
1743 subroutine setvert3d(glo_num,ngv,nx,nel,vertex,ifcenter)
1744c
1745c setup unique ids for dssum
1746c note:
1747c total number of unique vertices, edges and faces has to be smaller
1748c than 2**31 (integer-4 limit).
1749c if nelgt < 2**31/12 we're ok for sure (independent of N)!
1750c
1751 include 'SIZE'
1752 include 'CTIMER'
1753 include 'PARALLEL'
1754 include 'TOPOL'
1755 include 'GEOM'
1756
1757 integer*8 glo_num(1),ngv
1758 integer vertex(0:1,0:1,0:1,1),nx
1759 logical ifcenter
1760
1761 integer edge(0:1,0:1,0:1,3,lelt),enum(12,lelt),fnum(6,lelt)
1762 common /scrmg/ edge,enum,fnum
1763
1764 parameter (nsafe=8) ! OFTEN, nsafe=2 suffices
1765 integer etuple(4,12*lelt*nsafe),ftuple(5,6,lelt*nsafe)
1766 integer ind(12*lelt*nsafe)
1767 common /scrns/ ind,etuple
1768 equivalence (etuple,ftuple)
1769
1770 integer gvf(4),facet(4),aa(3),key(3),e
1771 logical ifij
1772
1773 integer*8 igv,ig0
1774 integer*8 ngvv,ngve,ngvs,ngvi,ngvm
1775 integer*8 n_on_edge,n_on_face,n_in_interior
1776 integer*8 i8glmax
1777c
1778 ny = nx
1779 nz = nx
1780 nxyz = nx*ny*nz
1781c
1782 key(1)=1
1783 key(2)=2
1784 key(3)=3
1785c
1786c Assign hypercube ordering of vertices
1787c -------------------------------------
1788c
1789c Count number of unique vertices
1790 nlv = 2**ldim
1791 ngvv = iglmax(vertex,nlv*nel)
1792c
1793 do e=1,nel
1794 do k=0,1
1795 do j=0,1
1796 do i=0,1
1797c Local to global node number (vertex)
1798 il = 1 + (nx-1)*i + nx*(nx-1)*j + nx*nx*(nx-1)*k
1799 ile = il + nx*ny*nz*(e-1)
1800 glo_num(ile) = vertex(i,j,k,e)
1801 enddo
1802 enddo
1803 enddo
1804 enddo
1805 ngv = ngvv
1806c
1807 if (nx.eq.2) return
1808c
1809c Assign global vertex numbers to SEM nodes on each edge
1810c ------------------------------------------------------
1811c
1812c Assign edge labels by bounding vertices.
1813 do e=1,nel
1814 do k=0,1
1815 do j=0,1
1816 do i=0,1
1817 edge(i,j,k,1,e) = vertex(i,j,k,e) ! r-edge
1818 edge(j,i,k,2,e) = vertex(i,j,k,e) ! s-edge
1819 edge(k,i,j,3,e) = vertex(i,j,k,e) ! t-edge
1820 enddo
1821 enddo
1822 enddo
1823 enddo
1824c
1825c Sort edges by bounding vertices.
1826 do i=0,12*nel-1
1827 if (edge(0,i,0,1,1).gt.edge(1,i,0,1,1)) then
1828 kswap = edge(0,i,0,1,1)
1829 edge(0,i,0,1,1) = edge(1,i,0,1,1)
1830 edge(1,i,0,1,1) = kswap
1831 endif
1832 etuple(3,i+1) = edge(0,i,0,1,1)
1833 etuple(4,i+1) = edge(1,i,0,1,1)
1834 enddo
1835c
1836c Assign a number (rank) to each unique edge
1837 m = 4
1838 n = 12*nel
1839 nmax = 12*lelt*nsafe ! nsafe for crystal router factor of safety
1840 call gbtuple_rank(etuple,m,n,nmax,cr_h,nid,np,ind)
1841 do i=1,12*nel
1842 enum(i,1) = etuple(3,i)
1843 enddo
1844 n_unique_edges = iglmax(enum,12*nel)
1845c
1846 n_on_edge = nx-2
1847 ngve = n_unique_edges*n_on_edge
1848 do e=1,nel
1849 iedg_loc = 0
1850c
1851c Edges 1-4
1852 do k=0,1
1853 do j=0,1
1854 igv = ngv + n_on_edge*(enum(iedg_loc+1,e)-1)
1855 i0 = nx*(nx-1)*j + nx*nx*(nx-1)*k
1856 i0e = i0 + nxyz*(e-1)
1857 if (glo_num(i0e+1).lt.glo_num(i0e+nx)) then
1858 do i=2,nx-1 ! std forward case
1859 glo_num(i0e+i) = igv + i-1
1860 enddo
1861 else
1862 do i=2,nx-1 ! backward case
1863 glo_num(i0e+i) = igv + 1 + n_on_edge-(i-1)
1864 enddo
1865 endif
1866 iedg_loc = iedg_loc + 1
1867 enddo
1868 enddo
1869c
1870c Edges 5-8
1871 do k=0,1
1872 do i=0,1
1873 igv = ngv + n_on_edge*(enum(iedg_loc+1,e)-1)
1874 i0 = 1+(nx-1)*i + nx*nx*(nx-1)*k
1875 i0e = i0 + nxyz*(e-1)
1876 if (glo_num(i0e).lt.glo_num(i0e+nx*(nx-1))) then
1877 do j=2,nx-1 ! std forward case
1878 glo_num(i0e+(j-1)*nx) = igv + j-1
1879 enddo
1880 else
1881 do j=2,nx-1 ! backward case
1882 glo_num(i0e+(j-1)*nx) = igv + 1 + n_on_edge-(j-1)
1883 enddo
1884 endif
1885 iedg_loc = iedg_loc + 1
1886 enddo
1887 enddo
1888c
1889c Edges 9-12
1890 do j=0,1
1891 do i=0,1
1892 igv = ngv + n_on_edge*(enum(iedg_loc+1,e)-1)
1893 i0 = 1 + (nx-1)*i + nx*(nx-1)*j
1894 i0e = i0 + nxyz*(e-1)
1895 if (glo_num(i0e).lt.glo_num(i0e+nx*nx*(nx-1))) then
1896 do k=2,nx-1 ! std forward case
1897 glo_num(i0e+(k-1)*nx*nx) = igv + k-1
1898 enddo
1899 else
1900 do k=2,nx-1 ! backward case
1901 glo_num(i0e+(k-1)*nx*nx) = igv + 1 + n_on_edge-(k-1)
1902 enddo
1903 endif
1904 iedg_loc = iedg_loc + 1
1905 enddo
1906 enddo
1907 enddo
1908 ngv = ngv + ngve
1909c
1910c Asign global node numbers on the interior of each face
1911c ------------------------------------------------------
1912c
1913c Assign faces by 3-tuples
1914c
1915c (The following variables all take the symmetric
1916c notation of IFACE as arguments:)
1917c
1918c ICFACE(i,IFACE) - Gives the 4 vertices which reside on face IFACE
1919c as depicted below, e.g. ICFACE(i,2)=2,4,6,8.
1920c
1921c 3+-----+4 ^ Y
1922c / 2 /| |
1923c Edge 1 extends / / | |
1924c from vertex 7+-----+8 +2 +----> X
1925c 1 to 2. | 4 | / /
1926c | |/ /
1927c 5+-----+6 Z
1928c 3
1929c
1930 nfaces=ldim*2
1931 ncrnr =2**(ldim-1)
1932 do e=1,nel
1933 do ifac=1,nfaces
1934 do icrn=1,ncrnr
1935 i = icface(icrn,ifac)-1
1936 facet(icrn) = vertex(i,0,0,e)
1937 enddo
1938 call isort(facet,ind,ncrnr)
1939 call icopy(ftuple(3,ifac,e),facet,ncrnr-1)
1940 enddo
1941 enddo
1942
1943c Assign a number (rank) to each unique face
1944 m = 5
1945 n = 6*nel
1946 nmax = 6*lelt*nsafe ! nsafe for crystal router factor of safety
1947 call gbtuple_rank(ftuple,m,n,nmax,cr_h,nid,np,ind)
1948 do i=1,6*nel
1949 fnum(i,1) = ftuple(3,i,1)
1950 enddo
1951 n_unique_faces = iglmax(fnum,6*nel)
1952c
1953 call dsset (nx,ny,nz)
1954 do e=1,nel
1955 do iface=1,nfaces
1956 i0 = skpdat(1,iface)
1957 i1 = skpdat(2,iface)
1958 is = skpdat(3,iface)
1959 j0 = skpdat(4,iface)
1960 j1 = skpdat(5,iface)
1961 js = skpdat(6,iface)
1962c
1963c On each face, count from minimum global vertex number,
1964c towards smallest adjacent vertex number. e.g., suppose
1965c the face is defined by the following global vertex numbers:
1966c
1967c
1968c 11+--------+81
1969c |c d|
1970c | |
1971c | |
1972c |a b|
1973c 15+--------+62
1974c
1975c We would count from c-->a, then towards d.
1976c
1977 gvf(1) = glo_num(i0+nx*(j0-1)+nxyz*(e-1))
1978 gvf(2) = glo_num(i1+nx*(j0-1)+nxyz*(e-1))
1979 gvf(3) = glo_num(i0+nx*(j1-1)+nxyz*(e-1))
1980 gvf(4) = glo_num(i1+nx*(j1-1)+nxyz*(e-1))
1981c
1982 call irank(gvf,ind,4)
1983c
1984c ind(1) tells which element of gvf() is smallest.
1985c
1986 ifij = .false.
1987 if (ind(1).eq.1) then
1988 idir = 1
1989 jdir = 1
1990 if (gvf(2).lt.gvf(3)) ifij = .true.
1991 elseif (ind(1).eq.2) then
1992 idir = -1
1993 jdir = 1
1994 if (gvf(1).lt.gvf(4)) ifij = .true.
1995 elseif (ind(1).eq.3) then
1996 idir = 1
1997 jdir = -1
1998 if (gvf(4).lt.gvf(1)) ifij = .true.
1999 elseif (ind(1).eq.4) then
2000 idir = -1
2001 jdir = -1
2002 if (gvf(3).lt.gvf(2)) ifij = .true.
2003 endif
2004c
2005 if (idir.lt.0) then
2006 it=i0
2007 i0=i1
2008 i1=it
2009 is=-is
2010 endif
2011c
2012 if (jdir.lt.0) then
2013 jt=j0
2014 j0=j1
2015 j1=jt
2016 js=-js
2017 endif
2018c
2019 nxx = nx*nx
2020 n_on_face = (nx-2)*(ny-2)
2021 ngvs = n_unique_faces*n_on_face
2022 ig0 = ngv + n_on_face*(fnum(iface,e)-1)
2023 if (ifij) then
2024 k=0
2025 l=0
2026 do j=j0,j1,js
2027 do i=i0,i1,is
2028 k=k+1
2029c this is a serious kludge to stay on the face interior
2030 if (k.gt.nx.and.k.lt.nxx-nx .and.
2031 $ mod(k,nx).ne.1.and.mod(k,nx).ne.0) then
2032c interior
2033 l = l+1
2034 glo_num(i+nx*(j-1)+nxyz*(e-1)) = l + ig0
2035 endif
2036 enddo
2037 enddo
2038 else
2039 k=0
2040 l=0
2041 do i=i0,i1,is
2042 do j=j0,j1,js
2043 k=k+1
2044c this is a serious kludge to stay on the face interior
2045 if (k.gt.nx.and.k.lt.nxx-nx .and.
2046 $ mod(k,nx).ne.1.and.mod(k,nx).ne.0) then
2047c interior
2048 l = l+1
2049 glo_num(i+nx*(j-1)+nxyz*(e-1)) = l + ig0
2050 endif
2051 enddo
2052 enddo
2053 endif
2054 enddo
2055 enddo
2056 ngv = ngv + ngvs
2057c
2058c Finally, number interiors (only ifcenter=.true.)
2059c -------------------------------------------------
2060c
2061 n_in_interior = (nx-2)*(ny-2)*(nz-2)
2062 ngvi = n_in_interior*nelgt
2063 if (ifcenter) then
2064 do e=1,nel
2065 ig0 = ngv + n_in_interior*(lglel(e)-1)
2066 l = 0
2067 do k=2,nz-1
2068 do j=2,ny-1
2069 do i=2,nx-1
2070 l = l+1
2071 glo_num(i+nx*(j-1)+nx*ny*(k-1)+nxyz*(e-1)) = ig0+l
2072 enddo
2073 enddo
2074 enddo
2075 enddo
2076 ngv = ngv + ngvi
2077 else
2078 do e=1,nel
2079 l = 0
2080 do k=2,nz-1
2081 do j=2,ny-1
2082 do i=2,nx-1
2083 l = l+1
2084 glo_num(i+nx*(j-1)+nx*ny*(k-1)+nxyz*(e-1)) = 0
2085 enddo
2086 enddo
2087 enddo
2088 enddo
2089 endif
2090c
2091c Quick check on maximum #dofs:
2092 m = nxyz*nelt
2093 ngvm = i8glmax(glo_num,m)
2094 ngvv = ngvv + ngve + ngvs ! number of unique ids w/o interior
2095 ngvi = ngvi + ngvv ! total number of unique ids
2096 if (nio.eq.0) write(6,1) nx,ngvv,ngvi,ngv,ngvm
2097 1 format(' setvert3d:',i4,4i12)
2098c
2099 return
2100 end
2101c-----------------------------------------------------------------------
2102 subroutine setvert2d(glo_num,ngv,nx,nel,vertex,ifcenter)
2103c
2104c setup unique ids for dssum
2105c
2106 include 'SIZE'
2107 include 'CTIMER'
2108 include 'PARALLEL'
2109 include 'TOPOL'
2110 include 'GEOM'
2111
2112 integer*8 glo_num(1),ngv
2113 integer vertex(0:1,0:1,1),nx
2114 logical ifcenter
2115
2116 integer edge(0:1,0:1,2,lelt),enum(4,lelt)
2117 common /scrmg/ edge,enum
2118
2119 parameter (nsafe=8) ! OFTEN, nsafe=2 suffices
2120 integer etuple(4,4*lelt*nsafe),ind(4*lelt*nsafe)
2121 common /scrns/ ind,etuple
2122
2123 integer gvf(4),aa(3),key(3),e,eg
2124 logical ifij
2125
2126 integer*8 igv,ig0
2127 integer*8 ngvv,ngve,ngvs,ngvi,ngvm
2128 integer*8 n_on_edge,n_on_face,n_in_interior
2129 integer*8 i8glmax
2130c
2131c
2132c memory check...
2133c
2134 ny = nx
2135 nz = 1
2136 nxyz = nx*ny*nz
2137c
2138 key(1)=1
2139 key(2)=2
2140 key(3)=3
2141c
2142c Count number of unique vertices
2143 nlv = 2**ldim
2144 ngvv = iglmax(vertex,nlv*nel)
2145 ngv = ngvv
2146c
2147c Assign hypercube ordering of vertices.
2148 do e=1,nel
2149 do j=0,1
2150 do i=0,1
2151c Local to global node number (vertex)
2152 il = 1 + (nx-1)*i + nx*(nx-1)*j
2153 ile = il + nx*ny*(e-1)
2154 glo_num(ile) = vertex(i,j,e)
2155 enddo
2156 enddo
2157 enddo
2158 if (nx.eq.2) return
2159c
2160c Assign edge labels by bounding vertices.
2161 do e=1,nel
2162 do j=0,1
2163 do i=0,1
2164 edge(i,j,1,e) = vertex(i,j,e) ! r-edge
2165 edge(j,i,2,e) = vertex(i,j,e) ! s-edge
2166 enddo
2167 enddo
2168 enddo
2169
2170c Sort edges by bounding vertices.
2171 do i=0,4*nel-1
2172 if (edge(0,i,1,1).gt.edge(1,i,1,1)) then
2173 kswap = edge(0,i,1,1)
2174 edge(0,i,1,1) = edge(1,i,1,1)
2175 edge(1,i,1,1) = kswap
2176 endif
2177 etuple(3,i+1) = edge(0,i,1,1)
2178 etuple(4,i+1) = edge(1,i,1,1)
2179 enddo
2180
2181c Assign a number (rank) to each unique edge
2182 m = 4
2183 n = 4*nel
2184 nmax = 4*lelt*nsafe ! nsafe for crystal router factor of safety
2185
2186 call gbtuple_rank(etuple,m,n,nmax,cr_h,nid,np,ind)
2187 do i=1,4*nel
2188 enum(i,1) = etuple(3,i)
2189 enddo
2190 n_unique_edges = iglmax(enum,4*nel)
2191
2192c= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2193c Assign global vertex numbers to SEM nodes on each edge
2194 n_on_edge = nx-2
2195 do e=1,nel
2196
2197 iedg_loc = 0
2198
2199c Edges 1-2
2200 do j=0,1
2201 igv = ngv + n_on_edge*(enum(iedg_loc+1,e)-1)
2202 i0 = nx*(nx-1)*j
2203 i0e = i0 + nxyz*(e-1)
2204 if (glo_num(i0e+1).lt.glo_num(i0e+nx)) then
2205 do i=2,nx-1 ! std forward case
2206 glo_num(i0e+i) = igv + i-1
2207 enddo
2208 else
2209 do i=2,nx-1 ! backward case
2210 glo_num(i0e+i) = igv + 1 + n_on_edge-(i-1)
2211 enddo
2212 endif
2213 iedg_loc = iedg_loc + 1
2214 enddo
2215c
2216c Edges 3-4
2217 do i=0,1
2218 igv = ngv + n_on_edge*(enum(iedg_loc+1,e)-1)
2219 i0 = 1+(nx-1)*i
2220 i0e = i0 + nxyz*(e-1)
2221 if (glo_num(i0e).lt.glo_num(i0e+nx*(nx-1))) then
2222 do j=2,nx-1 ! std forward case
2223 glo_num(i0e+(j-1)*nx) = igv + j-1
2224 enddo
2225 else
2226 do j=2,nx-1 ! backward case
2227 glo_num(i0e+(j-1)*nx) = igv + 1 + n_on_edge-(j-1)
2228 enddo
2229 endif
2230 iedg_loc = iedg_loc + 1
2231 enddo
2232 enddo
2233
2234 ngve = n_unique_edges*n_on_edge
2235 ngv = ngv + ngve
2236c
2237c Finally, number interiors
2238c
2239 n_in_interior = (nx-2)*(ny-2)
2240 ngvi = n_in_interior*nelgt
2241 if (ifcenter) then
2242 do e=1,nel
2243 ig0 = ngv + n_in_interior*(lglel(e)-1)
2244 l = 0
2245 do j=2,ny-1
2246 do i=2,nx-1
2247 l = l+1
2248 glo_num(i+nx*(j-1)+nxyz*(e-1)) = ig0+l
2249 enddo
2250 enddo
2251 enddo
2252 ngv = ngv + ngvi
2253 else
2254 do e=1,nel
2255 l = 0
2256 do j=2,ny-1
2257 do i=2,nx-1
2258 l = l+1
2259 glo_num(i+nx*(j-1)+nxyz*(e-1)) = 0
2260 enddo
2261 enddo
2262 enddo
2263 endif
2264
2265c
2266c Quick check on maximum #dofs:
2267 m = nxyz*nelt
2268 ngvm = i8glmax(glo_num,m)
2269 ngvv = ngvv + ngve ! number of unique ids w/o interior
2270 ngvi = ngvi + ngvv ! total number of unique ids
2271 if (nio.eq.0) write(6,1) nx,ngvv,ngvi,ngv,ngvm
2272 1 format(' setvert2d:',i4,4i12)
2273c
2274 return
2275 end
2276c-----------------------------------------------------------------------
2277c
2278 subroutine map_to_crs(a,na,b,nb,if3d,w,ldw)
2279c
2280c Input: b
2281c Output: a
2282c
2283 real a(1),b(1),w(1)
2284 logical if3d
2285c
2286 parameter(lx=40)
2287 real za(lx),zb(lx)
2288c
2289 real iba(lx*lx),ibat(lx*lx)
2290 save iba,ibat
2291c
2292 integer nao,nbo
2293 save nao,nbo
2294 data nao,nbo / -9, -9/
2295c
2296 if (na.gt.lx.or.nb.gt.lx) then
2297 write(6,*)'ERROR: increase lx in map_to_crs to max:',na,nb
2298 call exitt
2299 endif
2300c
2301 if (na.ne.nao .or. nb.ne.nbo) then
2302 nao = na
2303 nbo = nb
2304 call zwgll(za,w,na)
2305 call zwgll(zb,w,nb)
2306 call igllm(iba,ibat,zb,za,nb,na,nb,na)
2307 endif
2308c
2309 call specmpn(a,na,b,nb,iba,ibat,if3d,w,ldw)
2310
2311 return
2312 end
2313c-----------------------------------------------------------------------
2314 subroutine check_p_bc(glo_num,nx,ny,nz,nel)
2315
2316 include 'SIZE'
2317 include 'TOTAL'
2318
2319 integer*8 glo_num(nx,ny,nz,nel)
2320 integer*8 gmn
2321
2322 integer e,f,fo,ef,efo
2323 integer eface0(6)
2324 save eface0
2325 data eface0 / 4,2,1,3,5,6 /
2326
2327 ifld = 2
2328 if (ifflow) ifld = 1
2329
2330 nface=2*ldim
2331 do e=1,nelt
2332 do f=1,nface,2
2333 fo = f+1
2334 ef = eface0(f)
2335 efo = eface0(fo)
2336 if (cbc(ef,e,ifld).eq.'p '.and.cbc(efo,e,ifld).eq.'p ') then
2337 if (f.eq.1) then ! r=-/+1
2338 do k=1,nz
2339 do j=1,ny
2340 gmn = min(glo_num(1,j,k,e),glo_num(nx,j,k,e))
2341 glo_num(1 ,j,k,e) = gmn
2342 glo_num(nx,j,k,e) = gmn
2343 enddo
2344 enddo
2345 elseif (f.eq.3) then ! s=-/+1
2346 do k=1,nz
2347 do i=1,nx
2348 gmn = min(glo_num(i,1,k,e),glo_num(i,ny,k,e))
2349 glo_num(i,1 ,k,e) = gmn
2350 glo_num(i,ny,k,e) = gmn
2351 enddo
2352 enddo
2353 else
2354 do j=1,ny
2355 do i=1,nx
2356 gmn = min(glo_num(i,j,1,e),glo_num(i,j,nz,e))
2357 glo_num(i,j,1 ,e) = gmn
2358 glo_num(i,j,nz,e) = gmn
2359 enddo
2360 enddo
2361 endif
2362 endif
2363 enddo
2364 enddo
2365
2366 return
2367 end
2368c-----------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.