File indexing completed on 2026-04-10 07:50:29
0001 #pragma once
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
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 #include "G4ThreeVector.hh"
0148 #include "Randomize.hh"
0149
0150 #include "SLOG.hh"
0151 #include "JPMT.h"
0152 #include "Layr.h"
0153 #include "U4Touchable.h"
0154
0155 #include "CustomStatus.h"
0156
0157
0158 #ifdef DEBUG_TAG
0159 #include "U4UniformRand.h"
0160 #include "SPhoton_Debug.h"
0161 template<> std::vector<SPhoton_Debug<'B'>> SPhoton_Debug<'B'>::record = {} ;
0162 #endif
0163
0164
0165
0166
0167
0168 template<typename J>
0169 struct CustomBoundary
0170 {
0171 static const constexpr plog::Severity LEVEL = debug ;
0172 static void Save(const char* fold);
0173
0174 J* parameter_accessor ;
0175 int count ;
0176 double zlocal ;
0177 double lposcost ;
0178
0179 G4ThreeVector& NewMomentum ;
0180 G4ThreeVector& NewPolarization ;
0181 G4ParticleChange& aParticleChange ;
0182 G4OpBoundaryProcessStatus& theStatus ;
0183
0184 const G4ThreeVector& theGlobalPoint ;
0185 const G4ThreeVector& OldMomentum ;
0186 const G4ThreeVector& OldPolarization ;
0187 const G4ThreeVector& theRecoveredNormal ;
0188 const G4double& thePhotonMomentum ;
0189
0190 CustomBoundary(
0191 G4ThreeVector& NewMomentum,
0192 G4ThreeVector& NewPolarization,
0193 G4ParticleChange& aParticleChange,
0194 G4OpBoundaryProcessStatus& theStatus,
0195 const G4ThreeVector& theGlobalPoint,
0196 const G4ThreeVector& OldMomentum,
0197 const G4ThreeVector& OldPolarization,
0198 const G4ThreeVector& theRecoveredNormal,
0199 const G4double& thePhotonMomentum
0200 );
0201
0202 char maybe_doIt(const char* OpticalSurfaceName, const G4Track& aTrack, const G4Step& aStep) ;
0203 char doIt(const G4Track& aTrack, const G4Step& aStep );
0204 };
0205
0206
0207 template<typename J>
0208 inline void CustomBoundary<J>::Save(const char* fold)
0209 {
0210 SPhoton_Debug<'B'>::Save(fold);
0211 }
0212
0213 template<typename J>
0214 inline CustomBoundary<J>::CustomBoundary(
0215 G4ThreeVector& NewMomentum_,
0216 G4ThreeVector& NewPolarization_,
0217 G4ParticleChange& aParticleChange_,
0218 G4OpBoundaryProcessStatus& theStatus_,
0219 const G4ThreeVector& theGlobalPoint_,
0220 const G4ThreeVector& OldMomentum_,
0221 const G4ThreeVector& OldPolarization_,
0222 const G4ThreeVector& theRecoveredNormal_,
0223 const G4double& thePhotonMomentum_
0224 )
0225 :
0226 parameter_accessor(new J),
0227 count(0),
0228 zlocal(-1.),
0229 lposcost(-2.),
0230 NewMomentum(NewMomentum_),
0231 NewPolarization(NewPolarization_),
0232 aParticleChange(aParticleChange_),
0233 theStatus(theStatus_),
0234 theGlobalPoint(theGlobalPoint_),
0235 OldMomentum(OldMomentum_),
0236 OldPolarization(OldPolarization_),
0237 theRecoveredNormal(theRecoveredNormal_),
0238 thePhotonMomentum(thePhotonMomentum_)
0239 {
0240 }
0241
0242 template<typename J>
0243 inline char CustomBoundary<J>::maybe_doIt(const char* OpticalSurfaceName, const G4Track& aTrack, const G4Step& aStep )
0244 {
0245 if( OpticalSurfaceName == nullptr || OpticalSurfaceName[0] != '@') return 'N' ;
0246
0247 const G4AffineTransform& transform = aTrack.GetTouchable()->GetHistory()->GetTopTransform();
0248 G4ThreeVector localPoint = transform.TransformPoint(theGlobalPoint);
0249 zlocal = localPoint.z() ;
0250 lposcost = localPoint.cosTheta() ;
0251
0252 if( zlocal <= 0. ) return 'Z' ;
0253
0254 char status = doIt(aTrack, aStep) ;
0255 assert( strchr("ARTD", status) != nullptr ) ;
0256
0257 return status ;
0258 }
0259
0260
0261 template<typename J>
0262 inline char CustomBoundary<J>::doIt(const G4Track& aTrack, const G4Step& aStep )
0263 {
0264 const G4ThreeVector& surface_normal = theRecoveredNormal ;
0265 const G4ThreeVector& direction = OldMomentum ;
0266 const G4ThreeVector& polarization = OldPolarization ;
0267
0268 G4double minus_cos_theta = direction*surface_normal ;
0269 G4double orientation = minus_cos_theta < 0. ? 1. : -1. ;
0270 G4ThreeVector oriented_normal = orientation*surface_normal ;
0271
0272 G4double energy = thePhotonMomentum ;
0273 G4double wavelength = twopi*hbarc/energy ;
0274
0275 G4double energy_eV = energy/eV ;
0276 G4double wavelength_nm = wavelength/nm ;
0277
0278 const G4VTouchable* touch = aTrack.GetTouchable();
0279 int replicaNumber = U4Touchable::ReplicaNumber(touch);
0280
0281 int pmtcat = J::DEFAULT_CAT ;
0282 double _qe = 0.0 ;
0283
0284
0285 StackSpec<double,4> spec ;
0286 spec.ls[0].d = 0. ;
0287 spec.ls[1].d = parameter_accessor->get_thickness_nm( pmtcat, J::L1 );
0288 spec.ls[2].d = parameter_accessor->get_thickness_nm( pmtcat, J::L2 );
0289 spec.ls[3].d = 0. ;
0290
0291 spec.ls[0].nr = parameter_accessor->get_rindex( pmtcat, J::L0, J::RINDEX, energy_eV );
0292 spec.ls[0].ni = parameter_accessor->get_rindex( pmtcat, J::L0, J::KINDEX, energy_eV );
0293
0294 spec.ls[1].nr = parameter_accessor->get_rindex( pmtcat, J::L1, J::RINDEX, energy_eV );
0295 spec.ls[1].ni = parameter_accessor->get_rindex( pmtcat, J::L1, J::KINDEX, energy_eV );
0296
0297 spec.ls[2].nr = parameter_accessor->get_rindex( pmtcat, J::L2, J::RINDEX, energy_eV );
0298 spec.ls[2].ni = parameter_accessor->get_rindex( pmtcat, J::L2, J::KINDEX, energy_eV );
0299
0300 spec.ls[3].nr = parameter_accessor->get_rindex( pmtcat, J::L3, J::RINDEX, energy_eV );
0301 spec.ls[3].ni = parameter_accessor->get_rindex( pmtcat, J::L3, J::KINDEX, energy_eV );
0302
0303
0304 Stack<double,4> stack( wavelength_nm, minus_cos_theta, spec );
0305
0306
0307
0308
0309
0310
0311 const double _ni = stack.ll[0].n.real() ;
0312 const double _si = stack.ll[0].st.real() ;
0313 const double _ci = stack.ll[0].ct.real() ;
0314
0315 const double _nt = stack.ll[3].n.real() ;
0316 const double _ct = stack.ll[3].ct.real() ;
0317 const double eta = _ni/_nt ;
0318
0319 Stack<double,4> stackNormal(wavelength_nm, -1. , spec );
0320
0321
0322
0323
0324
0325 double E_s2 = _si > 0. ? (polarization*direction.cross(oriented_normal))/_si : 0. ;
0326 E_s2 *= E_s2;
0327
0328 LOG(LEVEL)
0329 << " count " << count
0330 << " replicaNumber " << replicaNumber
0331 << " _si " << std::fixed << std::setw(10) << std::setprecision(5) << _si
0332 << " oriented_normal " << oriented_normal
0333 << " polarization*direction.cross(oriented_normal) " << polarization*direction.cross(oriented_normal)
0334 << " E_s2 " << std::fixed << std::setw(10) << std::setprecision(5) << E_s2
0335 ;
0336
0337 double fT_s = stack.art.T_s ;
0338 double fT_p = stack.art.T_p ;
0339 double fR_s = stack.art.R_s ;
0340 double fR_p = stack.art.R_p ;
0341 double one = 1.0 ;
0342 double T = fT_s*E_s2 + fT_p*(one-E_s2);
0343 double R = fR_s*E_s2 + fR_p*(one-E_s2);
0344 double A = one - (T+R);
0345
0346
0347 LOG(LEVEL)
0348 << " count " << count
0349 << " E_s2 " << std::fixed << std::setw(10) << std::setprecision(5) << E_s2
0350 << " fT_s " << std::fixed << std::setw(10) << std::setprecision(5) << fT_s
0351 << " 1-E_s2 " << std::fixed << std::setw(10) << std::setprecision(5) << (1.-E_s2)
0352 << " fT_p " << std::fixed << std::setw(10) << std::setprecision(5) << fT_p
0353 << " T " << std::fixed << std::setw(10) << std::setprecision(5) << T
0354 ;
0355
0356 LOG(LEVEL)
0357 << " count " << count
0358 << " E_s2 " << std::fixed << std::setw(10) << std::setprecision(5) << E_s2
0359 << " fR_s " << std::fixed << std::setw(10) << std::setprecision(5) << fR_s
0360 << " 1-E_s2 " << std::fixed << std::setw(10) << std::setprecision(5) << (1.-E_s2)
0361 << " fR_p " << std::fixed << std::setw(10) << std::setprecision(5) << fR_p
0362 << " R " << std::fixed << std::setw(10) << std::setprecision(5) << R
0363 << " A " << std::fixed << std::setw(10) << std::setprecision(5) << A
0364 ;
0365
0366
0367 double fT_n = stackNormal.art.T ;
0368 double fR_n = stackNormal.art.R ;
0369 double An = one - (fT_n+fR_n);
0370 double D = _qe/An;
0371
0372 LOG_IF(error, D > 1.)
0373 << " ERR: D > 1. : " << D
0374 << " _qe " << _qe
0375 << " An " << An
0376 ;
0377
0378 double u0 = G4UniformRand();
0379 double u1 = G4UniformRand();
0380
0381
0382
0383
0384
0385
0386
0387
0388 char status = u0 < A ? ( u1 < D ? 'D' : 'A' ) : ( u0 < A + R ? 'R' : 'T' ) ;
0389
0390
0391
0392 #ifdef DEBUG_TAG
0393 int u0_idx = U4UniformRand::Find(u0, SEvt::UU);
0394 int u1_idx = U4UniformRand::Find(u1, SEvt::UU);
0395
0396 LOG(LEVEL)
0397 << " u0 " << U4UniformRand::Desc(u0)
0398 << " u0_idx " << u0_idx
0399 << " A " << std::setw(10) << std::fixed << std::setprecision(4) << A
0400 << " A+R " << std::setw(10) << std::fixed << std::setprecision(4) << (A+R)
0401 << " T " << std::setw(10) << std::fixed << std::setprecision(4) << T
0402 << " status "
0403 << status
0404 << " DECISION "
0405 ;
0406 LOG(LEVEL)
0407 << " u1 " << U4UniformRand::Desc(u1)
0408 << " u1_idx " << u1_idx
0409 << " D " << std::setw(10) << std::fixed << std::setprecision(4) << D
0410 ;
0411 #endif
0412
0413
0414 NewMomentum = OldMomentum ;
0415 NewPolarization = OldPolarization ;
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430
0431
0432 if( status == 'R' )
0433 {
0434 theStatus = FresnelReflection ;
0435
0436 NewMomentum -= 2.*(OldMomentum*oriented_normal)*oriented_normal ;
0437 NewPolarization -= 2.*(OldPolarization*oriented_normal)*oriented_normal ;
0438
0439
0440
0441
0442 }
0443 else if( status == 'T' )
0444 {
0445 theStatus = FresnelRefraction ;
0446 NewMomentum = eta*OldMomentum + (eta*_ci - _ct)*oriented_normal ;
0447
0448
0449
0450
0451
0452
0453
0454 NewPolarization = (OldPolarization-(OldPolarization*NewMomentum)*NewMomentum).unit();
0455
0456
0457
0458
0459
0460 }
0461 else if(status == 'A' || status == 'D')
0462 {
0463 theStatus = status == 'D' ? Detection : Absorption ;
0464
0465 aParticleChange.ProposeLocalEnergyDeposit(status == 'D' ? thePhotonMomentum : 0.0) ;
0466 aParticleChange.ProposeTrackStatus(fStopAndKill) ;
0467 }
0468
0469
0470
0471 #ifdef DEBUG_TAG
0472 SPhoton_Debug<'B'> dbg ;
0473
0474 dbg.pos = theGlobalPoint ;
0475 dbg.time = aTrack.GetLocalTime();
0476
0477 dbg.mom = NewMomentum ;
0478 dbg.iindex = 0 ;
0479
0480 dbg.pol = NewPolarization ;
0481 dbg.wavelength = wavelength_nm ;
0482
0483 dbg.nrm = theRecoveredNormal ;
0484 dbg.spare = 0. ;
0485
0486 dbg.u0 = u0 ;
0487 dbg.x1 = 0. ;
0488 dbg.x2 = 0. ;
0489 dbg.u0_idx = 0 ;
0490
0491 LOG(LEVEL)
0492 << " time " << dbg.time
0493 << " dbg.Count " << dbg.Count()
0494 << " dbg.Name " << dbg.Name()
0495 << " status " << status
0496 << " CustomStatus::Name(status) " << CustomStatus::Name(status)
0497 ;
0498
0499 dbg.add();
0500 #endif
0501
0502 return status ;
0503 }
0504
0505