Error on trying to use `boundaries()` in `stencilDist`

I was using the following code to access elements of the physical boundary in a global array A irrespective of the number of locales the code runs on. For this, I was following the Modifying Exterior Ghost Cells section in Chapel documentation on Stencil distribution

import StencilDist.stencilDist;

config const n = 10;
const Space = {1..n};

const Dist = Space dmapped new stencilDist(Space, fluff=(2,), periodic=false);
var A: [Dist] real;

// Initialize interior values
forall i in A.domain do
  A[i] = i:real;

// Print full array including ghost cells
writeln("Full array including ghost cells:");
for i in A.domain do
  writeln("A[", i, "] = ", A[i]);

// Access and print the ghost boundaries
const physical_ghostLeft = A.domain.boundaries(0, -1);
const physical_ghostRight = A.domain.boundaries(0, 1);

writeln("\nLeft ghost boundary:");
for i in physical_ghostLeft do
  writeln("A[", i, "] = ", A[i]);

writeln("\nRight ghost boundary:");
for i in physical_ghostRight do
  writeln("A[", i, "] = ", A[i]);

However, compiling this code gives me the following error:

stencil-demo.chpl:19: error: unresolved call 'StencilDom(1,int(64),one,false).boundaries(0, -1)'
stencil-demo.chpl:19: note: because no functions named boundaries found in scope

I'm not sure if this is the correct way to use this procedure. I would appreciate any help in this regard.

Hi @dutta-alankar ,

Could you try calling boundaries on the array instead of the domain?

Vass

Hi @vass ,
Yes this crossed my mind and I have tried it. Replacing A.domain.boundaries with A.boundaries still gives a similar compilation error.

Hi @dutta-alankar,

Apologies for shooting in the dark. The following changes made your code compile for me:

  • import --> use
  • A.domain.boundaries(....) --> A.boundaries() // no arguments
  • print out the values yielded by this iterator directly
use StencilDist;

config const n = 10;
const Space = {1..n};

const Dist = Space dmapped new stencilDist(Space, fluff=(2,), periodic=false);
var A: [Dist] real;

// Initialize interior values
forall i in A.domain do
  A[i] = i:real;

// Print full array including ghost cells
writeln("Full array including ghost cells:");
for i in A.domain do
  writeln("A[", i, "] = ", A[i]);

// Access and print the ghost boundaries
const physical_ghostLeft = A.boundaries();
const physical_ghostRight = A.boundaries();

writeln("\nLeft ghost boundary:");
for a in physical_ghostLeft do
  writeln(a);

writeln("\nRight ghost boundary:");
for a in physical_ghostRight do
  writeln(a);

From the module doc: "This iterator yields a tuple where the first component is the ghost cell element to be modified, and the second component is a tuple indicating the side on which this ghost cell lives. This direction tuple will contain values in the range -1..1."

Let us know how it goes!

Vass

1 Like

P.S. The following also compiles for me, where I am modifying the ghost cells:

... code as before ...
for (a, off) in physical_ghostLeft {
  a += 1;
  writeln((a, off));
}

Vass

1 Like

@vass Thanks a lot! Following your suggestion, the below code now compiles. But nothing gets printed in the for loop using the iterator returned by boundaries()
Since I was creating 2 fluff cells, I was expecting 4 prints (2 on each side).

import StencilDist.stencilDist;
import StencilDist.boundaries;

config const n = 10;
const Space = {1..n};

const Dist = Space dmapped new stencilDist(Space, fluff=(2,), periodic=false);
var A: [Dist] real;

// Initialize interior values
forall i in A.domain do
  A[i] = i:real;

// Print full array including ghost cells
writeln("Full array including ghost cells:");
for i in A.domain do
  writeln("A[", i, "] = ", A[i]);
A.updateFluff();

// Access and print the ghost boundaries
writeln("\nGhost boundaries:");
for (val, edge) in A.boundaries() do
    writeln((val, edge));

