139 auto it_begin = fTrackHolder->GetMainList()->begin();
140 while(it_begin != fTrackHolder->GetMainList()->end()){
155 fNx =
G4int((fXMax-fXMin)/fRCutOff) == 0 ? 1 :
G4int((fXMax-fXMin)/fRCutOff);
156 fNy =
G4int((fYMax-fYMin)/fRCutOff) == 0 ? 1 :
G4int((fYMax-fYMin)/fRCutOff);
157 fNz =
G4int((fZMax-fZMin)/fRCutOff) == 0 ? 1 :
G4int((fZMax-fZMin)/fRCutOff);
163 auto it_begin = fTrackHolder->GetMainList()->begin();
164 while(it_begin != fTrackHolder->GetMainList()->end()){
165 G4int I =
FindBin(fNx, fXMin, fXMax, it_begin->GetPosition().x());
166 G4int J =
FindBin(fNy, fYMin, fYMax, it_begin->GetPosition().y());
167 G4int K =
FindBin(fNz, fZMin, fZMax, it_begin->GetPosition().z());
169 spaceBinned[I][J][K].push_back(*it_begin);
181 const vector<const G4MolecularConfiguration*>* reactivesVector =
184 if(reactivesVector ==
nullptr)
return;
196 for (
int ii = xiniIndex; ii <= xendIndex; ii++ ) {
197 for (
int jj = yiniIndex; jj <= yendIndex; jj++ ) {
198 for (
int kk = ziniIndex; kk <= zendIndex; kk++ ) {
200 std::vector<G4Track*> spaceBin = spaceBinned[ii][jj][kk];
201 for (
int n = 0; n < (int)spaceBinned[ii][jj][kk].size(); n++ ) {
202 if((spaceBin[n] ==
nullptr) || track == spaceBin[n])
continue;
206 if(molB ==
nullptr)
continue;
211 auto it = std::find(reactivesVector->begin(), reactivesVector->end(), molConfB);
212 if(it == reactivesVector->end())
continue;
222 sigma = std::sqrt(2.0 * diffusionCoefficient * dt);
224 x = G4RandGauss::shoot(0., 1.0)*sigma;
225 y = G4RandGauss::shoot(0., 1.0)*sigma;
226 z = G4RandGauss::shoot(0., 1.0)*sigma;
229 }
else if(dt < 0)
continue;
235 if(irt>=0 && irt<timeMax - globalTime)
238 if(irt < minTime) minTime = irt;
242 fReactionSet->AddReaction(irt,track,spaceBin[n]);
261 for(
size_t u=0; u<fReactionDatas->size();u++){
262 if((*fReactionDatas)[u]->GetReactant2()->GetDiffusionCoefficient() == 0){
263 G4double kObs = (*fReactionDatas)[u]->GetObservedReactionRateConstant();
264 if(kObs == 0)
continue;
266 if( time < minTime && time >= globalTime && time < timeMax){
275 G4cout<<
"scavenged: "<<minTime<<
'\t'<<molConfA->
GetName()<<it_begin->GetTrackID()<<
'\n';
277 auto fakeMol =
new G4Molecule((*fReactionDatas)[index]->GetReactant2());
279 fTrackHolder->Push(fakeTrack);
280 fReactionSet->AddReaction(minTime, track, fakeTrack);
286 const auto pMoleculeA = molA;
287 const auto pMoleculeB = molB;
289 G4int reactionType = fReactionData->GetReactionType();
291 if(r0 == 0) r0 += 1e-3*nm;
295 if(
D == 0)
D += 1e-20*(m2/s);
296 G4double rc = fReactionData->GetOnsagerRadius();
298 if ( reactionType == 0){
299 G4double sigma = fReactionData->GetEffectiveReactionRadius();
301 if(sigma > r0)
return 0;
302 if( rc != 0) r0 = -rc / (1-std::exp(rc/r0));
307 if (
W > 0 &&
W < Winf ) irt = (0.25/
D) * std::pow( (r0-sigma)/erfc->erfcInv(r0*
W/sigma), 2 );
311 if ( reactionType == 1 ){
312 G4double sigma = fReactionData->GetReactionRadius();
313 G4double kact = fReactionData->GetActivationRateConstant();
314 G4double kdif = fReactionData->GetDiffusionRateConstant();
315 G4double kobs = fReactionData->GetObservedReactionRateConstant();
320 a = 1/sigma * kact / kobs;
321 b = (r0 - sigma) / 2;
323 G4double v = kact/Avogadro/(4*CLHEP::pi*pow(sigma,2) * exp(-rc / sigma));
324 G4double alpha = v+rc*
D/(pow(sigma,2)*(1-exp(-rc/sigma)));
325 a = 4*pow(sigma,2)*alpha/(
D*pow(rc,2))*pow(sinh(rc/(2*sigma)),2);
326 b = rc/4*(cosh(rc/(2*r0))/sinh(rc/(2*r0))-cosh(rc/(2*sigma))/sinh(rc/(2*sigma)));
327 r0 = -rc/(1-std::exp(rc/r0));
328 sigma = fReactionData->GetEffectiveReactionRadius();
332 if(fReactionData->GetProbability() >
G4UniformRand())
return 0;
335 Winf = sigma / r0 * kobs / kdif;
398 pChanges->Initialize(trackA, trackB);
402 const auto pReactionData =
fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
408 G4double effectiveReactionRadius = pReactionData->GetEffectiveReactionRadius();
410 const G4double D1 = pMoleculeA->GetDiffusionCoefficient();
411 const G4double D2 = pMoleculeB->GetDiffusionCoefficient();
422 S1.
setMag(effectiveReactionRadius);
426 if(dt != 0 && (D1 + D2) != 0 && r0 != 0){
429 if(s12 == 0) r2 = r1;
430 else if(s22 == 0) r1 = r2;
432 G4double alpha = effectiveReactionRadius * r0 / (2*(D1 + D2)*dt);
434 G4RandGauss::shoot(0, s12 + s22 * s22 / s12),
435 G4RandGauss::shoot(0, s12 + s22 * s22 / s12));
441 S1.
setTheta(rad * std::acos(1.0 + 1./alpha * std::log(1.0 -
G4UniformRand() * (1 - std::exp(-2.0 * alpha)))));
443 r1 = (D1 * S1 + D2 * S2) / (D1 + D2);
444 r2 = D2 * (S2 - S1) / (D1 + D2);
448 auto pTrackA =
const_cast<G4Track*
>(pChanges->GetTrackA());
449 auto pTrackB =
const_cast<G4Track*
>(pChanges->GetTrackB());
452 pTrackB->SetPosition(r2);
454 pTrackA->SetGlobalTime(globalTime);
455 pTrackB->SetGlobalTime(globalTime);
460 const G4int nbProducts = pReactionData->GetNbProducts();
464 const G4double sqrD1 = D1 == 0. ? 0. : std::sqrt(D1);
465 const G4double sqrD2 = D2 == 0. ? 0. : std::sqrt(D2);
466 if((sqrD1 + sqrD2) == 0){
469 const G4double inv_numerator = 1./(sqrD1 + sqrD2);
473 std::vector<G4ThreeVector>
position;
477 }
else if(nbProducts == 2){
480 }
else if (nbProducts == 3){
486 for(
G4int u = 0; u < nbProducts; u++){
488 auto product =
new G4Molecule(pReactionData->GetProduct(u));
489 auto productTrack = product->BuildTrack(globalTime,
492 productTrack->SetTrackStatus(
fAlive);
493 fTrackHolder->Push(productTrack);
495 pChanges->AddSecondary(productTrack);
501 spaceBinned[I][J][K].push_back(productTrack);
507 fTrackHolder->MergeSecondariesWithMainList();
508 pChanges->KillParents(
true);
519 std::vector<std::unique_ptr<G4ITReactionChange>> fReactionInfo;
520 fReactionInfo.clear();
522 if (pReactionSet ==
nullptr)
524 return fReactionInfo;
528 assert(fReactionsetInTime.begin() != fReactionsetInTime.end());
530 auto it_begin = fReactionsetInTime.begin();
531 while(it_begin != fReactionsetInTime.end())
533 G4double irt = it_begin->get()->GetTime();
535 if(fGlobalTime < irt)
break;
539 G4Track* pTrackA = it_begin->get()->GetReactants().first;
540 G4Track* pTrackB = it_begin->get()->GetReactants().second;
541 auto pReactionChange =
MakeReaction(*pTrackA, *pTrackB);
544 fReactionInfo.push_back(std::move(pReactionChange));
548 it_begin = fReactionsetInTime.begin();
551 return fReactionInfo;