Ошибки METIS Seg при запуске из Фортрана

Я пытаюсь использовать библиотеку METIS для разбиения сетки как часть программы на Фортране, которую я написал для конечно-элементных вычислений. METIS написана на C, но она должна нормально работать с Fortran 90. Но я продолжаю получать ошибки seg.

Один потенциальный сбой заключается в том, что есть несколько аргументов, на которые я даю нулевые указатели. У некоторых других людей возникли проблемы с получением вызова C-функции из Фортрана для распознавания объекта с нулевым указателем. Это было решено здесь, и я не думаю, что это проблема, которую я имею.

Я думаю, что проблема в том, чтобы заставить METIS изменить индекс начального массива; в С это 0, в Фортране это 1. Там есть options массив передается каждой функции, которая должна иметь поле METIS_OPTION_NUMBERING что вы измените на 1 если вы хотите соглашение Фортрана. Невыполнение этого требования приведет к тому, что программы на C попытаются получить доступ к индексу 0, что приведет к ошибке seg.

Пост edunlop1 здесь предполагает, что я просто делаю массив options и некоторые согласованные соглашения с METIS определяют, какой элемент этого массива должен быть установлен в 1 для того, чтобы он перенумеровывал все. Но что это меняет в зависимости от того, какую подпрограмму вы используете, равно как и длину массива.

Во всяком случае, вот мой код:

integer :: ndomains,ncommon,objval
integer :: options(0:40)
integer, dimension(:), allocatable :: eptr,eind
integer, pointer :: vwgt(:)=>null(), vsize(:)=>null(), opts(:)=>null()
real(kind=8), pointer :: tpwgts(:)=>null()

! Read in the mesh data
call getarg(1,meshname)
call readmesh(meshname)
allocate(color(ne),domain(nn))
allocate(eind(3*ne),eptr(ne+1))
do n=1,ne
    eptr(n) = 1+3*(n-1)
    do i=1,3
        eind( eptr(n)+i-1 ) = elem(i,n)
    enddo
enddo

! Try and call METIS
ncommon = 2
ndomains = 2
options = 0
options(0) = 1
options(8) = 1
call METIS_PartMeshDual(ne,nn,eptr,eind,vwgt,vsize, &
    & ncommon,ndomains,tpwgts,options,objval,color,domain)

Соответствующий код в METIS для изменения нумерации находится в файле libmetis/meshpart.c:

/* renumber the mesh */
if (options && options[METIS_OPTION_NUMBERING] == 1) {
  ChangeMesh2CNumbering(*ne, eptr, eind);
  renumber = 1;
}

Какие-нибудь мысли? Я могу опубликовать вывод Valgrind, если это будет полезно.

3 ответа

Решение

Использование:

vwgt=>null() 

вместо

vwgt(:)=>null()

для всех нулей (т. е. vwgt, vsize, opts, tpwgts и т. д.). Проблема в том, что vwgt(:) на самом деле не определен в отличие от vwgt или vwgt(1). Если у вас все еще есть проблемы, используйте отладчик для проверки всех значений.

Я был ОП в теме, упомянутой во 2-м пункте. Окончательное решение, к сожалению, находится в верхней части ответов (см. Отметку времени). Надеюсь, это поможет.

Возможно, в этом нет ничего, но, возможно, связанный пост во втором абзаце вопроса по-прежнему актуален.

POINTER в Fortran и указатель в C - это не совсем одно и то же понятие, особенно если указатель Fortran относится к массиву. Реализация указателя на массив в Фортране должна хранить дополнительную информацию (границы массива или эквивалентную) сверх той, которая хранится в указателе C (который является просто адресом данных).

(Технически, если соответствующие определения фиктивных аргументов для METIS_PartMeshDual не имеют дополнительных атрибутов или атрибутов указателя (невозможно, если вызывается функция C, а языковой стандарт <= F2008), тогда ссылки на разобщенные указатели в вызове в Fortran являются незаконно. Опять же - реализация зависит от того, что произойдет - я могу представить варианты реализации, где это будет работать, а где нет.)

Обратите внимание, что в сообщении, которое вы связали с объявлениями нулевых указателей, в качестве решения было изменено значение массива на скаляры (первый ответ в списке - проверьте время публикации). В коде примера, размещенном как часть вопроса, объявления для "нулевых" вещей все еще показывают массивы. Я подозреваю, что изменение в объявлении изменяет "установку" для вызова C api и / или как выглядит диссоциированный указатель для вашего компилятора.

В наши дни при вызове C API из Fortran я предпочитаю (где это возможно) писать интерфейсные блоки для C API, используя возможности взаимодействия с C на Fortran 2003 (BIND(C) и друзья). Это намного более надежно и позволяет избежать такого рода проблем, зависящих от платформы. Для этого требуется единовременная предварительная работа, а также компилятор Fortran, поддерживающий этот аспект F2003. Поставщики библиотек, которые занимаются предоставлением таких блоков интерфейса для своих пользователей на Фортране, получают большую галочку и много добрых мыслей от меня.

Размеры массивов Fortran более гибки, чем C. Вы можете сделать массивы Fortran 0-indexed или любой начальный индекс, который вы хотите.

real, dimension (0:N-1) :: array
real, dimension (:), allocatable :: group
allocate (group (0:N-1))

Если проблема заключается в разногласиях по поводу начального индекса, возможно, это поможет.

Другие вопросы по тегам