def solve_bvp_casadi(self): """ Uses casadi's interface to sundials to solve the boundary value problem using a single-shooting method with automatic differen- tiation. Related to PCSJ code. """ self.bvpint = cs.Integrator('cvodes', self.modlT) self.bvpint.setOption('abstol', self.intoptions['bvp_abstol']) self.bvpint.setOption('reltol', self.intoptions['bvp_reltol']) self.bvpint.setOption('tf', 1) self.bvpint.setOption('disable_internal_warnings', True) self.bvpint.setOption('fsens_err_con', True) self.bvpint.init() # Vector of unknowns [y0, T] V = cs.MX.sym("V", self.neq + 1) y0 = V[:-1] T = V[-1] param = cs.vertcat([self.param, T]) yf = self.bvpint.call(cs.integratorIn(x0=y0, p=param))[0] fout = self.modlT.call(cs.daeIn(t=T, x=y0, p=param))[0] # objective: continuity obj = (yf - y0)**2 # yf and y0 are the same ..i.e. 2 ends of periodic fcn obj.append( fout[0]) # y0 is a peak for state 0, i.e. fout[0] is slope state 0 #set up the matrix we want to solve F = cs.MXFunction([V], [obj]) F.init() guess = np.append(self.y0, self.T) solver = cs.ImplicitFunction('kinsol', F) solver.setOption('abstol', self.intoptions['bvp_ftol']) solver.setOption('strategy', 'linesearch') solver.setOption('exact_jacobian', False) solver.setOption('pretype', 'both') solver.setOption('use_preconditioner', True) if self.intoptions['constraints'] == 'positive': solver.setOption('constraints', (2, ) * (self.neq + 1)) solver.setOption('linear_solver_type', 'dense') solver.init() solver.setInput(guess) solver.evaluate() sol = solver.output().toArray().squeeze() self.y0 = sol[:-1] self.T = sol[-1]
def corestationary(self,guess=None,contstraints='positive'): """ find stationary solutions that satisfy ydot = 0 for stability analysis. """ guess=None if guess is None: guess = np.array(self.y0) else: guess = np.array(guess) y = self.model.inputExpr(cs.DAE_X) t = self.model.inputExpr(cs.DAE_T) p = self.model.inputExpr(cs.DAE_P) ode = self.model.outputExpr() fn = cs.SXFunction([y,t,p],ode) kfn = cs.ImplicitFunction('kinsol',fn) abstol = 1E-10 kfn.setOption("abstol",abstol) if self.intoptions['constraints']=='positive': # constain using kinsol to >0, for physical kfn.setOption("constraints",(2,)*self.neq) kfn.setOption("linear_solver_type","dense") kfn.setOption("exact_jacobian",True) kfn.setOption("u_scale",(100/guess).tolist()) kfn.setOption("disable_internal_warnings",True) kfn.init() kfn.setInput(self.param,2) kfn.setInput(guess) kfn.evaluate() y0out = kfn.output().toArray() if any(np.isnan(y0out)): raise RuntimeError("findstationary: KINSOL failed to find \ acceptable solution") self.ss = y0out.flatten() if np.linalg.norm(self.dydt(self.ss)) >= abstol or any(y0out <= 0): raise RuntimeError("findstationary: KINSOL failed to reach"+ " acceptable bounds") self.eigs = np.linalg.eigvals(self.dfdy(self.ss))