コード例 #1
0
def ode_sim(t_final):
    y0 = get_initial()  # initial conditions from Parameter.py
    t0 = 0.0
    param = new_param()

    ecoli_ode = lambda t, x: rhs(t, x, param)
    model = Explicit_Problem(ecoli_ode, y0, t0)  # Create an Assimulo problem
    model.name = 'E Coli ODE'
    sim = CVode(model)  # Create the solver CVode

    sim.rtol = 1e-8
    sim.atol = 1e-8
#    pdb.set_trace()
    t, y = sim.simulate(t_final)  # Use the .simulate method to simulate and provide the final time

    # Plot
    met_labels = ["ACCOA", "ACEx", "ACO", "ACP", "ADP", "AKG", "AMP", "ASP", "ATP", "BPG", "CAMP", "CIT", "COA", "CYS",
                  "DAP", "E4P", "ei", "eiia", "eiiaP", "eiicb", "eiicbP", "eiP", "F6P", "FDP", "FUM", "G6P", "GAP",
                  "GL6P", "GLCx", "GLX", "HCO3", "hpr", "hprP", "icd", "icdP", "ICIT", "KDPG", "MAL", "MG", "MN", "NAD",
                  "NADH", "NADP", "NADPH", "OAA", "P", "PEP", "PGA2", "PGA3", "PGN", "PYR", "PYRx", "Q", "QH2", "R5P",
                  "RU5P", "S7P", "SUC", "SUCCOA", "SUCx", "tal", "talC3", "tkt", "tktC2", "X5P", "Px", "Pp", "GLCp",
                  "ACEp", "ACE", "Hc", "Hp", "FAD", "FADH2", "O2", "FEED"]

    for i in y:
        if i.any() < 0:
            print i

    plt.plot([t, t], [y[:, i] for i in [4, 9]], label=["ADP", "ATP"])
    plt.title('Metabolite Concentrations Over Time')
    plt.xlabel('Time')
    plt.ylabel('Concentration')
    plt.legend()
    plt.savefig('concentration.png')

    return model, sim
コード例 #2
0
    def simulate(self, Tend, nIntervals, gridWidth):

        problem = Explicit_Problem(self.rhs, self.y0)
        problem.name = 'CVode'
        # solver.rhs = self.right_hand_side
        problem.handle_result = self.handle_result
        problem.state_events = self.state_events
        problem.handle_event = self.handle_event
        problem.time_events = self.time_events
        problem.finalize = self.finalize

        simulation = CVode(problem)

        # Change multistep method: 'adams' or 'VDF'
        if self.discr == 'Adams':
            simulation.discr = 'Adams'
            simulation.maxord = 12
        else:
            simulation.discr = 'BDF'
            simulation.maxord = 5
        # Change iteration algorithm: functional(FixedPoint) or newton
        if self.iter == 'FixedPoint':
            simulation.iter = 'FixedPoint'
        else:
            simulation.iter = 'Newton'

        # Sets additional parameters
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = self.verbosity
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used

        # '''Initialize problem '''
        # self.t_cur = self.t0
        # self.y_cur = self.y0

        # Calculate nOutputIntervals:
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Check for feasible input parameters
        if nOutputIntervals == 0:
            print 'Error: gridWidth too high or nIntervals set to 0! Continue with nIntervals=1'
            nOutputIntervals = 1
        # Perform simulation
        simulation.simulate(
            Tend, nOutputIntervals
        )  # to get the values: t_new, y_new = simulation.simulate
コード例 #3
0
def run_example(with_plots=True):
    """
    The same as example :doc:`EXAMPLE_cvode_basic`  but now integrated backwards in time.
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Define the rhs
    def f(t, y):
        ydot = -y[0]
        return N.array([ydot])

    #Define an Assimulo problem
    exp_mod = Explicit_Problem(
        f,
        t0=5,
        y0=0.02695,
        name=r'CVode Test Example (reverse time): $\dot y = - y$ ')

    #Define an explicit solver
    exp_sim = CVode(exp_mod)  #Create a CVode solver

    #Sets the parameters
    exp_sim.iter = 'Newton'  #Default 'FixedPoint'
    exp_sim.discr = 'BDF'  #Default 'Adams'
    exp_sim.atol = [1e-8]  #Default 1e-6
    exp_sim.rtol = 1e-8  #Default 1e-6
    exp_sim.backward = True

    #Simulate
    t, y = exp_sim.simulate(0)  #Simulate 5 seconds (t0=5 -> tf=0)

    #print 'y(5) = {}, y(0) ={}'.format(y[0][0],y[-1][0])

    #Basic test
    nose.tools.assert_almost_equal(float(y[-1]), 4.00000000, 3)

    #Plot
    if with_plots:
        P.plot(t, y, color="b")
        P.title(exp_mod.name)
        P.ylabel('y')
        P.xlabel('Time')
        P.show()

    return exp_mod, exp_sim
コード例 #4
0
def run_example(with_plots=True):
    r"""
    Demonstration of the use of CVode by solving the
    linear test equation :math:`\dot y = - y`
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Define the rhs
    def f(t, y):
        ydot = -y[0]
        return N.array([ydot])

    #Define an Assimulo problem
    exp_mod = Explicit_Problem(f,
                               y0=4,
                               name=r'CVode Test Example: $\dot y = - y$')

    #Define an explicit solver
    exp_sim = CVode(exp_mod)  #Create a CVode solver

    #Sets the parameters
    exp_sim.iter = 'Newton'  #Default 'FixedPoint'
    exp_sim.discr = 'BDF'  #Default 'Adams'
    exp_sim.atol = [1e-4]  #Default 1e-6
    exp_sim.rtol = 1e-4  #Default 1e-6

    #Simulate
    t1, y1 = exp_sim.simulate(5, 100)  #Simulate 5 seconds
    t2, y2 = exp_sim.simulate(7)  #Simulate 2 seconds more

    #Plot
    if with_plots:
        import pylab as P
        P.plot(t1, y1, color="b")
        P.plot(t2, y2, color="r")
        P.title(exp_mod.name)
        P.ylabel('y')
        P.xlabel('Time')
        P.show()

    #Basic test
    nose.tools.assert_almost_equal(float(y2[-1]), 0.00347746, 5)
    nose.tools.assert_almost_equal(exp_sim.get_last_step(), 0.0222169642893, 3)

    return exp_mod, exp_sim
コード例 #5
0
def simulate_prob(t_start, t_stop, x0, p, ncp, with_plots=False):
    """Simulates the problem using Assimulo.

    Args:
        t_start (double): Simulation start time.
        t_stop (double): Simulation stop time.
        x0 (list): Initial value.
        p (list): Problem specific parameters.
        ncp (int): Number of communication points.
        with_plots (bool): Plots the solution.

    Returns:
        tuple: (t,y). Time vector and solution at each time.

    """

    # Assimulo
    # Define the right-hand side
    def f(t, y):
        xd_1 = p[0] * y[0]
        xd_2 = p[1] * (y[1] - y[0]**2)
        return np.array([xd_1, xd_2])

    # Define an Assimulo problem
    exp_mod = Explicit_Problem(f, y0=x0, name='Planar ODE')

    # Define an explicit solver
    exp_sim = CVode(exp_mod)

    # Sets the solver parameters
    exp_sim.atol = 1e-12
    exp_sim.rtol = 1e-11

    # Simulate
    t, y = exp_sim.simulate(tfinal=t_stop, ncp=ncp)

    # Plot
    if with_plots:
        x1 = y[:, 0]
        x2 = y[:, 1]
        plt.figure()
        plt.title('Planar ODE')
        plt.plot(t, x1, 'b')
        plt.plot(t, x2, 'k')
        plt.legend(['x1', 'x2'])
        plt.xlim(t_start, t_stop)
        plt.xlabel('Time (s)')
        plt.ylabel('x')
        plt.grid(True)

    return t, y.T
コード例 #6
0
    def simulate(self, Tend, nIntervals, gridWidth):

        problem = Explicit_Problem(self.rhs, self.y0)
        problem.name = 'CVode'
        # solver.rhs = self.right_hand_side
        problem.handle_result = self.handle_result
        problem.state_events = self.state_events
        problem.handle_event = self.handle_event
        problem.time_events = self.time_events
        problem.finalize = self.finalize

        simulation = CVode(problem)

        # Change multistep method: 'adams' or 'VDF'
        if self.discr == 'Adams':
            simulation.discr = 'Adams'
            simulation.maxord = 12
        else:
            simulation.discr = 'BDF'
            simulation.maxord = 5
        # Change iteration algorithm: functional(FixedPoint) or newton
        if self.iter == 'FixedPoint':
            simulation.iter = 'FixedPoint'
        else:
            simulation.iter = 'Newton'

        # Sets additional parameters
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = self.verbosity
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used

        # '''Initialize problem '''
        # self.t_cur = self.t0
        # self.y_cur = self.y0

        # Calculate nOutputIntervals:
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Check for feasible input parameters
        if nOutputIntervals == 0:
            print 'Error: gridWidth too high or nIntervals set to 0! Continue with nIntervals=1'
            nOutputIntervals = 1
        # Perform simulation
        simulation.simulate(Tend, nOutputIntervals)  # to get the values: t_new, y_new = simulation.simulate
コード例 #7
0
ファイル: TransientSimulation.py プロジェクト: SysMo/SmoWeb
	def setUp(self):
		"""
		Configures the solver
		"""
		#Define an explicit solver 
		simSolver = CVode(self) 
		#Create a CVode solver
		#Sets the parameters 
		#simSolver.verbosity = LOUD
		#simSolver.report_continuously = True
		simSolver.iter = 'Newton' #Default 'FixedPoint'
		simSolver.discr = 'BDF' #Default 'Adams'
		#simSolver.discr = 'Adams' 
		simSolver.atol = [1e-6]	#Default 1e-6 
		simSolver.rtol = 1e-6 	#Default 1e-6
		#simSolver.problem_info['step_events'] = True # activates step events
		#simSolver.maxh = 1.0
		#simSolver.store_event_points = True
		self.simSolver = simSolver
コード例 #8
0
ファイル: TransientSimulation.py プロジェクト: birdol/SmoWeb
    def setUp(self):
        """
		Configures the solver
		"""
        #Define an explicit solver
        simSolver = CVode(self)
        #Create a CVode solver
        #Sets the parameters
        #simSolver.verbosity = LOUD
        #simSolver.report_continuously = True
        simSolver.iter = 'Newton'  #Default 'FixedPoint'
        simSolver.discr = 'BDF'  #Default 'Adams'
        #simSolver.discr = 'Adams'
        simSolver.atol = [1e-6]  #Default 1e-6
        simSolver.rtol = 1e-6  #Default 1e-6
        #simSolver.problem_info['step_events'] = True # activates step events
        #simSolver.maxh = 1.0
        #simSolver.store_event_points = True
        self.simSolver = simSolver
コード例 #9
0
    def make_explicit_sim(self):
        explicit_sim = CVode(self.explicit_problem)
        explicit_sim.iter = 'Newton'
        explicit_sim.discr = 'BDF'
        explicit_sim.rtol = 1e-7
        explicit_sim.atol = 1e-7
        explicit_sim.sensmethod = 'SIMULTANEOUS'
        explicit_sim.suppress_sens = True
        explicit_sim.report_continuously = False
        explicit_sim.usesens = False
        explicit_sim.verbosity = 50

        if self.use_jac and self.model_jac is not None:
            explicit_sim.usejac = True

        else:
            explicit_sim.usejac = False

        return explicit_sim
コード例 #10
0
ファイル: Simulation.py プロジェクト: birdol/SmoWeb
    def prepareSimulation(self, params=None):
        if params == None:
            params = AttributeDict({
                'absTol': 1e-6,
                'relTol': 1e-6,
            })

        #Define an explicit solver
        simSolver = CVode(self)
        #Create a CVode solver
        #Sets the parameters
        #simSolver.verbosity = LOUD
        simSolver.report_continuously = True
        simSolver.iter = 'Newton'  #Default 'FixedPoint'
        simSolver.discr = 'BDF'  #Default 'Adams'
        #simSolver.discr = 'Adams'
        simSolver.atol = [params.absTol]  #Default 1e-6
        simSolver.rtol = params.relTol  #Default 1e-6
        simSolver.problem_info['step_events'] = True  # activates step events
        #simSolver.maxh = 1.0
        simSolver.store_event_points = True
        self.simSolver = simSolver
コード例 #11
0
ファイル: Simulation.py プロジェクト: SysMo/SmoWeb
	def prepareSimulation(self, params = None):
		if params == None:
			params = AttributeDict({
				'absTol' : 1e-6, 
				'relTol' : 1e-6,
			})
		
		#Define an explicit solver 
		simSolver = CVode(self) 
		#Create a CVode solver
		#Sets the parameters 
		#simSolver.verbosity = LOUD
		simSolver.report_continuously = True
		simSolver.iter = 'Newton' #Default 'FixedPoint'
		simSolver.discr = 'BDF' #Default 'Adams'
		#simSolver.discr = 'Adams' 
		simSolver.atol = [params.absTol]	#Default 1e-6 
		simSolver.rtol = params.relTol 	#Default 1e-6		
		simSolver.problem_info['step_events'] = True # activates step events
		#simSolver.maxh = 1.0
		simSolver.store_event_points = True
		self.simSolver = simSolver
コード例 #12
0
def mySolve(xf,boltz_eqs,rtol,atol,verbosity=50):
    """Sets the main options for the ODE solver and solve the equations. Returns the
    array of x,y points for all components.
    If numerical instabilities are found, re-do the problematic part of the evolution with smaller steps"""
        
    boltz_solver = CVode(boltz_eqs)  #Define solver method
    boltz_solver.rtol = rtol
    boltz_solver.atol = atol
    boltz_solver.verbosity = verbosity
    boltz_solver.linear_solver = 'SPGMR'
    boltz_solver.maxh = xf/300.
    xfinal = xf
    xres = []
    yres = []
    sw = boltz_solver.sw[:]
    while xfinal <= xf:
        try:
            boltz_solver.re_init(boltz_eqs.t0,boltz_eqs.y0)
            boltz_solver.sw = sw[:]
            x,y = boltz_solver.simulate(xfinal)
            xres += x
            for ypt in y: yres.append(ypt)
            if xfinal == xf: break   #Evolution has been performed until xf -> exit            
        except Exception,e:
            print e
            if not e.t or 'first call' in e.msg[e.value]:
                logger.error("Error solving equations:\n "+str(e))
                return False
            xfinal = max(e.t*random.uniform(0.85,0.95),boltz_eqs.t0+boltz_solver.maxh)  #Try again, but now only until the error
            logger.warning("Numerical instability found. Restarting evolution from x = "
                           +str(boltz_eqs.t0)+" to x = "+str(xfinal))
            continue
        xfinal = xf  #In the next step try to evolve from xfinal -> xf
        sw = boltz_solver.sw[:]
        x0 = float(x[-1])
        y0 = [float(yval) for yval in y[-1]]
        boltz_eqs.updateValues(x0,y0,sw)
