FORTRAN 77 3维数组初始化等效于C#

时间:2017-08-19 16:26:08

标签: c# fortran fortran77

我正在尝试将在FORTRAN 77中声明和初始化的三维数组编码为C#中的等效数组。

在做了一些研究之后,我发现FORTRAN 77遵循列主要方法。我仍然无法想象如何表示在C#中用FORTRAN 77初始化的三维数组。这是FORTRAN 77代码,它声明并初始化一个三维数组:

real*4 temperature_factors(2,6,9)/
     c  .000,.054, .055,.070, .071,.085, .086,.105, .106,.200,
     c  -1.0,-1.0,
     c  -1.0,-1.0, -1.0,-1.0, .125,.164, .165,.204, .205,.404,
     c  .405,.604,
     c  0.0,12.0, 12.1,35.4, 35.5,55.4, 55.5,150.4, 150.5,250.4,
     c  250.5,500.4,
     c  0.0,54.0, 55.0,154.0, 155.0,254.0, 255.0,354.0, 355.0,424.0,
     c  425.0,604.0,
     c  0.0,4.4, 4.5,9.4, 9.5,12.4, 12.5,15.4, 15.5,30.4,
     c  30.5,50.4,
     c  .000,.035, .036,.75, .76,.185, -1.,  -1.,  -1., -1.,
     c   -1., -1.,
     c   -1., -1.,  -1., -1., -1., -1.,.186,.304, .305,.604,
     c  .605,1.004,
     c  -1.0,10.0, -1.0,-1.0, -1.0,-1.0, -1.0,-1.0, -1.,-1.0,
     c  -1.0,10.0,
     c  .000,.053, .054,.100, .101,.360, .361,.649, .650,1.249,
     c  1.250,2.049/

我最初尝试在C#中表示上述内容:

double[, ,] temperature_factors = new double[2, 6, 9]
            {
                {
                    {0.000, 0.054,  0.055,  0.070,  0.071,  0.085,  0.086,  0.105,  0.106,},
                    {0.200, -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   0.125,  0.164},
                    {0.165, 0.204,  0.205,  0.404,  0.405,  0.604,  0.0,    12.0,   12.1},
                    {35.4,  35.5,   55.4,   55.5,   150.4,  150.5,  250.4,  250.5,  500.4},
                    {0.0,   54.0,   55.0,   154.0,  155.0,  254.0,  255.0,  354.0,  355.0},
                    {424.0, 425.0,  604.0,  0.0,    4.4,    4.5,    9.4,    9.5,    12.4}
                },

                {
                    {12.5,  15.4,   15.5,   30.4,   30.5,   50.4,   0.000,  0.035,  0.036},
                    {0.75,  0.76,   0.185,  -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   -1.0},
                    {-1.0,  -1.0,   -1.0,   -1.0,   -1.0,   -1.0,   0.186,  0.304,  0.305},
                    {0.604, 0.605,  1.004,  -1.0,   10.0,   -1.0,   -1.0,   -1.0,   -1.0},
                    {-1.0,  -1.0,   -1.0,   -1.0,   -1.0,   10.0,   0.000,  0.053,  0.054},
                    {0.100, 0.101,  0.360,  0.361,  0.649,  0.650,  1.249,  1.250,  2.049}
                }
            };

但显然这不正确。任何人都可以帮我初始化用FORTRAN 77编写的3维数组到C#中的等价数据。

谢谢。

1 个答案:

答案 0 :(得分:0)

Fortran数组是列专用的,因此Fortran代码中的文字值按A的顺序填充到A(1,1,1), A(2,1,1), A(1,2,1), A(2,2,1), ..., A(1,6,9), A(2,6,9)(其中A表示temperature_factors)。另一方面,C#数组是行主要的(根据这个page和一个迷你测试(请参见本答案的底部)),所以我认为我们需要切换索引的顺序来利用直接的文字值序列。具体来说,我们首先从文字值创建一个1D(临时)数组

