简体   繁体   中英

Use intermediate value on ode MATLAB solver

I am doing a time integration of a system of ODEs using a stiff solver (ode15s). It is working, but I want to speed things up.

The system of equations is given in state space form:

function [dx] = fun(t,x,M,C,K,other_parameters)
    % Mx'' + Cx' + Kx = F(t)
    % BUNCH OF CALCULATIONS
    F = solveP(x,t);

    A = [zeros(n) eye(n) ; -M\K -M\C];
    b = M\F;

    dx = A*x + b
end

The trick part here is the forcing function F. It is highly nonlinear and depends on the x and t parameters. It uses the x parameters to solve a Poisson-type 2D equation (by the Finite Volume method). The force F is proportional to the Poisson equation solution.

function [F] = solveP(x,t)
    % initialize solution
    Phi = zeros(Ni,Nj);

    % solve iteratively
    % ...
    while (~converged)
         % some calculations

         % iterative solver
         Phi(i,j) = (aE*Phi(i,j+1) + aW*Phi(i,j-1) + aN*Phi(i+1,j) +...
                     aS*Phi(i-1,j) + S(i,j))/aP;
    end


    % calculate F
    F = sum(Phi(:)); % discrete integration over domain
end

Solving the Poisson equation by a iterative method requires an initial condition, which I set to zero ( Phi=zeros(Ni,Nj) ). I thought I could improve the speed of calculations by providing a better initial estimative of the ϕ field (a better initial condition would take faster to reach the sought answer). The optimal initial condition I can think (besides ϕ=0) is the value of the ϕ field obtained in the previous iteration (the last step) of the ode solver ( ϕ(k)_initial=ϕ(k-1) ).

Bottom line is: how do I use/save intermediate values in the ode solution?

PS: I tried using the persistent variables, but that is not a good solution. The ode solver calculates the function in several points before advancing in time. The persistent variable saves the converged ϕ field every time the ode calls the odefun fun. That is not exactly what I want and this actually provides wrong answers as time marching goes on.

A possible fix is to write the found solution for Phi to the base workspace after one iteration. First you have to initialize Phi in the base workspace:

Phi = zeros(Ni, Nj);

Then you can just recall this Phi in the solveP function by using evalin . Then after you found an updated solution for Phi , be sure to assign it again in the base workspace using assignin . solveP would then look like this:

function [F] = solveP(x,t)
    % initialize solution
    Phi = evalin('base','Phi');

    % solve iteratively
    % ...
    while (~converged)
         % some calculations

         % iterative solver
         Phi(i,j) = (aE*Phi(i,j+1) + aW*Phi(i,j-1) + aN*Phi(i+1,j) +...
                     aS*Phi(i-1,j) + S(i,j))/aP;
    end


    % calculate F
    F = sum(Phi(:)); % discrete integration over domain

    % assign updated Phi in base workspace
    assignin('base', 'Phi2', Phi)
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM