2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему
 
 Mathematica: ускорение численного интегрирования
Сообщение04.12.2017, 21:48 


22/06/12
417
Столкнулся с бедой, что NIntegrate и Plot3D работают крайне медленно. Один график строится полдня. Приведу минимальный пример, в котором отображен основной алгоритм расчёта.

Сначала я численно решаю уравнение:
Код:
eqn = j - Sqrt[q^2 + qp^2 - 2*q*qp*Cos[\[Theta]]] -
         Sqrt[qp^2 + (1/2)*(16*m5^2 + ma^2 + mp^2 -
                  Sqrt[(-(16*m5^2) - ma^2 - mp^2)^2 -
                      4*(ma^2*mp^2 - 16*m5^2*qp^2)])] == 0;
With[{gensol = Solve[eqn, qp]},
     Block[{m = 5.5, M = 300, Nc = 3,
         c = ScientificForm[-44687.3983417778],
         b = ScientificForm[161593.81818181818],
         k1 = ScientificForm[16.485010961790245],
         k2 = ScientificForm[-13.131344420001051], ma, mp, j},
       {j = Sqrt[q^2 + (1/2)*(16*m5^2 + ma^2 + mp^2 +
                     Sqrt[(-(16*m5^2) - ma^2 - mp^2)^2 -
                         4*(ma^2*mp^2 - 16*m5^2*q^2)])],
          ma = Sqrt[-2*(M^2 - 2*(3*k1 + k2)*
                     (Sqrt[(c + M^2 + 2*m5^2)/(2*(k1 + k2))] +
                          m*(b/(2*(c + M^2 + 2*m5^2))))^2 - c +
                   2*m5^2)], mp = Sqrt[(2*b*m)/
                (Sqrt[(c + M^2 + 2*m5^2)/(2*(k1 + k2))] +
                   m*(b/(2*(c + M^2 + 2*m5^2))))]};
        sols = gensol]];
qpC12 = Compile[{{q, _Complex}, {m5, _Complex},
         {\[Theta], _Complex}}, Evaluate[qp /. sols[[2]]],
       RuntimeOptions -> "EvaluateSymbolically" -> False];
qp32 = Re[qpC12[q, m5, \[Theta]]];


Далее я провожу численное интегрирование:
Код:
  qqq[q_?NumericQ, m5_?NumericQ] :=
  NIntegrate[(
     q^2 qp32^2 Sin[\[Theta]]^2 )/((2 (2 \[Pi])^2)  Sqrt[-(2 q Cos[\
\[Theta]] qp32) + qp32^2 + q^2]) , {\[Theta], 0, Pi/2}];


И строю график:
Код:
Plot3D[qqq[q, m5], {q, 0.8, 150}, {m5, 0, 150}]


Данный пример занимает 80 секунд. Читал советы, что ускорить расчёт можно через первообразную, но у меня функция нескольких параметров и я не сильно понимаю как это сделать для неё.
Пробовал так:
Код:
f1[q_, m5_, \[Theta]_] := (q^2 qp32[q,
      m5, \[Theta]]^2 Sin[\[Theta]]^2)/((2 (2 \[Pi])^2) Sqrt[-(2 q \
Cos[\[Theta]] qp32[q, m5, \[Theta]]) + qp32[q, m5, \[Theta]]^2 + q^2])

f2sol = ParametricNDSolve[{D[f2[q, m5, \[Theta]], \[Theta]] ==
    f1[q, m5, \[Theta]], D[f2[q, m5, \[Theta]], \[Theta]] == 0},
  f2, {\[Theta], 0, Pi/2}, {q, m5},
  Method -> {"ParametricSensitivity" -> None}]
Plot3D[f2sol[q, m5, \[Theta]], {q, 0.8, 150}, {m5, 0, 150}]