Got it! I had to set periodic=true to achieve this. It gives the following output:

adutt@freya01:grid-code$ chpl ./stencil-demo.chpl -o stencil-demo
adutt@freya01:grid-code$ ./stencil-demo -nl 2
Full array including ghost cells:
A[1] = 1.0
A[2] = 2.0
A[3] = 3.0
A[4] = 4.0
A[5] = 5.0
A[6] = 6.0
A[7] = 7.0
A[8] = 8.0
A[9] = 9.0
A[10] = 10.0

Ghost boundaries:
adutt@freya01:grid-code$ chpl ./stencil-demo.chpl -o stencil-demo
adutt@freya01:grid-code$ ./stencil-demo -nl 2
Full array including ghost cells:
A[1] = 1.0
A[2] = 2.0
A[3] = 3.0
A[4] = 4.0
A[5] = 5.0
A[6] = 6.0
A[7] = 7.0
A[8] = 8.0
A[9] = 9.0
A[10] = 10.0

Ghost boundaries:
9.0(-1,)
10.0(-1,)
1.0(1,)
2.0(1,)

However, I'm unable to change the edge values on ghost. I get a compile error on trying to do so.

Here's the code:

import StencilDist.stencilDist;
import StencilDist.boundaries;

const side_low  =  1;
const side_high = -1;
config const n = 10;
const Space = {1..n};

const Dist = Space dmapped new stencilDist(Space, fluff=(2,), periodic=true);
var A: [Dist] real;

// Initialize interior values
forall i in A.domain do
  A[i] = i:real;

// Print full array including ghost cells
writeln("Full array:");
forall i in A.domain do
  writeln("A[", i, "] = ", A[i]);
A.updateFluff();

// Access and print the ghost boundaries
writeln("\nGhost boundaries (before update):");
forall (arr_val, edge) in A.boundaries() {
    // writeln(edge, " ", edge.type:string);
    // writeln(arr_val, " ", arr_val.type:string);
    for edge_dir in edge {
        if edge_dir==side_low {
            writeln("Left ghost: ", arr_val);
            arr_val = arr_val+1;
        }
        if edge_dir==side_high {
            writeln("Right ghost: ", arr_val);
            arr_val = arr_val+1;
        }
    }
}
A.updateFluff();

writeln("Full array (after update):");
forall i in A.domain do
  writeln("A[", i, "] = ", A[i]);

The compilation error message is

stencil-demo.chpl:31: error: cannot assign to const variable
stencil-demo.chpl:35: error: cannot assign to const variable

To clarify, do you really want this stencil-distributed array to be periodic? If not, you could just write directly to those indices:

use StencilDist;

config const n = 10;
const Space = {1..n};

const Dist = Space dmapped new stencilDist(Space, fluff=(2,), periodic=false);
var A: [Dist] real;

// Initialize interior values
forall i in A.domain do
  A[i] = i:real;

const Outer = Space.expand(2);
// For ghost cells, set to -1.0
for i in Outer {
  // Note 'A.domain.contains(i)' includes ghost cells, so we use 'Space'
  if !Space.contains(i) {
    A[i] = -1.0;
  }
}

A.updateFluff();

// Print full array including ghost cells
writeln("Full array including ghost cells:");
for i in Outer do
  writeln("A[", i, "] = ", A[i]);

For me, this prints:

Full array including ghost cells:
A[-1] = -1.0
A[0] = -1.0
A[1] = 1.0
A[2] = 2.0
A[3] = 3.0
A[4] = 4.0
A[5] = 5.0
A[6] = 6.0
A[7] = 7.0
A[8] = 8.0
A[9] = 9.0
A[10] = 10.0
A[11] = -1.0
A[12] = -1.0
1 Like

@benharsh Awesome! I guess what I wanted was things to be periodic b default with the ability to be changed. I can mix your code and the one I previously had to achieve precisely that. This works. Thanks a lot!