diff --git a/Tests/Py/Functional/sliced_compounds.py b/Tests/Py/Functional/known_slicing.py similarity index 63% rename from Tests/Py/Functional/sliced_compounds.py rename to Tests/Py/Functional/known_slicing.py index e0889771cf0049609a7728312974e35396e8d602..9f3f435fa4e0be8d889c068dd92fa5b1f5337dd2 100644 --- a/Tests/Py/Functional/sliced_compounds.py +++ b/Tests/Py/Functional/known_slicing.py @@ -1,5 +1,6 @@ """ -Check slicing mechanism for compound particles crossing an interface. +Check slicing mechanism for spherical particles crossing an interface, +using known decomposition of particles (as opposed to automatic slicing, tested elsewhere) """ import unittest @@ -7,11 +8,102 @@ import PyFuTestInfrastructure as infrastruct import bornagain as ba from bornagain import deg, R3 -matSubstrate = ba.RefractiveMaterial("Substrate", 3e-6, 3e-8) +matSubstrate = ba.RefractiveMaterial("Substrate", 3.2e-6, 3.2e-8) matVacuum = ba.RefractiveMaterial("Vacuum", 0, 0) -matParticle = ba.RefractiveMaterial("Ag", 1e-5, 5e-7) +matParticle = ba.RefractiveMaterial("Ag", 1.2e-5, 5.4e-7) + R = 10.0 -dz = 4.0 +dz = 4.0 # shift beneath interface + + +class SlicedSpheresTest(unittest.TestCase): + + def get_sample(self, particle_to_air=None, particle_to_substrate=None): + """ + Returns a sample, with given particles attached to substrate or vacuum layer. + """ + + vacuum_layer = ba.Layer(matVacuum) + if particle_to_air: + layout = ba.ParticleLayout() + layout.addParticle(particle_to_air) + vacuum_layer.addLayout(layout) + + substrate = ba.Layer(matSubstrate) + if particle_to_substrate: + layout = ba.ParticleLayout() + layout.addParticle(particle_to_substrate) + substrate.addLayout(layout) + + sample = ba.MultiLayer() + sample.addLayer(vacuum_layer) + sample.addLayer(substrate) + return sample + + def get_result(self, particle_to_air=None, particle_to_substrate=None): + sample = self.get_sample(particle_to_air, particle_to_substrate) + simulation = infrastruct.get_simulation_MiniGISAS(sample) + return simulation.simulate() + + def testSphericalCupOnTopOfSubstrate(self): + """ + Simulation #1: truncated sphere on top of substrate. + Simulation #2: sphere crossing the interface. + Both particles are made of same material as substrate. + Same scattering expected from both sample models. + """ + + # truncated sphere (dz removed from bottom) on top of substrate + truncatedSphere = ba.Particle(matSubstrate, + ba.TruncatedSphere(R, R * 2 - dz, 0)) + reference = self.get_result(truncatedSphere) + + # same without truncation, sphere penetrating into substrate layer + sphere = ba.Particle(matSubstrate, ba.Sphere(R)) + sphere.translate(0, 0, -dz) + data = self.get_result(sphere) + + diff = ba.meanRelativeDifference(data, reference) + self.assertLess(diff, 1e-15) + + def testSphericalLacuneInSubstrate(self): + """ + Similar to previous. Truncated sphere and sphere are made of vacuum material. + From scattering point of view, both cases should look like an vacuum lacune in substrate. + """ + + # Sphere truncated from top. Intended to go below interface. + truncatedSphere = ba.Particle(matVacuum, + ba.TruncatedSphere(R, R * 2, R * 2 - dz)) + truncatedSphere.translate(0, 0, -dz) + reference = self.get_result(truncatedSphere) + + # sphere crossing interface to look like truncated sphere above + sphere = ba.Particle(matVacuum, ba.Sphere(R)) + sphere.translate(0, 0, -dz) + data = self.get_result(sphere) + + diff = ba.meanRelativeDifference(data, reference) + self.assertLess(diff, 1e-15) + + def testSpheresCrossingInterface(self): + """ + Same particle in same position, but attached to two different layers. + Of course, results shall be identical. + """ + + # Sphere intended for vacuum layer and crossing interface + sphere1 = ba.Particle(matParticle, ba.Sphere(R)) + sphere1.translate(0, 0, -dz) + reference = self.get_result(particle_to_air=sphere1) + + # Sphere intended for substrate layer and crossing interface + sphere2 = ba.Particle(matParticle, ba.Sphere(R)) + sphere2.translate(0, 0, -dz) + data = self.get_result(particle_to_substrate=sphere2) + + diff = ba.meanRelativeDifference(data, reference) + self.assertLess(diff, 1e-15) class SlicedSpheresTest(unittest.TestCase): diff --git a/Tests/Py/Functional/sliced_spheres.py b/Tests/Py/Functional/sliced_spheres.py deleted file mode 100644 index aa76bda30d26a6e09cf1dafe4e608f75d1e75d01..0000000000000000000000000000000000000000 --- a/Tests/Py/Functional/sliced_spheres.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -Check slicing mechanism for spherical particles crossing an interface. -""" - -import unittest -import PyFuTestInfrastructure as infrastruct -import bornagain as ba - -matSubstrate = ba.RefractiveMaterial("Substrate", 3.2e-6, 3.2e-8) -matVacuum = ba.RefractiveMaterial("Vacuum", 0, 0) -matParticle = ba.RefractiveMaterial("Ag", 1.2e-5, 5.4e-7) - -R = 10.0 -dz = 4.0 # shift beneath interface - - -class SlicedSpheresTest(unittest.TestCase): - - def get_sample(self, particle_to_air=None, particle_to_substrate=None): - """ - Returns a sample, with given particles attached to substrate or vacuum layer. - """ - - vacuum_layer = ba.Layer(matVacuum) - if particle_to_air: - layout = ba.ParticleLayout() - layout.addParticle(particle_to_air) - vacuum_layer.addLayout(layout) - - substrate = ba.Layer(matSubstrate) - if particle_to_substrate: - layout = ba.ParticleLayout() - layout.addParticle(particle_to_substrate) - substrate.addLayout(layout) - - sample = ba.MultiLayer() - sample.addLayer(vacuum_layer) - sample.addLayer(substrate) - return sample - - def get_result(self, particle_to_air=None, particle_to_substrate=None): - sample = self.get_sample(particle_to_air, particle_to_substrate) - simulation = infrastruct.get_simulation_MiniGISAS(sample) - return simulation.simulate() - - def testSphericalCupOnTopOfSubstrate(self): - """ - Simulation #1: truncated sphere on top of substrate. - Simulation #2: sphere crossing the interface. - Both particles are made of same material as substrate. - Same scattering expected from both sample models. - """ - - # truncated sphere (dz removed from bottom) on top of substrate - truncatedSphere = ba.Particle(matSubstrate, - ba.TruncatedSphere(R, R * 2 - dz, 0)) - reference = self.get_result(truncatedSphere) - - # same without truncation, sphere penetrating into substrate layer - sphere = ba.Particle(matSubstrate, ba.Sphere(R)) - sphere.translate(0, 0, -dz) - data = self.get_result(sphere) - - diff = ba.meanRelativeDifference(data, reference) - self.assertLess(diff, 1e-15) - - def testSphericalLacuneInSubstrate(self): - """ - Similar to previous. Truncated sphere and sphere are made of vacuum material. - From scattering point of view, both cases should look like an vacuum lacune in substrate. - """ - - # Sphere truncated from top. Intended to go below interface. - truncatedSphere = ba.Particle(matVacuum, - ba.TruncatedSphere(R, R * 2, R * 2 - dz)) - truncatedSphere.translate(0, 0, -dz) - reference = self.get_result(truncatedSphere) - - # sphere crossing interface to look like truncated sphere above - sphere = ba.Particle(matVacuum, ba.Sphere(R)) - sphere.translate(0, 0, -dz) - data = self.get_result(sphere) - - diff = ba.meanRelativeDifference(data, reference) - self.assertLess(diff, 1e-15) - - def testSpheresCrossingInterface(self): - """ - Same particle in same position, but attached to two different layers. - Of course, results shall be identical. - """ - - # Sphere intended for vacuum layer and crossing interface - sphere1 = ba.Particle(matParticle, ba.Sphere(R)) - sphere1.translate(0, 0, -dz) - reference = self.get_result(particle_to_air=sphere1) - - # Sphere intended for substrate layer and crossing interface - sphere2 = ba.Particle(matParticle, ba.Sphere(R)) - sphere2.translate(0, 0, -dz) - data = self.get_result(particle_to_substrate=sphere2) - - diff = ba.meanRelativeDifference(data, reference) - self.assertLess(diff, 1e-15) - - -if __name__ == '__main__': - unittest.main()