Как запустить два цикла попеременно на Matlab?

Я хотел бы использовать Matlab для вычисления двух циклов конечных разностей таким образом, что если у нас есть два уравнения, скажем, (1) и (2), он завершает один шаг (1), затем решает (2) за один шаг, затем (1) для следующего шага, а затем (2) и так далее и тому подобное.

С этой целью я предоставляю параметры моего кода ниже:

%% Parameters

L = 5; % size of domain 
T = 5; % measurement time
dx = 1e-2; % spatial step
dt = 1e-3; % time step
x0 = 0;
c = 1;

%%

t = 0:dt:T; % time vector
x = (0:dx:L)'; % spatial vector
nt = length(t);
nx = length(x);
Lx = (1/dx^2)*spdiags(ones(nx,1)*[1 -2 1],-1:1,nx,nx); % discrete Laplace operator
mu = dt/dx;
I = eye(nx,nx); % identity matrix
A = spdiags(ones(nx,1)*[-1 1 0],-1:1,nx,nx); % finite difference matrix

Тогда первая петля задается

%% Finite Difference Equation (1)

% preallocate memory
u = zeros(nx,nt);
v = zeros(nx,nt);
% initial condition in time
u(:,1) = sinc((x-x0)/dx);
v(:,1) = sinc((x-x0)/dx);
for i = 1:nx-1
    u(:,i+1) = ((1/(c*dt))*I+(1/dx)*A)\((1/(c*dt))*u(:,i)+v(:,i));
end

а второе уравнение (2) имеет вид

%% Finite Difference Equation (2)

% preallocate memory
u = zeros(nx,nt);
v = zeros(nx,nt);
% final condition in time
u(:,nt) = sinc((x-x0)/dt);
% initial condition in space
for j = nt:-1:2
    v(:,j-1) = ((1/dx)*A+(1/(c*dt))*I)\((1/(c*dt))*v(:,j)
end

В текущем формате Matlab запустит первый цикл i = 1:nx-1, а затем второй цикл j = nt:-1:2.

Но я хочу запустить два цикла следующим образом: i = 1, затем j = nt, затем i = 2, затем j = nt-1 и так далее и тому подобное. Как мне это закодировать?


person Jason Born    schedule 24.07.2017    source источник
comment
nt и nx это одно и то же? Я думаю, что нет, так как же вы можете выполнять итерацию в одном и том же цикле по двум векторам разного размера?   -  person Ivan    schedule 24.07.2017
comment
@Иван № nt = 5001 и nx = 501. Да, это точка. Возможно, это возможно, если я интерполирую t на x?   -  person Jason Born    schedule 24.07.2017
comment
Как вы должны выполнять эти итерации всего с одним циклом, как вы хотите?   -  person Ivan    schedule 24.07.2017
comment
@Ivan Ну, я думал об интерполяции как об одной из возможностей. Хотя, наверное, нет. Другим способом может быть решение первого уравнения для десяти значений i перед решением одного значения j, поскольку nt примерно в десять раз больше, чем nx. Можно ли это закодировать?   -  person Jason Born    schedule 24.07.2017
comment
да, возможно, что-то вроде проверки, равен ли (nt-i) mod 10 0, и изменение значения j=((nt-i)/10)+1 в этом случае (потому что первый раз будет в i=1 , то 5001-1=5000, так что вы хотите проверить j=501). Просто идея, ничего не пробовал+   -  person Ivan    schedule 24.07.2017
comment
@ Иван Я пробую эту идею сейчас, но странно то, что запуск for i = 1:nx-1 j = ((nt-i)/10)-1; end возвращает одно значение.   -  person Jason Born    schedule 24.07.2017


Ответы (2)


Вы можете составить две петли следующим образом:

% define other variables and preallocations
j = nt;
for i = 1:nx-1 
    u(:,i+1) = ((1/(c*dt))*I+(1/dx)*A)\((1/(c*dt))*u(:,i)+v(:,i));
    v(:,j-1) = ((1/dx)*A+(1/(c*dt))*I)\((1/(c*dt))*v(:,j)
    j = j - 1;
end
person OmG    schedule 24.07.2017
comment
Спасибо за ответ, но интересно, что такая формулировка приводит к нежелательному v, у которого везде нули (т.е. метод становится нестабильным). Возможно, мне нужно упорядочить свои начальные условия и т. д., так как могут быть некоторые совпадения - person Jason Born; 24.07.2017

for i = 1:nx-1
    u(:,i+1) = ((1/(c*dt))*I+(1/dx)*A)\((1/(c*dt))*u(:,i)+v(:,i));
    %This if will be true once each 10 iterations
    if(mod((nt-i),10)==0)
        j=((nt-i)/10)+1;
        v(:,j-1) = ((1/dx)*A+(1/(c*dt))*I)\((1/(c*dt))*v(:,j);
    end
end

На самом деле не знаю, сработает ли это, но сделайте его более удобным, поскольку вы пробуете мою идею.

person Ivan    schedule 26.07.2017
comment
Кстати, вы уверены в индексе в u и v?, в обоих из них вы назначаете все строки в столбце, и оба они имеют ntcolumns - person Ivan; 26.07.2017