classdef asynctrcircuit < qucstrans
% asynchronous circuit solver for use with the ode integrator routines
% based on an interface to the qucs transient circuit solvers
%
%
% Copyright Richard Crozier 2013, 2014
properties (SetAccess = private, GetAccess = public)
% used to determine if we need to accept or reject a step before
% continuing
step_solved;
end
methods
function this = asynctrcircuit(netlist)
this = this@qucstrans(netlist);
end
function init(this, tstart, firstdelta)
% initialises the circuit solver
this.cppcall('init_async', tstart, firstdelta);
this.isinitialised = true;
this.step_solved = false;
end
function stepsolve(this, t)
% solves an asynchronous step at the supplied time
%
% Syntax
%
% stepsolve(this, t)
%
% Input
%
% t - the time point at which the circuit simulation is to be
% solved
%
% Description
%
% This function causes the qucs solvers to attempt to solve the
% circuit at the time t. The result is stored internally, and
% can be retrieved with the getsolution method. The solution is
% not added to the history of time steps used by the circuit
% integrators. To add the solution to the history and move on
% to the next step, the acceptstep_sync function must be used.
%
if this.step_solved == true
error ('A time step has already been solved and must be accepted or rejected before solving another.');
end
if ~isscalar(t)
error('t must be a scalar.');
end
this.cppcall('stepsolve_async', t);
this.step_solved = true;
end
function [sol, NM] = getsolution(this)
% retrieves the last solution generated by the circuit solver
%
% Syntax
%
% [sol, NM] = getsolution(this)
%
% Description
%
% getsolution returns an vector containing the nodal voltages
% and branch currents at the last solution generated by a call
% to stepsolve acceptstep, or just initialisation. The number
% of nodal voltages and branch currents respectively are
% returned in the two element vector NM.
%
[sol, NM] = this.cppcall('getsolution');
end
function acceptstep(this, t)
% recalculates and accepts a time step solution into the
% internal history of solutions for the circuit integrators
%
% Syntax
%
% acceptstep(this, t)
%
% Input
%
% t - the time point at which the circuit is to be
% recalculated and added to the solution history
%
if this.step_solved == false
if nargin < 2
error ('If no step has been solved, you must supply a time step at which to calculate it.');
end
% solve the step if it hasn't been done already
stepsolve(this, t);
end
this.cppcall('acceptstep_async');
% reset the step_solved flag
this.step_solved = false;
end
function rejectstep(this)
% rejects an asynchronous step, resetting the internal history
% to the last accepted step
%
% Syntax
%
% rejectstep(this)
%
this.cppcall('rejectstep_async');
% reset the step_solved flag
this.step_solved = false;
end
end
methods(Static)
function status = odeoutputfcn(t, y, flag, qtr_async)
% static method for updating the asynchronous circuit on each
% time step of an ode solution
%
% Syntax
%
% status = odeoutputfcn(t, y, flag, qtr_async)
%
% Description
%
% This function must be called as the output function, or
% within the output function of an ode solution incorporating
% the synchronous circuit solver. See the help for odeset.m for
% more details on the ode solver OutputFcn option.
%
%
status = 0;
if isempty(flag)
% solve and accept the time step into the circuit solution
% history
qtr_async.acceptstep(t);
elseif strcmp(flag, 'init')
% initialise the circuit
% qtr_async.init(t(1));
elseif strcmp(flag, 'done')
end
end
end
end