Вопрос

Здесь Matlab./Фреймат код я должен решить Ода численно используя отсталый эйлер метод. Однако результаты несовместимы с моими результатами учебников, а иногда даже смехотворенно непоследовательны. Что не так с кодом?

function [x,y] = backEuler(f,xinit,yinit,xfinal,h)

    %f - this is your y prime
    %xinit - initial X
    %yinit - initial Y
    %xfinal - final X
    %h - step size

    n = (xfinal-xinit)/h; %Calculate steps

    %Inititialize arrays...
    %The first elements take xinit and yinit corespondigly, the rest fill with 0s.
    x = [xinit zeros(1,n)];
    y = [yinit zeros(1,n)];

    %Numeric routine
    for i = 1:n
        x(i+1) = x(i)+h;
        ynew = y(i)+h*(f(x(i),y(i)));
        y(i+1) = y(i)+h*f(x(i+1),ynew);
    end
end
Это было полезно?

Решение

Ваш метод является методом новый вид. Отказ Это не назад, ни вперед, Эйлер. :-)

Вперед Эйлер: y1 = y0 + h*f(x0,y0)

Отсталый эйлер solve in y1: y1 - h*f(x1,y1) = y0

Ваш метод: y1 = y0 +h*f(x0,x0+h*f(x0,y0))

Ваш метод есть нет назад Эйлер.

Вы не решаете в y1, Вы просто оцениваете y1 С форвардным методом Эйлера. Я не хочу преследовать анализ вашего метода, но я верю, что он будет вести себя плохо, даже по сравнению с передним Эулером, поскольку вы оцениваете функцию f на неправильном смысле.

Вот ближайший метод вашего метода, который я могу думать о, явным, а также дают гораздо лучшие результаты. Это Метод Хеуна:

y1 = y0 + h/2*(f(x0,y0) + f(x1,x0+h*f(x0,y0)))

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

Единственный вопрос, который я могу определить, это то, что линия:

n=(xfinal-xinit)/h

Должно быть:

n = abs((xfinal-xinit)/h)

Чтобы избежать отрицательного количества шагов. Если вы перемещаетесь в направлении отрицательного-х, убедитесь, что функция отрицательный размер шага.

Ваши ответы, вероятно, отклоняются из-за того, насколько грубо вы приближаетесь к вашему ответу. Чтобы получить полуточный результат, Deltax должен быть очень очень маленьким, а размер вашего шага должен быть очень очень очень маленьким.

Придавать Это не «обратный метод Эйлера», это просто обычный метод старого Эйлера.

Если это домашнее задание, пожалуйста, пометите его так.

Посмотри на Численные рецепты, В частности, глава 16, интеграция обыкновенных дифференциальных уравнений. Известно, что метод Эйлера имеет проблемы:

Существует несколько причин, по которым метод Эйлера не рекомендуется для практического использования, среди них, (i) метод не очень точно по сравнению с другими, факторами, методами, работающими в эквивалентных схемах, а (II) не так и не очень стабильны

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

Если только ты не В самом деле хочу решить ODE через метод Эйлера, который вы написали самостоятельно, вы должны посмотреть на Встроенные решатели ODE.

На Sidenote: вам не нужно создавать x(i) Внутри петли, как это: x(i+1) = x(i)+h;. Отказ Вместо этого вы можете просто написать x = xinit:h:xfinal;. Отказ Кроме того, вы можете написать n = round(xfinal-xinit)/h); избегать предупреждений.


Вот решатели, реализованные MatLab.

ODE45 основан на формуле runge-Kutta (4,5), паре Dormand-Prince. Это одноэтапный решатель - в вычислении y (tn), ему нужна только решение при непосредственном предыдущем времени времени, y (Tn-1). В общем, ODE45 - лучшая функция, чтобы подать заявку в качестве первой попытки для большинства проблем.

ODE23 представляет собой реализацию явной пары Bogacki и шампина Runge-Kutta (2,3). Это может быть более эффективным, чем ODE45 на неочищенных допусках и при наличии умеренной жесткости. Как ODE45, ODE23 - одноэтапный решатель.

ODE113 - это вариабельный порядок Adams-Bashforth-Moulton Pece Solver. Это может быть более эффективным, чем ODE45 на жестких допусках и когда функция файла ODE особенно дорогая для оценки. ODE113 - это многоэтапный решатель - он обычно нуждается в решениях в нескольких предыдущих точках времени для вычисления текущего решения.

Вышеуказанные алгоритмы предназначены для решения нестифтных систем. Если они кажутся чрезмерно медленными, попробуйте использовать один из жестких решений ниже.

ODE15S - это решатель переменного порядка на основе формул численного дифференцирования (NDF). Необязательно, он использует формулы обратного дифференцировки (BDFS, также известные как метод Gear), которые обычно менее эффективны. Как ODE113, ODE15S - многоэтапный решатель. Попробуйте ODE15S, когда ODE45 не удается, или очень неэффективно, и вы подозреваете, что проблема жесткая, или при решении дифференциальной алгебраической задачи.

ODE23S основан на модифицированной формуле розброка порядка 2. Поскольку это одноэтапный решатель, оно может быть более эффективным, чем ODE15S на нефте допуски. Это может решить некоторые виды жестких проблем, для которых ODE15S не эффективен.

ODE23T - это реализация трапециевидального правила с использованием «свободного» интерполянта. Используйте этот решатель, если проблема только умеренно жесткая, и вам нужно решение без численного демпфирования. ODE23T может решить DAES.

ODE23TB - это внедрение TR-BDF2, подразумевая формула Runge-Kutta с первым этапом, которая представляет собой трапециевидную стадию правила и второй этап, который является формулой обратной дифференцировки по порядку. По конструкции такая же итерационная матрица используется при оценке обе этапов. Как и ODE23S, этот решатель может быть более эффективным, чем ODE15S на неочищенных допусках.

Я думаю, что этот код может работать. Попробуй это.

for i =1:n
    t(i +1)=t(i )+dt;
    y(i+1)=solve('y(i+1)=y(i)+dt*f(t(i+1),y(i+1)');
    end 

Код в порядке. Просто вы должны добавить еще один цикл внутри цикла. Проверить уровень согласованности.

if abs((y(i+1) - ynew)/ynew) > 0.0000000001 
    ynew = y(i+1);
    y(i+1) = y(i)+h*f(x(i+1),ynew);
end

Я проверил на фиктивную функцию, и результаты были многообещающими.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top