コード例 #13
0
def run_simulation(filename, start_time, save_output, temp, RH, RO2_indices,
                   H2O, input_dict, simulation_time, batch_step):

    from assimulo.solvers import RodasODE, CVode  #Choose solver accoring to your need.
    from assimulo.problem import Explicit_Problem

    # In this function, we import functions that have been pre-compiled for use in the ODE solver
    # The function that calculates the RHS of the ODE is also defined within this function, such
    # that it can be used by the Assimulo solvers

    # The variables passed to this function are defined as follows:

    #-------------------------------------------------------------------------------------
    # define the ODE function to be called
    def dydt_func(t, y):
        """
        This function defines the right-hand side [RHS] of the ordinary differential equations [ODEs] to be solved
        input:
        • t - time variable [internal to solver]
        • y - array holding concentrations of all compounds in both gas and particulate [molecules/cc]
        output:
        dydt - the dy_dt of each compound in both gas and particulate phase [molecules/cc.sec]
        """

        #pdb.set_trace()
        # Calculate time of day
        time_of_day_seconds = start_time + t

        # make sure the y array is not a list. Assimulo uses lists
        y_asnumpy = numpy.array(y)

        #Calculate the concentration of RO2 species, using an index file created during parsing
        RO2 = numpy.sum(y[RO2_indices])

        #Calculate reaction rate for each equation.
        # Note that H2O will change in parcel mode
        # The time_of_day_seconds is used for photolysis rates - need to change this if want constant values
        rates = evaluate_rates_fortran(RO2, H2O, temp, time_of_day_seconds)
        #pdb.set_trace()
        # Calculate product of all reactants and stochiometry for each reaction [A^a*B^b etc]
        reactants = reactants_fortran(y_asnumpy)
        #pdb.set_trace()
        #Multiply product of reactants with rate coefficient to get reaction rate
        reactants = numpy.multiply(reactants, rates)
        #pdb.set_trace()
        # Now use reaction rates with the loss_gain matri to calculate the final dydt for each compound
        # With the assimulo solvers we need to output numpy arrays
        dydt = loss_gain_fortran(reactants)
        #pdb.set_trace()

        return dydt

    #-------------------------------------------------------------------------------------
    #-------------------------------------------------------------------------------------
    # define jacobian function to be called
    def jacobian(t, y):
        """
        This function defines Jacobian of the ordinary differential equations [ODEs] to be solved
        input:
        • t - time variable [internal to solver]
        • y - array holding concentrations of all compounds in both gas and particulate [molecules/cc]
        output:
        dydt_dydt - the N_compounds x N_compounds matrix of Jacobian values
        """

        # Different solvers might call jacobian at different stages, so we have to redo some calculations here
        # Calculate time of day
        time_of_day_seconds = start_time + t

        # make sure the y array is not a list. Assimulo uses lists
        y_asnumpy = numpy.array(y)

        #Calculate the concentration of RO2 species, using an index file created during parsing
        RO2 = numpy.sum(y[RO2_indices])

        #Calculate reaction rate for each equation.
        # Note that H2O will change in parcel mode
        rates = evaluate_rates_fortran(RO2, H2O, temp, time_of_day_seconds)
        #pdb.set_trace()
        # Now use reaction rates with the loss_gain matrix to calculate the final dydt for each compound
        # With the assimulo solvers we need to output numpy arrays
        dydt_dydt = jacobian_fortran(rates, y_asnumpy)
        #pdb.set_trace()
        return dydt_dydt

    #-------------------------------------------------------------------------------------

    #import static compilation of Fortran functions for use in ODE solver
    print("Importing pre-compiled Fortran modules")
    from rate_coeff_f2py import evaluate_rates as evaluate_rates_fortran
    from reactants_conc_f2py import reactants as reactants_fortran
    from loss_gain_f2py import loss_gain as loss_gain_fortran
    from jacobian_f2py import jacobian as jacobian_fortran

    # 'Unpack' variables from input_dict
    species_dict = input_dict['species_dict']
    species_dict2array = input_dict['species_dict2array']
    species_initial_conc = input_dict['species_initial_conc']
    equations = input_dict['equations']

    #Specify some starting concentrations [ppt]
    Cfactor = 2.55e+10  #ppb-to-molecules/cc

    # Create variables required to initialise ODE
    num_species = len(species_dict.keys())
    y0 = [0] * num_species  #Initial concentrations, set to 0
    t0 = 0.0  #T0

    # Define species concentrations in ppb
    # You have already set this in the front end script, and now we populate the y array with those concentrations
    for specie in species_initial_conc.keys():
        y0[species_dict2array[specie]] = species_initial_conc[
            specie] * Cfactor  #convert from pbb to molcules/cc

    #Set the total_time of the simulation to 0 [havent done anything yet]
    total_time = 0.0

    # Now run through the simulation in batches.
    # I do this to enable testing of coupling processes. Some initial investigations with non-ideality in
    # the condensed phase indicated that even defining a maximum step was not enough for ODE solvers to
    # overshoot a stable region. It also helps with in-simulation debugging. Its up to you if you want to keep this.
    # To not run in batches, just define one batch as your total simulation time. This will reduce any overhead with
    # initialising the solvers
    # Set total simulation time and batch steps in seconds

    # Note also that the current module outputs solver information after each batch step. This can be turned off and the
    # the batch step change for increased speed
    #simulation_time= 3600.0
    #batch_step=100.0
    t_array = []
    time_step = 0
    number_steps = int(
        simulation_time /
        batch_step)  # Just cycling through 3 steps to get to a solution

    # Define a matrix that stores values as outputs from the end of each batch step. Again, you can remove
    # the need to run in batches. You can tell the Assimulo solvers the frequency of outputs.
    y_matrix = numpy.zeros((int(number_steps), len(y0)))

    print("Starting simulation")

    # In the following, we can
    while total_time < simulation_time:

        if total_time == 0.0:
            #Define an Assimulo problem
            #Define an explicit solver
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        else:
            y0 = y_output[
                -1, :]  # Take the output from the last batch as the start of this
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        # Define ODE parameters.
        # Initial steps might be slower than mid-simulation. It varies.
        #exp_mod.jac = dydt_jac
        # Define which ODE solver you want to use
        exp_sim = CVode(exp_mod)
        tol_list = [1.0e-3] * num_species
        exp_sim.atol = tol_list  #Default 1e-6
        exp_sim.rtol = 0.03  #Default 1e-6
        exp_sim.inith = 1.0e-6  #Initial step-size
        #exp_sim.discr = 'Adams'
        exp_sim.maxh = 100.0
        # Use of a jacobian makes a big differece in simulation time. This is relatively
        # easy to define for a gas phase - not sure for an aerosol phase with composition
        # dependent processes.
        exp_sim.usejac = True  # To be provided as an option in future update.
        #exp_sim.fac1 = 0.05
        #exp_sim.fac2 = 50.0
        exp_sim.report_continuously = True
        exp_sim.maxncf = 1000
        #Sets the parameters
        t_output, y_output = exp_sim.simulate(
            batch_step)  #Simulate 'batch' seconds
        total_time += batch_step
        t_array.append(
            total_time
        )  # Save the output from the end step, of the current batch, to a matrix
        y_matrix[time_step, :] = y_output[-1, :]

        #now save this information into a matrix for later plotting.
        time_step += 1

    # Do you want to save the generated matrix of outputs?
    if save_output:
        numpy.save(filename + '_output', y_matrix)
        df = pd.DataFrame(y_matrix)
        df.to_csv(filename + "_output_matrix.csv")
        w = csv.writer(open(filename + "_output_names.csv", "w"))
        for specie, number in species_dict2array.items():
            w.writerow([specie, number])

    with_plots = True

    #pdb.set_trace()
    #Plot the change in concentration over time for a given specie. For the user to change / remove
    #In a future release I will add this as a seperate module
    if with_plots:

        try:
            P.plot(t_array,
                   numpy.log10(y_matrix[:, species_dict2array['APINENE']]),
                   marker='o',
                   label="APINENE")
            P.plot(t_array,
                   numpy.log10(y_matrix[:, species_dict2array['PINONIC']]),
                   marker='o',
                   label="PINONIC")
            P.title(exp_mod.name)
            P.legend(loc='upper left')
            P.ylabel("Concetration log10[molecules/cc]")
            P.xlabel("Time [seconds] since start of simulation")
            P.show()
        except:
            print(
                "There is a problem using Matplotlib in your environment. If using this within a docker container, you will need to transfer the data to the host or configure your container to enable graphical displays. More information can be found at http://wiki.ros.org/docker/Tutorials/GUI "
            )
コード例 #14
0
def func_set_system():
    ##############################################
    #% initial conditions
    P_0           = depth*9.8*2500.           #;      % initial chamber pressure (Pa)
    T_0           = 1200            #;       % initial chamber temperature (K)
    eps_g0        = 0.04            #;       % initial gas volume fraction
    rho_m0        = 2600            #;       % initial melt density (kg/m^3)
    rho_x0        = 3065            #;       % initial crystal density (kg/m^3)
    a             = 1000            #;       % initial radius of the chamber (m)
    V_0           = (4.*pi/3.)*a**3.  #; % initial volume of the chamber (m^3)

    ##############################################
    ##############################################
    IC = numpy.array([P_0,T_0,eps_g0,V_0,rho_m0,rho_x0]) #   % store initial conditions
    ## Gas (eps_g = zero), eps_x is zero, too many crystals, 50 % crystallinity,eruption (yes/no)

    sw0 = [False,False,False,False,False]

    ##############################################
    #% error tolerances used in ode method
    dt = 30e7
    N  = int(round((end_time-begin_time)/dt))
    ##############################################

    #Define an Assimulo problem
    exp_mod = Chamber_Problem(depth=depth,t0=begin_time,y0=IC,sw0=sw0)
    exp_mod.param['T_in'] = 1200.
    exp_mod.param['eps_g_in'] = 0.0    # Gas fraction of incoming melt - gas phase ..
    exp_mod.param['m_eq_in'] = 0.05    # Volatile fraction of incoming melt
    exp_mod.param['Mdot_in']    = mdot
    exp_mod.param['eta_x_max'] = 0.64                                     # Locking fraction
    exp_mod.param['delta_Pc']   = 20e6
    exp_mod.tcurrent = begin_time
    exp_mod.radius = a
    exp_mod.permeability = perm_val
    exp_mod.R_steps = 1500
    exp_mod.dt_init = dt
    #################
    exp_mod.R_outside = numpy.linspace(a,3.*a,exp_mod.R_steps);
    exp_mod.T_out_all =numpy.array([exp_mod.R_outside*0.])
    exp_mod.P_out_all =numpy.array([exp_mod.R_outside*0.])
    exp_mod.sigma_rr_all    = numpy.array([exp_mod.R_outside*0.])
    exp_mod.sigma_theta_all = numpy.array([exp_mod.R_outside*0.])
    exp_mod.sigma_eff_rr_all = numpy.array([exp_mod.R_outside*0.])
    exp_mod.sigma_eff_theta_all = numpy.array([exp_mod.R_outside*0.])
    exp_mod.max_count = 1 # counting for the append me arrays ..

    exp_mod.P_list = append_me()
    exp_mod.P_list.update(P_0-exp_mod.plith)
    exp_mod.T_list = append_me()
    exp_mod.T_list.update(T_0-exp_mod.param['T_S'])
    exp_mod.P_flux_list = append_me()
    exp_mod.P_flux_list.update(0)
    exp_mod.T_flux_list = append_me()
    exp_mod.T_flux_list.update(0)
    exp_mod.times_list = append_me()
    exp_mod.times_list.update(1e-7)
    exp_mod.T_out,exp_mod.P_out,exp_mod.sigma_rr,exp_mod.sigma_theta,exp_mod.T_der= Analytical_sol_cavity_T_Use(exp_mod.T_list.data[:exp_mod.max_count],exp_mod.P_list.data[:exp_mod.max_count],exp_mod.radius,exp_mod.times_list.data[:exp_mod.max_count],exp_mod.R_outside,exp_mod.permeability,exp_mod.param['material'])
    exp_mod.param['heat_cond'] = 1                                             # Turn on/off heat conduction
    exp_mod.param['visc_relax'] = 1                                            # Turn on/off viscous relaxation
    exp_mod.param['press_relax'] = 1                                          ## Turn on/off pressure diffusion
    exp_mod.param['frac_rad_Temp'] =0.75
    exp_mod.param['vol_degass'] = 1.
    #exp_mod.state_events = stopChamber #Sets the state events to the problem
    #exp_mod.handle_event = handle_event #Sets the event handling to the problem
    #Sets the options to the problem
    #exp_mod.p0   = [beta_r, beta_m]#, beta_x, alpha_r, alpha_m, alpha_x, L_e, L_m, c_m, c_g, c_x, eruption, heat_cond, visc_relax]  #Initial conditions for parameters
    #exp_mod.pbar  = [beta_r, beta_m]#, beta_x, alpha_r, alpha_m, alpha_x, L_e, L_m, c_m, c_g, c_x, eruption, heat_cond, visc_relax]
    #Define an explicit solver
    exp_sim = CVode(exp_mod) #Create a CVode solver

    #Sets the parameters
    #exp_sim.iter = 'Newton'
    #exp_sim.discr = 'BDF'
    #exp_sim.inith = 1e-7

    exp_sim.rtol = 1.e-7
    exp_sim.maxh = 3e7
    exp_sim.atol = 1e-7
    exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used
    exp_sim.suppress_sens = False       #Dont suppress the sensitivity variables in the error test.
    #exp_sim.usesens = True
    #exp_sim.report_continuously = True
    return exp_mod,exp_sim,N
