lib/eulim/chemistry/reaction.rb in eulim-0.0.13 vs lib/eulim/chemistry/reaction.rb in eulim-0.0.14
- old
+ new
@@ -1,27 +1,44 @@
+require 'matrix'
+
module Eulim
module Chemistry
# This class has functionality for reaction
# Ex: check for balanced rxn, validity of a rxn
class Reaction
- attr_accessor :equation, :is_valid, :is_balanced, :species
+ attr_accessor :equation, :is_valid, :species, :participants, :balanced_eqn, :rate_equation
STATES = {
'(s)' => 'solid', '(l)' => 'liquid',
'(g)' => 'gaseous', '(aq)' => 'aqueous',
- '' => 'liquid'
+ '' => ''
}.freeze
- def initialize(arg)
- @equation = arg
+ def initialize(args)
+ # rate_eqn should be of the form: 'r_{CaO} = k[CaO][CO2]'
+ @equation = args[:equation]
@species = build_species
@is_valid = valid_rxn?
- @is_balanced = balanced_rxn?
+ p participant_elements
+ # @balanced_eqn = balance_rxn
+ @rate_equation = validify_rate_eqn args[:rate_equation]
end
private
+ def validify_rate_eqn(rate_eqn)
+ if rate_eqn
+ rate_eqn.gsub('_{', '')
+ .gsub('}', '')
+ .gsub('[', ' * c')
+ .gsub(']', '')
+ else
+ specie = @species[:reactants].keys.first
+ 'r' + specie + ' = k * c' + specie
+ end
+ end
+
def build_species
r = {}
result = {}
r[:reactants], r[:products] = @equation.split('>>')
r.each do |type, _type_species|
@@ -78,9 +95,64 @@
specie.match(/^\d*/).to_a.first.to_i
end
def get_state(specie)
specie.match(/\((s|l|g|aq)\)$/).to_s
+ end
+
+ def participant_elements
+ participants = []
+ @species[:reactants].keys.each do |r|
+ participants << @species[:reactants][r][:compound].constituents.keys
+ end
+ @participants = participants.flatten.uniq
+ end
+
+ def get_participant_row(parti)
+ row = []
+ @species.keys.each do |key|
+ i = key == :reactants ? 1 : -1
+ @species[key].keys.each do |specie|
+ if specie.include? parti
+ row << @species[key][specie][:compound]
+ .constituents[parti][:atom_count] * i
+ else
+ row << 0
+ end
+ end
+ end
+ row
+ end
+
+ def write_matrix
+ @matrix = Matrix[]
+ @participants.each do |parti|
+ @matrix = Matrix.rows(@matrix.to_a << get_participant_row(parti))
+ end
+ @matrix
+ end
+
+ def balanced_coeff_array
+ write_matrix
+ null_space_array = @matrix.nullspace_array
+ lcm = null_space_array.collect(&:denominator).reduce(1, :lcm)
+ null_space_array.collect { |x| (x * lcm).to_i }
+ end
+
+ def balance_rxn
+ exp = ''
+ i = 0
+ bal_coeff = balanced_coeff_array
+ @species.keys.each do |key|
+ @species[key].keys.each do |comp|
+ coeff = bal_coeff[i] == 1 ? ' ' : ' ' + bal_coeff[i].abs.to_s
+ state = STATES.key(@species[key][comp][:state])
+ exp = exp + coeff + comp + state + ' +'
+ i += 1
+ end
+ exp = key == :reactants ? exp.chomp('+') + '>>' : exp.chomp('+')
+ end
+ exp.strip
end
end
end
end