[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