|
| 1 | +using Parameters |
| 2 | + |
| 3 | +abstract type AbstractRatevec end |
| 4 | +export AbstractRatevec |
| 5 | + |
| 6 | +@with_kw struct Arrheniusvec{N<:Array,K<:Array,Q<:Array} <: AbstractRatevec |
| 7 | + A::N |
| 8 | + n::K |
| 9 | + Ea::Q |
| 10 | +end |
| 11 | +function Arrheniusvec(arrs::T) where {T<:AbstractArray} |
| 12 | + A = zeros(length(arrs)) |
| 13 | + n = zeros(length(arrs)) |
| 14 | + Ea = zeros(length(arrs)) |
| 15 | + for (i,aval) in enumerate(arrs) |
| 16 | + A[i] = aval.A |
| 17 | + n[i] = aval.n |
| 18 | + Ea[i] = aval.Ea |
| 19 | + end |
| 20 | + return Arrheniusvec(A=A,n=n,Ea=Ea) |
| 21 | +end |
| 22 | +@inline (arr::Arrheniusvec)(;T::Q,P::N=0.0,C::S=0.0) where {Q<:Real,N<:Real,S<:Real} = @fastmath @inbounds arr.A.*exp.(arr.n.*log(T).-arr.Ea.*(1.0/(R*T)))::Array{Q,1} |
| 23 | +@inline (arr::Arrheniusvec)(T::Q;P::N=0.0,C::S=0.0) where {Q<:Real,N<:Real,S<:Real} = @fastmath @inbounds arr.A.*exp.(arr.n.*log(T).-arr.Ea.*(1.0/(R*T)))::Array{Q,1} |
| 24 | +export Arrheniusvec |
| 25 | + |
| 26 | +@with_kw struct Chebyshevvec{T<:AbstractArray,Q<:Real,S<:Real,V<:Real,B<:Real} <: AbstractRate |
| 27 | + coefs::T |
| 28 | + Tmin::Q |
| 29 | + Tmax::S |
| 30 | + Pmin::V |
| 31 | + Pmax::B |
| 32 | +end |
| 33 | + |
| 34 | +function Chebyshevvec(chevs::T) where {T<:AbstractArray} |
| 35 | + coefs = zeros(length(chevs),size(chevs[1].coefs)[1],size(chevs[1].coefs)[2]) |
| 36 | + for k in 1:size(chevs[1].coefs)[2] |
| 37 | + for j in 1:size(chevs[1].coefs)[1] |
| 38 | + for i in 1:length(chevs) |
| 39 | + coefs[i,j,k] = chevs[i].coefs[j,k] |
| 40 | + end |
| 41 | + end |
| 42 | + end |
| 43 | + return Chebyshevvec(coefs=coefs,Tmin=chevs[1].Tmin,Tmax=chevs[1].Tmax,Pmin=chevs[1].Pmin,Pmax=chevs[1].Pmax) |
| 44 | +end |
| 45 | +export Chebyshevvec |
| 46 | + |
| 47 | +@inline function evalChebyshevPolynomial(ch::Chebyshevvec,n::N,x::Q) where {N<:Integer,Q<:Real} |
| 48 | + """ |
| 49 | + evaluate the nth order Chebyshev Polynomial at x |
| 50 | + """ |
| 51 | + if n==0 |
| 52 | + return 1.0 |
| 53 | + elseif n == 1 |
| 54 | + return x |
| 55 | + else |
| 56 | + T = 0.0 |
| 57 | + T0 = 1.0 |
| 58 | + T1 = x |
| 59 | + for i in 1:(n-1) |
| 60 | + @fastmath T = 2*x*T1-T0 |
| 61 | + T0 = T1 |
| 62 | + T1 = T |
| 63 | + end |
| 64 | + return T |
| 65 | + end |
| 66 | +end |
| 67 | +export evalChebyshevPolynomial |
| 68 | + |
| 69 | +@inline function getredtemp(ch::Chebyshevvec,T::N) where {N<:Real} |
| 70 | + """ |
| 71 | + return a reduced temperature corresponding to the given tempeprature |
| 72 | + for the Chebyshev polynomial, maps the inverse of temperautre onto [-1,1] |
| 73 | + """ |
| 74 | + return @fastmath (2.0/T-1.0/ch.Tmin-1.0/ch.Tmax)/(1.0/ch.Tmax-1.0/ch.Tmin) |
| 75 | +end |
| 76 | +export getredtemp |
| 77 | + |
| 78 | +@inline function getredpress(ch::Chebyshevvec,P::N) where {N<:Real} |
| 79 | + """ |
| 80 | + return a reduced pressure corresponding to the given temperature |
| 81 | + for the Chebyshev polynomial maps the logarithm of pressure onto [-1,1] |
| 82 | + """ |
| 83 | + return @fastmath (2.0*log10(P)-log10(ch.Pmin)-log10(ch.Pmax))/(log10(ch.Pmax)-log10(ch.Pmin)) |
| 84 | +end |
| 85 | +export getredpress |
| 86 | + |
| 87 | +@inline function (ch::Chebyshevvec)(;T::N,P::Q=0.0,C::B=0.0) where {N<:Real,B<:Real,Q<:Real} |
| 88 | + k = zeros(size(ch.coefs)[1]) |
| 89 | + Tred = getredtemp(ch,T) |
| 90 | + Pred = getredpress(ch,P) |
| 91 | + klen,Tlen,Plen = size(ch.coefs) |
| 92 | + @simd for j = 1:Plen |
| 93 | + @simd for i = 1:Tlen |
| 94 | + @fastmath @inbounds k .+= ch.coefs[:,i,j].*(evalChebyshevPolynomial(ch,i-1,Tred)*evalChebyshevPolynomial(ch,j-1,Pred)) |
| 95 | + end |
| 96 | + end |
| 97 | + return @fastmath 10.0.^k |
| 98 | +end |
| 99 | + |
| 100 | +@with_kw struct Troevec{P<:AbstractArray,Q<:AbstractArray,F<:AbstractArray,L<:AbstractArray,N<:Integer,K<:AbstractFloat,R<:AbstractRateUncertainty} <: AbstractFalloffRate |
| 101 | + arrhigh::Arrheniusvec |
| 102 | + arrlow::Arrheniusvec |
| 103 | + a::P |
| 104 | + T3::Q |
| 105 | + T1::F |
| 106 | + T2::L |
| 107 | + efficiencies::Array{Dict{N,K},1} |
| 108 | + unc::R = EmptyRateUncertainty() |
| 109 | +end |
| 110 | + |
| 111 | +function Troevec(troes::T) where {T<:AbstractArray} |
| 112 | + |
| 113 | + Ahigh = zeros(length(troes)) |
| 114 | + nhigh = zeros(length(troes)) |
| 115 | + Ehigh = zeros(length(troes)) |
| 116 | + Alow = zeros(length(troes)) |
| 117 | + nlow = zeros(length(troes)) |
| 118 | + Elow = zeros(length(troes)) |
| 119 | + a = zeros(length(troes)) |
| 120 | + T3 = zeros(length(troes)) |
| 121 | + T1 = zeros(length(troes)) |
| 122 | + T2 = zeros(length(troes)) |
| 123 | + efficiencies = [Dict{Int64,Float64}() for x in troes] |
| 124 | + for (i,falloff) in enumerate(troes) |
| 125 | + if isa(falloff, ThirdBody) |
| 126 | + Alow[i] = falloff.arr.A |
| 127 | + nlow[i] = falloff.arr.n |
| 128 | + Elow[i] = falloff.arr.Ea |
| 129 | + Ahigh[i] = 1e20 #very high limited by energy transfer process |
| 130 | + T3[i] = Inf |
| 131 | + T1[i] = Inf |
| 132 | + if length(efficiencies) > 0 |
| 133 | + efficiencies[i] = falloff.efficiencies |
| 134 | + end |
| 135 | + elseif isa(falloff,Lindemann) |
| 136 | + Alow[i] = falloff.arrlow.A |
| 137 | + nlow[i] = falloff.arrlow.n |
| 138 | + Elow[i] = falloff.arrlow.Ea |
| 139 | + Ahigh[i] = falloff.arrhigh.A |
| 140 | + nhigh[i] = falloff.arrhigh.n |
| 141 | + Ehigh[i] = falloff.arrhigh.Ea |
| 142 | + T3[i] = Inf |
| 143 | + T1[i] = Inf |
| 144 | + if length(efficiencies) > 0 |
| 145 | + efficiencies[i] = falloff.efficiencies |
| 146 | + end |
| 147 | + elseif isa(falloff,Troe) |
| 148 | + Alow[i] = falloff.arrlow.A |
| 149 | + nlow[i] = falloff.arrlow.n |
| 150 | + Elow[i] = falloff.arrlow.Ea |
| 151 | + Ahigh[i] = falloff.arrhigh.A |
| 152 | + nhigh[i] = falloff.arrhigh.n |
| 153 | + Ehigh[i] = falloff.arrhigh.Ea |
| 154 | + a[i] = falloff.a |
| 155 | + T3[i] = falloff.T3 |
| 156 | + T1[i] = falloff.T1 |
| 157 | + T2[i] = falloff.T2 |
| 158 | + if length(efficiencies) > 0 |
| 159 | + efficiencies[i] = falloff.efficiencies |
| 160 | + end |
| 161 | + else |
| 162 | + val = typeof(falloff) |
| 163 | + error("could not process type $val in Troevec creation") |
| 164 | + end |
| 165 | + end |
| 166 | + return Troevec(arrhigh=Arrheniusvec(Ahigh,nhigh,Ehigh),arrlow=Arrheniusvec(Alow,nlow,Elow), |
| 167 | + a=a,T3=T3,T1=T1,T2=T2,efficiencies=efficiencies) |
| 168 | +end |
| 169 | +export Troevec |
| 170 | + |
| 171 | +@inline function (tr::Troevec)(;T::Q=nothing,P::R=0.0,C::S=nothing) where {Q<:Real,R<:Real,S<:Real} |
| 172 | + k0 = tr.arrlow(T=T) |
| 173 | + kinf = tr.arrhigh(T=T) |
| 174 | + @fastmath Pr = k0.*C./kinf |
| 175 | + @fastmath log10Pr = log10.(Pr) |
| 176 | + @fastmath log10Fcent = log10.((1.0.-tr.a).*exp.(-T./tr.T3).+tr.a.*exp.(-T./tr.T1).+exp.(-tr.T2./T)) |
| 177 | + d = 0.14 |
| 178 | + @fastmath n = 0.75.-1.27.*log10Fcent |
| 179 | + @fastmath c = -0.4.-0.67.*log10Fcent |
| 180 | + F = 10.0.^((.!isinf.(tr.T1)) .* @fastmath (log10Fcent./(1.0.+((log10Pr.+c)./(n.-d.*(log10Pr))).^2))) |
| 181 | + return @fastmath ((k0.*C)./(1.0.+Pr)).*F |
| 182 | +end |
| 183 | + |
| 184 | +@with_kw struct PdepArrheniusvec{T<:Real,Q<:AbstractRateUncertainty,Z<:Arrheniusvec} <: AbstractRate |
| 185 | + Ps::Array{T,1} |
| 186 | + arrvecs::Array{Z,1} |
| 187 | + unc::Q = EmptyRateUncertainty() |
| 188 | +end |
| 189 | + |
| 190 | +function PdepArrheniusvec(pdeparrs::T) where {T<:AbstractArray} |
| 191 | + Ps = pdeparrs[1].Ps |
| 192 | + arrs = [Array{Arrhenius,1}() for i = 1:length(Ps)] |
| 193 | + for ind in 1:length(pdeparrs) |
| 194 | + for i =1:length(Ps) |
| 195 | + push!(arrs[i],pdeparrs[ind].arrs[i]) |
| 196 | + end |
| 197 | + end |
| 198 | + return PdepArrheniusvec(;Ps=Ps,arrvecs=Arrheniusvec.(arrs)) |
| 199 | +end |
| 200 | +export PdepArrheniusvec |
| 201 | + |
| 202 | +@inline function (parr::PdepArrheniusvec)(;T::Q=nothing,P::V=nothing,C::S=0.0) where {Q<:Real,V<:Real,S<:Real} |
| 203 | + inds = getBoundingIndsSorted(P,parr.Ps)::Tuple{Int64,Int64} |
| 204 | + if inds[2] == -1 |
| 205 | + return @inbounds parr.arrvecs[inds[1]](T=T) |
| 206 | + else |
| 207 | + @inbounds highk = parr.arrvecs[inds[2]](T=T) |
| 208 | + @inbounds lowk = parr.arrvecs[inds[1]](T=T) |
| 209 | + @inbounds Plow = parr.Ps[inds[1]] |
| 210 | + @inbounds Phigh = parr.Ps[inds[2]] |
| 211 | + return @inbounds @fastmath lowk.*10.0.^(log10.(P./Plow)/log10.(Phigh./Plow)*log10.(highk./lowk)) |
| 212 | + end |
| 213 | +end |
| 214 | +export PdepArrheniusvec |
0 commit comments