Как использовать MATLAB для численного решения уравнения с неизвестным, встроенным в интеграл?
Я пытался использовать MATLAB для решения таких уравнений:
B = альфа *Y0*sqrt(эпсилон)/(pi*ln(b/a)*sqrt(epsilon_t))* интеграл от 0 до пи (2*sinint(k0*sqrt(эпсилон *(a^2+b) ^2-2abcos(тета))-sinint(2*k0* SQRT (эпсилон) * а * грех (тета /2))-sinint(2*k0* SQRT (эпсилон) * б * грех (тета /2))) в отношении тета
Где эпсилон - неизвестно.
Я знаю, как символически решать уравнения с неизвестными, встроенными в интеграл, используя int()
а также solve()
, но с использованием символического интегратора int()
занимает слишком много времени для уравнений это сложно. Когда я пытаюсь использовать quad()
, quadl()
а также quadgk()
У меня проблемы с тем, как неизвестное встраивается в интеграл.
1 ответ
Такие вещи усложняются очень быстро. Хотя все это можно сделать в одном встроенном уравнении, я бы посоветовал вам разбить его на несколько вложенных функций, хотя бы для удобства чтения.
Лучший пример того, почему важна читабельность: у вас есть проблема с брекетингом в уравнении, которое вы разместили; закрывающих скобок недостаточно, поэтому я не совсем уверен, как выглядит уравнение в математической записи:)
В любом случае, вот один из способов сделать это с версией, которую, я думаю, вы имели в виду:
function test
% some random values for testing
Y0 = rand;
b = rand;
a = rand;
k0 = rand;
alpha = rand;
epsilon_t = rand;
% D is your B
D = -0.015;
% define SIMPLE anonymous function
Bb = @(ep) F(ep).*main_integral(ep) - D;
% aaaand...solve it!
sol = fsolve(Bb, 1)
% The anonymous function above is only simple, because of these:
% the main integral
function val = main_integral(epsilon)
% we need for loop through epsilon, due to how quad(gk) solves things
val = zeros(size(epsilon));
for ii = 1:numel(epsilon)
ep = epsilon(ii);
% NOTE how the sinint's all have a different function as argument:
val(ii) = quadgk(@(th)...
2*sinint(A(ep,th)) - sinint(B(ep,th)) - sinint(C(ep,th)), ...
0, pi);
end
end
% factor in front of integral
function f = F(epsilon)
f = alpha*Y0*sqrt(epsilon)./(pi*log(b/a)*sqrt(epsilon_t)); end
% first sinint argument
function val = A(epsilon, theta)
val = k0*sqrt(epsilon*(a^2+b^2-2*a*b*cos(theta))); end
% second sinint argument
function val = B(epsilon, theta)
val = 2*k0*sqrt(epsilon)*a*sin(theta/2); end
% third sinint argument
function val = C(epsilon, theta)
val = 2*k0*sqrt(epsilon)*b*sin(theta/2); end
end
Решение выше все еще будет довольно медленным, но я думаю, что это нормально для сложных интегралов.
Я не думаю, что реализовать свой собственный sinint
очень поможет, так как большая часть потери скорости происходит из-за циклов for с не встроенными функциями... Если вам нужна скорость, я бы пошел на реализацию MEX с вашей собственной адаптивной квадратурной подпрограммой Гаусса-Кронрода.