double[] arr1 = new double[ 9 * 6 * 2 ]
    {
        .000,.054,  .055,.070,  .071,.085,   .086,.105,   .106,.200,    -1.0,-1.0,
        -1.0,-1.0,  -1.0,-1.0,  .125,.164,   .165,.204,   .205,.404,    .405,.604,
        0.0,12.0,   12.1,35.4,  35.5,55.4,   55.5,150.4,  150.5,250.4,  250.5,500.4,
        0.0,54.0,   55.0,154.0, 155.0,254.0, 255.0,354.0, 355.0,424.0,  425.0,604.0,
        0.0,4.4,    4.5,9.4,    9.5,12.4,    12.5,15.4,   15.5,30.4,    30.5,50.4,
        .000,.035,  .036,.75,   .76,.185,    -1.0,-1.0,   -1.0,-1.0,    -1.0,-1.0,
        -1.0,-1.0,  -1.0,-1.0,  -1.0,-1.0,   .186,.304,   .305,.604,    .605,1.004,
        -1.0,10.0,  -1.0,-1.0,  -1.0,-1.0,   -1.0,-1.0,   -1.0,-1.0,    -1.0,10.0,
        .000,.053,  .054,.100,  .101,.360,   .361,.649,   .650,1.249,    1.250,2.049
    };

然后通过循环逐个复制元素(最右边的索引k应该运行得最快):

double [,,] arr3 = new double[ 9, 6, 2 ];

int ind = 0;
for (int i = 0; i < 9; i++)
for (int j = 0; j < 6; j++)
for (int k = 0; k < 2; k++) {
    arr3[ i, j, k ] = arr1[ ind ];
    ind++;
}

或等效地,直接复制一块内存(根据此page

Buffer.BlockCopy( arr1, 0, arr3, 0, arr1.Length * sizeof(double) );

我们可以通过打印arr3的几个元素来检查结果:

// using static System.Console;
WriteLine( arr3[ 0, 0, 0 ] );
WriteLine( arr3[ 0, 0, 1 ] );
WriteLine( arr3[ 0, 1, 0 ] );
WriteLine( arr3[ 0, 1, 1 ] );
WriteLine( "..." );
WriteLine( arr3[ 8, 4, 0 ] );
WriteLine( arr3[ 8, 4, 1 ] );
WriteLine( arr3[ 8, 5, 0 ] );
WriteLine( arr3[ 8, 5, 1 ] );

给出了

0         // A(1,1,1) in Fortran
0.054     // A(2,1,1)
0.055     // A(1,2,1)
0.07      // A(2,2,1)
...
0.65      // A(1,5,9)
1.249     // A(2,5,9)
1.25      // A(1,6,9)
2.049     // A(2,6,9)

要使用与Fortran相同的索引顺序,它也可能有用 创建另一个反转索引顺序的3D数组,例如:

double [,,] arr3_alt = new double[ 2, 6, 9 ];

for (int i = 0; i < 2; i++)
for (int j = 0; j < 6; j++)
for (int k = 0; k < 9; k++) {
    arr3_alt[ i, j, k ] = arr3[ k, j, i ];
}

WriteLine( arr3_alt[ 0, 0, 0 ] );
WriteLine( arr3_alt[ 1, 0, 0 ] );
WriteLine( arr3_alt[ 0, 1, 0 ] );
WriteLine( arr3_alt[ 1, 1, 0 ] );
WriteLine( "..." );
WriteLine( arr3_alt[ 0, 4, 8 ] );
WriteLine( arr3_alt[ 1, 4, 8 ] );
WriteLine( arr3_alt[ 0, 5, 8 ] );
WriteLine( arr3_alt[ 1, 5, 8 ] );

这是一个迷你测试,我试图检查对齐 内存中的数组元素:

    int[,] A = new int[2,3] { {1,2,3}, {4,5,6} };
    int[]  B = new int[6];

    Buffer.BlockCopy( A, 0, B, 0, sizeof(int) * 6 );  // A=src, B=dest, 0=offset, count=in-bytes

    WriteLine( "B[0] = " + B[0] + " A[0,0] = " + A[0,0] );
    WriteLine( "B[1] = " + B[1] + " A[0,1] = " + A[0,1] );
    WriteLine( "B[2] = " + B[2] + " A[0,2] = " + A[0,2] );
    WriteLine( "B[3] = " + B[3] + " A[1,0] = " + A[1,0] );
    WriteLine( "B[4] = " + B[4] + " A[1,1] = " + A[1,1] );
    WriteLine( "B[5] = " + B[5] + " A[1,2] = " + A[1,2] );

给出了

B[0] = 1 A[0,0] = 1
B[1] = 2 A[0,1] = 2
B[2] = 3 A[0,2] = 3
B[3] = 4 A[1,0] = 4
B[4] = 5 A[1,1] = 5
B[5] = 6 A[1,2] = 6