1

I am currently implementing a computational fluid dynamics algorithm in C. It is already working for 2d systems and now I am working on it solving axisymmetric systems.

During the simulation all the data are stored in several 2-dimensional arrays (for the 2-d simulations) and 3-dimensional arrays (for the axisymmetric one).

Currently I have a solver function to solve several of the equations.

void solver(double ** data, Coefficients *coeff, Grid *grid)

Where:

data

contains the array I want to store the solved equations in

This works fine for the 2d system. When doing the axisymmetric system I would like to re-use this function without having to re-write or change it to take a 3d array, as I only need to solve one slice along the axis.

To do this I am thinking of creating a new 2-d array that holds all the pointers to the 2-d slice of the 3-d array.

I have been playing around with some test code to try out this concept but I can't get it to produce output that makes sense. This is what I have come up with so far:

#include <stdlib.h>
#include <stdio.h>


double *** alloc_3d_matrix(int x_dim, int y_dim, int z_dim)
{
    int i, j;
    double *** m;
    m = calloc(x_dim, sizeof(double**));

    for (i = 0; i < x_dim; i++)
    {
        m[i] = calloc(y_dim, sizeof(double*));
        for (j = 0; j < y_dim; j++)
        {
            m[i][j] = calloc(z_dim, sizeof(double));
        }
    }

   return m;
}

double *** alloc_2d_matrix(int x_dim, int y_dim)
{
    int i;
    double *** m;
    m = calloc(x_dim, sizeof(double*));
    for (i = 0; i < y_dim; i++)
    {
        m[i] = calloc(y_dim, sizeof(double));
    }
    return m; 
}

void free_3d_matrix(void *** m, int x_dim, int y_dim)
{
    int i, j;
    for (i = 0; i < x_dim; i++)
    {
        for (j = 0; j < y_dim; j++)
        {
            free(m[i][j]);
        }
        free(m[i]);
    }
    free(m);
}

void free_2d_matrix(void ***m, int x_dim)
{
    int i;
    for (i = 0; i < x_dim; i++)
    {
        free(m[i]);
    }
    free(m);
}


void increment(double ** slice)
{
    int i, j;
    int sum = 0;
    for (i = 0; i < 5; i++)
    {

        for (j = 0; j < 5; j++)
        {
            sum++;
            slice[i][j] = sum;
        }
    }
}


int main()
{
    int i, j;
    double *** d3, ***d2;
    FILE *fp;
    fp = fopen("test.txt", "w");

    d2 = (double***)alloc_2d_matrix(5, 5);
    d3 = alloc_3d_matrix(5, 5, 5);

    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
            d2[i][j] = &d3[i][j][0];
        }
    }

    increment(*d2);

    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
            fprintf(fp,"%f, %p, %p\n", d3[i][j][0], &d3[i][j][0], d2[i][j]);
        }
    }

    fclose(fp);
    free_3d_matrix(d3, 5, 5);
    return 0;

}

I feel like this should produce an output that looks like this:

1.000000, 00E5A4B0, 00E5A4B0

2.000000, 00E5FCA8, 00E5FCA8

3.000000, 00E5FD00, 00E5FD00

4.000000, 00E5FBA0, 00E5FBA0

5.000000, 00E5F678, 00E5F678

etc.

Instead I'm getting an output of this:

1.000000, 00E5A4B0, 00E5A4B0

6.000000, 00E5FCA8, 00E5FCA8

11.000000, 00E5FD00, 00E5FD00

16.000000, 00E5FBA0, 00E5FBA0

21.000000, 00E5F678, 00E5F678

0.000000, 00E5FB48, 00E5FB48

0.000000, 00E5F728, 00E5F728

0.000000, 00E5F620, 00E5F620

0.000000, 00E5FD58, 00E5FD58

I'm not sure where I have gone wrong in my code and would appreciate any help.

Edit:

Added the rest of the functions.

7
  • 1
    That you have to cast the result of alloc_2d_matrix is a good indicator that you're doing something you should not do. Can you please show the function (or at least its declaration)? Commented Dec 11, 2015 at 9:10
  • Need to see an MCVE. Commented Dec 11, 2015 at 9:20
  • instead of this d2[i][j] = &d3[i][j][0]; try this d2[i][j] = &d3[0][i][j]; Commented Dec 11, 2015 at 9:30
  • 1
    Your alloc_2d_matrix function is not correct. It allocates an array of arrays of double, instead of an array of arrays of pointers to double. If you compare it to the alloc_3d_matrix function you will undoubtedly see that it returns the same type, which means it needs to do just about the same thing (except the innermost allocation). You can avoid this problem by not using the specific types in the sizeof expression, but instead do e.g. sizeof(*m) for the outer level, and sizeof(*m[i]) for the inner. Commented Dec 11, 2015 at 9:49
  • I added the rest of the functions Commented Dec 11, 2015 at 9:49

1 Answer 1

1

In C, a multi-dimensional array is conceptually an array whose elements are also arrays. So if you do:

int array[2][3]; Conceptually you end up with:

array[0] => [0, 1, 2]
array[1] => [0, 1, 2]

int array[2][3][2]; ...will give you a structure like:

array[0] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]
array[1] => [0] => [0, 1]
            [1] => [0, 1]
            [2] => [0, 1]

so try this d2[i][j] = &d3[0][i][j]; instead of d2[i][j] = &d3[i][j][0];

EDIT ---- try d2[i][j]=&d3[i][j][j];

Sign up to request clarification or add additional context in comments.

1 Comment

This made the first row of the output correct but the rest of them were all 0 and the memory addresses didn't match.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.