Ejemplo n.º 1
0
def run_example(with_plots=True):
    r"""
    An example for IDA with scaled preconditioned GMRES method
    as a special linear solver.
    Note, how the operation Jacobian times vector is provided.
    
    ODE:
    
    .. math::
       
       \dot y_1 - y_2 &= 0\\
       \dot y_2 -9.82 &= 0
       
    
    on return:
    
       - :dfn:`imp_mod`    problem instance
    
       - :dfn:`imp_sim`    solver instance
       
    """

    #Defines the residual
    def res(t, y, yd):
        res_0 = yd[0] - y[1]
        res_1 = yd[1] + 9.82

        return N.array([res_0, res_1])

    #Defines the Jacobian*vector product
    def jacv(t, y, yd, res, v, c):
        jy = N.array([[0, -1.], [0, 0]])
        jyd = N.array([[1, 0.], [0, 1]])
        j = jy + c * jyd
        return N.dot(j, v)

    #Initial conditions
    y0 = [1.0, 0.0]
    yd0 = [0.0, -9.82]

    #Defines an Assimulo implicit problem
    imp_mod = Implicit_Problem(
        res, y0, yd0, name='Example using the Jacobian Vector product')

    imp_mod.jacv = jacv  #Sets the jacobian

    imp_sim = IDA(imp_mod)  #Create an IDA solver instance

    #Set the parameters
    imp_sim.atol = 1e-5  #Default 1e-6
    imp_sim.rtol = 1e-5  #Default 1e-6
    imp_sim.linear_solver = 'SPGMR'  #Change linear solver
    #imp_sim.options["usejac"] = False

    #Simulate
    t, y, yd = imp_sim.simulate(
        5, 1000)  #Simulate 5 seconds with 1000 communication points

    #Basic tests
    nose.tools.assert_almost_equal(y[-1][0], -121.75000000, 4)
    nose.tools.assert_almost_equal(y[-1][1], -49.100000000)

    #Plot
    if with_plots:
        P.plot(t, y)
        P.xlabel('Time')
        P.ylabel('State')
        P.title(imp_mod.name)
        P.show()
    return imp_mod, imp_sim
Ejemplo n.º 2
0
    def DAE_integration_assimulo(self, **kwargs):
        """
        Perform time integration for DAEs with the assimulo package
        """
        assert self.set_time_setting == 1, 'Time discretization must be specified first'
        
        if self.tclose > 0:
            close    = True
        else:
            close    = False
            
        # Control vector
        self.U = interpolate(self.boundary_cntrl_space, self.Vb).vector()[self.bndr_i_b]
        if self.discontinous_boundary_values == 1:
            self.U[self.Corner_indices] = self.U[self.Corner_indices]/2

        # Definition of the sparse solver for the DAE res function to
        # be defined next M should be invertible !! 
        my_solver = factorized(csc_matrix(self.M))
        rhs       = self.my_mult(self.J, self.my_mult(self.Q,self.A0)) + self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(0.,self.tclose))
        self.AD0  = my_solver(rhs) 
        
        # Definition of the rhs function required in assimulo
        def res(t,y,yd):
            """
            Definition of the residual function required in the DAE part of assimulo
            """   
            if close:
                if t < self.tclose:
                    z = self.my_mult(self.M,yd) - self.my_mult(self.J, self.my_mult(self.Q,y)) - self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(t,self.tclose))
                else:
                    z = self.my_mult(self.M,yd) - self.my_mult((self.J - self.R), self.my_mult(self.Q,y))
            else:
                z = self.my_mult(self.M,yd) - self.my_mult(self.J, self.my_mult(self.Q,y)) - self.my_mult(self.Bext,self.U* self.boundary_cntrl_time(t,self.tclose)) 
            
            return z
  

        # Definition of the jacobian function required in assimulo
        def jac(c,t,y,yd):
            """
            Definition of the Jacobian matrix required in the DAE part of assimulo
            """  
            Matrix = csr_matrix(self.my_mult(self.J,self.Q))
            
            if close and t > self.tclose:
                    Matrix = csr_matrix(self.my_mult(self.J - self.R, self.Q))
            
            return c*csr_matrix(self.M) - Matrix
        
        # Definition of the jacobian matrix vector function required in assimulo
        def jacv(t,y,yd,res,v,c):
            """
            Jacobian matrix-vector product required in the DAE part of assimulo
            """  
            w = self.my_mult(self.Q, v)
            z = self.my_mult(self.J, w)
            
            if close and t > self.tclose:
                z -= self.my_mult(self.R, w)
                
            return c*self.my_mult(self.M,v) - z
        
        print('DAE Integration using assimulo built-in functions:')

        
        model                     = Implicit_Problem(res,self.A0,self.AD0,self.tinit)
        model.jacv                = jacv
        #sim                       = Radau5DAE(model,**kwargs)
        #
        # IDA method from Assimulo
        #
        sim                       = IDA(model,**kwargs)
        sim.algvar                = [1 for i in range(self.M.shape[0])]
        sim.atol                  = 1.e-6
        sim.rtol                  = 1.e-6
        sim.report_continuously   = True
        ncp                       = self.Nt
        sim.usejac                = True
        sim.suppress_alg          = True
        sim.inith                 = self.dt
        sim.maxord                = 5
        #sim.linear_solver         = 'SPGMR'
        time_span, DAE_y, DAE_yd  = sim.simulate(self.tfinal,ncp)
        
        #print(sim.get_options())
        print(sim.print_statistics())
        
        A_dae = DAE_y.transpose()
        
        # Hamiltonian
        self.Nt    = A_dae.shape[1]
        self.tspan = np.array(time_span)
        
        Ham_dae = np.zeros(self.Nt)
        
        for k in range(self.Nt):
            #Ham_dae[k] = 1/2 * A_dae[:,k] @ self.M @ self.Q @ A_dae[:,k]
            Ham_dae[k] = 1/2 * self.my_mult(A_dae[:,k].T, \
                               self.my_mult(self.M, self.my_mult(self.Q, A_dae[:,k])))
      
        # Get q variables
        Aq_dae = A_dae[:self.Nq,:] 
        
        # Get p variables
        Ap_dae = A_dae[self.Nq:,:]

        # Get Deformation
        Rho = np.zeros(self.Np)
        for i in range(self.Np):
            Rho[i] = self.rho(self.coord_p[i])
            
        W_dae = np.zeros((self.Np,self.Nt))
        theta = .5
        for k in range(self.Nt-1):
            W_dae[:,k+1] = W_dae[:,k] + self.dt * 1/Rho[:] * ( theta * Ap_dae[:,k+1] + (1-theta) * Ap_dae[:,k] ) 

        self.Ham_dae = Ham_dae
    
        return Aq_dae, Ap_dae, Ham_dae, W_dae, np.array(time_span)