Problem with function

Hello everyone,

I am working in the field of Computational Fluid Dynamics (CFD). I use to use FORTRAN for writing my codes. Now I decided to use C++. I am new in C++. I have watched some tutorial videos on Youtube. Now, I intend to convert one of my simple FORTRAN codes for heat conduction to a C++ code. I am using CodeBlocks on Windows 10. The following is the main body of my C++ code:

/**********************************************************************
Name: US
Date: July 22, 2018
Program name: practice.ccp
Program description: learning how to work with c++ in CodeBlocks,
***********************************************************************/
#include <iostream>
#include "input.h"
#include "grid.h"
using namespace std;

int main(){
int nx, ny, ml, mr, ms, mn;
double k, lx, ly, dx, dy, ro, cp, alfa, q, Tl, Tr, Ts, Tn;

input(nx, ny, lx, ly, k, ro, cp, alfa, Tl, Tr, Ts, Tn, q, ml, mr, ms, mn);

double x[nx+1][ny+1], y[nx+1][ny+1], T[nx+1][ny+1], aw[nx+1][ny+1], as[nx+1][ny+1], ap[nx+1][ny+1], ae[nx+1][ny+1], an[nx+1][ny+1], bp[nx+1][ny+1];

grid (nx, ny, lx, ly, dx, dy, x, y);
cout << x[1][5] << endl;

return 0;

}

The input function has been defined like this:

void input(int &nx, int &ny, double &lx, double &ly, double &k, double &ro, double &cp, double &alfa, double &Tl, double &Tr, double &Ts, double &Tn, double &q, int &ml, int &mr, int &ms, int &mn){
//length
lx = 1;
//aspect ratio
double AR = 1;
// height
ly = AR * lx;
//nx:x-division number, ny:y-division number
nx=20;
ny=20;
//conductivity
k = 1;
//density
ro = 1;
// heat capacity
cp = 1;
// thermal difusivity
alfa = k/(ro * cp);
// heat flux/(ro*cp)
q = 0;
// boundary indicator (Dirichlet: m=0 and Neumann: m=1) when m=0
//left bondary
ml = 0;
if (ml == 0)Tl = 1;
// right boundary
mr = 0;
if (mr == 0)Tr = 1;
// south boundary
ms = 1;
if (ms == 0)Ts =0;
// north boundary
mn = 0;
if (mn == 0)Tn = 0;
}

#endif // INPUT_H_INCLUDED

the grid function has been defined like this:

void grid (int nx, int ny, double lx, double ly, double &dx, double &dy, double x[][ny], double y[][ny]){
dx = lx / nx;
dy = ly / ny;
for (int i = 0; i < nx+1; i++){
for (int j = 0; j < ny+1; j++){
x[i][j] = (i - 1) * dx;
y[i][j] = (j - 1) * dy;
}
}
}
#endif // GRID_H_INCLUDED

I do not have any problem with inout function. My problem is that I am facing an error in grid function saying that I am not allowed to transfer x and y in this manner.

Could you please let me know what error I have made in the code?

Thanks
It's abnormal to put code in a header file. That's not their usual purpose.
And you have a lot of variables that you aren't using.

I'm not answering your question, just redisplaying the 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
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
71
72
73
void grid (
    int     nx,      int     ny,
    double  lx,      double  ly,
    double &dx,      double &dy,
    double  x[][ny], double  y[][ny])
{
    dx = lx / nx;
    dy = ly / ny;
    for (int i = 0; i < nx+1; i++){
        for (int j = 0; j < ny+1; j++){
            x[i][j] = (i - 1) * dx;
            y[i][j] = (j - 1) * dy;
        }
    }
}

void input(
    int    &nx, int    &ny,
    double &lx, double &ly,
    double &k,  double &ro, double &cp, double &alfa,
    double &Tl, double &Tr, double &Ts, double &Tn,
    double &q,  int    &ml, int    &mr, int    &ms,  int &mn)
{
    double AR = 1; // aspect ratio

    lx = 1;        // length
    ly = AR * lx;  // height
    nx = 20;       // x-division number
    ny = 20;       // y-division number
    k  = 1;        // conductivity
    ro = 1;        // density
    cp = 1;        // heat capacity
    alfa = k / (ro * cp);    // thermal difusivity
    q  = 0;        // heat flux/(ro*cp)

    // boundary indicator (Dirichlet: m=0 and Neumann: m=1) when m=0

    //left bondary
    ml = 0;
    if (ml == 0) Tl = 1;

    // right boundary
    mr = 0;
    if (mr == 0) Tr = 1;

    // south boundary
    ms = 1;
    if (ms == 0) Ts = 0;

    // north boundary
    mn = 0;
    if (mn == 0) Tn = 0;
}

#include <iostream>
using namespace std;

