Example #1
0
    def __init__(self, params=None, **kwargs):
        super(ChemostatSimple, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Initialize parameters
        self.m = params.m
        self.K = params.K
        self.S_in = params.S_in
        self.X_in = params.X_in
        self.gamma = params.gamma
        self.D_vals = params.D_vals

        # Create state vector and derivative vector
        stateVarNames = ['S', 'X']
        self.y = NamedStateVector(stateVarNames)
        self.yRes = NamedStateVector(stateVarNames)
        self.yDot = NamedStateVector(stateVarNames)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(varList=['t'] +
                                                 stateVarNames + ['D'],
                                                 chunkSize=1e4)

        # Register time event (changed of D)
        D_val = self.D_vals[0]
        self.D = D_val[1]

        tChangedD = D_val[0]
        for i in range(len(self.D_vals) - 1):
            self.D_val = self.D_vals[i + 1]
            self.timeEventRegistry.add(
                ChemostatSimpleTimeEvent(t=tChangedD,
                                         newValue_D=self.D_val[1]))
            tChangedD += self.D_val[0]

        # Set initial values of the states
        self.y.S = params.S0
        self.y.X = params.X0

        # Set all the initial state values
        self.y0 = self.y.get(copy=True)

        # Set the initial flags
        self.sw0 = [True]
Example #2
0
    def __init__(self, params=None, **kwargs):
        """
        #params.reactions = [reactionEquation, rateConstants]
        #params.species = [speciesVariable, initialValue]
        """
        super(BiochemicalReactions, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values
        self.Xs = np.empty(len(params.species), dtype=(np.str_, 256))
        self.X0s = np.zeros(len(params.species))
        for i, itSpecies in enumerate(params.species):
            self.Xs[i] = itSpecies[0]
            self.X0s[i] = itSpecies[1]

        # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where:
        # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions)
        # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions)
        # k - the rate constant of the reaction
        # ss - the stoichiometric coefficients of reactants  (e.g. [0,1,1,0,...,1])
        # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0])
        # f - the fluxs (e.g. k*X2*X3*...*Xn)
        self.reactions = self.readReactions(params.reactions, self.Xs)
        #for reaction in self.reactions: print reaction

        # Create a vector with state variable names
        stateVarNames = list(self.Xs)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(varList=['t'] + stateVarNames,
                                                 chunkSize=1e4)

        # Set the initial state values
        self.y0 = self.X0s

        # Set the initial flags
        self.sw0 = [True]
Example #3
0
	def __init__(self, params = None, **kwargs):
		super(ChemostatSimple, self).__init__(**kwargs)
		if params == None:
			params = AttributeDict(kwargs)
		
		# Initialize update progress function
		self.updateProgress = params.updateProgress
					
		# Initialize parameters
		self.m = params.m
		self.K = params.K
		self.S_in = params.S_in
		self.X_in = params.X_in
		self.gamma = params.gamma
		self.D_vals = params.D_vals

		# Create state vector and derivative vector
		stateVarNames = ['S', 'X'] 
		self.y = NamedStateVector(stateVarNames)
		self.yRes = NamedStateVector(stateVarNames)
		self.yDot = NamedStateVector(stateVarNames)

		# Initialize data storage
		self.resultStorage = ResultStorage(
			filePath = dataStorageFilePath,
			datasetPath = dataStorageDatasetPath)
		if (kwargs.get('initDataStorage', True)):
			self.resultStorage.initializeWriting(
				varList = ['t'] + stateVarNames + ['D'],
				chunkSize = 1e4)
		
		# Register time event (changed of D)
		D_val = self.D_vals[0]
		self.D = D_val[1]
		
		tChangedD = D_val[0]
		for i in range(len(self.D_vals)-1):
			self.D_val = self.D_vals[i+1]
			self.timeEventRegistry.add(ChemostatSimpleTimeEvent(t = tChangedD, newValue_D = self.D_val[1]))
			tChangedD += self.D_val[0]
		
		# Set initial values of the states
		self.y.S = params.S0
		self.y.X = params.X0
				
		# Set all the initial state values
		self.y0 = self.y.get(copy = True)
		
		# Set the initial flags
		self.sw0 = [True]
Example #4
0
    def __init__(self, params=None, **kwargs):
        """
        #params.reactions = [reactionEquation, rateConstants]
        #params.species = [speciesVariable, initialValue]
        """
        super(BiochemicalReactions, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values
        self.Xs = np.empty(len(params.species), dtype=(np.str_, 256))
        self.X0s = np.zeros(len(params.species))
        for i, itSpecies in enumerate(params.species):
            self.Xs[i] = itSpecies[0]
            self.X0s[i] = itSpecies[1]

        # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where:
        # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions)
        # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions)
        # k - the rate constant of the reaction
        # ss - the stoichiometric coefficients of reactants  (e.g. [0,1,1,0,...,1])
        # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0])
        # f - the fluxs (e.g. k*X2*X3*...*Xn)
        self.reactions = self.readReactions(params.reactions, self.Xs)
        # for reaction in self.reactions: print reaction

        # Create a vector with state variable names
        stateVarNames = list(self.Xs)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath)
        if kwargs.get("initDataStorage", True):
            self.resultStorage.initializeWriting(varList=["t"] + stateVarNames, chunkSize=1e4)

        # Set the initial state values
        self.y0 = self.X0s

        # Set the initial flags
        self.sw0 = [True]
Example #5
0
class ChemostatSimple(Simulation):
	"""
	Class for implementation the model of a simple chemostat 
	"""
	name = 'Model of a simple chemostat.'
	
	def __init__(self, params = None, **kwargs):
		super(ChemostatSimple, self).__init__(**kwargs)
		if params == None:
			params = AttributeDict(kwargs)
		
		# Initialize update progress function
		self.updateProgress = params.updateProgress
					
		# Initialize parameters
		self.m = params.m
		self.K = params.K
		self.S_in = params.S_in
		self.X_in = params.X_in
		self.gamma = params.gamma
		self.D_vals = params.D_vals

		# Create state vector and derivative vector
		stateVarNames = ['S', 'X'] 
		self.y = NamedStateVector(stateVarNames)
		self.yRes = NamedStateVector(stateVarNames)
		self.yDot = NamedStateVector(stateVarNames)

		# Initialize data storage
		self.resultStorage = ResultStorage(
			filePath = dataStorageFilePath,
			datasetPath = dataStorageDatasetPath)
		if (kwargs.get('initDataStorage', True)):
			self.resultStorage.initializeWriting(
				varList = ['t'] + stateVarNames + ['D'],
				chunkSize = 1e4)
		
		# Register time event (changed of D)
		D_val = self.D_vals[0]
		self.D = D_val[1]
		
		tChangedD = D_val[0]
		for i in range(len(self.D_vals)-1):
			self.D_val = self.D_vals[i+1]
			self.timeEventRegistry.add(ChemostatSimpleTimeEvent(t = tChangedD, newValue_D = self.D_val[1]))
			tChangedD += self.D_val[0]
		
		# Set initial values of the states
		self.y.S = params.S0
		self.y.X = params.X0
				
		# Set all the initial state values
		self.y0 = self.y.get(copy = True)
		
		# Set the initial flags
		self.sw0 = [True]
		
	def mu(self, S):
		return self.m * S / (self.K + S)
		
	def rhs(self, t, y, sw):
		# Set state values
		self.y.set(y)
		
		try:
			# Get state values
			S = self.y.S
			X = self.y.X
			
			# Compute state derivatives
			S_dot = (self.S_in - S)*self.D - (1/self.gamma)*self.mu(S)*X
			X_dot = (self.X_in - X)*self.D + self.mu(S)*X
			
		except Exception, e:
			self.resultStorage.finalizeResult()
			# Log the error if it happens in the rhs() function
			print("Exception at time {}: {}".format(t, e))
			raise e
			
		self.yDot.S = S_dot
		self.yDot.X = X_dot
		return self.yDot.get()
Example #6
0
	def __init__(self, webModel, 
				paramsRH2, concentrsRH2, 
				paramsRCH4, concentrsRCH4,
				**kwargs):
		super(ADM1H2CH4Bioreactors, self).__init__(**kwargs)
		
		# Initialize update progress function
		self.updateProgress = webModel.updateProgress
					
		# Initialize parameters
		self.paramsRH2 = paramsRH2		
		self.paramsRCH4 = paramsRCH4	
				
		# Initialize concentrations
		self.concentrsRH2 = concentrsRH2
		self.concentrsRCH4 = concentrsRCH4
		
		# Create state vector and derivative vector
		stateVarNames = [
			'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2',
			'X_c_RH2', 'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2', 
			'intQ_h2_RH2',
			
			'S_ac_RCH4',
			'X_ac_RCH4', 
			'intQ_ch4_RCH4'
		] 
		self.y = NamedStateVector(stateVarNames)
		self.yRes = NamedStateVector(stateVarNames)
		self.yDot = NamedStateVector(stateVarNames)

		# Initialize data storage
		self.resultStorage = ResultStorage(
			filePath = dataStorageFilePath,
			datasetPath = dataStorageDatasetPath)
		if (kwargs.get('initDataStorage', True)):
			self.resultStorage.initializeWriting(
				varList = ['time'] + stateVarNames + ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'],
				chunkSize = 1e4
			)
		
		# Register time event (changed of D)
		tChangedD =  paramsRH2.D_liq_arr[0][0]
		self.D_RH2 =  paramsRH2.D_liq_arr[0][1]

		self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2
		
		for i in range(len(paramsRH2.D_liq_arr)-1):
			self.timeEventRegistry.add(
				ADM1TimeEvent(
					t = tChangedD,
					newValue_D = paramsRH2.D_liq_arr[i + 1][1]
				)
			)
			tChangedD += paramsRH2.D_liq_arr[i+1][0]
		
		# Set initial values of the states
		self.y.S_su_RH2 = concentrsRH2.S_su_0
		self.y.S_aa_RH2 = concentrsRH2.S_aa_0
		self.y.S_fa_RH2 = concentrsRH2.S_fa_0
		self.y.S_ac_RH2 = concentrsRH2.S_ac_0
		self.y.X_c_RH2 = concentrsRH2.X_c_0
		self.y.X_ch_RH2 = concentrsRH2.X_ch_0
		self.y.X_pr_RH2 = concentrsRH2.X_pr_0
		self.y.X_li_RH2 = concentrsRH2.X_li_0
		self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0
		self.y.X_fa_RH2 = concentrsRH2.X_fa_0
		self.y.intQ_h2_RH2 = 0.0
		self.Q_h2_RH2 = 0.0
		
		self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0
		self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0
		self.y.intQ_ch4_RCH4 = 0.0
		self.Q_ch4_RCH4 = 0.0
				
		# Set all the initial state values
		self.y0 = self.y.get(copy = True)
		
		# Set the initial flags
		self.sw0 = [True]
Example #7
0
class ADM1H2CH4Bioreactors(Simulation):
	"""
	Class for implementation the model of a ADM1 H2 and CH4 Bioreactors
	"""
	name = 'Model of a bioreactor that produces hydrogen.'
	
	def __init__(self, webModel, 
				paramsRH2, concentrsRH2, 
				paramsRCH4, concentrsRCH4,
				**kwargs):
		super(ADM1H2CH4Bioreactors, self).__init__(**kwargs)
		
		# Initialize update progress function
		self.updateProgress = webModel.updateProgress
					
		# Initialize parameters
		self.paramsRH2 = paramsRH2		
		self.paramsRCH4 = paramsRCH4	
				
		# Initialize concentrations
		self.concentrsRH2 = concentrsRH2
		self.concentrsRCH4 = concentrsRCH4
		
		# Create state vector and derivative vector
		stateVarNames = [
			'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2',
			'X_c_RH2', 'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2', 
			'intQ_h2_RH2',
			
			'S_ac_RCH4',
			'X_ac_RCH4', 
			'intQ_ch4_RCH4'
		] 
		self.y = NamedStateVector(stateVarNames)
		self.yRes = NamedStateVector(stateVarNames)
		self.yDot = NamedStateVector(stateVarNames)

		# Initialize data storage
		self.resultStorage = ResultStorage(
			filePath = dataStorageFilePath,
			datasetPath = dataStorageDatasetPath)
		if (kwargs.get('initDataStorage', True)):
			self.resultStorage.initializeWriting(
				varList = ['time'] + stateVarNames + ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'],
				chunkSize = 1e4
			)
		
		# Register time event (changed of D)
		tChangedD =  paramsRH2.D_liq_arr[0][0]
		self.D_RH2 =  paramsRH2.D_liq_arr[0][1]

		self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2
		
		for i in range(len(paramsRH2.D_liq_arr)-1):
			self.timeEventRegistry.add(
				ADM1TimeEvent(
					t = tChangedD,
					newValue_D = paramsRH2.D_liq_arr[i + 1][1]
				)
			)
			tChangedD += paramsRH2.D_liq_arr[i+1][0]
		
		# Set initial values of the states
		self.y.S_su_RH2 = concentrsRH2.S_su_0
		self.y.S_aa_RH2 = concentrsRH2.S_aa_0
		self.y.S_fa_RH2 = concentrsRH2.S_fa_0
		self.y.S_ac_RH2 = concentrsRH2.S_ac_0
		self.y.X_c_RH2 = concentrsRH2.X_c_0
		self.y.X_ch_RH2 = concentrsRH2.X_ch_0
		self.y.X_pr_RH2 = concentrsRH2.X_pr_0
		self.y.X_li_RH2 = concentrsRH2.X_li_0
		self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0
		self.y.X_fa_RH2 = concentrsRH2.X_fa_0
		self.y.intQ_h2_RH2 = 0.0
		self.Q_h2_RH2 = 0.0
		
		self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0
		self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0
		self.y.intQ_ch4_RCH4 = 0.0
		self.Q_ch4_RCH4 = 0.0
				
		# Set all the initial state values
		self.y0 = self.y.get(copy = True)
		
		# Set the initial flags
		self.sw0 = [True]
		
	def rhs(self, t, y, sw):
		paramsRH2 = self.paramsRH2
		concentrsRH2 = self.concentrsRH2
	
		paramsRCH4 = self.paramsRCH4
		concentrsRCH4 = self.concentrsRCH4
		
		# Set state values
		self.y.set(y)
		
		try:
		# Bioreactor - RH2	
			# Get state values
			S_su_RH2 = self.y.S_su_RH2
			S_aa_RH2 = self.y.S_aa_RH2
			S_fa_RH2 = self.y.S_fa_RH2
			S_ac_RH2 = self.y.S_ac_RH2
			X_c_RH2 = self.y.X_c_RH2
			X_ch_RH2 = self.y.X_ch_RH2
			X_pr_RH2 = self.y.X_pr_RH2
			X_li_RH2 = self.y.X_li_RH2
			X_suaa_RH2 = self.y.X_suaa_RH2
			X_fa_RH2 = self.y.X_fa_RH2
			
			# Compute biochemical process rates
			r1 = paramsRH2.k_dis * X_c_RH2
			r2 = paramsRH2.k_hyd_ch * X_ch_RH2
			r3 = paramsRH2.k_hyd_pr * X_pr_RH2
			r4 = paramsRH2.k_hyd_li * X_li_RH2
			r5 = paramsRH2.k_m_suaa * (S_su_RH2 / (paramsRH2.K_S_suaa + S_su_RH2)) * X_suaa_RH2 * (S_su_RH2/(S_su_RH2+S_aa_RH2))
			r6 = paramsRH2.k_m_suaa * (S_aa_RH2 / (paramsRH2.K_S_suaa + S_aa_RH2)) * X_suaa_RH2 * (S_aa_RH2/(S_su_RH2+S_aa_RH2))
			r7 = paramsRH2.k_m_fa * (S_fa_RH2 / (paramsRH2.K_S_fa + S_fa_RH2)) * X_fa_RH2
			
			# Compute state derivatives		
			S_su_RH2_dot = self.D_RH2*(concentrsRH2.S_su_in - S_su_RH2) \
				+ r2 + paramsRH2.f_su_li*r4 - r5 #1.1
			S_aa_RH2_dot = self.D_RH2*(concentrsRH2.S_aa_in - S_aa_RH2) \
				+ r3 - r6 #2.1
			S_fa_RH2_dot = self.D_RH2*(concentrsRH2.S_fa_in - S_fa_RH2) \
				+ paramsRH2.f_fa_li*r4 - r7 #3.1
			S_ac_RH2_dot = self.D_RH2*(concentrsRH2.S_ac_in - S_ac_RH2) \
				+ (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_su*r5 \
				+ (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_aa*r6 \
				+ (1 - paramsRH2.Y_fa)*0.7*r7 #7.1
			X_c_RH2_dot = self.D_RH2*(concentrsRH2.X_c_in - X_c_RH2) \
				- r1 #13.1
			X_ch_RH2_dot = self.D_RH2*(concentrsRH2.X_ch_in - X_ch_RH2) \
				+ paramsRH2.f_ch_xc*r1 - r2 #14.1
			X_pr_RH2_dot = self.D_RH2*(concentrsRH2.X_pr_in - X_pr_RH2) \
				+ paramsRH2.f_pr_xc*r1 - r3 #15.1
			X_li_RH2_dot = self.D_RH2*(concentrsRH2.X_li_in - X_li_RH2) \
				+ paramsRH2.f_li_xc*r1 - r4 #16.1
			X_suaa_RH2_dot = self.D_RH2*(concentrsRH2.X_suaa_in - X_suaa_RH2) \
				+ paramsRH2.Y_suaa*r5 \
				+ paramsRH2.Y_suaa*r6 #17.1
			X_fa_RH2_dot = self.D_RH2*(concentrsRH2.X_fa_in - X_fa_RH2) \
				+ paramsRH2.Y_fa*r7 #19.1
		
			self.Q_h2_RH2 = paramsRH2.Y_h2_su * r5 \
				+ paramsRH2.Y_h2_aa * r6 \
				+ paramsRH2.Y_h2_fa * r7
			intQ_h2_RH2_dot = self.Q_h2_RH2
			
			# Set state derivatives
			self.yDot.S_su_RH2 = S_su_RH2_dot
			self.yDot.S_aa_RH2 = S_aa_RH2_dot
			self.yDot.S_fa_RH2 = S_fa_RH2_dot
			self.yDot.S_ac_RH2 = S_ac_RH2_dot
			self.yDot.X_c_RH2 = X_c_RH2_dot
			self.yDot.X_ch_RH2 = X_ch_RH2_dot
			self.yDot.X_pr_RH2 = X_pr_RH2_dot
			self.yDot.X_li_RH2 = X_li_RH2_dot
			self.yDot.X_suaa_RH2 = X_suaa_RH2_dot
			self.yDot.X_fa_RH2 = X_fa_RH2_dot
			self.yDot.intQ_h2_RH2 = intQ_h2_RH2_dot
		
		# Bioreactor - RCH4
			# Get state values
			S_ac_RCH4 = self.y.S_ac_RCH4
			X_ac_RCH4 = self.y.X_ac_RCH4
			
			# Compute biochemical process rates
			r11 = paramsRCH4.k_m_ac * (S_ac_RCH4 / (paramsRCH4.K_S_ac + S_ac_RCH4)) * X_ac_RCH4
			
			# Compute state derivatives		
			S_ac_RCH4_dot = self.D_RCH4*(S_ac_RH2 - S_ac_RCH4) \
				-r11#7.2
			X_ac_RCH4_dot = self.D_RCH4*(concentrsRCH4.X_ac_in - X_ac_RCH4) \
				+ paramsRCH4.Y_ac * r11 #22.2
			self.Q_ch4_RCH4 = paramsRCH4.Y_ch4_ac * r11 
			intQ_ch4_RCH4_dot = self.Q_ch4_RCH4
			
			# Set state derivatives
			self.yDot.S_ac_RCH4 = S_ac_RCH4_dot
			self.yDot.X_ac_RCH4 = X_ac_RCH4_dot
			self.yDot.intQ_ch4_RCH4 = intQ_ch4_RCH4_dot
			
		except Exception, e:
			self.resultStorage.finalizeResult()
			# Log the error if it happens in the rhs() function
			print("Exception at time {}: {}".format(t, e))
			raise e
		
		return self.yDot.get()
Example #8
0
class ChemostatSimple(Simulation):
    """
	Class for implementation the model of a simple chemostat 
	"""
    name = 'Model of a simple chemostat.'

    def __init__(self, params=None, **kwargs):
        super(ChemostatSimple, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Initialize parameters
        self.m = params.m
        self.K = params.K
        self.S_in = params.S_in
        self.X_in = params.X_in
        self.gamma = params.gamma
        self.D_vals = params.D_vals

        # Create state vector and derivative vector
        stateVarNames = ['S', 'X']
        self.y = NamedStateVector(stateVarNames)
        self.yRes = NamedStateVector(stateVarNames)
        self.yDot = NamedStateVector(stateVarNames)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(varList=['t'] +
                                                 stateVarNames + ['D'],
                                                 chunkSize=1e4)

        # Register time event (changed of D)
        D_val = self.D_vals[0]
        self.D = D_val[1]

        tChangedD = D_val[0]
        for i in range(len(self.D_vals) - 1):
            self.D_val = self.D_vals[i + 1]
            self.timeEventRegistry.add(
                ChemostatSimpleTimeEvent(t=tChangedD,
                                         newValue_D=self.D_val[1]))
            tChangedD += self.D_val[0]

        # Set initial values of the states
        self.y.S = params.S0
        self.y.X = params.X0

        # Set all the initial state values
        self.y0 = self.y.get(copy=True)

        # Set the initial flags
        self.sw0 = [True]

    def mu(self, S):
        return self.m * S / (self.K + S)

    def rhs(self, t, y, sw):
        # Set state values
        self.y.set(y)

        try:
            # Get state values
            S = self.y.S
            X = self.y.X

            # Compute state derivatives
            S_dot = (self.S_in - S) * self.D - (1 /
                                                self.gamma) * self.mu(S) * X
            X_dot = (self.X_in - X) * self.D + self.mu(S) * X

        except Exception, e:
            self.resultStorage.finalizeResult()
            # Log the error if it happens in the rhs() function
            print("Exception at time {}: {}".format(t, e))
            raise e

        self.yDot.S = S_dot
        self.yDot.X = X_dot
        return self.yDot.get()
Example #9
0
    def __init__(self, webModel, paramsRH2, concentrsRH2, paramsRCH4,
                 concentrsRCH4, **kwargs):
        super(ADM1H2CH4Bioreactors, self).__init__(**kwargs)

        # Initialize update progress function
        self.updateProgress = webModel.updateProgress

        # Initialize parameters
        self.paramsRH2 = paramsRH2
        self.paramsRCH4 = paramsRCH4

        # Initialize concentrations
        self.concentrsRH2 = concentrsRH2
        self.concentrsRCH4 = concentrsRCH4

        # Create state vector and derivative vector
        stateVarNames = [
            'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2', 'X_c_RH2',
            'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2',
            'intQ_h2_RH2', 'S_ac_RCH4', 'X_ac_RCH4', 'intQ_ch4_RCH4'
        ]
        self.y = NamedStateVector(stateVarNames)
        self.yRes = NamedStateVector(stateVarNames)
        self.yDot = NamedStateVector(stateVarNames)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(
                varList=['time'] + stateVarNames +
                ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'],
                chunkSize=1e4)

        # Register time event (changed of D)
        tChangedD = paramsRH2.D_liq_arr[0][0]
        self.D_RH2 = paramsRH2.D_liq_arr[0][1]

        self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2

        for i in range(len(paramsRH2.D_liq_arr) - 1):
            self.timeEventRegistry.add(
                ADM1TimeEvent(t=tChangedD,
                              newValue_D=paramsRH2.D_liq_arr[i + 1][1]))
            tChangedD += paramsRH2.D_liq_arr[i + 1][0]

        # Set initial values of the states
        self.y.S_su_RH2 = concentrsRH2.S_su_0
        self.y.S_aa_RH2 = concentrsRH2.S_aa_0
        self.y.S_fa_RH2 = concentrsRH2.S_fa_0
        self.y.S_ac_RH2 = concentrsRH2.S_ac_0
        self.y.X_c_RH2 = concentrsRH2.X_c_0
        self.y.X_ch_RH2 = concentrsRH2.X_ch_0
        self.y.X_pr_RH2 = concentrsRH2.X_pr_0
        self.y.X_li_RH2 = concentrsRH2.X_li_0
        self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0
        self.y.X_fa_RH2 = concentrsRH2.X_fa_0
        self.y.intQ_h2_RH2 = 0.0
        self.Q_h2_RH2 = 0.0

        self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0
        self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0
        self.y.intQ_ch4_RCH4 = 0.0
        self.Q_ch4_RCH4 = 0.0

        # Set all the initial state values
        self.y0 = self.y.get(copy=True)

        # Set the initial flags
        self.sw0 = [True]
Example #10
0
class ADM1H2CH4Bioreactors(Simulation):
    """
	Class for implementation the model of a ADM1 H2 and CH4 Bioreactors
	"""
    name = 'Model of a bioreactor that produces hydrogen.'

    def __init__(self, webModel, paramsRH2, concentrsRH2, paramsRCH4,
                 concentrsRCH4, **kwargs):
        super(ADM1H2CH4Bioreactors, self).__init__(**kwargs)

        # Initialize update progress function
        self.updateProgress = webModel.updateProgress

        # Initialize parameters
        self.paramsRH2 = paramsRH2
        self.paramsRCH4 = paramsRCH4

        # Initialize concentrations
        self.concentrsRH2 = concentrsRH2
        self.concentrsRCH4 = concentrsRCH4

        # Create state vector and derivative vector
        stateVarNames = [
            'S_su_RH2', 'S_aa_RH2', 'S_fa_RH2', 'S_ac_RH2', 'X_c_RH2',
            'X_ch_RH2', 'X_pr_RH2', 'X_li_RH2', 'X_suaa_RH2', 'X_fa_RH2',
            'intQ_h2_RH2', 'S_ac_RCH4', 'X_ac_RCH4', 'intQ_ch4_RCH4'
        ]
        self.y = NamedStateVector(stateVarNames)
        self.yRes = NamedStateVector(stateVarNames)
        self.yDot = NamedStateVector(stateVarNames)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(
                varList=['time'] + stateVarNames +
                ['Q_h2_RH2', 'Q_ch4_RCH4', 'D_RH2', 'D_RCH4'],
                chunkSize=1e4)

        # Register time event (changed of D)
        tChangedD = paramsRH2.D_liq_arr[0][0]
        self.D_RH2 = paramsRH2.D_liq_arr[0][1]

        self.D_RCH4 = self.D_RH2 / paramsRCH4.V_liq_RCH4_del_V_liq_RH2

        for i in range(len(paramsRH2.D_liq_arr) - 1):
            self.timeEventRegistry.add(
                ADM1TimeEvent(t=tChangedD,
                              newValue_D=paramsRH2.D_liq_arr[i + 1][1]))
            tChangedD += paramsRH2.D_liq_arr[i + 1][0]

        # Set initial values of the states
        self.y.S_su_RH2 = concentrsRH2.S_su_0
        self.y.S_aa_RH2 = concentrsRH2.S_aa_0
        self.y.S_fa_RH2 = concentrsRH2.S_fa_0
        self.y.S_ac_RH2 = concentrsRH2.S_ac_0
        self.y.X_c_RH2 = concentrsRH2.X_c_0
        self.y.X_ch_RH2 = concentrsRH2.X_ch_0
        self.y.X_pr_RH2 = concentrsRH2.X_pr_0
        self.y.X_li_RH2 = concentrsRH2.X_li_0
        self.y.X_suaa_RH2 = concentrsRH2.X_suaa_0
        self.y.X_fa_RH2 = concentrsRH2.X_fa_0
        self.y.intQ_h2_RH2 = 0.0
        self.Q_h2_RH2 = 0.0

        self.y.S_ac_RCH4 = concentrsRCH4.S_ac_0
        self.y.X_ac_RCH4 = concentrsRCH4.X_ac_0
        self.y.intQ_ch4_RCH4 = 0.0
        self.Q_ch4_RCH4 = 0.0

        # Set all the initial state values
        self.y0 = self.y.get(copy=True)

        # Set the initial flags
        self.sw0 = [True]

    def rhs(self, t, y, sw):
        paramsRH2 = self.paramsRH2
        concentrsRH2 = self.concentrsRH2

        paramsRCH4 = self.paramsRCH4
        concentrsRCH4 = self.concentrsRCH4

        # Set state values
        self.y.set(y)

        try:
            # Bioreactor - RH2
            # Get state values
            S_su_RH2 = self.y.S_su_RH2
            S_aa_RH2 = self.y.S_aa_RH2
            S_fa_RH2 = self.y.S_fa_RH2
            S_ac_RH2 = self.y.S_ac_RH2
            X_c_RH2 = self.y.X_c_RH2
            X_ch_RH2 = self.y.X_ch_RH2
            X_pr_RH2 = self.y.X_pr_RH2
            X_li_RH2 = self.y.X_li_RH2
            X_suaa_RH2 = self.y.X_suaa_RH2
            X_fa_RH2 = self.y.X_fa_RH2

            # Compute biochemical process rates
            r1 = paramsRH2.k_dis * X_c_RH2
            r2 = paramsRH2.k_hyd_ch * X_ch_RH2
            r3 = paramsRH2.k_hyd_pr * X_pr_RH2
            r4 = paramsRH2.k_hyd_li * X_li_RH2
            r5 = paramsRH2.k_m_suaa * (S_su_RH2 /
                                       (paramsRH2.K_S_suaa + S_su_RH2)
                                       ) * X_suaa_RH2 * (S_su_RH2 /
                                                         (S_su_RH2 + S_aa_RH2))
            r6 = paramsRH2.k_m_suaa * (S_aa_RH2 /
                                       (paramsRH2.K_S_suaa + S_aa_RH2)
                                       ) * X_suaa_RH2 * (S_aa_RH2 /
                                                         (S_su_RH2 + S_aa_RH2))
            r7 = paramsRH2.k_m_fa * (S_fa_RH2 /
                                     (paramsRH2.K_S_fa + S_fa_RH2)) * X_fa_RH2

            # Compute state derivatives
            S_su_RH2_dot = self.D_RH2*(concentrsRH2.S_su_in - S_su_RH2) \
             + r2 + paramsRH2.f_su_li*r4 - r5 #1.1
            S_aa_RH2_dot = self.D_RH2*(concentrsRH2.S_aa_in - S_aa_RH2) \
             + r3 - r6 #2.1
            S_fa_RH2_dot = self.D_RH2*(concentrsRH2.S_fa_in - S_fa_RH2) \
             + paramsRH2.f_fa_li*r4 - r7 #3.1
            S_ac_RH2_dot = self.D_RH2*(concentrsRH2.S_ac_in - S_ac_RH2) \
             + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_su*r5 \
             + (1 - paramsRH2.Y_suaa)*paramsRH2.f_ac_aa*r6 \
             + (1 - paramsRH2.Y_fa)*0.7*r7 #7.1
            X_c_RH2_dot = self.D_RH2*(concentrsRH2.X_c_in - X_c_RH2) \
             - r1 #13.1
            X_ch_RH2_dot = self.D_RH2*(concentrsRH2.X_ch_in - X_ch_RH2) \
             + paramsRH2.f_ch_xc*r1 - r2 #14.1
            X_pr_RH2_dot = self.D_RH2*(concentrsRH2.X_pr_in - X_pr_RH2) \
             + paramsRH2.f_pr_xc*r1 - r3 #15.1
            X_li_RH2_dot = self.D_RH2*(concentrsRH2.X_li_in - X_li_RH2) \
             + paramsRH2.f_li_xc*r1 - r4 #16.1
            X_suaa_RH2_dot = self.D_RH2*(concentrsRH2.X_suaa_in - X_suaa_RH2) \
             + paramsRH2.Y_suaa*r5 \
             + paramsRH2.Y_suaa*r6 #17.1
            X_fa_RH2_dot = self.D_RH2*(concentrsRH2.X_fa_in - X_fa_RH2) \
             + paramsRH2.Y_fa*r7 #19.1

            self.Q_h2_RH2 = paramsRH2.Y_h2_su * r5 \
             + paramsRH2.Y_h2_aa * r6 \
             + paramsRH2.Y_h2_fa * r7
            intQ_h2_RH2_dot = self.Q_h2_RH2

            # Set state derivatives
            self.yDot.S_su_RH2 = S_su_RH2_dot
            self.yDot.S_aa_RH2 = S_aa_RH2_dot
            self.yDot.S_fa_RH2 = S_fa_RH2_dot
            self.yDot.S_ac_RH2 = S_ac_RH2_dot
            self.yDot.X_c_RH2 = X_c_RH2_dot
            self.yDot.X_ch_RH2 = X_ch_RH2_dot
            self.yDot.X_pr_RH2 = X_pr_RH2_dot
            self.yDot.X_li_RH2 = X_li_RH2_dot
            self.yDot.X_suaa_RH2 = X_suaa_RH2_dot
            self.yDot.X_fa_RH2 = X_fa_RH2_dot
            self.yDot.intQ_h2_RH2 = intQ_h2_RH2_dot

            # Bioreactor - RCH4
            # Get state values
            S_ac_RCH4 = self.y.S_ac_RCH4
            X_ac_RCH4 = self.y.X_ac_RCH4

            # Compute biochemical process rates
            r11 = paramsRCH4.k_m_ac * (
                S_ac_RCH4 / (paramsRCH4.K_S_ac + S_ac_RCH4)) * X_ac_RCH4

            # Compute state derivatives
            S_ac_RCH4_dot = self.D_RCH4*(S_ac_RH2 - S_ac_RCH4) \
             -r11#7.2
            X_ac_RCH4_dot = self.D_RCH4*(concentrsRCH4.X_ac_in - X_ac_RCH4) \
             + paramsRCH4.Y_ac * r11 #22.2
            self.Q_ch4_RCH4 = paramsRCH4.Y_ch4_ac * r11
            intQ_ch4_RCH4_dot = self.Q_ch4_RCH4

            # Set state derivatives
            self.yDot.S_ac_RCH4 = S_ac_RCH4_dot
            self.yDot.X_ac_RCH4 = X_ac_RCH4_dot
            self.yDot.intQ_ch4_RCH4 = intQ_ch4_RCH4_dot

        except Exception, e:
            self.resultStorage.finalizeResult()
            # Log the error if it happens in the rhs() function
            print("Exception at time {}: {}".format(t, e))
            raise e

        return self.yDot.get()
Example #11
0
class BiochemicalReactions(Simulation):
    """
    Class for implementation the model of biochemical reactions @see http://en.wikipedia.org/wiki/Rate_equation#Stoichiometric_reaction_networks
    """
    def __init__(self, params=None, **kwargs):
        """
        #params.reactions = [reactionEquation, rateConstants]
        #params.species = [speciesVariable, initialValue]
        """
        super(BiochemicalReactions, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values
        self.Xs = np.empty(len(params.species), dtype=(np.str_, 256))
        self.X0s = np.zeros(len(params.species))
        for i, itSpecies in enumerate(params.species):
            self.Xs[i] = itSpecies[0]
            self.X0s[i] = itSpecies[1]

        # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where:
        # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions)
        # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions)
        # k - the rate constant of the reaction
        # ss - the stoichiometric coefficients of reactants  (e.g. [0,1,1,0,...,1])
        # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0])
        # f - the fluxs (e.g. k*X2*X3*...*Xn)
        self.reactions = self.readReactions(params.reactions, self.Xs)
        #for reaction in self.reactions: print reaction

        # Create a vector with state variable names
        stateVarNames = list(self.Xs)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath,
                                           datasetPath=dataStorageDatasetPath)
        if (kwargs.get('initDataStorage', True)):
            self.resultStorage.initializeWriting(varList=['t'] + stateVarNames,
                                                 chunkSize=1e4)

        # Set the initial state values
        self.y0 = self.X0s

        # Set the initial flags
        self.sw0 = [True]

    def readReactions(self, reactions, Xs):
        resReactions = []
        for reaction in reactions:
            txtReaction = reaction[0]
            txtReaction_orig = txtReaction
            txtReaction = txtReaction.replace(" ", "")

            # Get and check the direction of the reaction
            dirReaction = re.findall("[-=<>]+", txtReaction)
            if len(dirReaction) == 0:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is missing"
                    ", use one of {1}".format(txtReaction_orig,
                                              validReactionDiractions))
            if len(dirReaction) > 1:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nToo many directions of the reaction."
                    .format(txtReaction_orig))

            dirReaction = dirReaction[0]
            if not (dirReaction in validReactionDiractions):
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction '{1}' is wrong"
                    ", use one of {2}".format(txtReaction_orig, dirReaction,
                                              validReactionDiractions))

            # Get and check the rate constants of the reaction
            txtRateConstants = reaction[1]
            kForward, kBackward = self.readReactionRateConstants(
                txtReaction_orig, txtRateConstants)

            if kForward == 0.0 and dirReaction in forwardReactionDiractions:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', "
                    "but the forward rate constant is {2}".format(
                        txtReaction_orig, dirReaction, kForward))

            if kBackward == 0.0 and dirReaction in backwardReactionDiractions:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', "
                    "but the backward rate constant is {2}".format(
                        txtReaction_orig, dirReaction, kBackward))

            # Get and check the reaction parts
            partsReaction = re.split("[-=<>]+", txtReaction)
            if len(partsReaction) <> 2:
                raise ValueError(
                    "\nInvalid reaction '{0}'.".format(txtReaction_orig))

            # Get and check the Xs of the leftPart of the reaction
            leftPartEq = partsReaction[0]
            leftXs = leftPartEq.split('+')
            for X in leftXs:
                if not X in Xs:
                    raise ValueError(
                        "\nInvalid reaction '{0}'.\nInvalid species variable "
                        "'{1}', use one of {2}".format(txtReaction_orig, X,
                                                       Xs))

            rightPartEq = partsReaction[1]
            rightXs = rightPartEq.split('+')
            for X in rightXs:
                if not X in Xs:
                    raise ValueError(
                        "\nInvalid reaction '{0}'.\nInvalid species variable "
                        "'{1}', use one of {2}".format(txtReaction_orig, X,
                                                       Xs))

            # Add to the reactions
            if dirReaction in forwardReactionDiractions:
                f = ""
                ss = np.zeros(len(Xs))
                for X in leftXs:
                    i = np.where(Xs == X)
                    ss[i] = 1
                    f += "[{0}]".format(X)
                f = "{0}".format(kForward) + f

                rs = np.zeros(len(Xs))
                for X in rightXs:
                    i = np.where(Xs == X)
                    rs[i] = 1
                resReactions.append([leftXs, rightXs, kForward, ss, rs, f])

            if dirReaction in backwardReactionDiractions:
                f = ""
                ss = np.zeros(len(Xs))
                for X in rightXs:
                    i = np.where(Xs == X)
                    ss[i] = 1
                    f += "[{0}]".format(X)
                f = "{0}".format(kBackward) + f

                rs = np.zeros(len(Xs))
                for X in leftXs:
                    i = np.where(Xs == X)
                    rs[i] = 1
                resReactions.append([rightXs, leftXs, kBackward, ss, rs, f])

        return resReactions

    def readReactionRateConstants(self, txtReaction, txtRateConstants):
        partsRate = re.split("[,;]+", txtRateConstants)

        if len(partsRate) == 0:
            raise ValueError(
                "The rate constants of the reaction '{0}' are not set.\n"
                "Enter one or two rate constants with a delimiter , or ;".
                format(txtReaction))

        if len(partsRate) > 2:
            raise ValueError(
                "\Invalid rate constants '{0}' of the reaction '{1}'.\n"
                "Enter one or two rate constants with a delimiter , or ;".
                format(txtRateConstants, txtReaction))

        try:
            kForward = float(partsRate[0])
        except ValueError:
            raise ValueError(
                "\Invalid rate constants '{0}' of the reaction '{1}', \n"
                "the forward rate constant '{2}' is not valid real number.".
                format(txtRateConstants, txtReaction, partsRate[0]))

        kBackward = 0.0
        if len(partsRate) == 2:
            try:
                kBackward = float(partsRate[1])
            except ValueError:
                raise ValueError(
                    "\Invalid rate constants '{0}' of the reaction '{1}', \n"
                    "the backward rate constant '{2}' is not valid real number."
                    .format(txtRateConstants, txtReaction, partsRate[1]))

        return (kForward, kBackward)

    def rhs(self, t, y, sw):
        yDot = np.zeros(len(y))
        try:
            # Compute fluxes
            fs = np.ones(len(self.reactions))
            for j, eq in enumerate(self.reactions):
                (_leftXs, _rightXs, k, ss, _rs, _f) = self.splitReaction(eq)
                fs[j] = k
                for i in range(len(y)):
                    fs[j] *= np.power(y[i], ss[i])

            # Compute state derivatives
            for i in range(len(y)):
                for j, eq in enumerate(self.reactions):
                    (_leftXs, _rightXs, _k, ss, rs,
                     _f) = self.splitReaction(eq)
                    S = rs[i] - ss[i]
                    yDot[i] += S * fs[j]

        except Exception, e:
            self.resultStorage.finalizeResult()
            # Log the error if it happens in the rhs() function
            print("Exception at time {}: {}".format(t, e))
            raise e

        return yDot