コード例 #15
0
def run_example(with_plots=True):
    r"""
    An example for CVode 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 \\
       \dot y_2 &= -9.82
       
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Defines the rhs
    def f(t, y):
        yd_0 = y[1]
        yd_1 = -9.82

        return N.array([yd_0, yd_1])

    #Defines the Jacobian*vector product
    def jacv(t, y, fy, v):
        j = N.array([[0, 1.], [0, 0]])
        return N.dot(j, v)

    y0 = [1.0, 0.0]  #Initial conditions

    #Defines an Assimulo explicit problem
    exp_mod = Explicit_Problem(
        f, y0, name='Example using the Jacobian Vector product')

    exp_mod.jacv = jacv  #Sets the Jacobian

    exp_sim = CVode(exp_mod)  #Create a CVode solver

    #Set the parameters
    exp_sim.iter = 'Newton'  #Default 'FixedPoint'
    exp_sim.discr = 'BDF'  #Default 'Adams'
    exp_sim.atol = 1e-5  #Default 1e-6
    exp_sim.rtol = 1e-5  #Default 1e-6
    exp_sim.linear_solver = 'SPGMR'  #Change linear solver
    #exp_sim.options["usejac"] = False

    #Simulate
    t, y = exp_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(exp_mod.name)
        P.show()

    return exp_mod, exp_sim
コード例 #16
0
    def simulate(self, Tend, nIntervals, gridWidth):

        # define assimulo problem:(has to be done here because of the starting value in Explicit_Problem
        solver = Explicit_Problem(self.rhs, self.y0)
        ''' *******DELETE LATER '''''''''
#        problem.handle_event = handle_event
#        problem.state_events = state_events
#        problem.init_mode = init_mode

        solver.handle_result = self.handle_result


        solver.name = 'Simple Explicit Example'
        simulation = CVode(solver)  # Create a RungeKutta34 solver
        # simulation.inith = 0.1 #Sets the initial step, default = 0.01

        # Change multistep method: 'adams' or 'VDF'
        if self.discr == 'Adams':
            simulation.discr = 'Adams'
            simulation.maxord = 12
        else:
            simulation.discr = 'BDF'
            simulation.maxord = 5

        # Change iteration algorithm: functional(FixedPoint) or newton
        if self.iter == 'FixedPoint':
            simulation.iter = 'FixedPoint'
        else:
            simulation.iter = 'Newton'

        # Sets additional parameters
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = 0
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used

        # Create Solver and set settings
#        noRootFunctions = np.size(self.state_events(self.t0, np.array(self.y0)))

#        solver = sundials.CVodeSolver(RHS = self.f, ROOT = self.rootf, SW = [False]*noRootFunctions,
#                       abstol = self.atol, reltol = self.rtol)
        # solver.settings.JAC = None   #Add user-dependent jacobian here

        '''Initialize problem '''
#        solver.init(self.t0, self.y0)
        self.handle_result(self.t0, self.y0)
        nextTimeEvent = self.time_events(self.t0, self.y0)
        self.t_cur = self.t0
        self.y_cur = self.y0
        state_event = False
#
#
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Define step length depending on if gridWidth or nIntervals has been chosen
        if nOutputIntervals > 0:
            # Last point on grid (does not have to be Tend:)
            if(gridWidth <> None):
                dOutput = gridWidth
            else:
                dOutput = (Tend - self.t0) / nIntervals
        else:
            dOutput = Tend

        outputStepCounter = long(1)
        nextOutputPoint = min(self.t0 + dOutput, Tend)

        while self.t_cur < Tend:

            # Time-Event detection and step time adjustment
            if nextTimeEvent is None or nextOutputPoint < nextTimeEvent:
                time_event = False
                self.t_cur = nextOutputPoint
            else:
                time_event = True
                self.t_cur = nextTimeEvent



            try:
#                #Integrator step
#                self.y_cur = solver.step(self.t_cur)
#                self.y_cur = np.array(self.y_cur)
#                state_event = False
                # Simulate




                # take a step to next output point:
                t_new, y_new = simulation.simulate(self.t_cur)  # 5, 10) #5, 10  self.t_cur self.t_cur  2. argument nsteps Simulate 5 seconds
                # t_new, y_new are both vectors of the time and states at t_cur and all intermediate
                # points before it! So take last values:
                self.t_cur = t_new[-1]
                self.y_cur = y_new[-1]
                state_event = False

            except:
                import sys
                print "Unexpected error:", sys.exc_info()[0]
#            except CVodeRootException, info:
#                self.t_cur = info.t
#                self.y_cur = info.y
#                self.y_cur = np.array(self.y_cur)
#                time_event = False
#                state_event = True
#
#
            # Depending on events have been detected do different tasks
            if time_event or state_event:
                event_info = [state_event, time_event]
                if not self.handle_event(self, event_info):
                    break
                solver.init(self.t_cur, self.y_cur)

                nextTimeEvent = self.time_events(self.t_cur, self.y_cur)
                # If no timeEvent happens:
                if nextTimeEvent <= self.t_cur:
                    nextTimeEvent = None

            if self.t_cur == nextOutputPoint:
                # Write output if not happened before:
                if not time_event and not state_event:
                    self.handle_result(nextOutputPoint, self.y_cur)
                outputStepCounter += 1
                nextOutputPoint = min(self.t0 + outputStepCounter * dOutput, Tend)

        self.finalize()
コード例 #17
0
ファイル: tester.py プロジェクト: zicvic/FMNN05
#Create an Assimulo Problem
mod = Explicit_Problem(pendulum, y0, t0, sw0=switches0)

mod.state_events = state_events #Sets the state events to the problem
mod.handle_event = handle_event #Sets the event handling to the problem
mod.name = 'Pendulum with events'   #Sets the name of the problem


#Create an Assimulo solver (CVode)
sim = CVode(mod)

#Specifies options
sim.discr = 'Adams'     #Sets the discretization method
sim.iter = 'FixedPoint' #Sets the iteration method
sim.rtol = 1.e-8        #Sets the relative tolerance
sim.atol = 1.e-6        #Sets the absolute tolerance

#Simulation
ncp = 200     #Number of communication points
tfinal = 10.0 #Final time

t, y = sim.simulate(tfinal, ncp) #Simulate





#Plots the result
P.plot(t,y)
P.show()
コード例 #18
0
def run_simulation(filename, save_output, start_time, temp, RH, RO2_indices,
                   H2O, PInit, y_cond, input_dict, simulation_time, batch_step,
                   plot_mass):

    from assimulo.solvers import RodasODE, CVode, RungeKutta4, LSODAR  #Choose solver accoring to your need.
    from assimulo.problem import Explicit_Problem

    # In this function, we import functions that have been pre-compiled for use in the ODE solver
    # The function that calculates the RHS of the ODE is also defined within this function, such
    # that it can be used by the Assimulo solvers

    # The variables passed to this function are defined as follows:

    #-------------------------------------------------------------------------------------
    #-------------------------------------------------------------------------------------
    # define the ODE function to be called
    def dydt_func(t, y):
        """
        This function defines the right-hand side [RHS] of the ordinary differential equations [ODEs] to be solved
        input:
        • t - time variable [internal to solver]
        • y - array holding concentrations of all compounds in both gas and particulate [molecules/cc]
        output:
        dydt - the dy_dt of each compound in both gas and particulate phase [molecules/cc.sec]
        """

        dy_dt = numpy.zeros((total_length_y, 1), )

        #pdb.set_trace()
        # Calculate time of day
        time_of_day_seconds = start_time + t

        #pdb.set_trace()
        # make sure the y array is not a list. Assimulo uses lists
        y_asnumpy = numpy.array(y)
        Model_temp = temp
        #pdb.set_trace()
        #Calculate the concentration of RO2 species, using an index file created during parsing
        RO2 = numpy.sum(y[RO2_indices])

        #Calculate reaction rate for each equation.
        # Note that H2O will change in parcel mode
        # The time_of_day_seconds is used for photolysis rates - need to change this if want constant values
        rates = evaluate_rates_fortran(RO2, H2O, Model_temp,
                                       time_of_day_seconds)
        #pdb.set_trace()
        # Calculate product of all reactants and stochiometry for each reaction [A^a*B^b etc]
        reactants = reactants_fortran(y_asnumpy[0:num_species - 1])
        #pdb.set_trace()
        #Multiply product of reactants with rate coefficient to get reaction rate
        reactants = numpy.multiply(reactants, rates)
        #pdb.set_trace()
        # Now use reaction rates with the loss_gain matri to calculate the final dydt for each compound
        # With the assimulo solvers we need to output numpy arrays
        dydt_gas = loss_gain_fortran(reactants)
        #pdb.set_trace()

        dy_dt[0:num_species - 1, 0] = dydt_gas

        # Change the saturation vapour pressure of water
        # Need to re-think the change of organic vapour pressures with temperature.
        # At the moment this is kept constant as re-calulation using UManSysProp very slow
        sat_vap_water = numpy.exp((-0.58002206E4 / Model_temp) + 0.13914993E1 - \
        (0.48640239E-1 * Model_temp) + (0.41764768E-4 * (Model_temp**2.0E0))- \
        (0.14452093E-7 * (Model_temp**3.0E0)) + (0.65459673E1 * numpy.log(Model_temp)))
        sat_vp[-1] = (numpy.log10(sat_vap_water * 9.86923E-6))
        Psat = numpy.power(10.0, sat_vp)

        # Convert the concentration of each component in the gas phase into a partial pressure using the ideal gas law
        # Units are Pascals
        Pressure_gas = (y_asnumpy[0:num_species, ] /
                        NA) * 8.314E+6 * Model_temp  #[using R]

        core_mass_array = numpy.multiply(ycore_asnumpy / NA, core_molw_asnumpy)

        ####### Calculate the thermal conductivity of gases according to the new temperature ########
        K_water_vapour = (
            5.69 + 0.017 *
            (Model_temp - 273.15)) * 1e-3 * 4.187  #[W/mK []has to be in W/m.K]
        # Use this value for all organics, for now. If you start using a non-zero enthalpy of
        # vapourisation, this needs to change.
        therm_cond_air = K_water_vapour

        #----------------------------------------------------------------------------
        #F2c) Extract the current gas phase concentrations to be used in pressure difference calculations
        C_g_i_t = y_asnumpy[0:num_species, ]
        #Set the values for oxidants etc to 0 as will force no mass transfer
        #C_g_i_t[ignore_index]=0.0
        C_g_i_t = C_g_i_t[include_index]

        #pdb.set_trace()

        total_SOA_mass,aw_array,size_array,dy_dt_calc = dydt_partition_fortran(y_asnumpy,ycore_asnumpy,core_dissociation, \
        core_mass_array,y_density_array_asnumpy,core_density_array_asnumpy,ignore_index_fortran,y_mw,Psat, \
        DStar_org_asnumpy,alpha_d_org_asnumpy,C_g_i_t,N_perbin,gamma_gas_asnumpy,Latent_heat_asnumpy,GRAV, \
        Updraft,sigma,NA,kb,Rv,R_gas,Model_temp,cp,Ra,Lv_water_vapour)

        #pdb.set_trace()

        # Add the calculated gains/losses to the complete dy_dt array
        dy_dt[0:num_species + (num_species_condensed * num_bins),
              0] += dy_dt_calc[:]

        #pdb.set_trace()

        #----------------------------------------------------------------------------
        #F4) Now calculate the change in water vapour mixing ratio.
        #To do this we need to know what the index key for the very last element is
        #pdb.set_trace()
        #pdb.set_trace()
        #print "elapsed time=", elapsedTime
        dydt_func.total_SOA_mass = total_SOA_mass
        dydt_func.size_array = size_array
        dydt_func.temp = Model_temp
        dydt_func.RH = Pressure_gas[-1] / (Psat[-1] * 101325.0)
        dydt_func.water_activity = aw_array

        #----------------------------------------------------------------------------
        return dy_dt

    #-------------------------------------------------------------------------------------
    #-------------------------------------------------------------------------------------

    #import static compilation of Fortran functions for use in ODE solver
    print("Importing pre-compiled Fortran modules")
    from rate_coeff_f2py import evaluate_rates as evaluate_rates_fortran
    from reactants_conc_f2py import reactants as reactants_fortran
    from loss_gain_f2py import loss_gain as loss_gain_fortran
    from partition_f2py import dydt_partition as dydt_partition_fortran

    # 'Unpack' variables from input_dict
    species_dict = input_dict['species_dict']
    species_dict2array = input_dict['species_dict2array']
    species_initial_conc = input_dict['species_initial_conc']
    equations = input_dict['equations']
    num_species = input_dict['num_species']
    num_species_condensed = input_dict['num_species_condensed']
    y_density_array_asnumpy = input_dict['y_density_array_asnumpy']
    y_mw = input_dict['y_mw']
    sat_vp = input_dict['sat_vp']
    Delta_H = input_dict['Delta_H']
    Latent_heat_asnumpy = input_dict['Latent_heat_asnumpy']
    DStar_org_asnumpy = input_dict['DStar_org_asnumpy']
    alpha_d_org_asnumpy = input_dict['alpha_d_org_asnumpy']
    gamma_gas_asnumpy = input_dict['gamma_gas_asnumpy']
    Updraft = input_dict['Updraft']
    GRAV = input_dict['GRAV']
    Rv = input_dict['Rv']
    Ra = input_dict['Ra']
    R_gas = input_dict['R_gas']
    R_gas_other = input_dict['R_gas_other']
    cp = input_dict['cp']
    sigma = input_dict['sigma']
    NA = input_dict['NA']
    kb = input_dict['kb']
    Lv_water_vapour = input_dict['Lv_water_vapour']
    ignore_index = input_dict['ignore_index']
    ignore_index_fortran = input_dict['ignore_index_fortran']
    ycore_asnumpy = input_dict['ycore_asnumpy']
    core_density_array_asnumpy = input_dict['core_density_array_asnumpy']
    y_cond = input_dict['y_cond_initial']
    num_bins = input_dict['num_bins']
    core_molw_asnumpy = input_dict['core_molw_asnumpy']
    core_dissociation = input_dict['core_dissociation']
    N_perbin = input_dict['N_perbin']
    include_index = input_dict['include_index']

    # pdb.set_trace()

    #Specify some starting concentrations [ppt]
    Cfactor = 2.55e+10  #ppb-to-molecules/cc

    # Create variables required to initialise ODE
    y0 = [0] * (num_species + num_species_condensed * num_bins
                )  #Initial concentrations, set to 0
    t0 = 0.0  #T0

    # Define species concentrations in ppb fr the gas phase
    # You have already set this in the front end script, and now we populate the y array with those concentrations
    for specie in species_initial_conc.keys():
        if specie is not 'H2O':
            y0[species_dict2array[specie]] = species_initial_conc[
                specie] * Cfactor  #convert from pbb to molcules/cc
        elif specie is 'H2O':
            y0[species_dict2array[specie]] = species_initial_conc[specie]

    # Now add the initial condensed phase [including water]
    #pdb.set_trace()
    y0[num_species:num_species +
       ((num_bins) * num_species_condensed)] = y_cond[:]
    #pdb.set_trace()

    #Set the total_time of the simulation to 0 [havent done anything yet]
    total_time = 0.0

    # Define a 'key' that represents the end of the composition variables to track
    total_length_y = len(y0)
    key = num_species + ((num_bins) * num_species) - 1

    #pdb.set_trace()

    # Now run through the simulation in batches.
    # I do this to enable testing of coupling processes. Some initial investigations with non-ideality in
    # the condensed phase indicated that even defining a maximum step was not enough for ODE solvers to
    # overshoot a stable region. It also helps with in-simulation debugging. Its up to you if you want to keep this.
    # To not run in batches, just define one batch as your total simulation time. This will reduce any overhead with
    # initialising the solvers
    # Set total simulation time and batch steps in seconds

    # Note also that the current module outputs solver information after each batch step. This can be turned off and the
    # the batch step change for increased speed
    # simulation_time= 3600.0
    # batch_step=300.0
    t_array = []
    time_step = 0
    number_steps = int(
        simulation_time /
        batch_step)  # Just cycling through 3 steps to get to a solution

    # Define a matrix that stores values as outputs from the end of each batch step. Again, you can remove
    # the need to run in batches. You can tell the Assimulo solvers the frequency of outputs.
    y_matrix = numpy.zeros((int(number_steps), len(y0)))
    # Also define arrays and matrices that hold information such as total SOA mass
    SOA_matrix = numpy.zeros((int(number_steps), 1))
    size_matrix = numpy.zeros((int(number_steps), num_bins))

    print("Starting simulation")

    # In the following, we can
    while total_time < simulation_time:

        if total_time == 0.0:
            #Define an Assimulo problem
            #Define an explicit solver
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        else:
            y0 = y_output[
                -1, :]  # Take the output from the last batch as the start of this
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        # Define ODE parameters.
        # Initial steps might be slower than mid-simulation. It varies.
        #exp_mod.jac = dydt_jac
        # Define which ODE solver you want to use
        exp_sim = CVode(exp_mod)
        tol_list = [1.0e-2] * len(y0)
        exp_sim.atol = tol_list  #Default 1e-6
        exp_sim.rtol = 1.0e-4  #Default 1e-6
        exp_sim.inith = 1.0e-6  #Initial step-size
        #exp_sim.discr = 'Adams'
        exp_sim.maxh = 100.0
        # Use of a jacobian makes a big differece in simulation time. This is relatively
        # easy to define for a gas phase - not sure for an aerosol phase with composition
        # dependent processes.
        exp_sim.usejac = False  # To be provided as an option in future update.
        #exp_sim.fac1 = 0.05
        #exp_sim.fac2 = 50.0
        exp_sim.report_continuously = True
        exp_sim.maxncf = 1000
        #Sets the parameters
        t_output, y_output = exp_sim.simulate(
            batch_step)  #Simulate 'batch' seconds
        total_time += batch_step
        t_array.append(
            total_time
        )  # Save the output from the end step, of the current batch, to a matrix
        y_matrix[time_step, :] = y_output[-1, :]
        SOA_matrix[time_step, 0] = dydt_func.total_SOA_mass
        size_matrix[time_step, :] = dydt_func.size_array
        print("SOA [micrograms/m3] = ", dydt_func.total_SOA_mass)

        #now save this information into a matrix for later plotting.
        time_step += 1

    if save_output is True:

        print(
            "Saving the model output as a pickled object for later retrieval")
        # save the dictionary to a file for later retrieval - have to do each seperately.
        with open(filename + '_y_output.pickle', 'wb') as handle:
            pickle.dump(y_matrix, handle, protocol=pickle.HIGHEST_PROTOCOL)
        with open(filename + '_t_output.pickle', 'wb') as handle:
            pickle.dump(t_array, handle, protocol=pickle.HIGHEST_PROTOCOL)
        with open(filename + '_SOA_output.pickle', 'wb') as handle:
            pickle.dump(SOA_matrix, handle, protocol=pickle.HIGHEST_PROTOCOL)
        with open(filename + '_size_output.pickle', 'wb') as handle:
            pickle.dump(size_matrix, handle, protocol=pickle.HIGHEST_PROTOCOL)
        with open(filename + 'include_index.pickle', 'wb') as handle:
            pickle.dump(include_index,
                        handle,
                        protocol=pickle.HIGHEST_PROTOCOL)

    #pdb.set_trace()
    #Plot the change in concentration over time for a given specie. For the user to change / remove
    #In a future release I will add this as a seperate module
    if plot_mass is True:
        try:
            P.plot(t_array, SOA_matrix[:, 0], marker='o')
            P.title(exp_mod.name)
            P.ylabel("SOA mass [micrograms/m3]")
            P.xlabel("Time [seconds] since start of simulation")
            P.show()
        except:
            print(
                "There is a problem using Matplotlib in your environment. If using this within a docker container, you will need to transfer the data to the host or configure your container to enable graphical displays. More information can be found at http://wiki.ros.org/docker/Tutorials/GUI "
            )
コード例 #19
0
def run_example(with_plots=True):
    r"""
    This example shows how to use Assimulo and CVode for simulating sensitivities
    for initial conditions.

    .. math::
    
       \dot y_1 &= -(k_{01}+k_{21}+k_{31}) y_1 + k_{12} y_2 + k_{13} y_3 + b_1\\
       \dot y_2 &= k_{21} y_1 - (k_{02}+k_{12}) y_2 \\
       \dot y_3 &= k_{31} y_1 - k_{13} y_3
     
    with the parameter dependent inital conditions 
    :math:`y_1(0) = 0, y_2(0) = 0, y_3(0) = 0` . The initial values are taken as parameters :math:`p_1,p_2,p_3`
    for the computation of the sensitivity matrix, 
    see http://sundials.2283335.n4.nabble.com/Forward-sensitivities-for-initial-conditions-td3239724.html
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
    
    """
    def f(t, y, p):
        y1, y2, y3 = y
        k01 = 0.0211
        k02 = 0.0162
        k21 = 0.0111
        k12 = 0.0124
        k31 = 0.0039
        k13 = 0.000035
        b1 = 49.3

        yd_0 = -(k01 + k21 + k31) * y1 + k12 * y2 + k13 * y3 + b1
        yd_1 = k21 * y1 - (k02 + k12) * y2
        yd_2 = k31 * y1 - k13 * y3

        return N.array([yd_0, yd_1, yd_2])

    #The initial conditions
    y0 = [0.0, 0.0, 0.0]  #Initial conditions for y
    p0 = [0.0, 0.0, 0.0]  #Initial conditions for parameters
    yS0 = N.array([[1, 0, 0], [0, 1, 0], [0, 0, 1.]])

    #Create an Assimulo explicit problem
    exp_mod = Explicit_Problem(f,
                               y0,
                               p0=p0,
                               name='Example: Computing Sensitivities')

    #Sets the options to the problem
    exp_mod.yS0 = yS0

    #Create an Assimulo explicit solver (CVode)
    exp_sim = CVode(exp_mod)

    #Sets the paramters
    exp_sim.iter = 'Newton'
    exp_sim.discr = 'BDF'
    exp_sim.rtol = 1e-7
    exp_sim.atol = 1e-6
    exp_sim.pbar = [
        1, 1, 1
    ]  #pbar is used to estimate the tolerances for the parameters
    exp_sim.report_continuously = True  #Need to be able to store the result using the interpolate methods
    exp_sim.sensmethod = 'SIMULTANEOUS'  #Defines the sensitvity method used
    exp_sim.suppress_sens = False  #Dont suppress the sensitivity variables in the error test.

    #Simulate
    t, y = exp_sim.simulate(400)  #Simulate 400 seconds

    #Basic test
    nose.tools.assert_almost_equal(y[-1][0], 1577.6552477, 5)
    nose.tools.assert_almost_equal(y[-1][1], 611.9574565, 5)
    nose.tools.assert_almost_equal(y[-1][2], 2215.88563217, 5)
    nose.tools.assert_almost_equal(exp_sim.p_sol[0][1][0], 1.0)

    #Plot
    if with_plots:
        title_text = r"Sensitivity w.r.t.  ${}$"
        legend_text = r"$\mathrm{{d}}{}/\mathrm{{d}}{}$"
        P.figure(1)
        P.subplot(221)
        P.plot(t,
               N.array(exp_sim.p_sol[0])[:, 0], t,
               N.array(exp_sim.p_sol[0])[:, 1], t,
               N.array(exp_sim.p_sol[0])[:, 2])
        P.title(title_text.format('p_1'))
        P.legend((legend_text.format('y_1',
                                     'p_1'), legend_text.format('y_1', 'p_2'),
                  legend_text.format('y_1', 'p_3')))
        P.subplot(222)
        P.plot(t,
               N.array(exp_sim.p_sol[1])[:, 0], t,
               N.array(exp_sim.p_sol[1])[:, 1], t,
               N.array(exp_sim.p_sol[1])[:, 2])
        P.title(title_text.format('p_2'))
        P.legend((legend_text.format('y_2',
                                     'p_1'), legend_text.format('y_2', 'p_2'),
                  legend_text.format('y_2', 'p_3')))
        P.subplot(223)
        P.plot(t,
               N.array(exp_sim.p_sol[2])[:, 0], t,
               N.array(exp_sim.p_sol[2])[:, 1], t,
               N.array(exp_sim.p_sol[2])[:, 2])
        P.title(title_text.format('p_3'))
        P.legend((legend_text.format('y_3',
                                     'p_1'), legend_text.format('y_3', 'p_2'),
                  legend_text.format('y_3', 'p_3')))
        P.subplot(224)
        P.title('ODE Solution')
        P.plot(t, y)
        P.suptitle(exp_mod.name)
        P.show()

        return exp_mod, exp_sim
コード例 #20
0
def func_set_system():
    ##############################################
    #% initial conditions
    P_0           = depth*9.8*2600.           #;      % initial chamber pressure (Pa)
    T_0           = 1200            #;       % initial chamber temperature (K)
    eps_g0        = 0.04            #;       % initial gas volume fraction
    rho_m0        = 2600            #;       % initial melt density (kg/m^3)
    rho_x0        = 3065            #;       % initial crystal density (kg/m^3)
    a             = 2000.            #;       % initial radius of the chamber (m)
    V_0           = (4.*np.pi/3.)*a**3.  #; % initial volume of the chamber (m^3)

    ##############################################
    ##############################################
    IC = np.array([P_0, T_0, eps_g0, V_0, rho_m0, rho_x0])  # % store initial conditions
    ## Gas (eps_g = zero), eps_x is zero, too many crystals, 50 % crystallinity,eruption (yes/no)
    sw0 = [False,False,False,False,False]

    ##############################################
    #% error tolerances used in ode method
    dt = 3e7*10.
    begin_time = 0  # ; % initialize time
    N  = int(round((end_time-begin_time)/dt))
    ##############################################

    #Define an Assimulo problem
    exp_mod = Chamber_Problem(depth=depth,t0=begin_time,y0=IC,sw0=sw0)
    exp_mod.param['T_S'] = 500.#+273.
    exp_mod.param['T_in'] = 1200.
    exp_mod.param['eps_g_in'] = 0.0    # Gas fraction of incoming melt - gas phase ..
    exp_mod.param['m_eq_in'] = 0.03    # Volatile fraction of incoming melt
    exp_mod.param['Mdot_in']    = mdot
    exp_mod.param['eta_x_max'] = 0.55                                     # Locking fraction
    exp_mod.param['delta_Pc']   = 20e6
    exp_mod.allow_diffusion_init = True
    exp_mod.radius = a
    exp_mod.permeability = perm_val
    exp_mod.R_steps = 1500
    exp_mod.dt_init = dt
    inp_func1 = inp.Input_functions_Degruyer()
    exp_mod.set_input_functions(inp_func1)
    exp_mod.get_constants()
    exp_mod.set_init_crust(material = 'Westerly_Granite')
    #################
    begin_time = exp_mod.set_init_crust_profile(T_0)
    exp_mod.tcurrent = begin_time
    P_0 = exp_mod.plith
    exp_mod.t0 = begin_time
    exp_mod.param['heat_cond'] = 1.                                             # Turn on/off heat conduction
    exp_mod.param['visc_relax'] = 1.                                          # Turn on/off viscous relaxation
    exp_mod.param['press_relax'] = 1.                                          ## Turn on/off pressure diffusion
    exp_mod.param['frac_rad_Temp'] =0.75
    exp_mod.param['vol_degass'] = 1.
    exp_mod.param['outflow_model'] = None  # 'huppert'
    IC = np.array([P_0, T_0, eps_g0, V_0, rho_m0, rho_x0])  # % store initial conditions
    exp_mod.y0 = IC

    #Define an explicit solver
    exp_sim = CVode(exp_mod) #Create a CVode solver
    # exp_sim = LSODAR(exp_mod) #Create a CVode solver

    #Sets the parameters
    exp_sim.store_event_points = True
    #exp_sim.iter = 'Newton'
    #exp_sim.discr = 'BDF'
    exp_sim.inith = 1e2
    #exp_sim.display_progress = True
    exp_sim.rtol = 1.e-7
    #exp_sim.maxh = 3e8*5. # 10 years
    exp_sim.atol = 1e-7
    #exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used
    #exp_sim.suppress_sens = True       #Dont suppress the sensitivity variables in the error test.
    #exp_sim.usesens = True
    #exp_sim.report_continuously = True
    return exp_mod,exp_sim,N
コード例 #21
0
    def run_sim(Y, time, Y_AER1, YICE):
        def dy_dt_func(t, Y):

            dy_dt = np.zeros(len(Y))

            # add condensed semi-vol mass into bins
            if n.SV_flag:
                MBIN2[-1 * n.n_sv:, :] = np.reshape(Y[INDSV1:INDSV2],
                                                    [n.n_sv, nbins * nmodes])
            # calculate saturation vapour pressure over liquid
            svp1 = f.svp_liq(Y[ITEMP])
            # saturation ratio
            SL = svp1 * Y[IRH] / (Y[IPRESS] - svp1)
            SL = (SL * Y[IPRESS] / (1 + SL)) / svp1

            # water vapour mixing ratio
            WV = c.eps * Y[IRH] * svp1 / (Y[IPRESS] - svp1)
            WL = np.sum(Y[IND1:IND2] * Y[:IND1])  # LIQUID MIXING RATIO
            WI = np.sum(YICE[IND1:IND2] * YICE[:IND1])  # ice mixing ratio
            RM = c.RA + WV * c.RV

            CPM = c.CP + WV * c.CPV + WL * c.CPW + WI * c.CPI

            if simulation_type.lower() == 'chamber':
                # CHAMBER MODEL - pressure change
                dy_dt[IPRESS] = -100 * PRESS1 * PRESS2 * np.exp(-PRESS2 *
                                                                (time + t))
            elif simulation_type.lower() == 'parcel':
                # adiabatic parcel
                dy_dt[IPRESS] = -Y[IPRESS] / RM / Y[
                    ITEMP] * c.g * w  #! HYDROSTATIC EQUATION
            else:
                print('simulation type unknown')
                return

    # ----------------------------change in vapour content: -----------------------
    # 1. equilibruim size of particles
            if n.kappa_flag:
                #if n.SV_flag:
                # need to recalc kappa taking into acount the condensed semi-vols
                Kappa = np.sum(
                    (MBIN2[:, :] / RHOBIN2[:, :]) * KAPPABIN2[:, :],
                    axis=0) / np.sum(MBIN2[:, :] / RHOBIN2[:, :], axis=0)
                #  print(Kappa)
                #  print(MBIN2/RHOBIN2)
                KK01 = f.kk01(Y[0:IND1], Y[ITEMP], MBIN2, RHOBIN2, Kappa)

            else:
                KK01 = f.K01(Y[0:IND1], Y[ITEMP], MBIN2, n.n_sv, RHOBIN2,
                             NUBIN2, MOLWBIN2)

        #  print(KK01[0])
            Dw = KK01[2]  # wet diameter
            RHOAT = KK01[1]  # density of particles inc water and aerosol mass
            RH_EQ = KK01[0]  # equilibrium RH
            #  print(MBIN2/MOLWBIN2)
            # 2. growth rate of particles, Jacobson p455
            # rate of change of radius
            growth_rate = f.DROPGROWTHRATE(Y[ITEMP], Y[IPRESS], SL, RH_EQ,
                                           RHOAT, Dw)
            growth_rate[np.isnan(growth_rate)] = 0  # get rid of nans
            growth_rate = np.where(Y[IND1:IND2] < 1e-9, 0.0, growth_rate)

            # 3. Mass of water condensing
            # change in mass of water per particle
            dy_dt[:IND1] = (np.pi * RHOAT * Dw**2) * growth_rate

            # 4. Change in vapour content
            # change in water vapour mixing ratio
            dwv_dt = -1 * np.sum(
                Y[IND1:IND2] *
                dy_dt[:IND1])  # change to np.sum for speed  # mass
            # -----------------------------------------------------------------------------

            if simulation_type.lower() == 'chamber':
                # CHAMBER MODEL - temperature change
                dy_dt[ITEMP] = -Temp1 * Temp2 * np.exp(-Temp2 * (time + t))
            elif simulation_type.lower() == 'parcel':
                # adiabatic parcel
                dy_dt[ITEMP] = RM / Y[IPRESS] * dy_dt[IPRESS] * Y[
                    ITEMP] / CPM  # TEMPERATURE CHANGE: EXPANSION
                dy_dt[ITEMP] = dy_dt[ITEMP] - c.LV / CPM * dwv_dt
            else:
                print('simulation type unknown')
                return

    # --------------------------------RH change------------------------------------
            dy_dt[IRH] = svp1 * dwv_dt * (Y[IPRESS] - svp1)
            dy_dt[IRH] = dy_dt[IRH] + svp1 * WV * dy_dt[IPRESS]
            dy_dt[IRH] = (
                dy_dt[IRH] - WV * Y[IPRESS] *
                derivative(f.svp_liq, Y[ITEMP], dx=1.0) * dy_dt[ITEMP])
            dy_dt[IRH] = dy_dt[IRH] / (c.eps * svp1**2)
            # -----------------------------------------------------------------------------

            # ------------------------------ SEMI-VOLATILES -------------------------------
            if n.SV_flag:
                #      SV_mass = np.reshape(Y[INDSV1:INDSV2],[n.n_sv,n.nmodes*n.nbins])
                #     SV_mass = np.where(SV_mass == 0.0,1e-30,SV_mass)
                #    MBIN2[n.n_sv*-1:,:] = SV_mass

                RH_EQ_SV = f.K01SV(Y[:IND1], Y[ITEMP], MBIN2, n.n_sv, RHOBIN2,
                                   NUBIN2, MOLWBIN2)

                RH_EQ = RH_EQ_SV[0]
                RHOAT = RH_EQ_SV[1]
                DW = RH_EQ_SV[2]

                SVP_ORG = f.SVP_GASES(n.semi_vols, Y[ITEMP],
                                      n.n_sv)  #C-C equation

                #RH_ORG = [x*Y[IPRESS]/c.RA/Y[ITEMP] for x in Y[IRH_SV]]
                RH_ORG = [x for x in Y[IRH_SV]]
                RH_ORG = [(x / c.aerosol_dict[key][0]) * c.R * Y[ITEMP]
                          for x, key in zip(RH_ORG, n.semi_vols[:n.n_sv])
                          ]  # just for n_sv keys in dictionary
                RH_ORG = [RH_ORG[x] / SVP_ORG[x] for x in range(n.n_sv)]

                dy_dt[INDSV1:INDSV2] = f.SVGROWTHRATE(Y[ITEMP], Y[IPRESS],
                                                      SVP_ORG, RH_ORG, RH_EQ,
                                                      DW, n.n_sv, n.nbins,
                                                      n.nmodes, MOLWBIN2)

                dy_dt[IRH_SV] = -np.sum(np.reshape(
                    dy_dt[INDSV1:INDSV2], [n.n_sv, IND1]) * Y[IND1:IND2],
                                        axis=1)  #see line 137

            return dy_dt

    #--------------------- SET-UP solver ------------------------------------------

        y0 = Y
        t0 = 0.0

        #define assimulo problem
        exp_mod = Explicit_Problem(dy_dt_func, y0, t0)

        # define an explicit solver
        exp_sim = CVode(exp_mod)
        exp_sim.iter = 'Newton'
        exp_sim.discr = 'BDF'
        #set parameters
        tol_list = np.zeros_like(Y)
        tol_list[0:IND1] = 1e-40  # this is now different to ACPIM (1e-25)
        tol_list[IND1:IND2] = 10  # number

        tol_list[IND2:IND3] = 1e-30  # capacitance
        tol_list[IND3:INDSV2] = 1e-26  #condendensed semi-vol mass
        tol_list[IRH_SV] = 1e-26  # RH of each semi-vol compound

        tol_list[IPRESS] = 10
        tol_list[ITEMP] = 1e-4
        tol_list[IRH] = 1e-8  # set tolerance for each dydt function
        exp_sim.atol = tol_list
        exp_sim.rtol = 1.0e-8
        exp_sim.inith = 0  # initial time step-size
        exp_sim.usejac = False
        exp_sim.maxncf = 100  # max number of convergence failures allowed by solver
        exp_sim.verbosity = 40
        t_output, y_output = exp_sim.simulate(1)

        return y_output[-1, :], t_output[:]
コード例 #22
0
    def run_sim_ice(Y, YLIQ):
        def dy_dt_func(t, Y):

            dy_dt = np.zeros(len(Y))

            svp = f.svp_liq(Y[ITEMP])
            svp_ice = f.svp_ice(Y[ITEMP])

            # vapour mixing ratio
            WV = c.eps * Y[IRH_ICE] * svp / (Y[IPRESS_ICE] - svp)
            # liquid mixing ratio
            WL = sum(YLIQ[IND1:IND2] * YLIQ[0:IND1])
            # ice mixing ratio
            WI = sum(Y[IND1:IND2] * Y[0:IND1])

            Cpm = c.CP + WV * c.CPV + WL * c.CPW + WI * c.CPI

            # RH with respect to ice
            RH_ICE = WV / (c.eps * svp_ice / (Y[IPRESS_ICE] - svp_ice))
            # ------------------------- growth rate of ice --------------------------
            RH_EQ = 1e0  # from ACPIM, FPARCELCOLD - MICROPHYSICS.f90

            CAP = f.CAPACITANCE01(Y[0:IND1], np.exp(Y[IND2:IND3]))

            growth_rate = f.ICEGROWTHRATE(Y[ITEMP_ICE], Y[IPRESS_ICE],
                                          RH_ICE, RH_EQ, Y[0:IND1],
                                          np.exp(Y[IND2:IND3]), CAP)
            growth_rate[np.isnan(growth_rate)] = 0  # get rid of nans
            growth_rate = np.where(Y[IND1:IND2] < 1e-6, 0.0, growth_rate)

            # Mass of water condensing
            dy_dt[:IND1] = growth_rate

            #---------------------------aspect ratio---------------------------------------
            DELTA_RHO = c.eps * svp / (Y[IPRESS_ICE] - svp)
            DELTA_RHOI = c.eps * svp_ice / (Y[IPRESS_ICE] - svp_ice)
            DELTA_RHO = Y[IRH_ICE] * DELTA_RHO - DELTA_RHOI
            DELTA_RHO = DELTA_RHO * Y[IPRESS_ICE] / Y[ITEMP_ICE] / c.RA

            RHO_DEP = f.DEP_DENSITY(DELTA_RHO, Y[ITEMP_ICE])

            # this is the rate of change of LOG of the aspect ratio
            dy_dt[IND2:IND3] = (dy_dt[0:IND1] *
                                ((f.INHERENTGROWTH(Y[ITEMP_ICE]) - 1) /
                                 (f.INHERENTGROWTH(Y[ITEMP_ICE]) + 2)) /
                                (Y[0:IND1] * c.rhoi * RHO_DEP))
            #------------------------------------------------------------------------------
            # Change in vapour content
            dwv_dt = -1 * sum(Y[IND1:IND2] * dy_dt[0:IND1])

            # change in water vapour mixing ratio
            DRI = -1 * dwv_dt

            dy_dt[ITEMP_ICE] = 0.0  #+c.LS/Cpm*DRI

            # if n.Simulation_type.lower() == 'parcel':
            #     dy_dt[ITEMP_ICE]=dy_dt[ITEMP_ICE] + c.LS/Cpm*DRI
            #---------------------------RH change------------------------------------------

            dy_dt[IRH_ICE] = (Y[IPRESS_ICE] - svp) * svp * dwv_dt

            dy_dt[IRH_ICE] = (
                dy_dt[IRH_ICE] - WV * Y[IPRESS_ICE] *
                derivative(f.svp_liq, Y[ITEMP_ICE], dx=1.0) * dy_dt[ITEMP_ICE])
            dy_dt[IRH_ICE] = dy_dt[IRH_ICE] / (c.eps * svp**2)
            #------------------------------------------------------------------------------
            return dy_dt

        #--------------------- SET-UP solver --------------------------------------

        y0 = Y
        t0 = 0.0

        #define assimulo problem
        exp_mod = Explicit_Problem(dy_dt_func, y0, t0)

        # define an explicit solver
        exp_sim = CVode(exp_mod)
        exp_sim.iter = 'Newton'
        exp_sim.discr = 'BDF'
        # set tolerance for each dydt function
        tol_list = np.zeros_like(Y)
        tol_list[0:IND1] = 1e-30  # mass
        tol_list[IND1:IND2] = 10  # number

        tol_list[IND2:IND3] = 1e-30  # aspect ratio
        # tol_list[IND3:IRH_SV_ICE] = 1e-26
        #tol_list[IRH_SV_ICE] = 1e-26

        tol_list[IPRESS_ICE] = 10
        tol_list[ITEMP_ICE] = 1e-4
        tol_list[IRH_ICE] = 1e-8

        exp_sim.atol = tol_list
        exp_sim.rtol = 1.0e-8
        exp_sim.inith = 1.0e-2  # initial time step-size
        exp_sim.usejac = False
        exp_sim.maxncf = 100  # max number of convergence failures allowed by solver
        exp_sim.verbosity = 40

        t_output, y_output = exp_sim.simulate(1)

        return y_output[-1, :]
コード例 #23
0
def run_example(with_plots=True):
    r"""
    Example to demonstrate the use of a preconditioner
    
    .. math::
        
        \dot y_1 & = 2 t \sin y_1  + t \sin y_2 \\
        \dot y_2 & = 3 t \sin y_1  + 2 t \sin y_2
        
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Define the rhs
    def rhs(t, y):
        A = np.array([[2.0, 1.0], [3.0, 2.0]])
        yd = np.dot(A * t, np.sin(y))
        return yd

    #Define the preconditioner setup function
    def prec_setup(t, y, fy, jok, gamma, data):
        A = np.array([[2.0, 1.0], [3.0, 2.0]])

        #If jok is false the jacobian data needs to be recomputed
        if jok == False:

            #Extract the diagonal of the jacobian to form a Jacobi preconditioner
            a0 = A[0, 0] * t * np.cos(y[0])
            a1 = A[1, 1] * t * np.cos(y[1])
            a = np.array([(1. - gamma * a0), (1. - gamma * a1)])

            #Return true (jacobian data was recomputed) and the new data
            return [True, a]

        #If jok is true the existing jacobian data can be reused
        if jok == True:

            #Return false (jacobian data was reused) and the old data
            return [False, data]

    #Define the preconditioner solve function
    def prec_solve(t, y, fy, r, gamma, delta, data):

        #Solve the system Pz = r
        z0 = r[0] / data[0]
        z1 = r[1] / data[1]

        z = np.array([z0, z1])
        return z

    #Initial conditions
    y0 = [1.0, 2.0]

    #Define an Assimulo problem
    exp_mod = Explicit_Problem(
        rhs, y0, name="Example of using a preconditioner in SUNDIALS")

    #Set the preconditioner setup and solve function for the problem
    exp_mod.prec_setup = prec_setup
    exp_mod.prec_solve = prec_solve

    #Create a CVode solver
    exp_sim = CVode(exp_mod)

    #Set the parameters for the solver
    exp_sim.iter = 'Newton'
    exp_sim.discr = 'BDF'
    exp_sim.atol = 1e-5
    exp_sim.rtol = 1e-5
    exp_sim.linear_solver = 'SPGMR'
    exp_sim.precond = "PREC_RIGHT"  #Set the desired type of preconditioning

    #Simulate
    t, y = exp_sim.simulate(5)

    if with_plots:
        exp_sim.plot()

    #Basic verification
    nose.tools.assert_almost_equal(y[-1, 0], 3.11178295, 4)
    nose.tools.assert_almost_equal(y[-1, 1], 3.19318992, 4)

    return exp_mod, exp_sim
