Многомерная интеграция с quadpack приводит к рекурсивному вызову нерекурсивной процедуры dqage.

Я пытаюсь численно выполнить 2D-интеграл, используя библиотеку quadpack double . Поскольку на этом веб-сайте нет встроенного движка Latex, я прилагаю картинку с математикой.

Также ниже прикрепляю свою реализацию этой операции в модуле test_module.

module test_module
  use f90_kind ! defines dp
  use physconst ! defines pi
  use global_variables ! defines the variables for quadpack
  use csv_file ! allows me to write to a csv file

  implicit none

  real(dp) :: a, b, c ! parameters I want to set

contains

  real(dp) function multi_val_func(theta)
    real(dp), intent(in) :: theta

    multi_val_func = exp(theta**2 + c*theta)

  end function multi_val_func

  real(dp) function theta_integral(phi)
    real(dp), intent(in) :: phi

    c = phi*(a+b)

    ! Quadpack variables
    epsabs = 1.0E-14_dp
    epsrel = 0.0E0_dp
    key    = 6
    ilow   = 0.0E0_dp
    ihigh  = 2.0E0_dp*pi

    call dqage(multi_val_func, ilow, ihigh, epsabs, epsrel, key, limit, &
               res, abserr, neval, ier, alist, blist, rlist, elist, iord, last)

    theta_integral = res

  end function theta_integral

  subroutine phi_integral(final_result)
    real(dp),intent(out) :: final_result

    a = 1.0E0_dp
    b = 1.0E0_dp

    ! Quadpack variables
    epsabs = 1.0E-14_dp
    epsrel = 0.0E0_dp
    key    = 6
    ilow   = 0.0E0_dp
    ihigh  = pi

    call dqage(theta_integral, ilow, ihigh, epsabs, epsrel, key, limit, &
               res, abserr, neval, ier, alist, blist, rlist, elist, iord, last)

    final_result = res

    print *, final_result

  end subroutine phi_integral

end module test_module

В основном файле я определяю переменную result, а затем call phi_integral(result). Я компилирую этот код, используя следующий make-файл

FFLAGS = -O0 -fcheck=all -ffree-line-length-none

debug:
    gfortran -c $(FFLAGS) $(srcdir)/f90_kind.f90
    gfortran -c $(FFLAGS) $(srcdir)/physconst.f90
    gfortran -c $(FFLAGS) $(srcdir)/global_variables.f90
    gfortran -c $(FFLAGS) $(extlib_qp)/quadpack_double.f90
    gfortran -c $(FFLAGS) $(extlib_csv)/csv_file.f90
    gfortran -c $(FFLAGS) $(srcdir)/multi_var_integration.f90
    gfortran -c $(FFLAGS) $(srcdir)/main.f90
    gfortran *.o -o debug -lblas -llapack
    rm -f *.o *.mod

Код компилируется, но когда я его запускаю, я получаю следующую ошибку:

Fortran runtime error: Recursive call to nonrecursive procedure 'dqage'

Error termination. Backtrace:
#0  0x103a28d3d
#1  0x103a299f5
#2  0x103a29fd6
#3  0x1039f94b6
#4  0x1039dee59
#5  0x1039fad68
#6  0x1039f9948
#7  0x1039dec7d
#8  0x1039def61
#9  0x1039defa3

Любое предложение по решению этой проблемы приветствуется.

Вы понимаете, что означает «Рекурсивный вызов нерекурсивной процедуры» и каковы последствия? Вероятно, вам лучше попытаться использовать квадратурную процедуру/пакет, предназначенный для двумерных интегралов.

francescalus 18.12.2020 18:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
1
253
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Не каждая подпрограмма или функция в Фортране является реентерабельной или, как ее называет Фортран, «рекурсивной». До Fortran 2018 подпрограмма, которую можно вызвать, находясь уже внутри себя (пусть даже косвенно), должна быть отмечена атрибутом recursive.

Даже если подпрограмма помечена таким образом, она может работать не так, как ожидалось, если она содержит статические (сохраненные) данные или если она использует глобальные переменные (общие блоки, модули).

Я не могу сразу увидеть какие-либо такие статические данные, используемые в http://www.netlib.no/netlib/quadpack/dqage.f, поэтому они могут работать после добавления recursive.

Однако, как указал Франческалус, вам лучше иметь специальную библиотеку 2d-квадратур.

Интеграл theta можно выполнить с помощью функции ошибок erf. См. вольфрам альфа.

Результатом этого является функция одной переменной phi, которую можно вычислить через quadpack. Таким образом, вам не нужна многомерная интегральная процедура.

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