Ошибки 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))
Если проблема заключается в разногласиях по поводу начального индекса, возможно, это поможет.