コード例 #24
0
def run_example(with_plots=True):
    """
    Simulations for the Gyro (Heavy Top) example in Celledoni/Safstrom: 
        Journal of Physics A, Vol 39, 5463-5478, 2006
        
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
    
    """
    def curl(v):
        return array([[0, v[2], -v[1]], [-v[2], 0, v[0]], [v[1], -v[0], 0]])

    #Defines the rhs
    def f(t, u):
        """
        Simulations for the Gyro (Heavy Top) example in Celledoni/Safstrom: 
        Journal of Physics A, Vol 39, 5463-5478, 2006
        """
        I1 = 1000.
        I2 = 5000.
        I3 = 6000.
        u0 = [0, 0, 1.]
        pi = u[0:3]
        Q = (u[3:12]).reshape((3, 3))
        Qu0 = dot(Q, u0)
        f = array([Qu0[1], -Qu0[0], 0.])
        f = 0
        omega = array([pi[0] / I1, pi[1] / I2, pi[2] / I3])
        pid = dot(curl(omega), pi) + f
        Qd = dot(curl(omega), Q)
        return hstack([pid, Qd.reshape((9, ))])

    def energi(state):
        energi = []
        for st in state:
            Q = (st[3:12]).reshape((3, 3))
            pi = st[0:3]
            u0 = [0, 0, 1.]
            Qu0 = dot(Q, u0)
            V = Qu0[2]  # potential energy
            T = 0.5 * (pi[0]**2 / 1000. + pi[1]**2 / 5000. + pi[2]**2 / 6000.)
            energi.append([T])
        return energi

    #Initial conditions
    y0 = hstack([[1000. * 10, 5000. * 10, 6000 * 10], eye(3).reshape((9, ))])

    #Create an Assimulo explicit problem
    exp_mod = Explicit_Problem(f, y0, name="Gyroscope Example")

    #Create an Assimulo explicit solver (CVode)
    exp_sim = CVode(exp_mod)

    #Sets the parameters
    exp_sim.discr = 'BDF'
    exp_sim.iter = 'Newton'
    exp_sim.maxord = 2  #Sets the maxorder
    exp_sim.atol = 1.e-10
    exp_sim.rtol = 1.e-10

    #Simulate
    t, y = exp_sim.simulate(0.1)

    #Plot
    if with_plots:
        import pylab as P
        P.plot(t, y / 10000.)
        P.xlabel('Time')
        P.ylabel('States, scaled by $10^4$')
        P.title(exp_mod.name)
        P.show()

    #Basic tests
    nose.tools.assert_almost_equal(y[-1][0], 692.800241862)
    nose.tools.assert_almost_equal(y[-1][8], 7.08468221e-1)

    return exp_mod, exp_sim