int main()
{
    int nx, ny, ml, mr, ms, mn;
    double k, lx, ly, dx, dy, ro, cp, alfa, q, Tl, Tr, Ts, Tn;

    input(nx, ny, lx, ly, k, ro, cp, alfa, Tl, Tr, Ts, Tn, q, ml, mr, ms, mn);

    double x[nx+1][ny+1],  y[nx+1][ny+1],  T[nx+1][ny+1],
          aw[nx+1][ny+1], as[nx+1][ny+1], ap[nx+1][ny+1],
          ae[nx+1][ny+1], an[nx+1][ny+1], bp[nx+1][ny+1];

    grid (nx, ny, lx, ly, dx, dy, x, y);
    cout << x[1][5] << endl;

    return 0;
}

Last edited on
Here's a possibility using std::vectors.

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
71
72
73
74
75
#include <iostream>
#include <vector>
using namespace std;

typedef vector<double> VD;
typedef vector<VD>     VVD;

void grid (
    int     nx,      int     ny,
    double  lx,      double  ly,
    double &dx,      double &dy,
    VVD    &x,       VVD    &y)
{
    dx = lx / nx;
    dy = ly / ny;
    for (int i = 0; i < nx+1; i++){
        for (int j = 0; j < ny+1; j++){
            x[i][j] = (i - 1) * dx;
            y[i][j] = (j - 1) * dy;
        }
    }
}

void input(
    int    &nx, int    &ny,
    double &lx, double &ly,
    double &k,  double &ro, double &cp, double &alfa,
    double &Tl, double &Tr, double &Ts, double &Tn,
    double &q,  int    &ml, int    &mr, int    &ms,  int &mn)
{
    double AR = 1; // aspect ratio

    lx = 1;        // length
    ly = AR * lx;  // height
    nx = 20;       // x-division number
    ny = 20;       // y-division number
    k  = 1;        // conductivity
    ro = 1;        // density
    cp = 1;        // heat capacity
    alfa = k / (ro * cp);    // thermal difusivity
    q  = 0;        // heat flux/(ro*cp)

    // boundary indicator (Dirichlet: m=0 and Neumann: m=1) when m=0
    //left bondary
    ml = 0; Tl = (ml == 0);
    // right boundary
    mr = 0; Tr = (mr == 0);
    // south boundary
    ms = 1; Ts = (ms != 0);
    // north boundary
    mn = 0; Tn = (mn != 0);
}

int main()
{
    int nx, ny, ml, mr, ms, mn;
    double k, lx, ly, dx, dy, ro, cp, alfa, q, Tl, Tr, Ts, Tn;

    input(nx, ny, lx, ly, k, ro, cp, alfa, Tl, Tr, Ts, Tn, q, ml, mr, ms, mn);

    VVD x (nx+1, VD(ny+1)),
        y (nx+1, VD(ny+1)),
        T (nx+1, VD(ny+1)),
        aw(nx+1, VD(ny+1)),
        as(nx+1, VD(ny+1)),
        ap(nx+1, VD(ny+1)),
        ae(nx+1, VD(ny+1)),
        an(nx+1, VD(ny+1)),
        bp(nx+1, VD(ny+1));

    grid (nx, ny, lx, ly, dx, dy, x, y);
    cout << x[1][5] << endl;

    return 0;
}


Do you mean to start i and j at 0 in the loops in grid? Or are you trying to use 1-based indexing. Starting them both at 0 means that the first (i-1) and (j-1) will both be -1 (but maybe that's what you want).

Assuming all of your T variables are supposed to either be 0 or 1, I changed that code a little. The way it is, they will have arbitrary values if the if condition isn't true. But you don't use the variables anyway, so....
Last edited on
It looks like you are confusing C++ arrays, whose indices start from 0, with arrays in Fortran where they start from 1 by default (although Fortran actually allows you to change that to start from anything). Hence your (i-1) in the grid generator should be i, etc.

You are also inconsistent with array size ny rather than ny+1 as argument to grid.
double x[nx+1][ny+1], y[nx+1][ny+1], ...
then
void grid (..., double x[][ny], double y[][ny] ...)
Which do you want?

In the declaration above you are using variable-length arrays (their size is declared at run time), which isn't legal in standard c++ (and only legal in Fortran if they are allocatable or automatic arrays).

I would seriously consider mapping to 1-d rather than 2-d arrays.

Your argument lists are incredibly long. You would be using modules (I hope) in fortran to pass this much data. Consider using structs or classes in c++. Actually, consider making this much more object-oriented. Your "grid" is fundamentally an object, as, later on, will be your "equation" set (aw[][], ae[][] etc.) and your "field" variables - temperature T[][] in this instance.

As @tpb said, you should only put function declarations (and, possibly, very small functions) in headers, not large function definitions - those should be in separate .cpp files. This is very different from modern fortran, where a module would serve both purposes.

If your grid is going to be uniform (as in this case) I would seriously question whether you need arrays x[][] and y[][]. You are only ever going to use dx and dy in creating your coefficients aw[][], ae[][] etc.


Love it that there seems to be a universal convention for naming arrays in CFD though! I, and all my colleagues, use exactly the same notation for arrays aw, ae, ... , bp etc. The legacy of Patankar's book and the early Imperial College CFD codes obviously lives on!
Last edited on
Topic archived. No new replies allowed.