def testMirrorReflection(self): manager = makeTheWorld() mirrorbox = ROOT.TGeoBBox("mirrorbox", 0.5 * m, 0.5 * m, 0.5 * m) mirror = ROOT.AMirror("mirror", mirrorbox) manager.GetTopVolume().AddNode(mirror, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0)'): manager.SetMultiThread(True) manager.SetMaxThreads(4) graph = ROOT.TGraph() graph.SetPoint(0, 300 * nm, 0.) graph.SetPoint(1, 500 * nm, .5) # 0.25 at 400 nm mirror.SetReflectivity(graph) self.assertAlmostEqual(mirror.GetReflectivity(400 * nm, 0), 0.25, 6) N = 10000 rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, 400 * nm, 0, 0, 0.8 * m, 0, 0, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) n = rays.GetExited().GetLast() + 1 ref = 0.25 self.assertGreater(ref, (n - n**0.5 * 3) / N) self.assertLess(ref, (n + n**0.5 * 3) / N) # Test of a 2D reflectance graph graph = ROOT.TGraph2D() deg = ROOT.TMath.DegToRad() # This should be 0.5 at (400 nm, 45 deg) graph.SetPoint(0, 300 * nm, 0 * deg, 0.0) graph.SetPoint(1, 300 * nm, 90 * deg, 0.3) graph.SetPoint(2, 500 * nm, 0 * deg, 0.7) graph.SetPoint(3, 500 * nm, 90 * deg, 1.0) mirror.SetReflectivity(graph) self.assertAlmostEqual(mirror.GetReflectivity(400 * nm, 45 * deg), 0.5, 3) rays = ROOT.ARayArray() for i in range(N): x, y, z, t = 0, 0, 0.51 * m, 0 px, py, pz = ROOT.TMath.Sqrt2(), 0, -ROOT.TMath.Sqrt2() ray = ROOT.ARay(i, 400 * nm, x, y, z, t, px, py, pz) rays.Add(ray) manager.TraceNonSequential(rays) n = rays.GetExited().GetLast() + 1 ref = 0.5 self.assertGreater(ref, (n - n**0.5 * 3) / N) self.assertLess(ref, (n + n**0.5 * 3) / N)
def testFresnelReflection(self): manager = makeTheWorld() manager.DisableFresnelReflection(False) # enable lensbox = ROOT.TGeoBBox("lensbox", 0.5 * m, 0.5 * m, 0.5 * m) lens = ROOT.ALens("lens", lensbox) lens.SetConstantAbsorptionLength(1 * um) idx = 3. lens.SetConstantRefractiveIndex(idx) manager.GetTopVolume().AddNode(lens, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0)'): manager.SetMultiThread(True) manager.SetMaxThreads(4) N = 10000 rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, 400 * nm, 0, 0, 0.8 * m, 0, 0, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) n = rays.GetExited().GetLast() + 1 ref = (idx - 1)**2 / (idx + 1)**2 self.assertGreater(ref, (n - n**0.5 * 3) / N) self.assertLess(ref, (n + n**0.5 * 3) / N)
def testMirrorScattaring(self): manager = makeTheWorld() mirrorbox = ROOT.TGeoBBox("mirrorbox", 0.5 * m, 0.5 * m, 0.5 * m) mirror = ROOT.AMirror("mirror", mirrorbox) condition = ROOT.ABorderSurfaceCondition(manager.GetTopVolume(), mirror) registerGeo((mirrorbox, mirror, condition)) sigma = 1 condition.SetGaussianRoughness(sigma * deg) manager.GetTopVolume().AddNode(mirror, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE;') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0);'): manager.SetMultiThread(True) manager.SetMaxThreads(4) N = 10000 rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, 400 * nm, 0, 0, 0.8 * m, 0, 0, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) exited = rays.GetExited() h2 = ROOT.TH2D("h2", "h2", 40, -10 * sigma, 10 * sigma, 40, -10 * sigma, 10 * sigma) for i in range(N): ray = exited.At(i) p = array.array("d", [0, 0, 0, 0]) ray.GetDirection(p) px = p[0] py = p[1] pz = p[2] h2.Fill(px * rad / deg, py * rad / deg) f2 = ROOT.TF2("f2", "[0]*exp(-(x*x + y*y)/(2*[1]*[1]))", -10 * sigma, 10 * sigma, -10 * sigma, 10 * sigma) f2.SetParameter(0, 1000) f2.SetParLimits(1, 0, 10) f2.SetParameter(1, sigma) h2.Draw("lego") ROOT.gPad.Update() h2.Fit("f2", "l") p = f2.GetParameter(1) e = f2.GetParError(1) self.assertGreater(2 * sigma, p - 3 * e) # reflected angle is 2 times larger self.assertLess(2 * sigma, p + 3 * e) cleanupGeo()
def testLimitForSuspended(self): manager = makeTheWorld() manager.SetLimit(1000) mirrorsphere = ROOT.TGeoSphere("mirrorsphere", 0.1 * m, 0.2 * m) mirror = ROOT.AMirror("mirror", mirrorsphere) manager.GetTopVolume().AddNode(mirror, 1) manager.CloseGeometry() manager.SetMultiThread(True) manager.SetMaxThreads(4) ray = ROOT.ARay(0, 400 * nm, 0, 0, 0, 0, 0, 0, -1) manager.TraceNonSequential(ray) n = ray.GetNpoints() self.assertEqual(n, 1000)
def testLensBoundaryMultilayer(self): manager = makeTheWorld() lensbox = ROOT.TGeoBBox("lensbox", 0.5 * m, 0.5 * m, 0.5 * m) lens = ROOT.AMirror("lens", lensbox) condition = ROOT.ABorderSurfaceCondition(manager.GetTopVolume(), lens) registerGeo((lensbox, lens, condition)) ROOT.gROOT.ProcessLine( 'auto lens_layer = std::make_shared<AMultilayer>(air, Si)') ROOT.lens_layer.InsertLayer(ROOT.SiO2, 2000 * nm) ROOT.lens_layer.InsertLayer(ROOT.Si3N4, 33 * nm) condition.SetMultilayer(ROOT.lens_layer) manager.GetTopVolume().AddNode(lens, 1) manager.CloseGeometry() N = 100000 for wl in range(300, 600, 50): rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, wl * nm, 0, 0, 0.51 * m, 0, 1, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) n_exited = rays.GetExited().GetEntries() n_absorbed = rays.GetAbsorbed().GetEntries() self.assertEqual(n_exited + n_absorbed, N) reflectance = ctypes.c_double() transmittance = ctypes.c_double() ROOT.lens_layer.CoherentTMMMixed( ROOT.std.complex(ROOT.double)(45 * deg), wl * nm, reflectance, transmittance) expected = N * reflectance.value e = expected**0.5 self.assertGreater(n_exited, expected - 3 * e) self.assertLess(n_exited, expected + 3 * e) cleanupGeo()
def testSnellsLaw(self): manager = makeTheWorld() manager.DisableFresnelReflection(True) lensbox = ROOT.TGeoBBox("lensbox", 0.5 * m, 0.5 * m, 1 * mm) lens = ROOT.ALens("lens", lensbox) idx = 1.5 ROOT.gROOT.ProcessLine( 'refidx = std::make_shared<ARefractiveIndex>(%.1f);' % idx) lens.SetRefractiveIndex(ROOT.refidx) manager.GetTopVolume().AddNode(lens, 1) focalbox = ROOT.TGeoBBox("focalbox", 0.5 * m, 0.5 * m, 0.1 * mm) focal = ROOT.AFocalSurface("focal", focalbox) registerGeo((lensbox, lens, focalbox, focal)) lens.AddNode(focal, 1) manager.CloseGeometry() theta = 30 * deg sint = ROOT.TMath.Sin(theta) cost = ROOT.TMath.Cos(theta) ray = ROOT.ARay(0, 400 * nm, 0 * m, 0 * m, 2 * mm, 0, sint, 0, -cost) arr = ROOT.ARayArray() #arr.Add(ray) ## calling TraceNonSequential(ARay*) causes a seg fault... manager.TraceNonSequential(ray) p = array.array("d", [0, 0, 0, 0]) ray.GetDirection(p) px = p[0] py = p[1] pz = p[2] self.assertAlmostEqual(px, sint / idx) self.assertAlmostEqual(py, 0) cleanupGeo()
def testSnellsLaw(self): manager = makeTheWorld() manager.SetLimit(1000) lensbox = ROOT.TGeoBBox("lensbox", 0.5 * m, 0.5 * m, 1 * mm) lens = ROOT.ALens("lens", lensbox) idx = 1.5 lens.SetConstantRefractiveIndex(idx) manager.GetTopVolume().AddNode(lens, 1) focalbox = ROOT.TGeoBBox("focalbox", 0.5 * m, 0.5 * m, 0.1 * mm) focal = ROOT.AFocalSurface("focal", focalbox) lens.AddNode(focal, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0)'): manager.SetMultiThread(True) manager.SetMaxThreads(4) manager.DisableFresnelReflection(True) theta = 30 * d2r sint = ROOT.TMath.Sin(theta) cost = ROOT.TMath.Cos(theta) ray = ROOT.ARay(0, 400 * nm, 0 * m, 0 * m, 2 * mm, 0, sint, 0, -cost) arr = ROOT.ARayArray() arr.Add(ray) # calling TraceNonSequential(ARay*) causes a seg fault... manager.TraceNonSequential(arr) p = array.array("d", [0, 0, 0, 0]) ray.GetDirection(p) px = p[0] py = p[1] pz = p[2] self.assertAlmostEqual(px, sint / idx) self.assertAlmostEqual(py, 0)
def testMirrorBoundaryMultilayer(self): manager = makeTheWorld() mirrorbox = ROOT.TGeoBBox("mirrorbox", 0.5 * m, 0.5 * m, 0.5 * m) mirror = ROOT.AMirror("mirror", mirrorbox) condition = ROOT.ABorderSurfaceCondition(manager.GetTopVolume(), mirror) ROOT.gROOT.ProcessLine( 'auto mirror_layer = std::make_shared<AMultilayer>(air, Al)') ROOT.mirror_layer.InsertLayer(ROOT.SiO2, 25.4 * nm) condition.SetMultilayer(ROOT.mirror_layer) manager.GetTopVolume().AddNode(mirror, 1) manager.CloseGeometry() N = 100000 for wl in range(300, 1100, 100): rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, wl * nm, 0, 0, 0.51 * m, 0, 1, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) n_exited = rays.GetExited().GetEntries() n_absorbed = rays.GetAbsorbed().GetEntries() self.assertEqual(n_exited + n_absorbed, N) reflectance = ROOT.double() transmittance = ROOT.double() ROOT.mirror_layer.CoherentTMMMixed( ROOT.std.complex(ROOT.double)(45 * deg), wl * nm, reflectance, transmittance) expected = N * reflectance e = expected**0.5 self.assertGreater(n_exited, expected - 3 * e) self.assertLess(n_exited, expected + 3 * e) print(wl, n_exited, n_absorbed)
def testLimitForSuspended(self): manager = makeTheWorld() manager.SetLimit(1000) mirrorsphere = ROOT.TGeoSphere("mirrorsphere", 0.1 * m, 0.2 * m) mirror = ROOT.AMirror("mirror", mirrorsphere) registerGeo((mirrorsphere, mirror)) manager.GetTopVolume().AddNode(mirror, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE;') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0);'): manager.SetMultiThread(True) manager.SetMaxThreads(4) ray = ROOT.ARay(0, 400 * nm, 0, 0, 0, 0, 0, 0, -1) manager.TraceNonSequential(ray) n = ray.GetNpoints() self.assertEqual(n, 1000) cleanupGeo()
def testFresnelReflection(self): manager = makeTheWorld() manager.DisableFresnelReflection(False) # enable lensbox = ROOT.TGeoBBox("lensbox", 0.5 * m, 0.5 * m, 0.5 * m) lens = ROOT.ALens("lens", lensbox) wl = 400 * nm absl = 1 * um idx = 3. ROOT.gROOT.ProcessLine('double idx, k;') ROOT.idx = idx ROOT.k = ROOT.ARefractiveIndex.AbsorptionLengthToExtinctionCoefficient( absl, wl) ROOT.gROOT.ProcessLine( 'refidx = std::make_shared<ARefractiveIndex>(idx, k);') lens.SetRefractiveIndex(ROOT.refidx) manager.GetTopVolume().AddNode(lens, 1) manager.CloseGeometry() if ROOT.gInterpreter.ProcessLine('ROOT_VERSION_CODE;') < \ ROOT.gInterpreter.ProcessLine('ROOT_VERSION(6, 2, 0);'): manager.SetMultiThread(True) manager.SetMaxThreads(4) N = 100000 rays = ROOT.ARayArray() for i in range(N): ray = ROOT.ARay(i, wl, 0, 0, 0.8 * m, 0, 0, 0, -1) rays.Add(ray) manager.TraceNonSequential(rays) n = rays.GetExited().GetLast() + 1 ref = (idx - 1)**2 / (idx + 1)**2 self.assertGreater(ref, (n - n**0.5 * 3) / N) self.assertLess(ref, (n + n**0.5 * 3) / N) layer = ROOT.AMultilayer(ROOT.air, ROOT.TiO2) angle = ROOT.std.complex(ROOT.double)(45 * deg) for wl in (200 * nm, 800 * nm): ref, trans = ctypes.c_double(), ctypes.c_double() layer.CoherentTMMMixed(angle, wl, ref, trans) lens.SetRefractiveIndex(ROOT.TiO2) rays = ROOT.ARayArray() z, dy, dz = 0.51 * m, 1 / 2**0.5, -1 / 2**0.5 for i in range(N): ray = ROOT.ARay(i, wl, 0, 0, z, 0, 0, dy, dz) rays.Add(ray) manager.SetLimit( 3) # stop tracking of photons that entered the lens manager.TraceNonSequential(rays) n = rays.GetExited().GetLast() + 1 self.assertGreater(ref.value, (n - n**0.5 * 3) / N) self.assertLess(ref.value, (n + n**0.5 * 3) / N)