コード例 #25
0
ファイル: ODE_solver.py プロジェクト: Mbex/PyBox
def run_simulation(filename, save_output, start_time, temp, RH, RO2_indices,
                   H2O, input_dict, simulation_time, batch_step):

    from assimulo.solvers import RodasODE, CVode  #Choose solver accoring to your need.
    from assimulo.problem import Explicit_Problem

    # In this function, we import functions that have been pre-compiled for use in the ODE solver
    # The function that calculates the RHS of the ODE is also defined within this function, such
    # that it can be used by the Assimulo solvers

    # In the standard Python version [not using Numba] I use Sparse matrix operations in calculating loss/gain of each compound.
    # This function loads the matrix created at the beginning of the module.
    def load_sparse_csr(filename):
        loader = numpy.load('loss_gain_' + filename + '.npz')
        return csr_matrix(
            (loader['data'], loader['indices'], loader['indptr']),
            shape=loader['shape'])

    def load_sparse_csr_reactants(filename):
        loader = numpy.load('reactants_indices_sparse_' + filename + '.npz')
        return csr_matrix(
            (loader['data'], loader['indices'], loader['indptr']),
            shape=loader['shape'])

    #-------------------------------------------------------------------------------------
    # define the ODE function to be called
    def dydt_func(t, y):
        """
        This function defines the right-hand side [RHS] of the ordinary differential equations [ODEs] to be solved
        input:
        • t - time variable [internal to solver]
        • y - array holding concentrations of all compounds in both gas and particulate [molecules/cc]
        output:
        dydt - the dy_dt of each compound in both gas and particulate phase [molecules/cc.sec]
        """

        #pdb.set_trace()
        #Here we use the pre-created Numba based functions to arrive at our value for dydt
        # Calculate time of day
        time_of_day_seconds = start_time + t

        # make sure the y array is not a list. Assimulo uses lists
        y_asnumpy = numpy.array(y)

        #pdb.set_trace()
        # reactants=numpy.zeros((equations),)

        #pdb.set_trace()
        #Calculate the concentration of RO2 species, using an index file created during parsing
        RO2 = numpy.sum(y[RO2_indices])

        #Calculate reaction rate for each equation.
        # Note that H2O will change in parcel mode [to be changed in the full aerosol mode]
        # The time_of_day_seconds is used for photolysis rates - need to change this if want constant values
        #pdb.set_trace()
        rates = evaluate_rates(time_of_day_seconds, RO2, H2O, temp,
                               numpy.zeros((equations)), numpy.zeros((63)))

        # Calculate product of all reactants and stochiometry for each reaction [A^a*B^b etc]
        reactants = reactant_product(y_asnumpy, equations,
                                     numpy.zeros((equations)))

        #Multiply product of reactants with rate coefficient to get reaction rate
        #pdb.set_trace()
        reactants = numpy.multiply(reactants, rates)

        # Now use reaction rates with the loss_gain information in a pre-created Numba file to calculate the final dydt for each compound
        dydt = dydt_eval(numpy.zeros((len(y_asnumpy))), reactants)

        #pdb.set_trace()

        ############ Development place-holder ##############
        # ----------------------------------------------------------------------------------
        # The following demonstrates the same procedure but using only Numpy and pure python
        # For the full MCM this is too slow, but is useful for demonstrations and testing

        #Calculate reaction rate for each equation.
        ## rates=test(time_of_day_seconds,RO2,H2O,temp)

        # Calculate product of all reactants and stochiometry for each reaction [A^a*B^b etc]
        # Take the approach of using sparse matrix operations from a python perspective
        # This approach uses the rule of logarithms and sparse matrix multiplication

        ##temp_array=reactants_indices_sparse @ numpy.log(y_asnumpy)
        ##indices=numpy.where(temp_array > 0.0)
        ##reactants[indices]=numpy.exp(temp_array[indices])

        #Multiply product of reactants with rate coefficient to get reaction rate
        ## reactants = numpy.multiply(reactants,rates)

        # Now use reaction rates with the loss_gain matri to calculate the final dydt for each compound
        # With the assimulo solvers we need to output numpy arrays

        ##dydt=numpy.array(loss_gain @ reactants)
        # ----------------------------------------------------------------------------------

        return dydt

    #-------------------------------------------------------------------------------------

    print(
        "Importing Numba modules [compiling if first import or clean build...please be patient]"
    )
    #import Numba functions for use in ODE solver
    from Rate_coefficients_numba import evaluate_rates
    from Reactants_conc_numba import reactants as reactant_product
    from Loss_Gain_numba import dydt as dydt_eval

    # 'Unpack' variables from input_dict
    species_dict = input_dict['species_dict']
    species_dict2array = input_dict['species_dict2array']
    species_initial_conc = input_dict['species_initial_conc']
    equations = input_dict['equations']

    # Set dive by zero to ignore for use of any sparse matrix multiplication
    numpy.errstate(divide='ignore')

    # --- For Numpy and pure Python runs ----
    # Load the sparse matrix used in calculating the reactant products and dydt function
    ## reactants_indices_sparse = load_sparse_csr_reactants(filename)
    ## loss_gain = load_sparse_csr(filename)

    #Specify some starting concentrations [ppt]
    Cfactor = 2.55e+10  #ppb-to-molecules/cc

    # Create variables required to initialise ODE
    num_species = len(species_dict.keys())
    y0 = [0] * num_species  #Initial concentrations, set to 0
    t0 = 0.0  #T0

    # Define species concentrations in ppb
    # You have already set this in the front end script, and now we populate the y array with those concentrations
    for specie in species_initial_conc.keys():
        y0[species_dict2array[specie]] = species_initial_conc[
            specie] * Cfactor  #convert from pbb to molcules/cc

    #Set the total_time of the simulation to 0 [havent done anything yet]
    total_time = 0.0

    # Now run through the simulation in batches.
    # I do this to enable testing of coupling processes. Some initial investigations with non-ideality in
    # the condensed phase indicated that even defining a maximum step was not enough for ODE solvers to
    # overshoot a stable region. It also helps with in-simulation debugging. Its up to you if you want to keep this.
    # To not run in batches, just define one batch as your total simulation time. This will reduce any overhead with
    # initialising the solvers
    # Set total simulation time and batch steps in seconds

    # Note also that the current module outputs solver information after each batch step. This can be turned off and the
    # the batch step change for increased speed
    # simulation_time= 3600.0 # seconds
    # batch_step=100.0 # seconds
    t_array = []
    time_step = 0
    number_steps = int(
        simulation_time /
        batch_step)  # Just cycling through 3 steps to get to a solution

    # Define a matrix that stores values as outputs from the end of each batch step. Again, you can remove
    # the need to run in batches. You can tell the Assimulo solvers the frequency of outputs.
    y_matrix = numpy.zeros((int(number_steps), len(y0)))

    print("Starting simulation")

    #pdb.set_trace()

    while total_time < simulation_time:

        if total_time == 0.0:
            #Define an Assimulo problem
            #Define an explicit solver
            #pdb.set_trace()
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        else:
            y0 = y_output[
                -1, :]  # Take the output from the last batch as the start of this
            exp_mod = Explicit_Problem(dydt_func, y0, t0, name=filename)

        # Define ODE parameters.
        # Initial steps might be slower than mid-simulation. It varies.
        #exp_mod.jac = dydt_jac
        # Define which ODE solver you want to use
        exp_sim = CVode(exp_mod)
        tol_list = [1.0e-3] * num_species
        exp_sim.atol = tol_list  #Default 1e-6
        exp_sim.rtol = 1e-6  #Default 1e-6
        exp_sim.inith = 1.0e-6  #Initial step-size
        #exp_sim.discr = 'Adams'
        exp_sim.maxh = 100.0
        # Use of a jacobian makes a big differece in simulation time. This is relatively
        # easy to define for a gas phase - not sure for an aerosol phase with composition
        # dependent processes.
        exp_sim.usejac = False  # To be provided as an option in future update. See Fortran variant for use of Jacobian
        #exp_sim.fac1 = 0.05
        #exp_sim.fac2 = 50.0
        exp_sim.report_continuously = True
        exp_sim.maxncf = 1000
        #Sets the parameters
        t_output, y_output = exp_sim.simulate(
            batch_step)  #Simulate 'batch' seconds
        total_time += batch_step
        t_array.append(
            total_time
        )  # Save the output from the end step, of the current batch, to a matrix
        y_matrix[time_step, :] = y_output[-1, :]

        #pdb.set_trace()

        #now save this information into a matrix for later plotting.
        time_step += 1

    # Do you want to save the generated matrix of outputs?
    if save_output:
        numpy.save(filename + '_output', y_matrix)
        df = pd.DataFrame(y_matrix)
        df.to_csv(filename + "_output_matrix.csv")
        w = csv.writer(open(filename + "_output_names.csv", "w"))
        for specie, number in species_dict2array.items():
            w.writerow([specie, number])

    with_plots = True

    #pdb.set_trace()
    #Plot the change in concentration over time for a given specie. For the user to change / remove
    #In a future release I will add this as a seperate module
    if with_plots:
        try:
            P.plot(t_array,
                   numpy.log10(y_matrix[:, species_dict2array['APINENE']]),
                   marker='o',
                   label="APINENE")
            P.plot(t_array,
                   numpy.log10(y_matrix[:, species_dict2array['PINONIC']]),
                   marker='o',
                   label="PINONIC")
            P.title(exp_mod.name)
            P.legend(loc='upper left')
            P.ylabel("Concetration log10[molecules/cc]")
            P.xlabel("Time [seconds] since start of simulation")
            P.show()
        except:
            print(
                "There is a problem using Matplotlib in your environment. If using this within a docker container, you will need to transfer the data to the host or configure your container to enable graphical displays. More information can be found at http://wiki.ros.org/docker/Tutorials/GUI "
            )
