Как я могу преобразовать эти операторы Фортрана в C #? - PullRequest
0 голосов
/ 03 июля 2018

Мне было поручено преобразовать несколько файлов Фортрана в C #. У меня нет выбора, и в этой ситуации я не могу использовать сетевой драйвер Dot для чтения Фортрана. Я любитель, когда дело доходит до C # и использовал Fortran в 1983 году как единственный раз.

У меня есть пара предложений, которые я не могу понять, как вести себя в C # - кто-нибудь, пожалуйста, укажет мне правильное направление?

У меня есть много экземпляров в Фортране, где массив выделяется с помощью команды ALLOCATABLE. Я не знаю, как сделать подобное в C #, позже, в коде, мне нужно ссылаться на это распределение как на проверку.

У меня есть объявление типа:

TYPE Cell
  DOUBLE PRECISION, POINTER :: column(:)
END TYPE Cell

Как мне преобразовать эту декларацию в C #?

У меня есть назначения с использованием вышеуказанной декларации:

TYPE(Cell), POINTER           :: PMAT(:)
TYPE(Cell), POINTER           :: PMATD(:) 
TYPE(Cell), POINTER           :: NMATD(:)     

Как мне объявить эти переменные в C #?

Ответы [ 2 ]

0 голосов
/ 03 июля 2018

Также не программист на C #, но, чтобы получить некоторый опыт, я попытался создать минимум примеров, просматривая учебные страницы. Первый код - это зубчатый массив, который @HPM упоминает в своем ответе:

using static System.Console;

class Program {

    static void Main() {

        double[][] pmat;            // reference to a jagged array
        pmat = new double[ 2 ][ ];  // creates a jagged array of size 2

        pmat[ 0 ] = new double[ 3 ];
        pmat[ 1 ] = new double[ 4 ];

        pmat[ 0 ][ 1 ] = 777.0;
        pmat[ 1 ][ 2 ] = 888.0;

        foreach( var x in pmat[ 0 ] ) WriteLine( x );  // prints 0 777 0
        foreach( var x in pmat[ 1 ] ) WriteLine( x );  // prints 0 0 888 0
    }
}

Второй код использует struct, который является типом значения и, вероятно, похож на type в Фортране. Таким образом, буквальный перевод кода OP может выглядеть как

using static System.Console;

public struct Cell
{
    public double[] column;    // reference to a double array
}

class Program {

    static void Main() {

        Cell[] pmat;  // reference to a Cell array

        pmat = new Cell[ 2 ];  // allocates an array of Cell objects

        pmat[ 0 ].column = new double[ 3 ];
        pmat[ 1 ].column = new double[ 4 ];

        pmat[ 0 ].column[ 1 ] = 777.0;
        pmat[ 1 ].column[ 2 ] = 888.0;

        foreach( var x in pmat[ 0 ].column ) WriteLine( x );  // 0 777 0
        foreach( var x in pmat[ 1 ].column ) WriteLine( x );  // 0 0 888 0
    }
}

Третьим кодом является использование class, который является ссылочным типом. Таким образом, его массив - это что-то вроде массива указателей на Фортране (но не указатель на массив, как объяснено в другом ответе).

using static System.Console;

public class Cell
{
    public double[] column;
}

class Program {

    static void Main() {

        Cell[] pmat;

        pmat = new Cell[ 2 ];  // allocates an array of references (to Cell objects)

        pmat[ 0 ] = new Cell();  // allocates a new object
        pmat[ 1 ] = pmat[ 0 ];   // can point to an existing object

        pmat[ 0 ].column = new double[ 3 ];

        pmat[ 0 ].column[ 1 ] = 777.0;
        pmat[ 1 ].column[ 2 ] = 888.0;  // modifies pmat[0] in practice

        foreach( var x in pmat[ 0 ].column ) WriteLine( x );  // 0 777 888
        foreach( var x in pmat[ 1 ].column ) WriteLine( x );  // 0 777 888
    }
}

Но то же самое кажется возможным и с помощью зубчатого массива (для этого конкретного случая):

double[][] pmat;
pmat = new double[ 2 ][ ];

pmat[ 0 ] = new double[ 3 ];
pmat[ 1 ] = pmat[ 0 ];

pmat[ 0 ][ 1 ] = 777.0;
pmat[ 1 ][ 2 ] = 888.0;

foreach( var x in pmat[ 0 ] ) WriteLine( x );  // 0 777 888
foreach( var x in pmat[ 1 ] ) WriteLine( x );  // 0 777 888
0 голосов
/ 03 июля 2018

Я не вижу никакой причины из того, что было опубликовано, почему эти объявления Фортрана не могут быть заменены вашим любимым подходом C # для определения зубчатых массивов , то есть массива, в котором каждая строка имеет различное количество элементов (в этом случае, конечно, удваивается).

Перво-наперво, объявление, такое как

TYPE(Cell), POINTER           :: PMAT(:)

не объявляет массив указателей на вещи type(cell), он объявляет указатель на массив вещей type(cell); то есть есть один указатель, а его указатель является массивом. В Фортране указатели имеют примерно две цели:

  1. Их можно использовать для динамического выделения памяти во время выполнения; это почти то же самое, что объявить переменную allocatable.
  2. Они могут использоваться для предоставления нескольких ссылок на одни и те же переменные и, в случае массивов, для ссылки на разные слайсы одного и того же массива. Вы узнаете, что происходит в вашем коде, если найдете переменные одного типа с атрибутом target. Если вы не можете, тогда использование pointer почти наверняка является просто способом достижения динамического управления памятью.

Определение типа

TYPE Cell
  DOUBLE PRECISION, POINTER :: column(:)
END TYPE Cell

объявляет cell массивом значений типа double, сколько будет установлено во время выполнения. Затем приходит

TYPE(Cell), POINTER           :: PMAT(:)

, который объявляет, что PMAT будет массивом cell с, и, чушь, у вас есть зазубренный массив двойных чисел. Это обычная фортрановская идиома для объявления зубчатых массивов. Как и все языки правильного мышления, он действительно рассматривает неровные массивы как мерзость, поэтому вам нужно прыгнуть через обруч, чтобы реализовать их.

Я не программист на C #, но я подозреваю, что все эти объявления могут быть реализованы в C # следующим образом:

double[][] pmat = new double[3][];
...
pmat[0] = new double[5];
pmat[1] = new double[4];
pmat[2] = new double[2];
...