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 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 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 testLambertian(self): manager = makeTheWorld() mirrorbox = ROOT.TGeoBBox("mirrorbox", 5 * cm, 5 * cm, 1 * um) mirror = ROOT.AMirror("mirror", mirrorbox) condition = ROOT.ABorderSurfaceCondition(manager.GetTopVolume(), mirror) registerGeo((mirrorbox, mirror, condition)) condition.EnableLambertian(True) manager.GetTopVolume().AddNode(mirror, 1) focalbox = ROOT.TGeoBBox("focalbox", 0.5 * cm, 0.5 * cm, 1 * um) focal = ROOT.AFocalSurface("focal", focalbox) registerGeo((focalbox, focal)) collimatorpgon = ROOT.TGeoPgon("focalboxcollimatorpgon", 0, 360, 4, 2) collimatorpgon.DefineSection(0, -3 * m, 0.5 * cm, 0.51 * cm) collimatorpgon.DefineSection(1, -1 * um, 0.5 * cm, 0.51 * cm) collimator = ROOT.AObscuration("collimator", collimatorpgon) registerGeo((collimatorpgon, collimator)) for i in range(90): theta = i rot = ROOT.TGeoRotation("", 0, theta, 0) rot2 = ROOT.TGeoRotation("", 0, theta, 45) cos = ROOT.TMath.Cos(theta * ROOT.TMath.Pi() / 180.) sin = ROOT.TMath.Sin(theta * ROOT.TMath.Pi() / 180.) tr = ROOT.TGeoTranslation(0, -10 * m * sin, 10 * m * cos) registerGeo((rot, rot2, tr)) manager.GetTopVolume().AddNode(focal, i + 1, ROOT.TGeoCombiTrans(tr, rot)) manager.GetTopVolume().AddNode(collimator, i + 1, ROOT.TGeoCombiTrans(tr, rot2)) manager.CloseGeometry() manager.GetTopVolume().Draw("ogl") h = ROOT.TH1D('h', ';Viewing Angle (deg);Number of Photons', 90, 0, 90) for j in range(-500, 501): rot = ROOT.TGeoRotation("", 0, 180, 0) dy = j * mm / 10. tr = ROOT.TGeoTranslation(0, dy, 2 * um) array = ROOT.ARayShooter.RandomSquare(400 * nm, 2 * cm, 1000000, rot, tr) manager.TraceNonSequential(array) objarray = ROOT.TObjArray() objarray.Add(array) # to delete ARayArray inside C++ objarray.SetOwner(True) focused = array.GetFocused() for i in range(focused.GetLast() + 1): ray = focused[i] history = ray.GetNodeHistory() angle = int( history.At( history.GetLast()).GetName().split('_')[1]) - 0.5 h.Fill(angle) if i < 1000 and j == 0: pol = ray.MakePolyLine3D() pol.SetLineColor(2) pol.SetLineWidth(2) pol.Draw() registerGeo((pol, )) ROOT.gPad.Modified() ROOT.gPad.Update() del objarray can = ROOT.TCanvas() h.Draw() h.Fit('pol0', '', '', 0, 50)