コード例 #26
0
def run_example(with_plots=True):
    """
    This is the same example from the Sundials package (cvsRoberts_FSA_dns.c)

    This simple example problem for CVode, due to Robertson, 
    is from chemical kinetics, and consists of the following three 
    equations:

    .. math:: 
    
       \dot y_1 &= -p_1 y_1 + p_2 y_2 y_3 \\
       \dot y_2 &= p_1 y_1 - p_2 y_2 y_3 - p_3 y_2^2 \\
       \dot y_3 &= p_3  y_2^2
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
    """
    def f(t, y, p):
        p3 = 3.0e7

        yd_0 = -p[0] * y[0] + p[1] * y[1] * y[2]
        yd_1 = p[0] * y[0] - p[1] * y[1] * y[2] - p3 * y[1]**2
        yd_2 = p3 * y[1]**2

        return N.array([yd_0, yd_1, yd_2])

    #The initial conditions
    y0 = [1.0, 0.0, 0.0]  #Initial conditions for y

    #Create an Assimulo explicit problem
    exp_mod = Explicit_Problem(f,
                               y0,
                               name='Sundials test example: Chemical kinetics')

    #Sets the options to the problem
    exp_mod.p0 = [0.040, 1.0e4]  #Initial conditions for parameters
    exp_mod.pbar = [0.040, 1.0e4]

    #Create an Assimulo explicit solver (CVode)
    exp_sim = CVode(exp_mod)

    #Sets the paramters
    exp_sim.iter = 'Newton'
    exp_sim.discr = 'BDF'
    exp_sim.rtol = 1.e-4
    exp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6])
    exp_sim.sensmethod = 'SIMULTANEOUS'  #Defines the sensitvity method used
    exp_sim.suppress_sens = False  #Dont suppress the sensitivity variables in the error test.
    exp_sim.report_continuously = True

    #Simulate
    t, y = exp_sim.simulate(
        4, 400)  #Simulate 4 seconds with 400 communication points

    #Plot
    if with_plots:
        import pylab as P
        P.plot(t, y)
        P.xlabel('Time')
        P.ylabel('State')
        P.title(exp_mod.name)
        P.show()

    #Basic test
    nose.tools.assert_almost_equal(y[-1][0], 9.05518032e-01, 4)
    nose.tools.assert_almost_equal(y[-1][1], 2.24046805e-05, 4)
    nose.tools.assert_almost_equal(y[-1][2], 9.44595637e-02, 4)
    nose.tools.assert_almost_equal(
        exp_sim.p_sol[0][-1][0], -1.8761,
        2)  #Values taken from the example in Sundials
    nose.tools.assert_almost_equal(exp_sim.p_sol[1][-1][0], 2.9614e-06, 8)

    return exp_mod, exp_sim
コード例 #27
0
def run_example(with_plots=True):
    r"""
    This is the same example from the Sundials package (cvsRoberts_FSA_dns.c)
    Its purpose is to demonstrate the use of parameters in the differential equation.

    This simple example problem for CVode, due to Robertson
    see http://www.dm.uniba.it/~testset/problems/rober.php, 
    is from chemical kinetics, and consists of the system:
    
    .. math:: 
    
       \dot y_1 &= -p_1 y_1 + p_2 y_2 y_3 \\
       \dot y_2 &= p_1 y_1 - p_2 y_2 y_3 - p_3 y_2^2 \\
       \dot y_3 &= p_3  y_ 2^2
       
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
    
    """
    
    def f(t, y, p):
        
        yd_0 = -p[0]*y[0]+p[1]*y[1]*y[2] 
        yd_1 = p[0]*y[0]-p[1]*y[1]*y[2]-p[2]*y[1]**2 
        yd_2 = p[2]*y[1]**2
        
        return N.array([yd_0,yd_1,yd_2])
        
    def jac(t,y, p):
        J = N.array([[-p[0], p[1]*y[2], p[1]*y[1]],
                     [p[0], -p[1]*y[2]-2*p[2]*y[1], -p[1]*y[1]],
                     [0.0, 2*p[2]*y[1],0.0]])
        return J
        
    def fsens(t, y, s, p):
        J = N.array([[-p[0], p[1]*y[2], p[1]*y[1]],
                     [p[0], -p[1]*y[2]-2*p[2]*y[1], -p[1]*y[1]],
                     [0.0, 2*p[2]*y[1],0.0]])
        P = N.array([[-y[0],y[1]*y[2],0],
                     [y[0], -y[1]*y[2], -y[1]**2],
                     [0,0,y[1]**2]])
        return J.dot(s)+P
    
    #The initial conditions
    y0 = [1.0,0.0,0.0]          #Initial conditions for y
    
    #Create an Assimulo explicit problem
    exp_mod = Explicit_Problem(f,y0, name='Robertson Chemical Kinetics Example')
    exp_mod.rhs_sens = fsens
    exp_mod.jac = jac
    
    #Sets the options to the problem
    exp_mod.p0 = [0.040, 1.0e4, 3.0e7]  #Initial conditions for parameters
    exp_mod.pbar = [0.040, 1.0e4, 3.0e7]

    #Create an Assimulo explicit solver (CVode)
    exp_sim = CVode(exp_mod)
    
    #Sets the solver paramters
    exp_sim.iter = 'Newton'
    exp_sim.discr = 'BDF'
    exp_sim.rtol = 1.e-4
    exp_sim.atol = N.array([1.0e-8, 1.0e-14, 1.0e-6])
    exp_sim.sensmethod = 'SIMULTANEOUS' #Defines the sensitvity method used
    exp_sim.suppress_sens = False       #Dont suppress the sensitivity variables in the error test.
    exp_sim.report_continuously = True

    #Simulate
    t, y = exp_sim.simulate(4,400) #Simulate 4 seconds with 400 communication points
    
    #Basic test
    nose.tools.assert_almost_equal(y[-1][0], 9.05518032e-01, 4)
    nose.tools.assert_almost_equal(y[-1][1], 2.24046805e-05, 4)
    nose.tools.assert_almost_equal(y[-1][2], 9.44595637e-02, 4)
    nose.tools.assert_almost_equal(exp_sim.p_sol[0][-1][0], -1.8761, 2) #Values taken from the example in Sundials
    nose.tools.assert_almost_equal(exp_sim.p_sol[1][-1][0], 2.9614e-06, 8)
    nose.tools.assert_almost_equal(exp_sim.p_sol[2][-1][0], -4.9334e-10, 12)
    
    #Plot
    if with_plots:
        P.plot(t, y)
        P.title(exp_mod.name)
        P.xlabel('Time')
        P.ylabel('State')
        P.show()  
        
    return exp_mod, exp_sim
コード例 #28
0
def ode_gen(t, y, num_speci, num_eqn, rindx, pindx, rstoi, pstoi, H2Oi, TEMP,
            RO2_indices, num_sb, Psat, mfp, accom_coeff, surfT, y_dens,
            N_perbin, DStar_org, y_mw, x, core_diss, Varr, Vbou, RH, rad0,
            Vol0, end_sim_time, pconc, save_step, rbou, therm_sp, Cw,
            light_time, light_stat, nreac, nprod, prodn, reacn, new_partr, MV,
            nucv1, nucv2, nucv3, inflectDp, pwl_xpre, pwl_xpro, inflectk,
            nuc_comp, ChamR, Rader, PInit, testf, kwgt):

    # ----------------------------------------------------------
    # inputs

    # t - suggested time step length (s)
    # num_speci - number of components
    # num_eqn - number of equations
    # Psat - saturation vapour pressures (molecules/cm3 (air))
    # y_dens - components' densities (g/cc)
    # y_mw - components' molecular weights (g/mol)
    # x - radii of particle size bins (um) (excluding walls)
    # therm_sp - thermal speed of components (m/s)
    # DStar_org - gas-phase diffusion coefficient of components (m2/s)
    # Cw - concentration of wall (molecules/cm3 (air))
    # light_time - times (s) of when lights on and lights off (corresponding to light
    # 				status in light_stat)
    # light_stat - order of lights on (1) and lights off (0)
    # chamA - chamber area (m2)
    # nreac - number of reactants per equation
    # nprod - number of products per equation
    # pindx - indices of equation products (cols) in each equation (rows)
    # prodn - pindx no. of columns
    # reacn - rindx no. of columns
    # rindx - index of reactants per equation
    # rstoi - stoichometry of reactants per equation
    # pstoi - stoichometry of products
    # pconc - concentration of seed particles (#/cc (air)) (1)
    # new_partr - radius of two ELVOC molecules together in a newly nucleating
    # particle (cm)
    # MV - molar volume (cc/mol) (1D array)
    # nuc_comp - index of the nucleating component
    # ChamR - spherical equivalent radius of chamber (below eq. 2 Charan (2018)) (m)
    # Rader - flag of whether or not to use Rader and McMurry approach
    # PInit - pressure inside chamber (Pa)
    # testf - flag to say whether in normal mode (0) or testing mode (1)
    # kgwt - mass transfer coefficient for vapour-wall partitioning (cm3/molecule.s)
    # ----------------------------------------------------------

    if testf == 1:
        return (0, 0, 0, 0)  # return dummies

    R_gas = si.R  # ideal gas constant (kg.m2.s-2.K-1.mol-1)
    NA = si.Avogadro  # Avogadro's number (molecules/mol)

    step = 0  # ode time interval step number
    t0 = t  # remember original suggested time step (s)
    # final +1 for ELVOC in newly nucleating particles
    y0 = np.zeros((num_speci + num_sb * num_speci))
    y0[:] = y[:]  # initial concentrations (molecules/cc (air))
    y00 = np.zeros((num_speci + num_sb * num_speci))
    y00[:] = y[:]  # initial concentrations (molecules/cc (air))

    # initial volumes of particles in size bins at start of time steps
    if num_sb > 1:
        Vstart = np.zeros((num_sb - 1))
        Vstart[:] = Vol0[:] * N_perbin
    else:
        Vstart = 0.0
    sumt = 0.0  # total time integrated over (s)

    # record initial values
    if num_sb > 0:
        # particle-phase concentrations (molecules/cc (air))
        yp = np.transpose(y[num_speci:-(num_speci)].reshape(
            num_sb - 1, num_speci))
    else:
        yp = 0.0
    [t_out, y_mat, Nresult,
     x2] = recording(y, N_perbin, x, step, sumt, 0, 0, 0, 0,
                     int(end_sim_time / save_step), num_speci, num_sb,
                     y_mw[:, 0], y_dens[:, 0] * 1.0e-3, yp, Vbou)

    tnew = 0.46875  # relatively small time step (s) for first bit
    # number concentration of nucleated particles formed (# particles/cc (air))
    new_part_sum1 = 0.0

    save_count = int(1)  # count on number of times saving code called
    # count in number of time steps since time interval was last reduced
    tinc_count = 10

    from rate_valu_calc import rate_valu_calc  # function to update rate coefficients
    print('starting ode solver')

    while sumt < end_sim_time:  # step through time intervals to do ode

        # increase time step if time step not been decreased for 10 steps
        if tinc_count == 0 and tnew < t0:
            tnew = tnew * 2.0

        # check whether lights on or off
        timediff = sumt - np.array(light_time)
        timedish = (timediff == np.min(timediff[timediff >= 0])
                    )  # reference time index
        lightm = (
            np.array(light_stat))[timedish]  # whether lights on or off now

        # update reaction rate coefficients
        reac_coef = rate_valu_calc(RO2_indices, y[H2Oi], TEMP, lightm, y)

        y0[:] = y[:]  # update initial concentrations (molecules/cc (air))
        # update particle volumes at start of time step (um3)
        Vstart = Varr * N_perbin
        redt = 1  # reset time reduction flag
        t = tnew  # reset integration time (s)

        if num_sb > 1:
            # update partitioning coefficients
            [kimt, kelv_fac
             ] = kimt_calc(y, mfp, num_sb, num_speci, accom_coeff, y_mw, surfT,
                           R_gas, TEMP, NA, y_dens, N_perbin, DStar_org,
                           x.reshape(1, -1) * 1.0e-6, Psat, therm_sp, H2Oi)

        # ensure no confusion that components are present due to low value fillers for
        # concentrations (molecules/cc (air))
        y0[y0 == 1.0e-40] = 0.0
        print()
        # enter a while loop that continues to decrease the time step until particle
        # size bins don't change by more than one size bin (given by moving centre)
        while redt == 1:
            print('cumulative time', sumt)

            # numba compiler to convert to machine code
            @jit(f8[:](f8, f8[:]), nopython=True)
            # ode solver -------------------------------------------------------------
            def dydt(t, y):

                # empty array to hold rate of change (molecules/cc(air).s)
                dydt = np.zeros((len(y)))
                # gas-phase rate of change ------------------------------------
                for i in range(num_eqn):  # equation loop

                    # gas-phase rate of change (molecules/cc (air).s)

                    gprate = ((y[rindx[i, 0:nreac[i]]]**
                               rstoi[i, 0:nreac[i]]).prod()) * reac_coef[i]
                    dydt[rindx[i, 0:nreac[i]]] -= gprate  # loss of reactants
                    dydt[pindx[i, 0:nprod[i]]] += gprate  # gain of products

                if num_sb > 1:

                    # -----------------------------------------------------------
                    for ibin in range(num_sb - 1):  # size bin loop

                        Csit = y[num_speci * (ibin + 1):num_speci * (ibin + 2)]
                        # sum of molecular concentrations per bin (molecules/cc (air))
                        conc_sum = np.zeros((1))
                        if pconc > 0.0:  # if seed particles present
                            conc_sum[0] = ((Csit[0:-1].sum()) +
                                           Csit[-1] * core_diss)
                        else:
                            conc_sum[0] = Csit.sum()
                        # prevent numerical error due to division by zero
                        ish = conc_sum == 0.0
                        conc_sum[ish] = 1.0e-40

                        # particle surface gas-phase concentration (molecules/cc (air))
                        Csit = (Csit / conc_sum) * Psat[:, 0] * kelv_fac[ibin]
                        # partitioning rate (molecules/cc.s)
                        dydt_all = kimt[:, ibin] * (y[0:num_speci] - Csit)

                        # gas-phase change
                        dydt[0:num_speci] -= dydt_all
                        # particle-phase change
                        dydt[num_speci * (ibin + 1):num_speci *
                             (ibin + 2)] += dydt_all

                # -----------------------------------------------------------
                # gas-wall partitioning eq. 14 of Zhang et al.
                # (2015) (https://www.atmos-chem-phys.net/15/4197/2015/
                # acp-15-4197-2015.pdf) (molecules/cc.s (air))

                # concentration at wall (molecules/cc (air))
                Csit = y[num_speci * num_sb:num_speci * (num_sb + 1)]
                Csit = (Psat[:, 0] * (Csit / Cw))

                # eq. 14 of Zhang et al. (2015)
                # (https://www.atmos-chem-phys.net/15/4197/2015/
                # acp-15-4197-2015.pdf) (molecules/cc.s (air))
                dydt_all = (kwgt * Cw) * (y[0:num_speci] - Csit)

                # gas-phase change
                dydt[0:num_speci] -= dydt_all
                # wall concentration change
                dydt[num_speci * num_sb:num_speci * (num_sb + 1)] += dydt_all

                return (dydt)

            mod = Explicit_Problem(dydt, y0)
            mod_sim = CVode(mod)  # define a solver instance
            mod_sim.atol = 1.0e-3  # absolute tolerance
            mod_sim.rtol = 1.0e-3  # relative tolerance
            mod_sim.discr = 'BDF'  # the integration approach, default is 'Adams'
            t_array, res = mod_sim.simulate(t)

            y = res[-1, :]

            # low value filler for concentrations (molecules/cc (air)) to prevent
            # numerical errors
            y0[y0 == 0.0] = 1.0e-40
            y[y == 0.0] = 1.0e-40

            if num_sb > 1 and (N_perbin > 1.0e-10).sum() > 0:

                # call on the moving centre method for rebinning particles
                (N_perbin, Varr, y[num_speci::], x, redt, t, tnew) = movcen(
                    N_perbin, Vbou,
                    np.transpose(y[num_speci::].reshape(num_sb, num_speci)),
                    (np.squeeze(y_dens * 1.0e-3)), num_sb, num_speci, y_mw, x,
                    Vol0, t, t0, tinc_count, y0[num_speci::], MV)
            else:
                redt = 0

            # if time step needs reducing then reset gas-phase concentrations to their
            # values preceding the ode, this will already have been done inside moving
            # centre module for particle-phase
            if redt == 1:
                y[0:num_speci] = y0[0:num_speci]

            # start counter to determine when to next try increasing time interval
            if redt == 1:
                tinc_count = 10
            if redt == 0 and tinc_count > -1:
                tinc_count -= 1
            if tinc_count == -1:
                tinc_count = 10

        sumt += t  # total time covered (s)
        step += 1  # ode time interval step number

        if num_sb > 1:
            if (N_perbin > 1.0e-10).sum() > 0:
                # coagulation
                # y indices due to final element in y being number of ELVOC molecules
                # contributing to newly nucleated particles
                [N_perbin, y[num_speci:-(num_speci)], x, Gi, eta_ai,
                 Varr] = coag(
                     RH, TEMP, x * 1.0e-6, (Varr * 1.0e-18).reshape(1, -1),
                     y_mw.reshape(-1, 1), x * 1.0e-6,
                     np.transpose(y[num_speci::].reshape(num_sb, num_speci)),
                     (N_perbin).reshape(1, -1), t,
                     (Vbou * 1.0e-18).reshape(1, -1), num_speci, 0,
                     (np.squeeze(y_dens * 1.0e-3)), rad0, PInit)

                # particle loss to walls
                [N_perbin, y[num_speci:-(num_speci)]
                 ] = wallloss(N_perbin.reshape(-1,
                                               1), y[num_speci:-(num_speci)],
                              Gi, eta_ai, x * 2.0e-6, y_mw, Varr * 1.0e-18,
                              num_sb, num_speci, TEMP, t, inflectDp, pwl_xpre,
                              pwl_xpro, inflectk, ChamR, Rader)

            # particle nucleation
            if sumt < 3600.0 and pconc == 0.0:
                [N_perbin, y, x[0], Varr[0],
                 new_part_sum1] = nuc(sumt, new_part_sum1, N_perbin, y,
                                      y_mw.reshape(-1, 1),
                                      np.squeeze(y_dens * 1.0e-3), num_speci,
                                      x[0], new_partr, t, MV, nucv1, nucv2,
                                      nucv3, nuc_comp)

        if sumt >= save_step * save_count:  # save at every time step given by save_step (s)

            if num_sb > 0:
                # particle-phase concentrations (molecules/cc (air))
                yp = np.transpose(y[num_speci:-(num_speci)].reshape(
                    num_sb - 1, num_speci))
            else:
                yp = 0.0

            # record new values
            [t_out, y_mat, Nresult,
             x2] = recording(y, N_perbin, x, save_count, sumt,
                             y_mat, Nresult, x2, t_out,
                             int(end_sim_time / save_step), num_speci, num_sb,
                             y_mw[:, 0], y_dens[:, 0] * 1.0e-3, yp, Vbou)
            save_count += int(1)

    return (t_out, y_mat, Nresult, x2)
