Skip to content

Commit 63ddc79

Browse files
authored
Merge pull request #203 from ReactionMechanismGenerator/deadend_radical
Deadend radical algorithm RMG-RMS twin PR
2 parents b47c822 + df1224e commit 63ddc79

File tree

2 files changed

+151
-7
lines changed

2 files changed

+151
-7
lines changed

src/EdgeAnalysis.jl

Lines changed: 150 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,10 @@ function processfluxes(sim::SystemSimulation,
330330
corespeciesconcentrations = cs[corespcsinds]
331331
corespeciesconsumptionrates = zeros(length(corespeciesconcentrations))
332332
corespeciesproductionrates = zeros(length(corespeciesconcentrations))
333+
# record the net consumption rates for core adicals, defined as sum_rxn max(L_rxn-P_rxn,0.0)
334+
corespeciesnetconsumptionrates = zeros(length(corespeciesconcentrations))
335+
# record the net termination rates for core radicals, defined as sum_rxn max(L_rxn-P_rxn,0.0) * min(radicalchange_rxn,0.0)
336+
coreradicalnetterminationrates = zeros(length(corespeciesconcentrations))
333337

334338
#process core species consumption and production rates
335339
index = 1
@@ -338,18 +342,28 @@ function processfluxes(sim::SystemSimulation,
338342
if @inbounds any(d.rxnarray[:,i].>length(corespeciesconcentrations))
339343
continue
340344
end
345+
net_forward_rate = max(frts[i+index]-rrts[i+index], 0.0)
341346
for j = 1:4
342347
if @inbounds d.rxnarray[j,i] != 0
343348
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += frts[i+index]
344349
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += rrts[i+index]
350+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_forward_rate
351+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
352+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_forward_rate * abs(min(d.phase.reactions[i].radicalchange, 0.0))
353+
end
345354
else
346355
break
347356
end
348357
end
358+
net_reverse_rate = max(rrts[i+index]-frts[i+index], 0.0)
349359
for j = 5:8
350360
if @inbounds d.rxnarray[j,i] != 0
351361
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += frts[i+index]
352362
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += rrts[i+index]
363+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_reverse_rate
364+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
365+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_reverse_rate * abs(min(-d.phase.reactions[i].radicalchange, 0.0))
366+
end
353367
else
354368
break
355369
end
@@ -363,18 +377,28 @@ function processfluxes(sim::SystemSimulation,
363377
if @inbounds any(d.rxnarray[:,i].>length(corespeciesconcentrations))
364378
continue
365379
end
380+
net_forward_rate = max(frts[i+index]-rrts[i+index], 0.0)
366381
for j = 1:4
367382
if @inbounds d.rxnarray[j,i] != 0
368383
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += frts[i+index]
369384
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += rrts[i+index]
385+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_forward_rate
386+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
387+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_forward_rate * abs(min(d.phase.reactions[i].radicalchange, 0.0))
388+
end
370389
else
371390
break
372391
end
373392
end
393+
net_reverse_rate = max(rrts[i+index]-frts[i+index], 0.0)
374394
for j = 5:8
375395
if @inbounds d.rxnarray[j,i] != 0
376396
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += frts[i+index]
377397
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += rrts[i+index]
398+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_reverse_rate
399+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
400+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_reverse_rate * abs(min(-d.phase.reactions[i].radicalchange, 0.0))
401+
end
378402
else
379403
break
380404
end
@@ -384,7 +408,7 @@ function processfluxes(sim::SystemSimulation,
384408
end
385409
end
386410

387-
return dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,corereactionrates,corespeciesconcentrations,corespeciesproductionrates,corespeciesconsumptionrates
411+
return dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,corereactionrates,corespeciesconcentrations,corespeciesproductionrates,corespeciesconsumptionrates,corespeciesnetconsumptionrates,coreradicalnetterminationrates
388412
end
389413

390414
"""
@@ -416,32 +440,44 @@ function processfluxes(sim::Simulation,corespcsinds,corerxninds,edgespcsinds,edg
416440
@inbounds corespeciesconcentrations = cs[corespcsinds]
417441
corespeciesconsumptionrates = zeros(length(corespeciesconcentrations))
418442
corespeciesproductionrates = zeros(length(corespeciesconcentrations))
443+
corespeciesnetconsumptionrates = zeros(length(corespeciesconcentrations))
444+
coreradicalnetterminationrates = zeros(length(corespeciesconcentrations))
419445

420446
#process core species consumption and production rates
421447
d = sim.domain
422448
@inbounds for i = 1:size(d.rxnarray)[2]
423449
if @inbounds any(d.rxnarray[:,i].>length(corespeciesconcentrations))
424450
continue
425451
end
452+
net_forward_rate = max(frts[i]-rrts[i], 0.0)
426453
for j = 1:4
427454
if @inbounds d.rxnarray[j,i] != 0
428455
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += frts[i]
429456
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += rrts[i]
457+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_forward_rate
458+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
459+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_forward_rate * abs(min(d.phase.reactions[i].radicalchange, 0.0))
460+
end
430461
else
431462
break
432463
end
433464
end
465+
net_reverse_rate = max(rrts[i]-frts[i], 0.0)
434466
for j = 5:8
435467
if @inbounds d.rxnarray[j,i] != 0
436468
@inbounds corespeciesproductionrates[d.rxnarray[j,i]] += frts[i]
437469
@inbounds corespeciesconsumptionrates[d.rxnarray[j,i]] += rrts[i]
470+
corespeciesnetconsumptionrates[d.rxnarray[j,i]] += net_reverse_rate
471+
if d.phase.species[d.rxnarray[j,i]].radicalelectrons == 1
472+
coreradicalnetterminationrates[d.rxnarray[j,i]] += net_reverse_rate * abs(min(-d.phase.reactions[i].radicalchange, 0.0))
473+
end
438474
else
439475
break
440476
end
441477
end
442478
end
443479

444-
return dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,corereactionrates,corespeciesconcentrations,corespeciesproductionrates,corespeciesconsumptionrates
480+
return dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,corereactionrates,corespeciesconcentrations,corespeciesproductionrates,corespeciesconsumptionrates,corespeciesnetconsumptionrates,coreradicalnetterminationrates
445481
end
446482

447483
export processfluxes
@@ -499,6 +535,74 @@ end
499535

500536
export calcbranchingnumbers
501537

538+
"""
539+
Calculate the ratio of net consumption/termination of core radicals contributed by each edge reaction compared to all core reactions
540+
"""
541+
function calcradconstermratios(sim,reactantinds,productinds,corespcsinds,corerxninds,edgerxninds,edgereactionrates,corespeciesnetconsumptionrates,coreradicalnetterminationrates)
542+
radconstermratios = zeros(length(edgereactionrates))
543+
for ind in 1:length(edgereactionrates)
544+
chain_termination = false
545+
chain_transfer = false
546+
547+
index = edgerxninds[ind]
548+
reactionrate = edgereactionrates[ind]
549+
550+
if reactionrate > 0
551+
reactantside = reactantinds[:,index]
552+
productside = productinds[:,index]
553+
else
554+
reactantside = productinds[:,index]
555+
productside = reactantinds[:,index]
556+
end
557+
558+
productrade = [sim.species[i].radicalelectrons for i in productside if i != 0]
559+
reactantrade = [sim.species[i].radicalelectrons for i in reactantside if i != 0]
560+
561+
if length(productrade) == 1 && length(reactantrade) == 2
562+
if productrade[1] == 0 && reactantrade[1] == 1 && reactantrade[2] == 1
563+
chain_termination = true
564+
end
565+
elseif length(reactantrade) == length(productrade) && length(productrade) == 2
566+
if (0 in reactantrade && 1 in reactantrade) && (0 in productrade && 1 in productrade)
567+
chain_transfer = true
568+
end
569+
end
570+
571+
if !(chain_transfer || chain_termination)
572+
continue
573+
end
574+
575+
for spcindex in reactantside
576+
if spcindex == 0
577+
continue
578+
elseif spcindex in corespcsinds
579+
if sim.species[spcindex].radicalelectrons != 1
580+
continue
581+
end
582+
583+
if chain_transfer
584+
consumption = corespeciesnetconsumptionrates[spcindex]
585+
consumption = max(consumption, 1e-40) # avoid divide by zeros
586+
radconstermratio = abs(reactionrate) / consumption
587+
end
588+
589+
if chain_termination
590+
termination = coreradicalnetterminationrates[spcindex]
591+
termination = max(termination, 1e-40) # avoid divide by zeros
592+
radconstermratio = abs(reactionrate) / termination
593+
end
594+
595+
if radconstermratio > radconstermratios[ind]
596+
radconstermratios[ind] = radconstermratio
597+
end
598+
end
599+
end
600+
end
601+
return radconstermratios
602+
end
603+
604+
export calcradconstermratios
605+
502606
"""
503607
determine species pairings that are concentrated enough that they should be reacted
504608
"""
@@ -551,7 +655,7 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
551655
trimolecularthreshold,maxedgespeciesrateratios,tolmovetocore,tolradmovetocore,tolinterruptsimulation,
552656
ignoreoverallfluxcriterion,filterreactions,maxnumobjsperiter,branchfactor,branchingratiomax,
553657
branchingindex,terminateatmaxobjects,termination,y0,invalidobjects,firsttime,
554-
filterthreshold,transitorydict,checktransitory)
658+
filterthreshold,transitorydict,checktransitory,deadendradicaltolerance)
555659

556660
rxnarray = vcat()
557661
t = sim.sol.t[end]
@@ -566,7 +670,8 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
566670
(dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,
567671
edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,
568672
corereactionrates,corespeciesconcentrations,
569-
corespeciesproductionrates,corespeciesconsumptionrates) = processfluxes(sim,corespcsinds,corerxninds,edgespcsinds,edgerxninds)
673+
corespeciesproductionrates,corespeciesconsumptionrates,
674+
corespeciesnetconsumptionrates, coreradicalnetterminationrates) = processfluxes(sim,corespcsinds,corerxninds,edgespcsinds,edgerxninds)
570675

571676
for i = 1:length(edgespeciesrateratios)
572677
if @inbounds edgespeciesrateratios[i] > maxedgespeciesrateratios[i]
@@ -584,6 +689,10 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
584689
return (false,true,0.0)
585690
end
586691

692+
if deadendradicaltolerance != 0.0 && !firsttime
693+
radconstermratios = calcradconstermratios(sim,reactantinds,productinds,corespcsinds,corerxninds,edgerxninds,edgereactionrates,corespeciesnetconsumptionrates,coreradicalnetterminationrates)
694+
end
695+
587696
if branchfactor != 0.0 && !firsttime
588697
branchingnums = calcbranchingnumbers(sim,reactantinds,productinds,corespcsinds,corerxninds,edgerxninds,edgereactionrates,
589698
corespeciesrateratios,corespeciesconsumptionrates,branchfactor,branchingratiomax,branchingindex)
@@ -666,6 +775,38 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
666775
tempnewobjecttype = []
667776
end
668777

778+
# dead-end radical species selection algorithm should be evaluated before branching algorithm as
779+
# branching algorithm tends to pick up propagation reactions first, and if these propagation reactions are added
780+
# into the core for many iterations in a row, it can create dead-end radicals
781+
if deadendradicaltolerance != 0.0 && !firsttime
782+
for (i,ind) in enumerate(edgerxninds)
783+
drr = radconstermratios[i]
784+
if drr > deadendradicaltolerance
785+
obj = sim.reactions[ind]
786+
if !(obj in newobjects || obj in invalidobjects)
787+
push!(tempnewobjects,obj)
788+
push!(tempnewobjectinds,ind)
789+
push!(tempnewobjectvals,drr)
790+
push!(tempnewobjecttype,"deadendradical")
791+
end
792+
end
793+
end
794+
795+
sortedinds = reverse(sortperm(tempnewobjectvals))
796+
797+
for q in sortedinds
798+
push!(newobjects,tempnewobjects[q])
799+
push!(newobjectinds,tempnewobjectinds[q])
800+
push!(newobjectvals,tempnewobjectvals[q])
801+
push!(newobjecttype,tempnewobjecttype[q])
802+
end
803+
804+
tempnewobjects = []
805+
tempnewobjectinds = Array{Int64,1}()
806+
tempnewobjectvals = Array{Float64,1}()
807+
tempnewobjecttype = []
808+
end
809+
669810
if !ignoreoverallfluxcriterion #radical rate ratios
670811
for (i,ind) in enumerate(edgerxninds)
671812
rr = edgerxnradrateratios[i]
@@ -797,6 +938,9 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
797938
@inbounds spcname = transitoryoutdict[ind]
798939
@inbounds tol = transitorydict[spcname]
799940
@info "at time $t sec, reaction $rstr at a normalized transitory sensitivity from $spcname of $sens exceeded the threshold of $tol for moving to model core"
941+
elseif newobjecttype[i] == "deadendradical"
942+
tol = deadendradicaltolerance
943+
@info "at time $t sec, reaction $rstr at a net radical consumption/termination ratio of $val exceeded the threshold of $tol for moving to model core"
800944
end
801945
end
802946
end
@@ -831,7 +975,7 @@ function selectobjects(react,edgereact,coreedgedomains,coreedgeinters,domains,in
831975
corep,coreedgep,tolmovetocore,tolradmovetocore,tolinterruptsimulation,ignoreoverallfluxcriterion,filterreactions,
832976
maxnumobjsperiter,tolbranchrxntocore,branchingratiomax,
833977
branchingindex,terminateatmaxobjects,termination,
834-
filterthreshold,transitorydict,transitorystepperiod;
978+
filterthreshold,transitorydict,transitorystepperiod,deadendradicaltolerance;
835979
atol=1e-20,rtol=1e-6,solver=CVODE_BDF())
836980

837981
(corespcsinds,corerxninds,edgespcsinds,edgerxninds,reactantindices,
@@ -876,7 +1020,7 @@ function selectobjects(react,edgereact,coreedgedomains,coreedgeinters,domains,in
8761020
tolinterruptsimulation,ignoreoverallfluxcriterion,filterreactions,
8771021
maxnumobjsperiter,branchfactor,branchingratiomax,
8781022
branchingindex,terminateatmaxobjects,termination,y0,invalidobjects,firsttime,
879-
filterthreshold,transitorydict,checktransitory)
1023+
filterthreshold,transitorydict,checktransitory,deadendradicaltolerance)
8801024
if firsttime
8811025
firsttime = false
8821026
end

src/TestEdgeAnalysis.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ using Sundials
5555
reactedge = Reactor(coreedgedomain,coreedgey0,(0.0,1e6);p=coreedgep);
5656
(terminated,resurrected,invalidobjects,unimolecularthreshold,bimolecularthreshold,
5757
trimolecularthreshold,maxedgespeciesrateratios) = selectobjects(react,reactedge,coreedgedomain,[],coredomain,
58-
[],corep,coreedgep,0.03,Inf,0.03,false,true,5,0.005,1.0,1.0,true,termination,1.0e8,Dict(),20)
58+
[],corep,coreedgep,0.03,Inf,0.03,false,true,5,0.005,1.0,1.0,true,termination,1.0e8,Dict(),20,Inf)
5959
@test terminated == false
6060
@test invalidobjects[1].name == "[CH2]CCC"
6161
@test unimolecularthreshold[5] == true

0 commit comments

Comments
 (0)