@@ -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 
388412end 
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 
445481end 
446482
447483export  processfluxes
499535
500536export  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""" 
503607determine 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 
0 commit comments