File indexing completed on 2025-01-18 09:58:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #ifndef G4DNASMOLUCHOWSKIDIFFUSION_HH_
0034 #define G4DNASMOLUCHOWSKIDIFFUSION_HH_
0035
0036
0037 #include <cstdlib>
0038 #include <cmath>
0039 #include <vector>
0040 #include <iostream>
0041 #include <algorithm>
0042
0043
0044
0045 #ifdef DNADEV_TEST
0046 #include <TF1.h>
0047 #endif
0048
0049 #include <cassert>
0050
0051 #ifndef DNADEV_TEST
0052 #include "globals.hh"
0053 #include "Randomize.hh"
0054 #endif
0055
0056 #ifdef DNADEV_TEST
0057 #include "TRandom.h"
0058 TRandom root_random;
0059 double G4UniformRand()
0060 {
0061 return root_random.Rndm();
0062 }
0063
0064 #define G4cout std::cout
0065 #define G4endl std::endl
0066 #endif
0067
0068 #include "G4Exp.hh"
0069
0070 class G4DNASmoluchowskiDiffusion
0071 {
0072 public:
0073 G4DNASmoluchowskiDiffusion(double epsilon = 1e-5);
0074 virtual ~G4DNASmoluchowskiDiffusion();
0075
0076 static double ComputeS(double r, double D, double t)
0077 {
0078 double sTransform = r / (2. * std::sqrt(D * t));
0079 return sTransform;
0080 }
0081
0082 static double ComputeDistance(double sTransform, double D, double t)
0083 {
0084 return sTransform * 2. * std::sqrt(D * t);
0085 }
0086
0087 static double ComputeTime(double sTransform, double D, double r)
0088 {
0089 return std::pow(r / sTransform, 2.) / (4. * D);
0090 }
0091
0092
0093
0094 double GetRandomDistance(double _time, double D)
0095 {
0096 double proba = G4UniformRand();
0097
0098 double sTransform = GetInverseProbability(proba);
0099
0100 return ComputeDistance(sTransform, D, _time);
0101 }
0102
0103 double GetRandomTime(double distance, double D)
0104 {
0105 double proba = G4UniformRand();
0106 double sTransform = GetInverseProbability(proba);
0107 return ComputeTime(sTransform, D, distance);
0108 }
0109
0110 double EstimateCrossingTime(double proba,
0111 double distance,
0112 double D)
0113 {
0114 double sTransform = GetInverseProbability(proba);
0115 return ComputeTime(sTransform, D, distance);
0116 }
0117
0118
0119
0120
0121
0122
0123 static double GetDifferential(double sTransform)
0124 {
0125 static double constant = -4./std::sqrt(3.141592653589793);
0126 return sTransform*sTransform*G4Exp(-sTransform*sTransform)*constant;
0127 }
0128
0129 static double GetDensityProbability(double r, double _time, double D)
0130 {
0131 static double my_pi = 3.141592653589793;
0132 static double constant = 4.*my_pi/std::pow(4.*my_pi, 1.5);
0133 return r*r/std::pow(D * _time,1.5)*G4Exp(-r*r/(4. * D * _time))*constant;
0134 }
0135
0136
0137
0138 struct BoundingBox
0139 {
0140 double fXmax;
0141 double fXmin;
0142 double fXmaxDef;
0143 double fXminDef;
0144 double fToleranceY;
0145 double fSum{0};
0146 double fIncreasingCumulativeFunction;
0147
0148 enum PreviousAction
0149 {
0150 IncreaseProba,
0151 DecreaseProba,
0152 Undefined
0153 };
0154
0155 PreviousAction fPreviousAction;
0156
0157 BoundingBox(double xmin,
0158 double xmax,
0159 double toleranceY) :
0160 fXmax(xmax), fXmin(xmin),
0161 fToleranceY(toleranceY)
0162 {
0163 if(fXmax < fXmin)
0164 {
0165 double tmp = fXmin;
0166 fXmin = fXmax;
0167 fXmax = tmp;
0168 }
0169
0170 fXminDef = fXmin;
0171 fXmaxDef = fXmax;
0172 fPreviousAction = BoundingBox::Undefined;
0173 fIncreasingCumulativeFunction = (GetCumulativeProbability(fXmax) - GetCumulativeProbability(fXmin))/(fXmax-fXmin);
0174 }
0175
0176 void Print()
0177 {
0178 G4cout << "fXmin: " << fXmin << " | fXmax: " << fXmax << G4endl;
0179 }
0180
0181 bool Propose(double proposedXValue,
0182 double proposedProba,
0183 double nextProba,
0184 double& returnedValue)
0185 {
0186
0187
0188
0189
0190
0191
0192
0193
0194 bool returnFlag = false;
0195
0196 if(proposedProba < nextProba-fToleranceY)
0197 {
0198
0199
0200 if(fIncreasingCumulativeFunction > 0)
0201 {
0202 if(proposedXValue > fXmin)
0203 fXmin = proposedXValue;
0204 }
0205 else if(fIncreasingCumulativeFunction < 0)
0206 {
0207 if(proposedXValue < fXmax)
0208 fXmax = proposedXValue;
0209 }
0210
0211 returnedValue = (fXmax + fXmin)/2;
0212 returnFlag = false;
0213 fPreviousAction = BoundingBox::IncreaseProba;
0214 }
0215 else if(proposedProba > nextProba+fToleranceY)
0216 {
0217
0218
0219 if(fIncreasingCumulativeFunction>0)
0220 {
0221 if(proposedXValue < fXmax)
0222 fXmax = proposedXValue;
0223 }
0224 else if(fIncreasingCumulativeFunction<0)
0225 {
0226 if(proposedXValue > fXmin)
0227 {
0228 fXmin = proposedXValue;
0229 }
0230 }
0231
0232 returnedValue = (fXmax + fXmin)/2;
0233 returnFlag = false;
0234 fPreviousAction = BoundingBox::DecreaseProba;
0235 }
0236 else
0237 {
0238
0239 fSum = proposedProba;
0240
0241
0242 if(fIncreasingCumulativeFunction<0)
0243 {
0244 fXmin = fXminDef;
0245 fXmax = proposedXValue;
0246 }
0247 else if(fIncreasingCumulativeFunction>0)
0248 {
0249 fXmin = proposedXValue;
0250 fXmax = fXmaxDef;
0251 }
0252 returnFlag = true;
0253 fPreviousAction = BoundingBox::Undefined;
0254 }
0255
0256 return returnFlag;
0257 }
0258 };
0259
0260
0261
0262 void PrepareReverseTable(double xmin, double xmax)
0263 {
0264 double x = xmax;
0265 int index = 0;
0266 double nextProba = fEpsilon;
0267 double proposedX;
0268
0269 BoundingBox boundingBox(xmin, xmax, fEpsilon*1e-5);
0270
0271 while(index <= fNbins)
0272
0273
0274 {
0275 nextProba = fEpsilon*index;
0276
0277 double newProba = GetCumulativeProbability(x);
0278
0279 if(boundingBox.Propose(x, newProba, nextProba, proposedX))
0280 {
0281 fInverse[index] = x;
0282 index++;
0283 }
0284 else
0285 {
0286 if(x == proposedX)
0287 {
0288 G4cout << "BREAK : x= " << x << G4endl;
0289 G4cout << "index= " << index << G4endl;
0290 G4cout << "nextProba= " << nextProba << G4endl;
0291 G4cout << "newProba= " << newProba << G4endl;
0292 abort();
0293 }
0294 x = proposedX;
0295 }
0296 }
0297
0298 fInverse[fNbins+1] = 0;
0299
0300
0301 }
0302
0303 static double GetCumulativeProbability(double sTransform)
0304 {
0305 static double constant = 2./std::sqrt(3.141592653589793);
0306 return erfc(sTransform) + constant*sTransform*G4Exp(-sTransform*sTransform);
0307 }
0308
0309 double GetInverseProbability(double proba)
0310 {
0311 auto index_low = (size_t) trunc(proba/fEpsilon);
0312
0313 if(index_low == 0)
0314 {
0315 index_low = 1;
0316 size_t index_up = 2;
0317 double low_y = fInverse[index_low];
0318 double up_y = fInverse[index_up];
0319 double low_x = index_low*fEpsilon;
0320 double up_x = proba+fEpsilon;
0321 double tangente = (low_y-up_y)/(low_x - up_x);
0322
0323 return low_y + tangente*(proba-low_x);
0324 }
0325
0326 size_t index_up = index_low+1;
0327 if(index_low > fInverse.size()) return fInverse.back();
0328 double low_y = fInverse[index_low];
0329 double up_y = fInverse[index_up];
0330
0331 double low_x = index_low*fEpsilon;
0332 double up_x = low_x+fEpsilon;
0333
0334 if(up_x > 1)
0335 {
0336 up_x = 1;
0337 up_y = 0;
0338 }
0339
0340 double tangente = (low_y-up_y)/(low_x - up_x);
0341
0342 return low_y + tangente*(proba-low_x);
0343 }
0344
0345 double PlotInverse(double* x, double* )
0346 {
0347 return GetInverseProbability(x[0]);
0348 }
0349
0350 double Plot(double* x, double* )
0351 {
0352 return GetDifferential(x[0]);
0353 }
0354
0355
0356 void InitialiseInverseProbability(double xmax = 3e28)
0357 {
0358
0359
0360
0361
0362
0363
0364
0365 assert(fNbins !=0);
0366 PrepareReverseTable(0,xmax);
0367 }
0368
0369 std::vector<double> fInverse;
0370 int fNbins;
0371 double fEpsilon;
0372 };
0373
0374 #endif