Как получить больше результатов от ODE45

У меня есть N = 2 связанные нелинейные динамические системы, связь которых задается матрицей 2 на 2 W. Каждая из них описывается n = 8 одой первого порядка. Приведенный ниже код решает эту связанную систему для многих значений параметра p:

for i=1:length(p)
    [t,y(:,:,i)] = ode45(@(t,y) ode(t,y,n,N,W,p(i,:)), t, y0);
end

function [dydt] = ode(t,y,n,N,W,p)
    dydt = NaN(n, N);
    y = reshape(y,[n, N]);    
    y_out = zeros(N,1);
    F_Global = zeros(N,1);
    for i = 1:N
        y_out(i) = y(3,i)-y(4,i);
    end
    for i = 1:N
        F_Global(i) = W(i,:)*sigm(y_out);
    end
    for i = 1:N
        dydt(1,i) = y(5,i);
        dydt(2,i) = y(6,i);
        dydt(3,i) = y(7,i);
        dydt(4,i) = y(8,i);
        dydt(5,i) = sigm(y(3,i) - y(4,i)) - y(5,i) - y(1,i) + F_Global(i);
        dydt(6,i) = sigm(y(3,i) - y(4,i)) - y(6,i) - y(2,i);
        dydt(7,i) = C2*sigm(y(1,i)) + p(i) - y(7,i) - y(3,i);
        dydt(8,i) = sigm(y(2,i)) - y(8,i) - y(4,i);
    end
    dydt = reshape(dydt,n*N, 1);
end

function X = sigm(u)
    ...
end

Внутри функции уже вычислена разница:

y_out(i) = y(3,i)-y(4,i);

Для i = 1,...,N и для всех времен и всех значений p предполагается, что это трехмерная матрица измерений

y_out = size(length(time), length(p), N);

Также внутри функции вычисляются:

F_Global(i) = W(i,:)*sigm(y_out);

который для i = 1,...,N и для всех значений p, но после усреднения по времени, предполагается, что это двумерная матрица измерений

F_Global = size(length(p),N);

Мне нужна помощь, чтобы извлечь y_out и F_Global как выходные данные ode45


person axel    schedule 09.11.2019    source источник
comment
Превратите y_out и F_global в функции y и оцените их по результатам интеграции. Точки, в которых оценивается производная, имеют лишь слабую связь с точками решения в выводе ode45, так что значения, которые вы могли бы оттуда извлечь, имеют небольшую ценность для дальнейших целей.   -  person Lutz Lehmann    schedule 10.11.2019
comment
Но y_out и F_Global уже являются функциями y. Как я могу их оценить по результатам интеграции? Я не продвинутый пользователь, извините, что много спрашиваю   -  person axel    schedule 10.11.2019
comment
Я имел в виду, сделать их явно функциями Matlab, чтобы всякий раз, когда вам нужно их значение, было одно и только одно место, откуда его можно получить, и всякий раз, когда вам нужно их изменить, вам нужно изменить только одно место. // Пожалуйста, объясните связь структуры массива вывода и структуры массива, которую вы устанавливаете внутри функции ode.   -  person Lutz Lehmann    schedule 10.11.2019
comment
структура массива требуется от ode45. Если я не преобразую его в массив, он выдает ошибку. Я пытаюсь сделать их явными функциями Matlab   -  person axel    schedule 10.11.2019
comment
Да, это ясно. Со стандартной функцией вы должны использовать функции-оболочки для преобразования из представления модели в плоский массив и обратно. Вопрос в том, что в возвращаемом значении вы берете последовательность плоских массивов и сохраняете ее в трехмерной структуре. По сути, вы получаете 4D-модель, хранящуюся в 3D, с индексами времени, плоской моделью nxN и индексом параметра. Это так, как ты задумал?   -  person Lutz Lehmann    schedule 10.11.2019
comment
Вы также можете добавить компоненты в состояние, производная которого равна F_global, чтобы усреднение F_global требовало только деления на общее время интегралов, вычисленных в этих компонентах. Преобразование в плоский массив и обратно становится немного более сложным, и, возможно, его следует выполнять в специальных функциях.   -  person Lutz Lehmann    schedule 10.11.2019


Ответы (1)


Измененный код

output_potential = NaN(length(time),N,length(p));
Sigm = NaN(N,length(p));
input_firingRate = NaN(N,length(p));

for i=1:length(p)
    [t,y(:,:,i)] = ode45(@(t,y) ode(t,y,n,N,W,p(:,i)), time, y0);
    for j = 1:N
        output_potential(:,j,i) = y(:,3+(j-1)*n,i) - y(:,4+(j-1)*n,i);
        Sigm(j,i) = sigm(mean(output_potential(:,j,i)));
    end
    input_firingRate(:,i) = p(:,i) + A*a*W(:,:)*Sigm(:,i);
end
person shade    schedule 09.11.2019
comment
Спасибо за предложения. У меня есть несколько вопросов: 1. что означает y0(:,p)? 2. Я решил включить цикл for в функцию ode, потому что система связана. Если бы количество связанных систем было, например, N = 190, что должно произойти в конце концов, было бы непозволительно записывать все эти уравнения. - person axel; 10.11.2019
comment
вы имеете в виду, что yout = y(:,3:8:end,:) - y(:,4:8:end,:); WW = repmat(W(:)',[size(y,1) 1 size(y,3)]); F_global = WW .* yout; должно быть помещено за пределы цикла for, точно так, как вы это написали? - person axel; 10.11.2019
comment
Да, после получения всех результатов - person shade; 10.11.2019
comment
Я получаю сообщение об ошибке: Размеры массива должны совпадать с операцией двоичного массива. Error in test3 (line 27) F_global = WW .* yout; - person axel; 11.11.2019
comment
Размер W равен 1xN? - person shade; 11.11.2019
comment
Нет, ни W, ни WW. Если я правильно понимаю, вы предлагаете вместо того, чтобы ode производить больше выходных данных, чтобы расчет был выполнен после завершения интеграции. Это правильно? - person axel; 11.11.2019
comment
Да, я хочу получить F_global и yout после завершения расчета/интеграции. Я внес поправку, попробуйте - person shade; 11.11.2019
comment
Matrix dimensions must agree. Error in test2 (line 35) FF(k1,k2) = sum(yout(k1,:).*W(k2,:)); Я что-то редактирую в вашем коде выше. Я был бы признателен за ваше мнение. Первоначальная цель состояла в том, чтобы F_Global и y_out напрямую поступали в качестве выходных данных функции ode без необходимости пересчитывать все после интеграции. - person axel; 11.11.2019
comment
Попробуйте изменить строку: yout = y1(:,3:8:end) - y1(:,4:8:end); - person shade; 11.11.2019