Skip to content

Commit e522b7d

Browse files
authored
Merge pull request #31 from ReactionMechanismGenerator/perfopt
Performance Optimizations
2 parents e62bc9b + 2347311 commit e522b7d

8 files changed

Lines changed: 542 additions & 46 deletions

File tree

src/Calculators/Rate.jl

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,21 @@ export getredpress
183183
end
184184
return @fastmath 10.0^k
185185
end
186+
export Chebyshev
186187

188+
@inline function getkineticstype(kin::B) where {B<:AbstractRate}
189+
return string(typeof(kin).name)
190+
end
187191

188-
export Chebyshev
192+
@inline function getkineticstype(kin::PdepArrhenius)
193+
if occursin("AbstractRate", string(typeof(kin).parameters[3])) || occursin("MultiArrhenius", string(typeof(kin).parameters[3])) #no optimized function so don't put kinetics name first
194+
return ("AbstRate",string(typeof(kin).name),trunc.(kin.Ps,digits=3))
195+
else #optimized function available so put kinetics name first
196+
return (string(typeof(kin).name),trunc.(kin.Ps,digits=3))
197+
end
198+
end
199+
200+
@inline function getkineticstype(kin::Chebyshev)
201+
return (string(typeof(kin).name),kin.Tmin,kin.Tmax,kin.Pmin,kin.Pmax,size(kin.coefs)) #different opt functions, but always can do
202+
end
203+
export getkineticstype

src/Calculators/Ratevec.jl

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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

src/Calculators/Thermovec.jl

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
using Parameters
2+
3+
abstract type AbstractThermovec end
4+
export AbstractThermovec
5+
6+
include("Thermo.jl")
7+
8+
@with_kw struct NASApolynomialvec <: AbstractThermo
9+
coefs::Array{Float64,2}
10+
Tmin::Float64
11+
Tmax::Float64
12+
end
13+
14+
@with_kw struct NASAvec{T<:AbstractThermoUncertainty} <: AbstractThermo
15+
polys::Array{NASApolynomialvec,1}
16+
unc::T = EmptyThermoUncertainty()
17+
end
18+
function NASAvec(nasas::B) where {B<:Array}
19+
Tmin = nasas[1].polys[1].Tmin
20+
Tmax = nasas[1].polys[end].Tmax
21+
Ts = Array{Float64,1}()
22+
for nasa in nasas
23+
for (i,poly) in enumerate(nasa.polys)
24+
if i == 1 && poly.Tmin > Tmin
25+
Tmin = poly.Tmin
26+
push!(Ts,poly.Tmax)
27+
elseif i == length(nasa.polys) && nasa.polys[end].Tmax < Tmax
28+
Tmax = poly.Tmax
29+
push!(Ts,poly.Tmin)
30+
else
31+
push!(Ts,poly.Tmin)
32+
push!(Ts,poly.Tmax)
33+
end
34+
end
35+
end
36+
Ts = [Tmin,Ts...,Tmax]
37+
Ts = unique(sort(Ts))
38+
polyvecs = Array{NASApolynomialvec,1}()
39+
for i in 1:length(Ts)-1
40+
T = (Ts[i]+Ts[i+1])/2.0
41+
if all([size(x.coefs)[1] == 7 for x in polyvecs])
42+
polyvec = zeros(7,length(nasas))
43+
else
44+
polyvec = zeros(9,length(nasas))
45+
end
46+
for (j,nasa) in enumerate(nasas)
47+
nasapoly = selectPoly(nasa,T)
48+
if size(polyvec)[1] == 9 && size(nasapoly.coefs)[1] == 7
49+
coefs = zeros(9)
50+
coefs[3:end] = nasapoly.coefs
51+
polyvec[:,j] = coefs
52+
else
53+
polyvec[:,j] = nasapoly.coefs
54+
end
55+
end
56+
nasapvec = NASApolynomialvec(polyvec,Ts[i],Ts[i+1])
57+
push!(polyvecs,nasapvec)
58+
end
59+
60+
return NASAvec(polys=polyvecs)
61+
62+
end
63+
@inline function selectPoly(nasa::NASAvec,T::N) where {N<:Real}
64+
"""
65+
retrieve the nasa polynomial corresponding to the T range
66+
"""
67+
for p in nasa.polys
68+
if T<=p.Tmax
69+
return p
70+
end
71+
end
72+
return nasa.polys[end]
73+
end
74+
export selectPoly
75+
76+
@inline function calcHSCpdless(poly::NASApolynomialvec,T::Float64)
77+
if size(poly.coefs)[1] != 7
78+
Tpoly0 = T
79+
Tpoly1 = T*T
80+
Tpoly2 = Tpoly1*T
81+
Tpoly3 = Tpoly2*T
82+
Tpoly4 = 1.0/T
83+
Tpoly5 = Tpoly4*Tpoly4
84+
Tpoly6 = log(T)
85+
86+
ct0 = poly.coefs[1,:].*Tpoly5
87+
ct1 = poly.coefs[2,:].*Tpoly4
88+
ct2 = poly.coefs[3,:]
89+
ct3 = poly.coefs[4,:].*Tpoly0
90+
ct4 = poly.coefs[5,:].*Tpoly1
91+
ct5 = poly.coefs[6,:].*Tpoly2
92+
ct6 = poly.coefs[7,:].*Tpoly3
93+
94+
cpdivR = ct0 .+ ct1 .+ ct2 .+ ct3 .+ ct4 .+ ct5 .+ ct6
95+
hdivRT = -ct0.+Tpoly6.*ct1.+ct2.+0.5.*ct3.+0.33333333333.*ct4.+0.25.*ct5+0.2.*ct6+poly.coefs[8,:].*Tpoly4
96+
sdivR = -0.5.*ct0 .- ct1 .+ Tpoly6.*ct2 .+ ct3 .+ 0.5.*ct4 .+ 0.33333333333.*ct5 .+ 0.25*ct6 .+ poly.coefs[9,:]
97+
else
98+
Tpoly0 = T
99+
Tpoly1 = T*T
100+
Tpoly2 = Tpoly1*T
101+
Tpoly3 = Tpoly2*T
102+
Tpoly4 = 1.0/T
103+
#Tpoly5 = Tpoly4*Tpoly4
104+
Tpoly6 = log(T)
105+
106+
#ct0 = 0.0
107+
#ct1 = 0.0
108+
ct2 = poly.coefs[1,:]
109+
ct3 = poly.coefs[2,:].*Tpoly0
110+
ct4 = poly.coefs[3,:].*Tpoly1
111+
ct5 = poly.coefs[4,:].*Tpoly2
112+
ct6 = poly.coefs[5,:].*Tpoly3
113+
114+
cpdivR = ct2 .+ ct3 .+ ct4 .+ ct5 .+ ct6
115+
hdivRT = ct2.+0.5.*ct3.+0.33333333333.*ct4.+0.25.*ct5.+0.2.*ct6.+poly.coefs[6,:].*Tpoly4
116+
sdivR = Tpoly6.*ct2 .+ ct3 .+ 0.5.*ct4 .+ 0.33333333333.*ct5 .+ 0.25.*ct6 .+ poly.coefs[7,:]
117+
end
118+
return (cpdivR,hdivRT,sdivR)
119+
end
120+
121+
@inline function calcHSCpdless(nasavec::NASAvec,T::Float64)
122+
poly = selectPoly(nasavec,T)
123+
return calcHSCpdless(poly,T)
124+
end

0 commit comments

Comments
 (0)