@@ -330,6 +330,10 @@ function processfluxes(sim::SystemSimulation,
330
330
corespeciesconcentrations = cs[corespcsinds]
331
331
corespeciesconsumptionrates = zeros (length (corespeciesconcentrations))
332
332
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))
333
337
334
338
# process core species consumption and production rates
335
339
index = 1
@@ -338,18 +342,28 @@ function processfluxes(sim::SystemSimulation,
338
342
if @inbounds any (d. rxnarray[:,i]. > length (corespeciesconcentrations))
339
343
continue
340
344
end
345
+ net_forward_rate = max (frts[i+ index]- rrts[i+ index], 0.0 )
341
346
for j = 1 : 4
342
347
if @inbounds d. rxnarray[j,i] != 0
343
348
@inbounds corespeciesconsumptionrates[d. rxnarray[j,i]] += frts[i+ index]
344
349
@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
345
354
else
346
355
break
347
356
end
348
357
end
358
+ net_reverse_rate = max (rrts[i+ index]- frts[i+ index], 0.0 )
349
359
for j = 5 : 8
350
360
if @inbounds d. rxnarray[j,i] != 0
351
361
@inbounds corespeciesproductionrates[d. rxnarray[j,i]] += frts[i+ index]
352
362
@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
353
367
else
354
368
break
355
369
end
@@ -363,18 +377,28 @@ function processfluxes(sim::SystemSimulation,
363
377
if @inbounds any (d. rxnarray[:,i]. > length (corespeciesconcentrations))
364
378
continue
365
379
end
380
+ net_forward_rate = max (frts[i+ index]- rrts[i+ index], 0.0 )
366
381
for j = 1 : 4
367
382
if @inbounds d. rxnarray[j,i] != 0
368
383
@inbounds corespeciesconsumptionrates[d. rxnarray[j,i]] += frts[i+ index]
369
384
@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
370
389
else
371
390
break
372
391
end
373
392
end
393
+ net_reverse_rate = max (rrts[i+ index]- frts[i+ index], 0.0 )
374
394
for j = 5 : 8
375
395
if @inbounds d. rxnarray[j,i] != 0
376
396
@inbounds corespeciesproductionrates[d. rxnarray[j,i]] += frts[i+ index]
377
397
@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
378
402
else
379
403
break
380
404
end
@@ -384,7 +408,7 @@ function processfluxes(sim::SystemSimulation,
384
408
end
385
409
end
386
410
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
388
412
end
389
413
390
414
"""
@@ -416,32 +440,44 @@ function processfluxes(sim::Simulation,corespcsinds,corerxninds,edgespcsinds,edg
416
440
@inbounds corespeciesconcentrations = cs[corespcsinds]
417
441
corespeciesconsumptionrates = zeros (length (corespeciesconcentrations))
418
442
corespeciesproductionrates = zeros (length (corespeciesconcentrations))
443
+ corespeciesnetconsumptionrates = zeros (length (corespeciesconcentrations))
444
+ coreradicalnetterminationrates = zeros (length (corespeciesconcentrations))
419
445
420
446
# process core species consumption and production rates
421
447
d = sim. domain
422
448
@inbounds for i = 1 : size (d. rxnarray)[2 ]
423
449
if @inbounds any (d. rxnarray[:,i]. > length (corespeciesconcentrations))
424
450
continue
425
451
end
452
+ net_forward_rate = max (frts[i]- rrts[i], 0.0 )
426
453
for j = 1 : 4
427
454
if @inbounds d. rxnarray[j,i] != 0
428
455
@inbounds corespeciesconsumptionrates[d. rxnarray[j,i]] += frts[i]
429
456
@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
430
461
else
431
462
break
432
463
end
433
464
end
465
+ net_reverse_rate = max (rrts[i]- frts[i], 0.0 )
434
466
for j = 5 : 8
435
467
if @inbounds d. rxnarray[j,i] != 0
436
468
@inbounds corespeciesproductionrates[d. rxnarray[j,i]] += frts[i]
437
469
@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
438
474
else
439
475
break
440
476
end
441
477
end
442
478
end
443
479
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
445
481
end
446
482
447
483
export processfluxes
499
535
500
536
export calcbranchingnumbers
501
537
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
+
502
606
"""
503
607
determine species pairings that are concentrated enough that they should be reacted
504
608
"""
@@ -551,7 +655,7 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
551
655
trimolecularthreshold,maxedgespeciesrateratios,tolmovetocore,tolradmovetocore,tolinterruptsimulation,
552
656
ignoreoverallfluxcriterion,filterreactions,maxnumobjsperiter,branchfactor,branchingratiomax,
553
657
branchingindex,terminateatmaxobjects,termination,y0,invalidobjects,firsttime,
554
- filterthreshold,transitorydict,checktransitory)
658
+ filterthreshold,transitorydict,checktransitory,deadendradicaltolerance )
555
659
556
660
rxnarray = vcat ()
557
661
t = sim. sol. t[end ]
@@ -566,7 +670,8 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
566
670
(dydt,rts,frts,rrts,cs,corespeciesrates,charrate,edgespeciesrates,
567
671
edgereactionrates,edgerxnradrateratios,corespeciesrateratios,edgespeciesrateratios,
568
672
corereactionrates,corespeciesconcentrations,
569
- corespeciesproductionrates,corespeciesconsumptionrates) = processfluxes (sim,corespcsinds,corerxninds,edgespcsinds,edgerxninds)
673
+ corespeciesproductionrates,corespeciesconsumptionrates,
674
+ corespeciesnetconsumptionrates, coreradicalnetterminationrates) = processfluxes (sim,corespcsinds,corerxninds,edgespcsinds,edgerxninds)
570
675
571
676
for i = 1 : length (edgespeciesrateratios)
572
677
if @inbounds edgespeciesrateratios[i] > maxedgespeciesrateratios[i]
@@ -584,6 +689,10 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
584
689
return (false ,true ,0.0 )
585
690
end
586
691
692
+ if deadendradicaltolerance != 0.0 && ! firsttime
693
+ radconstermratios = calcradconstermratios (sim,reactantinds,productinds,corespcsinds,corerxninds,edgerxninds,edgereactionrates,corespeciesnetconsumptionrates,coreradicalnetterminationrates)
694
+ end
695
+
587
696
if branchfactor != 0.0 && ! firsttime
588
697
branchingnums = calcbranchingnumbers (sim,reactantinds,productinds,corespcsinds,corerxninds,edgerxninds,edgereactionrates,
589
698
corespeciesrateratios,corespeciesconsumptionrates,branchfactor,branchingratiomax,branchingindex)
@@ -666,6 +775,38 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
666
775
tempnewobjecttype = []
667
776
end
668
777
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
+
669
810
if ! ignoreoverallfluxcriterion # radical rate ratios
670
811
for (i,ind) in enumerate (edgerxninds)
671
812
rr = edgerxnradrateratios[i]
@@ -797,6 +938,9 @@ function identifyobjects!(sim,corespcsinds,corerxninds,edgespcsinds,
797
938
@inbounds spcname = transitoryoutdict[ind]
798
939
@inbounds tol = transitorydict[spcname]
799
940
@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"
800
944
end
801
945
end
802
946
end
@@ -831,7 +975,7 @@ function selectobjects(react,edgereact,coreedgedomains,coreedgeinters,domains,in
831
975
corep,coreedgep,tolmovetocore,tolradmovetocore,tolinterruptsimulation,ignoreoverallfluxcriterion,filterreactions,
832
976
maxnumobjsperiter,tolbranchrxntocore,branchingratiomax,
833
977
branchingindex,terminateatmaxobjects,termination,
834
- filterthreshold,transitorydict,transitorystepperiod;
978
+ filterthreshold,transitorydict,transitorystepperiod,deadendradicaltolerance ;
835
979
atol= 1e-20 ,rtol= 1e-6 ,solver= CVODE_BDF ())
836
980
837
981
(corespcsinds,corerxninds,edgespcsinds,edgerxninds,reactantindices,
@@ -876,7 +1020,7 @@ function selectobjects(react,edgereact,coreedgedomains,coreedgeinters,domains,in
876
1020
tolinterruptsimulation,ignoreoverallfluxcriterion,filterreactions,
877
1021
maxnumobjsperiter,branchfactor,branchingratiomax,
878
1022
branchingindex,terminateatmaxobjects,termination,y0,invalidobjects,firsttime,
879
- filterthreshold,transitorydict,checktransitory)
1023
+ filterthreshold,transitorydict,checktransitory,deadendradicaltolerance )
880
1024
if firsttime
881
1025
firsttime = false
882
1026
end
0 commit comments