Example #12
0
class BiochemicalReactions(Simulation):
    """
    Class for implementation the model of biochemical reactions @see http://en.wikipedia.org/wiki/Rate_equation#Stoichiometric_reaction_networks
    """

    def __init__(self, params=None, **kwargs):
        """
        #params.reactions = [reactionEquation, rateConstants]
        #params.species = [speciesVariable, initialValue]
        """
        super(BiochemicalReactions, self).__init__(**kwargs)
        if params == None:
            params = AttributeDict(kwargs)

        # Initialize update progress function
        self.updateProgress = params.updateProgress

        # Get the species variables Xs = [X1, X2, ..., Xn] and their initial values
        self.Xs = np.empty(len(params.species), dtype=(np.str_, 256))
        self.X0s = np.zeros(len(params.species))
        for i, itSpecies in enumerate(params.species):
            self.Xs[i] = itSpecies[0]
            self.X0s[i] = itSpecies[1]

        # Get the reactions = [[left Xs, right Xs, k, ss, rs, f], ...], where:
        # left Xs - the species variables of reactants (i.e. the species variables of the left parts of the reactions)
        # rigth Xs - the species variables of products (i.e. the species variables of the right parts of the reactions)
        # k - the rate constant of the reaction
        # ss - the stoichiometric coefficients of reactants  (e.g. [0,1,1,0,...,1])
        # rs - the stoichiometric coefficients of products (e.g. [1,0,...,0])
        # f - the fluxs (e.g. k*X2*X3*...*Xn)
        self.reactions = self.readReactions(params.reactions, self.Xs)
        # for reaction in self.reactions: print reaction

        # Create a vector with state variable names
        stateVarNames = list(self.Xs)

        # Initialize data storage
        self.resultStorage = ResultStorage(filePath=dataStorageFilePath, datasetPath=dataStorageDatasetPath)
        if kwargs.get("initDataStorage", True):
            self.resultStorage.initializeWriting(varList=["t"] + stateVarNames, chunkSize=1e4)

        # Set the initial state values
        self.y0 = self.X0s

        # Set the initial flags
        self.sw0 = [True]

    def readReactions(self, reactions, Xs):
        resReactions = []
        for reaction in reactions:
            txtReaction = reaction[0]
            txtReaction_orig = txtReaction
            txtReaction = txtReaction.replace(" ", "")

            # Get and check the direction of the reaction
            dirReaction = re.findall("[-=<>]+", txtReaction)
            if len(dirReaction) == 0:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is missing"
                    ", use one of {1}".format(txtReaction_orig, validReactionDiractions)
                )
            if len(dirReaction) > 1:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nToo many directions of the reaction.".format(txtReaction_orig)
                )

            dirReaction = dirReaction[0]
            if not (dirReaction in validReactionDiractions):
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction '{1}' is wrong"
                    ", use one of {2}".format(txtReaction_orig, dirReaction, validReactionDiractions)
                )

            # Get and check the rate constants of the reaction
            txtRateConstants = reaction[1]
            kForward, kBackward = self.readReactionRateConstants(txtReaction_orig, txtRateConstants)

            if kForward == 0.0 and dirReaction in forwardReactionDiractions:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', "
                    "but the forward rate constant is {2}".format(txtReaction_orig, dirReaction, kForward)
                )

            if kBackward == 0.0 and dirReaction in backwardReactionDiractions:
                raise ValueError(
                    "\nInvalid reaction '{0}'.\nThe direction of the reaction is '{1}', "
                    "but the backward rate constant is {2}".format(txtReaction_orig, dirReaction, kBackward)
                )

            # Get and check the reaction parts
            partsReaction = re.split("[-=<>]+", txtReaction)
            if len(partsReaction) <> 2:
                raise ValueError("\nInvalid reaction '{0}'.".format(txtReaction_orig))

            # Get and check the Xs of the leftPart of the reaction
            leftPartEq = partsReaction[0]
            leftXs = leftPartEq.split("+")
            for X in leftXs:
                if not X in Xs:
                    raise ValueError(
                        "\nInvalid reaction '{0}'.\nInvalid species variable "
                        "'{1}', use one of {2}".format(txtReaction_orig, X, Xs)
                    )

            rightPartEq = partsReaction[1]
            rightXs = rightPartEq.split("+")
            for X in rightXs:
                if not X in Xs:
                    raise ValueError(
                        "\nInvalid reaction '{0}'.\nInvalid species variable "
                        "'{1}', use one of {2}".format(txtReaction_orig, X, Xs)
                    )

            # Add to the reactions
            if dirReaction in forwardReactionDiractions:
                f = ""
                ss = np.zeros(len(Xs))
                for X in leftXs:
                    i = np.where(Xs == X)
                    ss[i] = 1
                    f += "[{0}]".format(X)
                f = "{0}".format(kForward) + f

                rs = np.zeros(len(Xs))
                for X in rightXs:
                    i = np.where(Xs == X)
                    rs[i] = 1
                resReactions.append([leftXs, rightXs, kForward, ss, rs, f])

            if dirReaction in backwardReactionDiractions:
                f = ""
                ss = np.zeros(len(Xs))
                for X in rightXs:
                    i = np.where(Xs == X)
                    ss[i] = 1
                    f += "[{0}]".format(X)
                f = "{0}".format(kBackward) + f

                rs = np.zeros(len(Xs))
                for X in leftXs:
                    i = np.where(Xs == X)
                    rs[i] = 1
                resReactions.append([rightXs, leftXs, kBackward, ss, rs, f])

        return resReactions

    def readReactionRateConstants(self, txtReaction, txtRateConstants):
        partsRate = re.split("[,;]+", txtRateConstants)

        if len(partsRate) == 0:
            raise ValueError(
                "The rate constants of the reaction '{0}' are not set.\n"
                "Enter one or two rate constants with a delimiter , or ;".format(txtReaction)
            )

        if len(partsRate) > 2:
            raise ValueError(
                "\Invalid rate constants '{0}' of the reaction '{1}'.\n"
                "Enter one or two rate constants with a delimiter , or ;".format(txtRateConstants, txtReaction)
            )

        try:
            kForward = float(partsRate[0])
        except ValueError:
            raise ValueError(
                "\Invalid rate constants '{0}' of the reaction '{1}', \n"
                "the forward rate constant '{2}' is not valid real number.".format(
                    txtRateConstants, txtReaction, partsRate[0]
                )
            )

        kBackward = 0.0
        if len(partsRate) == 2:
            try:
                kBackward = float(partsRate[1])
            except ValueError:
                raise ValueError(
                    "\Invalid rate constants '{0}' of the reaction '{1}', \n"
                    "the backward rate constant '{2}' is not valid real number.".format(
                        txtRateConstants, txtReaction, partsRate[1]
                    )
                )

        return (kForward, kBackward)

    def rhs(self, t, y, sw):
        yDot = np.zeros(len(y))
        try:
            # Compute fluxes
            fs = np.ones(len(self.reactions))
            for j, eq in enumerate(self.reactions):
                (_leftXs, _rightXs, k, ss, _rs, _f) = self.splitReaction(eq)
                fs[j] = k
                for i in range(len(y)):
                    fs[j] *= np.power(y[i], ss[i])

            # Compute state derivatives
            for i in range(len(y)):
                for j, eq in enumerate(self.reactions):
                    (_leftXs, _rightXs, _k, ss, rs, _f) = self.splitReaction(eq)
                    S = rs[i] - ss[i]
                    yDot[i] += S * fs[j]

        except Exception, e:
            self.resultStorage.finalizeResult()
            # Log the error if it happens in the rhs() function
            print ("Exception at time {}: {}".format(t, e))
            raise e

        return yDot