コード例 #29
0
X = 165e-6 # [m]

### Initial conditions
c_init = 1000.0 # [mol/m^3]
c_centered = c_init*numpy.ones( N, dtype='d' )

exp_mod = MyProblem( N, X, c_centered, 'ce only model, explicit CVode' )
#exp_mod = MyProblem( N, X, numpy.linspace(c_init-c_init/5.,c_init+c_init/5.,N), 'ce only model, explicit CVode' )

# Set the ODE solver
exp_sim = CVode(exp_mod) #Create a CVode solver

#Set the parameters
exp_sim.iter  = 'Newton' #Default 'FixedPoint'
exp_sim.discr = 'BDF' #Default 'Adams'
exp_sim.atol = 1e-5 #Default 1e-6
exp_sim.rtol = 1e-5 #Default 1e-6

#Simulate
exp_mod.set_j_vec( 1.e-4 )
t1, y1 = exp_sim.simulate(100, 100)

exp_mod.set_j_vec( 0.0 )
t2, y2 = exp_sim.simulate(200, 100)

#exp_mod.set_j_vec( 0.0 )
#t3, y3 = exp_sim.simulate(10000, 200)

#Plot
#if with_plots:
f, ax = plt.subplots(1,2)
コード例 #30
0
def ode_solv(y, integ_step, rindx, pindx, rstoi, pstoi, nreac, nprod, rrc,
             jac_stoi, njac, jac_den_indx, jac_indx, Cinfl_now, y_arr, y_rind,
             uni_y_rind, y_pind, uni_y_pind, reac_col, prod_col, rstoi_flat,
             pstoi_flat, rr_arr, rr_arr_p, rowvals, colptrs, num_comp, num_sb,
             wall_on, Psat, Cw, act_coeff, kw, jac_wall_indx, seedi, core_diss,
             kelv_fac, kimt, num_asb, jac_part_indx, rindx_aq, pindx_aq,
             rstoi_aq, pstoi_aq, nreac_aq, nprod_aq, jac_stoi_aq, njac_aq,
             jac_den_indx_aq, jac_indx_aq, y_arr_aq, y_rind_aq, uni_y_rind_aq,
             y_pind_aq, uni_y_pind_aq, reac_col_aq, prod_col_aq, rstoi_flat_aq,
             pstoi_flat_aq, rr_arr_aq, rr_arr_p_aq, eqn_num):

    # inputs: -------------------------------------
    # y - initial concentrations (moleucles/cm3)
    # integ_step - the maximum integration time step (s)
    # rindx - index of reactants per equation
    # pindx - index of products per equation
    # rstoi - stoichiometry of reactants
    # pstoi - stoichiometry of products
    # nreac - number of reactants per equation
    # nprod - number of products per equation
    # rrc - reaction rate coefficient
    # jac_stoi - stoichiometries relevant to Jacobian
    # njac - number of Jacobian elements affected per equation
    # jac_den_indx - index of component denominators for Jacobian
    # jac_indx - index of Jacobian to place elements per equation (rows)
    # Cinfl_now - influx of components with constant influx
    #		(molecules/cc/s)
    # y_arr - index for matrix used to arrange concentrations,
    #	enabling calculation of reaction rate coefficients
    # y_rind - index of y relating to reactants for reaction rate
    # 	coefficient equation
    # uni_y_rind - unique index of reactants
    # y_pind - index of y relating to products
    # uni_y_pind - unique index of products
    # reac_col - column indices for sparse matrix of reaction losses
    # prod_col - column indices for sparse matrix of production gains
    # rstoi_flat - 1D array of reactant stoichiometries per equation
    # pstoi_flat - 1D array of product stoichiometries per equation
    # rr_arr - index for reaction rates to allow reactant loss
    # 	calculation
    # rr_arr_p - index for reaction rates to allow reactant loss
    # 	calculation
    # rowvals - row indices of Jacobian elements
    # colptrs - indices of  rowvals corresponding to each column of the
    # 	Jacobian
    # num_comp - number of components
    # num_sb - number of size bins
    # wall_on - flag saying whether to include wall partitioning
    # Psat - pure component saturation vapour pressures (molecules/cc)
    # Cw - effective absorbing mass concentration of wall (molecules/cc)
    # act_coeff - activity coefficient of components
    # kw - mass transfer coefficient to wall (/s)
    # jac_wall_indx - index of inputs to Jacobian by wall partitioning
    # seedi - index of seed material
    # core_diss - dissociation constant of seed material
    # kelv_fac - kelvin factor for particles
    # kimt - mass transfer coefficient for gas-particle partitioning (s)
    # num_asb - number of actual size bins (excluding wall)
    # jac_part_indx - index for sparse Jacobian for particle influence
    # eqn_num - number of gas- and aqueous-phase reactions
    # ---------------------------------------------

    def dydt(t, y):  # define the ODE(s)

        # empty array to hold rate of change per component
        dd = np.zeros((len(y)))

        # gas-phase reactions -------------------------
        # empty array to hold relevant concentrations for
        # reaction rate coefficient calculation
        rrc_y = np.ones((rindx.shape[0] * rindx.shape[1]))
        rrc_y[y_arr] = y[y_rind]
        rrc_y = rrc_y.reshape(rindx.shape[0], rindx.shape[1], order='C')
        # reaction rate (molecules/cc/s)
        rr = rrc[0:rindx.shape[0]] * ((rrc_y**rstoi).prod(axis=1))
        # loss of reactants
        data = rr[rr_arr] * rstoi_flat  # prepare loss values
        # convert to sparse matrix
        loss = SP.csc_matrix((data, y_rind, reac_col))
        # register loss of reactants
        dd[uni_y_rind] -= np.array((loss.sum(axis=1))[uni_y_rind])[:, 0]
        # gain of products
        data = rr[rr_arr_p] * pstoi_flat  # prepare loss values
        # convert to sparse matrix
        loss = SP.csc_matrix((data, y_pind, prod_col))
        # register gain of products
        dd[uni_y_pind] += np.array((loss.sum(axis=1))[uni_y_pind])[:, 0]

        # particle-phase reactions -------------------------
        if (eqn_num[1] > 0):
            # empty array to hold relevant concentrations for
            # reaction rate coefficient calculation
            # tile aqueous-phase reaction rate coefficients
            rr_aq = np.tile(rrc[rindx.shape[0]::], num_asb)
            # prepare aqueous-phase concentrations
            rrc_y = np.ones((rindx_aq.shape[0] * rindx_aq.shape[1]))
            rrc_y[y_arr_aq] = y[y_rind_aq]
            rrc_y = rrc_y.reshape(rindx_aq.shape[0],
                                  rindx_aq.shape[1],
                                  order='C')
            # reaction rate (molecules/cc/s)
            rr = rr_aq * ((rrc_y**rstoi_aq).prod(axis=1))
            # loss of reactants
            data = rr[rr_arr_aq] * rstoi_flat_aq  # prepare loss values
            # convert to sparse matrix
            loss = SP.csc_matrix((data[0, :], y_rind_aq, reac_col_aq))
            # register loss of reactants
            dd[uni_y_rind_aq] -= np.array((loss.sum(axis=1))[uni_y_rind_aq])[:,
                                                                             0]
            # gain of products
            data = rr[rr_arr_p_aq] * pstoi_flat_aq  # prepare loss values
            # convert to sparse matrix
            loss = SP.csc_matrix((data[0, :], y_pind_aq, prod_col_aq))
            # register gain of products
            dd[uni_y_pind_aq] += np.array((loss.sum(axis=1))[uni_y_pind_aq])[:,
                                                                             0]

        # gas-particle partitioning-----------------
        # transform particle phase concentrations into
        # size bins in rows, components in columns
        ymat = (y[num_comp:num_comp * (num_asb + 1)]).reshape(
            num_asb, num_comp)
        # total particle-phase concentration per size bin (molecules/cc (air))
        csum = ((ymat.sum(axis=1) - ymat[:, seedi].sum(axis=1)) + (
            (ymat[:, seedi] * core_diss).sum(axis=1)).reshape(-1)).reshape(
                -1, 1)
        # size bins with contents
        isb = (csum[:, 0] > 0.)

        # container for gas-phase concentrations at particle surface
        Csit = np.zeros((num_asb, num_comp))
        # mole fraction of components at particle surface
        Csit[isb, :] = (ymat[isb, :] / csum[isb, :])
        # gas-phase concentration of components at
        # particle surface (molecules/cc (air))
        Csit[isb, :] = Csit[isb, :] * Psat[isb, :] * kelv_fac[isb] * act_coeff[
            isb, :]
        # partitioning rate (molecules/cc/s)
        dd_all = kimt * (y[0:num_comp].reshape(1, -1) - Csit)
        # gas-phase change
        dd[0:num_comp] -= dd_all.sum(axis=0)
        # particle change
        dd[num_comp:num_comp * (num_asb + 1)] += (dd_all.flatten())

        # gas-wall partitioning ----------------
        # concentration on wall (molecules/cc (air))
        Csit = y[num_comp * num_sb:num_comp * (num_sb + 1)]
        # saturation vapour pressure on wall (molecules/cc (air))
        # note, just using the top rows of Psat and act_coeff
        # as do not need the repetitions over size bins
        if (Cw > 0.):
            Csit = Psat[0, :] * (Csit / Cw) * act_coeff[0, :]
            # rate of transfer (molecules/cc/s)
            dd_all = kw * (y[0:num_comp] - Csit)
            dd[0:num_comp] -= dd_all  # gas-phase change
            dd[num_comp * num_sb:num_comp *
               (num_sb + 1)] += dd_all  # wall change

        return (dd)

    def jac(t, y):  # define the Jacobian
        # elements of sparse Jacobian matrix
        data = np.zeros((94))

        for i in range(rindx.shape[0]):  # gas-phase reaction loop
            # reaction rate (molecules/cc/s)
            rr = rrc[i] * (y[rindx[i, 0:nreac[i]]].prod())
            # prepare Jacobian inputs
            jac_coeff = np.zeros((njac[i, 0]))
            # only fill Jacobian if reaction rate sufficient
            if (rr != 0.):
                jac_coeff = (rr * (jac_stoi[i, 0:njac[i, 0]]) /
                             (y[jac_den_indx[i, 0:njac[i, 0]]]))
            data[jac_indx[i, 0:njac[i, 0]]] += jac_coeff

        n_aqr = nreac_aq.shape[0]  # number of aqueous-phase reactions
        aqi = 0  # aqueous-phase reaction counter
        for i in range(rindx.shape[0],
                       rrc.shape[0]):  # aqueous-phase reaction loop
            # reaction rate (molecules/cc/s)
            rr = rrc[i] * (y[rindx_aq[aqi::n_aqr,
                                      0:nreac_aq[aqi]]].prod(axis=1))
            # spread along affected components
            rr = rr.reshape(-1, 1)
            rr = (np.tile(rr, int(njac_aq[aqi, 0] /
                                  (num_sb - wall_on)))).flatten(order='C')
            # prepare Jacobian inputs
            jac_coeff = np.zeros((njac_aq[aqi, 0]))
            nzi = (rr != 0)
            jac_coeff[nzi] = (
                rr[nzi] * ((jac_stoi_aq[aqi, 0:njac_aq[aqi, 0]])[nzi]) /
                ((y[jac_den_indx_aq[aqi, 0:njac_aq[aqi, 0]]])[nzi]))
            # stack size bins
            jac_coeff = jac_coeff.reshape(int(num_sb - wall_on),
                                          int(njac_aq[aqi, 0] /
                                              (num_sb - wall_on)),
                                          order='C')
            data[jac_indx_aq[aqi::n_aqr,
                             0:(int(njac_aq[aqi, 0] /
                                    (num_sb - wall_on)))]] += jac_coeff
            aqi += 1

        # gas-particle partitioning
        part_eff = np.zeros((56))
        part_eff[0:24:3] = -kimt.sum(axis=0)  # effect of gas on gas

        # transform particle phase concentrations into
        # size bins in rows, components in columns
        ymat = (y[num_comp:num_comp * (num_asb + 1)]).reshape(
            num_asb, num_comp)
        # total particle-phase concentration per size bin (molecules/cc (air))
        csum = ymat.sum(axis=1) - ymat[:, seedi].sum(
            axis=1) + (ymat[:, seedi] * core_diss).sum(axis=1)

        # effect of particle on gas
        for isb in range(int(num_asb)):  # size bin loop
            if csum[isb] > 0:  # if particles present
                # effect of gas on particle
                part_eff[1 + isb:num_comp * (num_asb + 1):num_asb +
                         1] = +kimt[isb, :]
                # start and finish index
                sti = int((num_asb + 1) * num_comp + isb * (num_comp * 2))
                fii = int(sti + (num_comp * 2.))
                # diagonal index
                diag_indxg = sti + np.arange(0, num_comp * 2, 2).astype('int')
                diag_indxp = sti + np.arange(1, num_comp * 2, 2).astype('int')
                # prepare for diagonal (component effect on itself)
                diag = kimt[isb, :] * Psat[0, :] * act_coeff[0, :] * kelv_fac[
                    isb, 0] * (csum[isb] - ymat[isb, :]) / (csum[isb]**2.)
                # implement to part_eff
                part_eff[diag_indxg] = +diag
                part_eff[diag_indxp] = -diag

        data[jac_part_indx] += part_eff

        if (Cw > 0.):
            wall_eff = np.zeros((32))
            wall_eff[0:16:2] = -kw  # effect of gas on gas
            wall_eff[1:16:2] = +kw  # effect of gas on wall
            # effect of wall on gas
            wall_eff[16:32:2] = +kw * (Psat[0, :] * act_coeff[0, :] / Cw)
            # effect of wall on wall
            wall_eff[16 + 1:32:2] = -kw * (Psat[0, :] * act_coeff[0, :] / Cw)
            data[jac_wall_indx] += wall_eff

        # create Jacobian
        j = SP.csc_matrix((data, rowvals, colptrs))
        return (j)

    mod = Explicit_Problem(dydt, y)  # instantiate solver
    mod.jac = jac  # set the Jacobian
    mod_sim = CVode(mod)  # define a solver instance
    # there is a general trend of an inverse relationship
    # between tolerances and computation time
    mod_sim.atol = 0.001
    mod_sim.rtol = 0.0001
    # integration approach (backward differentiation formula)
    mod_sim.discr = 'BDF'
    # call solver
    res_t, res = mod_sim.simulate(integ_step)
    # return concentrations following integration
    return (res, res_t)
