-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathPhase.jl
More file actions
288 lines (266 loc) · 10 KB
/
Phase.jl
File metadata and controls
288 lines (266 loc) · 10 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
using Parameters
import Base: length
using SparseArrays
abstract type AbstractPhase end
export AbstractPhase
abstract type IdealPhase <: AbstractPhase end
export IdealPhase
struct EmptyPhase <: AbstractPhase end
export EmptyPhase
include("Calculators/Ratevec.jl")
include("Calculators/Thermovec.jl")
include("Reaction.jl")
@with_kw struct IdealGas{W<:Tuple,W2,W3} <: IdealPhase
name::String = ""
species::Array{Species,1}
reactions::Array{ElementaryReaction,1}
spcdict::Dict{String,Int64}
stoichmatrix::W2
Nrp::Array{Float64,1}
rxnarray::Array{Int64,2}
veckinetics::W
veckineticsinds::Array{Int64,1}
vecthermo::NASAvec
otherreactions::Array{ElementaryReaction,1}
electronchange::W3
reversibility::Array{Bool,1}
diffusionlimited::Bool = false
end
function IdealGas(species,reactions; name="",diffusionlimited=false)
vectuple,vecinds,otherrxns,otherrxninds,posinds = getveckinetics(reactions)
rxns = vcat(reactions[vecinds],reactions[otherrxninds])
rxns = [ElementaryReaction(index=i,reactants=rxn.reactants,reactantinds=rxn.reactantinds,products=rxn.products,
productinds=rxn.productinds,kinetics=rxn.kinetics,radicalchange=rxn.radicalchange,reversible=rxn.reversible,pairs=rxn.pairs) for (i,rxn) in enumerate(rxns)]
therm = getvecthermo(species)
rxnarray = getreactionindices(species,rxns)
M,Nrp = getstoichmatrix(rxnarray,species)
echangevec = getfield.(rxns,:electronchange)
if all(echangevec .== 0)
electronchange = nothing
else
electronchange = convert(echangevec,Array{Float64,1})
end
reversibility = getfield.(rxns,:reversible)
return IdealGas(species=species,reactions=rxns,name=name,
spcdict=Dict([sp.name=>i for (i,sp) in enumerate(species)]),stoichmatrix=M,Nrp=Nrp,rxnarray=rxnarray,veckinetics=vectuple,
veckineticsinds=posinds, vecthermo=therm, otherreactions=otherrxns, electronchange=electronchange,
reversibility=reversibility,diffusionlimited=diffusionlimited,)
end
export IdealGas
@with_kw struct IdealDiluteSolution{W<:Tuple,W2,W3} <: IdealPhase
name::String = ""
species::Array{Species,1}
reactions::Array{ElementaryReaction,1}
solvent::Solvent
stoichmatrix::W2
Nrp::Array{Float64,1}
rxnarray::Array{Int64,2}
veckinetics::W
veckineticsinds::Array{Int64,1}
vecthermo::NASAvec
otherreactions::Array{ElementaryReaction,1}
electronchange::W3
spcdict::Dict{String,Int64}
reversibility::Array{Bool,1}
diffusionlimited::Bool = true
end
function IdealDiluteSolution(species,reactions,solvent; name="",diffusionlimited=true)
vectuple,vecinds,otherrxns,otherrxninds,posinds = getveckinetics(reactions)
rxns = vcat(reactions[vecinds],reactions[otherrxninds])
rxns = [ElementaryReaction(index=i,reactants=rxn.reactants,reactantinds=rxn.reactantinds,products=rxn.products,
productinds=rxn.productinds,kinetics=rxn.kinetics,radicalchange=rxn.radicalchange,reversible=rxn.reversible,pairs=rxn.pairs) for (i,rxn) in enumerate(rxns)]
therm = getvecthermo(species)
rxnarray = getreactionindices(species,rxns)
M,Nrp = getstoichmatrix(rxnarray,species)
echangevec = getfield.(rxns,:electronchange)
if all(echangevec .== 0)
electronchange = nothing
else
electronchange = convert(echangevec,Array{Float64,1})
end
reversibility = getfield.(rxns,:reversible)
return IdealDiluteSolution(species=species,reactions=rxns,solvent=solvent,name=name,
spcdict=Dict([sp.name=>i for (i,sp) in enumerate(species)]),stoichmatrix=M,Nrp=Nrp,rxnarray=rxnarray,veckinetics=vectuple,
veckineticsinds=posinds,vecthermo=therm,otherreactions=otherrxns,electronchange=electronchange,
reversibility=reversibility,diffusionlimited=diffusionlimited)
end
export IdealDiluteSolution
@with_kw struct IdealSurface{W<:Tuple,W2,W3,W4,W5} <: IdealPhase
name::String = ""
species::Array{Species,1}
reactions::Array{ElementaryReaction,1}
stoichmatrix::W2
Nrp::W5
rxnarray::Array{Int64,2}
veckinetics::W
veckineticsinds::Array{Int64,1}
vecthermo::W4
otherreactions::Array{ElementaryReaction,1}
electronchange::W3
spcdict::Dict{String,Int64}
reversibility::Array{Bool,1}
sitedensity::Float64
diffusionlimited::Bool = false
end
function IdealSurface(species,reactions,sitedensity;name="",diffusionlimited=false)
@assert diffusionlimited==false "diffusionlimited=true not supported for IdealSurface"
vectuple,vecinds,otherrxns,otherrxninds,posinds = getveckinetics(reactions)
rxns = vcat(reactions[vecinds],reactions[otherrxninds])
rxns = [ElementaryReaction(index=i,reactants=rxn.reactants,reactantinds=rxn.reactantinds,products=rxn.products,
productinds=rxn.productinds,kinetics=rxn.kinetics,radicalchange=rxn.radicalchange,electronchange=rxn.electronchange,reversible=rxn.reversible,pairs=rxn.pairs) for (i,rxn) in enumerate(rxns)]
therm = getvecthermo(species)
rxnarray = getreactionindices(species,rxns)
M,Nrp = getstoichmatrix(rxnarray,species)
echangevec = getfield.(rxns,:electronchange).*F
if all(echangevec .== 0)
electronchange = nothing
else
electronchange = convert(typeof(Nrp),echangevec)
end
reversibility = getfield.(rxns,:reversible)
return IdealSurface(species=species,reactions=rxns,name=name,
spcdict=Dict([sp.name=>i for (i,sp) in enumerate(species)]),stoichmatrix=M,Nrp=Nrp,rxnarray=rxnarray,veckinetics=vectuple,
veckineticsinds=posinds,vecthermo=therm,otherreactions=otherrxns,electronchange=electronchange,
reversibility=reversibility,sitedensity=sitedensity,diffusionlimited=diffusionlimited)
end
export IdealSurface
"""
construct the stochiometric matrix for the reactions and the reaction molecule # change
"""
function getstoichmatrix(rxnarray,spcs)
M = spzeros(size(rxnarray)[2],length(spcs))
Nrp = zeros(size(rxnarray)[2])
for i in 1:size(rxnarray)[2]
n = 0.0
for (j,ind) in enumerate(rxnarray[:,i])
if ind == 0
continue
elseif j > 5
M[i,ind] -= 1.0
n += 1.0
else
M[i,ind] += 1.0
n -= 1.0
end
end
Nrp[i] = n
end
return M,Nrp
end
"""
Split the reactions into groups with the same kinetics
"""
function splitreactionsbykinetics(rxns)
tps = []
rxnlists = []
for (i,rxn) in enumerate(rxns)
typ = getkineticstype(rxn.kinetics)
tind = findfirst(x->x==typ,tps)
if tind == nothing
push!(rxnlists,[])
push!(tps,typ)
push!(rxnlists[end],rxn)
else
push!(rxnlists[tind],rxn)
end
end
return (tps,rxnlists)
end
export splitreactionsbykinetics
"""
create vectorized kinetics calculators for the reactions
"""
function getveckinetics(rxns)
tps,rxnlists = splitreactionsbykinetics(rxns)
posinds = Array{Int64,1}()
fs = []
otherrxns = Array{ElementaryReaction,1}()
vecinds = Array{Int64,1}()
otherrxninds = Array{Int64,1}()
for (i,tp) in enumerate(tps)
if typeof(tp)<:Tuple
typ = split(tp[1],".")[end] #this split needs done because in pyrms the type names come as ReactionMechanismSimulator.Arrhenius instead of Arrhenius in RMS proper
else
typ = split(tp,".")[end]
end
rinds = [findfirst(isequal(rxn),rxns) for rxn in rxnlists[i]]
fcn = Symbol(typ * "vec")
if !(fcn in allowedfcnlist) || occursin("Troe",typ) #no vectorized kinetics or for the moment stuff with efficiencies
append!(otherrxns,rxnlists[i])
append!(otherrxninds,rinds)
else
append!(vecinds,rinds)
fcn = eval(fcn)
x = fcn([x.kinetics for x in rxnlists[i]])
push!(fs,x)
if posinds == Array{Int64,1}()
push!(posinds,length(rinds))
else
push!(posinds,length(rinds)+posinds[end])
end
end
end
vectuple = tuple(fs...)
return (vectuple,vecinds,otherrxns,otherrxninds,posinds)
end
export getveckinetics
"""
create vectorized thermo calculator for species
"""
function getvecthermo(spcs)
thermo = [sp.thermo for sp in spcs]
if isa(thermo[1],NASA)
typeassert.(thermo,NASA)
return NASAvec([sp.thermo for sp in spcs])
elseif isa(thermo[1],ConstantG)
typeassert.(thermo,ConstantG)
return ConstantGvec([th.G for th in thermo],thermo[1].T)
else
t = typeof(thermo[1])
error("Thermo type $t unsupported!")
end
end
export getvecthermo
function getC0(ph::X,T) where {X<:Union{IdealDiluteSolution,IdealGas}}
return 1.0e5/(R*T)
end
function getC0(ph::X,T) where {X<:IdealSurface}
return ph.sitedensity
end
export getC0
length(p::T) where {T<:AbstractPhase} = 1
export length
iterate(p::T) where {T<:AbstractPhase} = p
export iterate
Broadcast.broadcastable(p::T) where {T<:AbstractPhase} = Ref(p)
export broadcastable
function getreactionindices(spcs,rxns) where {Q<:AbstractPhase}
arr = zeros(Int64,(10,length(rxns)))
names = [spc.name for spc in spcs]
for (i,rxn) in enumerate(rxns)
inds = [findfirst(isequal(spc),spcs) for spc in rxn.reactants]
for (j,spc) in enumerate(rxn.reactants)
ind = findfirst(isequal(spc),spcs)
arr[j,i] = ind
rxn.reactantinds[j] = ind
end
for (j,spc) in enumerate(rxn.products)
ind = findfirst(isequal(spc),spcs)
arr[j+5,i] = ind
rxn.productinds[j] = ind
end
if hasproperty(rxn.kinetics,:efficiencies) && length(rxn.kinetics.nameefficiencies) > 0
while length(rxn.kinetics.efficiencies) > 0
pop!(rxn.kinetics.efficiencies)
end
for (key,val) in rxn.kinetics.nameefficiencies
ind = findfirst(isequal(key),names)
if !(ind === nothing)
rxn.kinetics.efficiencies[ind] = val
end
end
end
end
return arr
end
export getreactionindices