Но такой алгоритм не получилось завести. Для справки, для одной переменной, очень легко завести такой алгоритм. Например, простейший пример:
Код:
f[x_] := Sin[x^2]
iF = NDSolveValue[{F2'[x] == f[x], F2[0] == 0}, F2, {x, 0, 5}]
Plot[iF[x], {x, 0, 5}]


Буду благодарен любым советам и предложениям! Возможно стоит попробовать сделать всё на питоне?

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение05.12.2017, 12:08 


11/07/16
825
При построении графика получаю сообщение об ошибке
Код:
NIntegrate::inumr: The integrand (0.00832331 Re[(0.202667 Cos[\[Theta]] (<<1>>))/(2.11694*10^-7+<<5>>)-<<1>> <<1>>+1/2 Sqrt[<<1>>]]^2 Sin[\[Theta]]^2)/(\[Sqrt](0.657182 -1.62134 <<1>> Re[0.202667 Cos[<<1>>] Power[<<2>>] Plus[<<11>>]-<<1>>+1/2 Power[<<2>>]]+Re[0.202667 Cos[<<1>>] Power[<<2>>] Plus[<<11>>]-1/2 <<1>>+1/2 Power[<<2>>]]^2)) has evaluated to non-numerical values for all sampling points in the region with boundaries {{0,1.5708}}.

Задумайтесь над этим.

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение09.12.2017, 19:21 


22/06/12
417
Markiyan Hirnyk
к сожалению, пока не думается на счёт этого, можно подсказку?

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение09.12.2017, 19:53 
Заслуженный участник


27/04/09
28128
Решил-таки глянуть, что тут. Итак, зачем, к примеру, вы использовали ScientificForm при присвоении значений переменным блока? Это формат вывода, на значения он никак не влияет.

illuminates в сообщении #1273535 писал(а):
к сожалению, пока не думается на счёт этого, можно подсказку?
Вычислите просто qqq[1, 1], к примеру. Сообщение буквально говорит, что подынтегральное выражение (integrand) вычислолось во что-то нечисловое на всех точках некоторого промежутка. Если посмотреть на выдаваемое невычисленное выражение

Код:
NIntegrate[(1^2 qp32^2 Sin[\[Theta]]^2)/((2 (2 \[Pi])^2) Sqrt[-(2 Cos[\[Theta]] qp32) + qp32^2 + 1^2]), {\[Theta], 0, \[Pi]/2}]

видно, что вы напортачили с определениями, и qp32 не было вычислено вовремя.

-- Сб дек 09, 2017 21:59:58 --

А, нет, не так. Само qp32 вычисляется — но в громадное символьное выражение, зависящее от переменных, и притом ещё и весьма долго. Вы бы эти параметры выше определили, а то ваш минимальный пример на самом деле не пример, а хотелось бы, если вам интересны какие-то соображения, иметь возможность запускать то же, что и у вас.

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение11.12.2017, 11:21 


22/06/12
417
arseniiv
Извините, я хотел чтоб на форуме код максимально коротко и поэтому использовал ScientificForm, но действительно, оказалось что если скопировать предоставленный мной код, он просто не будет работать. Давайте ещё раз. Мой рабочий код это:

Код:
eqn = j -
    Sqrt[q^2 + qp^2 -
      2 q qp Cos[\[Theta]]] - \[Sqrt](qp^2 +
       1/2 (16 m5^2 + ma^2 + mp^2 -
          Sqrt[(-(16 m5^2) - ma^2 - mp^2)^2 -
            4 (ma^2 mp^2 - 16 m5^2 qp^2)])) == 0;
With[{gensol = Solve[eqn , qp]},
  Block[{m = 5.5, M = 300, Nc = 3, c = \!\(\*
TagBox[
InterpretationBox[
RowBox[{"\"\<-4.46874\>\"", "*",
SuperscriptBox["10", "\"\<4\>\""]}],
-44687.3983417778,
AutoDelete->True],
ScientificForm]\), b = \!\(\*
TagBox[
InterpretationBox[
RowBox[{"\"\<1.61594\>\"", "*",
SuperscriptBox["10", "\"\<5\>\""]}],
161593.81818181818`,
AutoDelete->True],
ScientificForm]\), k1 = \!\(\*
TagBox[
InterpretationBox[
RowBox[{"\"\<1.6485\>\"", "*",
SuperscriptBox["10", "\"\<1\>\""]}],
16.485010961790245`,
AutoDelete->True],
ScientificForm]\), k2 = \!\(\*
TagBox[
InterpretationBox[
RowBox[{"\"\<-1.31313\>\"", "*",
SuperscriptBox["10", "\"\<1\>\""]}],
-13.131344420001051`,
AutoDelete->True],
ScientificForm]\), ma, mp,
    j},(*subs vals when gensol is evaluated*){j = \[Sqrt](q^2 +
        1/2 (16 m5^2 + ma^2 + mp^2 +
           Sqrt[(-(16 m5^2) - ma^2 - mp^2)^2 -
             4 (ma^2 mp^2 - 16 m5^2 q^2)])),
    ma = \[Sqrt](-2 (M^2 -
          2 (3 k1 + k2) (Sqrt[(c + M^2 + 2 m5^2)/(2 (k1 + k2))] +
             m b/(2 (c + M^2 + 2 m5^2)))^2 - c + 2 m5^2)),
    mp = Sqrt[
     2 b m (Sqrt[(c + M^2 + 2 m5^2)/(2 (k1 + k2))] +
        m b/(2 (c + M^2 + 2 m5^2)))^-1]};
   sols = gensol]];
qpC12 = Compile[{{q, _Complex}, {m5, _Complex}, {\[Theta], _Complex}},
    Evaluate[qp /. sols[[2]]],
   RuntimeOptions -> "EvaluateSymbolically" -> False] ;
qp32 = Re@qpC12[q, m5, \[Theta]];

далее
Код:
qqq[q_?NumericQ, m5_?NumericQ] :=
NIntegrate[(q^2 qp32^2 Sin[\[Theta]]^2)/((2 (2 \[Pi])^2) Sqrt[-(2 q \
Cos[\[Theta]] qp32) + qp32^2 + q^2]), {\[Theta], 0, Pi/2}];

И далее
Код:
Plot3D[qqq[q,m5],{q,0.8,150},{m5,0,150}]

Постройка графика занимает 80 секунд. И мне хотелось бы понять, как можно ускорить код.

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение11.12.2017, 17:39 
Заслуженный участник


25/02/11
1797
Опция PlotPoints -> 10 в Plot3D уполовинивает время (возможно, за счет некоторого огрубления графика).

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение13.12.2017, 00:09 


22/06/12
417
Vince Diesel
Спасибо удалось ускорить расчет графика до 6 часов с 12-ти. Конечно тоже плохо, ибо графиков нужно пару десятков...

 Профиль  
                  
 
 Re: Mathematica: ускорение численного интегрирования
Сообщение13.12.2017, 09:14 
Заслуженный участник


25/02/11
1797
То ли у меня компьютер поновее, то ли версия математики - график из примера строится за 17 секунд вместо 80.

Если у процессора несколько ядер, можно распараллелить вычисления, математика позволяет. Например, командой ParallelTable. Кроме того, функция из примера сильно (неограниченно?) растет в одном из углов прямоугольника. Возможно, программа берет много точек (чтобы определить масштаб по вертикали?). Если этот угол не очень то нужен, как вариант, вырезать его из области опцией RegionFunction и посмотреть, не сократится ли время расчета. Еще, если на компьютере установлен компилятор Си, в Compile можно выставить опцию CompilationTarget -> "C". Иногда это ускоряет вычисления, но далеко не всегда.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group