コード例 #31
0
def run_example(with_plots=True):
    r"""
    Example for demonstrating the use of a user supplied Jacobian
    
    ODE:
    
    .. math::
       
       \dot y_1 &= y_2 \\
       \dot y_2 &= -9.82
       
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Defines the rhs
    def f(t, y):
        yd_0 = y[1]
        yd_1 = -9.82
        return N.array([yd_0, yd_1])

    #Defines the Jacobian
    def jac(t, y):
        j = N.array([[0, 1.], [0, 0]])
        return j

    #Defines an Assimulo explicit problem
    y0 = [1.0, 0.0]  #Initial conditions

    exp_mod = Explicit_Problem(f, y0, name='Example using analytic Jacobian')
    exp_mod.jac = jac  #Sets the Jacobian

    exp_sim = CVode(exp_mod)  #Create a CVode solver

    #Set the parameters
    exp_sim.iter = 'Newton'  #Default 'FixedPoint'
    exp_sim.discr = 'BDF'  #Default 'Adams'
    exp_sim.atol = 1e-5  #Default 1e-6
    exp_sim.rtol = 1e-5  #Default 1e-6

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

    #Plot
    if with_plots:
        import pylab as P
        P.plot(t, y, linestyle="dashed", marker="o")  #Plot the solution
        P.xlabel('Time')
        P.ylabel('State')
        P.title(exp_mod.name)
        P.show()

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

    return exp_mod, exp_sim
コード例 #32
0
    gamma = p[3]

    flux = np.array(
        [alpha * y[0], beta * y[0] * y[1], delta * y[0] * y[1], gamma * y[1]])
    rhs = np.array([flux[0] - flux[1], flux[2] - flux[3]])

    return rhs


if __name__ == '__main__':
    p = np.array([.5, .02, .4, .004])
    ode_function = lambda t, x: rhs_fun(t, x, p)

    # define explicit assimulo problem
    prob = Explicit_Problem(ode_function, y0=np.array([10, .0001]))

    # create solver instance
    solver = CVode(prob)

    solver.iter = 'Newton'
    solver.discr = 'Adams'
    solver.atol = 1e-10
    solver.rtol = 1e-10
    solver.display_progress = True
    solver.verbosity = 10

    # simulate system
    time_course, y_result = solver.simulate(10, 200)

    print time_course
    print y_result
コード例 #33
0
ファイル: task4.py プロジェクト: TuongL94/SimulationTools
    return ydot


#Create Assimulo problem model
mod_pen = Explicit_Problem(rhs, y0, t0)
mod_pen.name = 'Elastic Pendulum with CVode'
"""
Run simulation
"""
#Create solver object
sim_pen = CVode(mod_pen)

#Simulation parameters
#atol = 1.e-6*ones(shape(y0))
atol = rtol * N.array([1, 1, 1, 1])  #default 1e-06
sim_pen.atol = atol
sim_pen.rtol = rtol
sim_pen.maxh = hmax
sim_pen.maxord = maxord
sim_pen.inith = h0

#Simulate
t, y = sim_pen.simulate(tf)
"""
Plot results
"""
#Plot
#P.plot(t,y)
#P.legend(['$x$','$y$','$\dot{x}$','$\dot{y}$'])
#P.title('Elastic pendulum with k = ' + str(k) + ', stretch = ' + str(stretch))
#P.xlabel('time')
コード例 #34
0
ファイル: test1.py プロジェクト: lNsufficient/fmnn05
from assimulo.solvers import CVode
import matplotlib.pyplot as plt

def rhs(t,y):
    k = 1000 
    L = k*(math.sqrt(y[0]**2+y[1]**2)-1)/math.sqrt(y[0]**2+y[1]**2)
    result = numpy.array([y[2],y[3],-y[0]*L,-y[1]*L-1])
    return result
t0 = 0
y0 = numpy.array([0.8,-0.8,0,0])

model = Explicit_Problem(rhs,y0,t0)
model.name = 'task1'

sim = CVode(model)
sim.atol=numpy.array([1,1,1,1])*1e-5
sim.rtol=1e-6
sim.maxord=3
#sim.discr='BDF'
#sim.iter='Newton'


tfinal = 70

(t,y) = sim.simulate(tfinal)

#sim.plot()

plt.plot(y[:,0],y[:,1])
plt.axis('equal')
plt.show()
コード例 #35
0
    def simulate(self, Tend, nIntervals, gridWidth):

        # define assimulo problem:(has to be done here because of the starting value in Explicit_Problem
        solver = Explicit_Problem(self.rhs, self.y0)
        ''' *******DELETE LATER '''''''''
#        problem.handle_event = handle_event
#        problem.state_events = state_events
#        problem.init_mode = init_mode

        solver.handle_result = self.handle_result


        solver.name = 'Simple Explicit Example'
        simulation = CVode(solver)  # Create a RungeKutta34 solver
        # simulation.inith = 0.1 #Sets the initial step, default = 0.01

        # Change multistep method: 'adams' or 'VDF'
        if self.discr == 'Adams':
            simulation.discr = 'Adams'
            simulation.maxord = 12
        else:
            simulation.discr = 'BDF'
            simulation.maxord = 5

        # Change iteration algorithm: functional(FixedPoint) or newton
        if self.iter == 'FixedPoint':
            simulation.iter = 'FixedPoint'
        else:
            simulation.iter = 'Newton'

        # Sets additional parameters
        simulation.atol = self.atol
        simulation.rtol = self.rtol
        simulation.verbosity = 0
        if hasattr(simulation, 'continuous_output'):
            simulation.continuous_output = False  # default 0, if one step approach should be used
        elif hasattr(simulation, 'report_continuously'):
            simulation.report_continuously = False  # default 0, if one step approach should be used

        # Create Solver and set settings
#        noRootFunctions = np.size(self.state_events(self.t0, np.array(self.y0)))

#        solver = sundials.CVodeSolver(RHS = self.f, ROOT = self.rootf, SW = [False]*noRootFunctions,
#                       abstol = self.atol, reltol = self.rtol)
        # solver.settings.JAC = None   #Add user-dependent jacobian here

        '''Initialize problem '''
#        solver.init(self.t0, self.y0)
        self.handle_result(self.t0, self.y0)
        nextTimeEvent = self.time_events(self.t0, self.y0)
        self.t_cur = self.t0
        self.y_cur = self.y0
        state_event = False
#
#
        if gridWidth <> None:
            nOutputIntervals = int((Tend - self.t0) / gridWidth)
        else:
            nOutputIntervals = nIntervals
        # Define step length depending on if gridWidth or nIntervals has been chosen
        if nOutputIntervals > 0:
            # Last point on grid (does not have to be Tend:)
            if(gridWidth <> None):
                dOutput = gridWidth
            else:
                dOutput = (Tend - self.t0) / nIntervals
        else:
            dOutput = Tend

        outputStepCounter = long(1)
        nextOutputPoint = min(self.t0 + dOutput, Tend)

        while self.t_cur < Tend:

            # Time-Event detection and step time adjustment
            if nextTimeEvent is None or nextOutputPoint < nextTimeEvent:
                time_event = False
                self.t_cur = nextOutputPoint
            else:
                time_event = True
                self.t_cur = nextTimeEvent



            try:
#                #Integrator step
#                self.y_cur = solver.step(self.t_cur)
#                self.y_cur = np.array(self.y_cur)
#                state_event = False
                # Simulate




                # take a step to next output point:
                t_new, y_new = simulation.simulate(self.t_cur)  # 5, 10) #5, 10  self.t_cur self.t_cur  2. argument nsteps Simulate 5 seconds
                # t_new, y_new are both vectors of the time and states at t_cur and all intermediate
                # points before it! So take last values:
                self.t_cur = t_new[-1]
                self.y_cur = y_new[-1]
                state_event = False

            except:
                import sys
                print "Unexpected error:", sys.exc_info()[0]
#            except CVodeRootException, info:
#                self.t_cur = info.t
#                self.y_cur = info.y
#                self.y_cur = np.array(self.y_cur)
#                time_event = False
#                state_event = True
#
#
            # Depending on events have been detected do different tasks
            if time_event or state_event:
                event_info = [state_event, time_event]
                if not self.handle_event(self, event_info):
                    break
                solver.init(self.t_cur, self.y_cur)

                nextTimeEvent = self.time_events(self.t_cur, self.y_cur)
                # If no timeEvent happens:
                if nextTimeEvent <= self.t_cur:
                    nextTimeEvent = None

            if self.t_cur == nextOutputPoint:
                # Write output if not happened before:
                if not time_event and not state_event:
                    self.handle_result(nextOutputPoint, self.y_cur)
                outputStepCounter += 1
                nextOutputPoint = min(self.t0 + outputStepCounter * dOutput, Tend)

        self.finalize()
コード例 #36
0
ファイル: task2.py プロジェクト: Canneberge/Simulation-tools
# Define the rhs
def rhs(t, y):
    k = 10
    A = np.array([[0, 0, 1, 0],
                  [0, 0, 0, 1],
                  [-L(y, k), 0, 0, 0],
                  [0, -L(y, k), 0, 0]])
    b = np.array([0, 0, 0, -1])
    yd = np.dot(A, y) + b
    return yd

def L(y, k):
    norm = ln.norm(y[0:2])
    return k * (norm - 1) / norm

pend_mod = Explicit_Problem(rhs, y0 = np.array([1.0, 1.0, 1.0, 1.0]))
pend_mod.name = 'Nonlinear Pendulum'

# Define an explicit solver
exp_sim = BDF_3(pend_mod)  # Create a BDF solver
t, y = exp_sim.simulate(4)
exp_sim.plot()
mpl.show()

toltmp=0.1
cvod= CVode(pend_mod)
cvod.atol=toltmp
cvod.rtol=toltmp
cvod.maxord=19
cvod.simulate(5) 
cvod.plot()
コード例 #37
0
def run_example(with_plots=True):
    r"""
    Example for demonstrating the use of a user supplied Jacobian (sparse).
    Note that this will only work if Assimulo has been configured with
    Sundials + SuperLU. Based on the SUNDIALS example cvRoberts_sps.c
    
    ODE:
    
    .. math::
       
       \dot y_1 &= -0.04y_1 + 1e4 y_2 y_3 \\
       \dot y_2 &= - \dot y_1 - \dot y_3 \\
       \dot y_3 &= 3e7 y_2^2
       
    
    on return:
    
       - :dfn:`exp_mod`    problem instance
    
       - :dfn:`exp_sim`    solver instance
       
    """

    #Defines the rhs
    def f(t, y):
        yd_0 = -0.04 * y[0] + 1e4 * y[1] * y[2]
        yd_2 = 3e7 * y[1] * y[1]
        yd_1 = -yd_0 - yd_2
        return N.array([yd_0, yd_1, yd_2])

    #Defines the Jacobian
    def jac(t, y):

        colptrs = [0, 3, 6, 9]
        rowvals = [0, 1, 2, 0, 1, 2, 0, 1, 2]
        data = [
            -0.04, 0.04, 0.0, 1e4 * y[2], -1e4 * y[2] - 6e7 * y[1], 6e7 * y[1],
            1e4 * y[1], -1e4 * y[1], 0.0
        ]

        J = SP.csc_matrix((data, rowvals, colptrs))
        return J

    #Defines an Assimulo explicit problem
    y0 = [1.0, 0.0, 0.0]  #Initial conditions

    exp_mod = Explicit_Problem(f,
                               y0,
                               name='Example using analytic (sparse) Jacobian')

    exp_mod.jac = jac  #Sets the Jacobian
    exp_mod.jac_nnz = 9

    exp_sim = CVode(exp_mod)  #Create a CVode solver

    #Set the parameters
    exp_sim.iter = 'Newton'  #Default 'FixedPoint'
    exp_sim.discr = 'BDF'  #Default 'Adams'
    exp_sim.atol = [1e-8, 1e-14, 1e-6]  #Default 1e-6
    exp_sim.rtol = 1e-4  #Default 1e-6
    exp_sim.linear_solver = "sparse"

    #Simulate
    t, y = exp_sim.simulate(0.4)  #Simulate 0.4 seconds

    #Basic tests
    nose.tools.assert_almost_equal(y[-1][0], 0.9851, 3)

    #Plot
    if with_plots:
        P.plot(t, y[:, 1], linestyle="dashed", marker="o")  #Plot the solution
        P.xlabel('Time')
        P.ylabel('State')
        P.title(exp_mod.name)
        P.show()

    return exp_mod, exp_sim