[Nek5000-users] connect slab with inlet

Paul Fischer fischer at mcs.anl.gov
Tue Feb 3 11:35:06 CST 2009



Hi Stefan,

Without seeing the rest of the code, I can't comment for sure.
However, let me tell you the basic strategy.

First, an important observation about gs_op:

    .For each entry j such that glo_num(j) is unique (i.e.,
     glo_num(j) ^= glonum(j') for all j' ^= j), the effect
     of gs_op(...,u,...) on u(j) is a no-op.

     In fact, almost no memory is consumed in the internal
     storage of gs_op() by the presence of the unique glo_num(j)
     in the glo_num() list, becasue gs_op() works with pointers
     into the _active_ subset of u().

     Here, active means: there exists a (j',p') ^= (j,p) such that
     glo_num(j',p') = glo_num(j,p), where p',p \in [0,...,P-1] are
     (implicit) processor pointers.

     Bottom line:  you can call gs_setup() with a big list of pointers
     of which only a small subset have any overlap (i.e., are nonunique
     --active), without undue operational overhead.


Using the above fact, the idea is to connect a plane of data that is
downstream of the inlet to the inlet pointers.  Then, at each step, n,
we make a copy of the velocity field, say, W <-- V, and we zero out
the values of W on all inlet faces.   Then we invoke gs_op(W,'+'),
which will add the inlet values to those one the downstream plane
and copy the result to both locales.     All other values of W will 
be untouched.  [ The other values are in any case irrelevant because
userbc() will extract from W() only the values that are on the face,
and map these to the inlet of V at step n+1. ]

Here is a 1-D picture of a glo_num() array that will achieve the
transferral of


   |------------- p = 0 -------------|  |-------- p = 1 ------|
       e=1         e=2         e=3          e=1         e=2

      eg=1        eg=2        eg=3         eg=4        eg=5
    1  2  3  4  1  2  3  4  1  2  3  4   1  2  3  4  1  2  3  4

   o---.--.--o o---.--.--o o---.--.--o  o---.--.--o o---.--.--o

    1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20  glo_num()

Initially:

       do e=1,nelv
          eg=lglel(e,node)
          do i=1,nxyz
             glo_num(i,e) = i+nxyz*(eg-1)  ! Important: gs_op() is "1" based
          enddo
       enddo


Note that the above loop assigns a _unique_ value to glo_num().
Passing this array to gs_setup() will result in subsequent gs_op()
calls using the handle returned by gs_setup() to be NO-OP.

Now, suppose you want to copy values at Position 16 (eg=4,i=4) to
Position 1.   It suffices to set (p=1) glo_num(1,4)=1 or, conversely,
to set (p=0) glo_num(1,1)=16.  In 2D or 3D, this is best done by adding
an offset to the glo_num() for all values that are on the inflow faces, 
since these locations are readily identified and the offset is readily
computed in terms of number of elements per slab and the number of
slabs by which you wish to translate the BC.

That's what my original code does:

          nslab = 24                                ! 35 slabs total
          if (eg.le.2100) nslab = 25                ! 35 slabs total

          nface = 2*ndim
          do f=1,nface              ! connect inflow to elems above

             ioff = nxyz*60*nslab   ! 60 elem/slab x n slabs

             if (cbc(f,e,1).eq.'v  ') then
                do i=1,nx1*ny1
                   ptr(i,1,1,e) = ptr(i,1,1,e) + ioff
                enddo
             endif

          enddo

       enddo

       call gs_setup(gs_bc_hndl,ptr,n,nekcomm,np) ! connect v + downstream


Note as an additional refinement (not requisite), I set ptr==0 for
all points interior to the spectral elements.   If ptr (i.e., glo_num)
is zero, then gs_setup will ignore it, thus saving time and memory 
in the setup phase.   A consequence of this savings mechanism is
that glo_num() must be a 1-based, not 0-based, index.

Does this help at all?

Paul







On Tue, 3 Feb 2009, Stefan Kerkemeier wrote:

uups, that the right one:

      do e=1,nelv

         eg = lglel(e,node)
         do j=1,nxyz
             il   = j + nxyz*(e-1)
             eshift = eg + nslab*ne_per_slab
             ishift = j + nxyz*(eshift-1)
             glo_num(il) = 0
             if (eg.le.ne_per_slab) glo_num(il) = ishift
          enddo

       enddo


Stefan Kerkemeier wrote:
  Hi Paul,

  can you check the following code. I'am wondering if that's the correct way
  to connect a slab in the pipe (close to the outflow) with the pipe inlet.
  As in your example I assume that the mesh was created by n2to3.

        eshift = nslab*ne_per_slab  ! ne_per_slab=20, nslab=8, say

        do e=1,nelv
        do j=1,nxyz
           iloc   = j + nxyz*(e-1)
           ishift = j + nxyz*(eshift-1)
           glo_num(iloc) = 0
           ! connect second last slice with inflow
           if (eg.le.ne_per_slab) glo_num(iloc) = ishift
        enddo
        enddo

  Then I all gs_setup using the glo_num array to get a handle. Every gs_op()
  using this handle will act only on the inflow and slab close to the
  outflow.

  Is that right?


  -Stefan








More information about the Nek5000-users mailing list