3D C++ array

This feels like a pretty simple question, but I keep getting my indexing incorrect/confused here. Basically, I have these 2D C++ arrays that I am trying to extend to a 3D C++ array? For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static const int nx = 8; 
static const int ny = 8;

double Lx = 8;
double Ly = 8;
double dx = Lx / nx;
double dy = Ly / ny;

double *xarr;
xarr = (double*) fftw_malloc((nx*ny) *sizeof(double));
memset(XX, 42, (nx*ny) * sizeof(double)); 

double *yarr;
yarr= (double*) fftw_malloc((nx*ny) *sizeof(double));
memset(YY, 42, (nx*ny) * sizeof(double)); 
	
  for(int i = 0; i< nx; i++){
		for(int j = 0; j< ny; j++){ 
			xarr[j + ny*i] = i*dx;
			yarr[j + ny*i] = j * dy; 
 			
		}		
	}

Basically, I am trying to change xarr and yarr into a 3D c++ array (I know it's not the same idea as a tensor or anything) but I am trying to keep my indexing consistent with the above code. So, if I add a third array zarr and create the following nested for loop, is my indexing correct?:
1
2
3
4
5
6
7
8
9
10
for(int i = 0; i< nx; i++){
	for(int j = 0; j< ny; j++){
                for(int k=0; k<nz; k++){
                       xarr[k + nz * (j + ny * i)] = i*dx;
                       yarr[k + nz * (j + ny * i)] = j*dy;
                       zarr[k + nz * (j + ny * i)] = k*dz;
                }
           }
      }


I am not really sure if I am conveying what I am trying to do clearly.
Last edited on
What exactly are you trying to do?

A 3-d array is not 3 arrays. Each cell of an 3d array contain a 2d array. Each cell of a 2d array contains a 1d array. Thus when you want a 'flat' 3d array (1d -> 3d) you need to multiply the index of such a cell with the 2d size. If you want the index of a cell within the 2d array you need to multiply the index with the size of the 1d array:

index_1d = z * sizeof_2d + y * sizeof_1d + x

for 3d array size of 8x8x8:

index_1d = z * 8 * 8 + y * 8 + x
What exactly are you trying to do?

Basically, I have the following Eigen tensors that I am trying to rewrite as C++ arrays and get a matching outputs:

Eigen code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Eigen::Tensor<double, 3> eXX(nx,ny,nz); 
Eigen::Tensor<double, 3> eYY(nx,ny,nz); 
Eigen::Tensor<double, 3> eZZ(nx,ny,nz); 
for(int i = 0; i< nx; i++){
		for(int j = 0; j< ny; j++){
			for(int k = 0; k< nz; k++){ 
				xarr(k,i,j) = i*dx;
				yarr(j,i,k) = j*dy;
				zarr(j,i,k) = k*dz; 
			}

		}		
	}


C++ Array code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
double *XX;
	XX = (double*) fftw_malloc((nx*ny*nz) *sizeof(double));
	memset(XX, 42, (nx*ny*nz) * sizeof(double)); 

    double *YY;
	YY = (double*) fftw_malloc((nx*ny*nz) *sizeof(double));
	memset(YY, 42, (nx*ny*nz) * sizeof(double)); //test: XX for some reason isn't the correct dimensions, maybe this is why
	
	double *ZZ;
	ZZ = (double*) fftw_malloc((nx*ny*nz) *sizeof(double));
	memset(ZZ, 42, (nx*ny*nz) * sizeof(double)); //test: XX for some reason isn't the correct dimensions, maybe this is why
	

    for(int i = 0; i< nx; i++){
		for(int j = 0; j< ny; j++){ 
            for(int k =0; k<nz; k++){
                XX[k + nz * (j + ny * i)] = i*dx;
                YY[k + nz * (j + ny * i)] = j*dy;
                ZZ[k + nz * (j + ny * i)] = l*dz;
            }		
 			
	}		
}

The outputs from above codes only match for XX and eXX at least that's what I think is happening, kinda hard to compare the output of a for loop to a structured eigen tensor.

Outputs:
XX and eXX
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
160
160
160
160
160
160
160
160
160
160
160
160
160
160
160
160
320
320
320
320
320
320
320
320
320
320
320
320
320
320
320
320
480
480
480
480
480
480
480
480
480
480
480
480
480
480
480
480


  0 160 320 480   0 160 320 480   0 160 320 480   0 160 320 480
  0 160 320 480   0 160 320 480   0 160 320 480   0 160 320 480
  0 160 320 480   0 160 320 480   0 160 320 480   0 160 320 480
  0 160 320 480   0 160 320 480   0 160 320 480   0 160 320 480

However, the other two arrays/tensors aren't matching (YY, eYY and ZZ, eZZ).
Have you considered vector<vector<vector<double> > > ? The code will be easier, although it will have the disadvantage of lots of pointers.

I'd write a little class to represent the 3D array. Test the class and then use it. This isn't up to modern C++ practices, bit it gives you the idea:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>				 //Required for cin, cout

using std::cin;
using std::cout;

class Arr3D {
public:
    Arr3D(unsigned x, unsigned y, unsigned z);
    ~Arr3D();
    double &operator()(unsigned x, unsigned y, unsigned z);
private:
    Arr3D(const Arr3D&);
    double &operator=(const Arr3D&);
    unsigned nx, ny, nz;
    double *data;
};

Arr3D::Arr3D(unsigned x, unsigned y, unsigned z) :
    nx(x), ny(y), nz(z), data(new double[x*y*z])
{}

Arr3D::~Arr3D()
{
    delete[] data;
}

double &
Arr3D::operator()(unsigned x, unsigned y, unsigned z)
{
    return data[z + y*nz + x*ny*nz];
}

int
main(int argc, char **argv)
{
    unsigned nx, ny, nz;
    cin >> nx >> ny >> nz;
    Arr3D myarr(nx, ny, nz);
    int i=0;
    for (unsigned x=0; x<nx; ++x) {
	for (unsigned y=0; y<ny; ++y) {
	    for (unsigned z=0; z<nz; ++z) {
		myarr(x,y,z) = ++i;
	    }
	}
    }

    for (unsigned x=0; x<nx; ++x) {
	for (unsigned y=0; y<ny; ++y) {
	    for (unsigned z=0; z<nz; ++z) {
		cout << myarr(x,y,z) << ' ';
	    }
	    cout << '\n';
	}
	cout << '\n';
    }
}

Topic archived. No new replies allowed.