How can I include all eventualities?
This code takes in a 3array (position) and tests to see whether it sits in some region of the model or not. The problem is in the PbSheild method, I can't work out why though. This code will work as is (well it will not work as is, that's the point).
class Geometry $polyCylRad = 2.5 $polyCylFr = 15 $polyCylB = -2.0 $borPolyBoxL = 9.0 / 2 $pbCylRad = 3.0 $pbBoxL = 10.0 / 2 $cdBoxL = 9.5 / 2 $xSquared = Float $ySquared = Float $zSquared = Float $modX = Float $modY = Float $modZ =Float $position = Array.new def checkMaterial(params) $position = params $xSquared = $position ** 2 $ySquared = $position ** 2 $zSquared = $position ** 2 $modX = Math.sqrt($xSquared) $modY = Math.sqrt($ySquared) $modZ = Math.sqrt($zSquared) puts "polyCyl: " + self.polyCylinder.to_s puts "borpoly: " + self.borPolyBox.to_s puts "Cd: " + self.CdShield.to_s puts "Pb Cylinder: " + self.PbCylinder.to_s puts "Pb: " + self.PbShield.to_s puts "FreeSpace: " + self.FreeSpace.to_s material end def polyCylinder Math.sqrt($ySquared + $zSquared) <= $polyCylRad && $position >= $polyCylB && $position <= $polyCylFr end def borPolyBox !polyCylinder && ($modX <= $borPolyBoxL || $modY <= $borPolyBoxL || $modZ <= borPolyBoxL) && !($modX > $borPolyBoxL || $modY > $borPolyBoxL || $modZ > borPolyBoxL) end def CdShield !polyCylinder && !borPolyBox && ($modX <= $cdBoxL || $modY <= $cdBoxL || $modZ <= $cdBoxL) && !($modX > $cdBoxL || $modY > $cdBoxL || $modZ > $cdBoxL) end def PbCylinder !polyCylinder && $position >= $cdBoxL && $position <= $polyCylFr && Math.sqrt($ySquared + zSquared) <= $pbCylRad end def PbShield !polyCylinder && !borPolyBox && !CdShield && !PbCylinder && ($modX <= $pbBoxL || $modY <= $pbBoxL || $modZ <= $pbBoxL) && !($modX > $pbBoxL || $modY > $pbBoxL || $modZ > $pbBoxL) end def FreeSpace !polyCylinder && !borPolyBox && !CdShield && !PbShield && !PbCylinder end def material [ [:polyCylinder, 'poly'], [:borPolyBox, 'borPoly'], [:CdShield, 'Cd'], [:PbCylinder, 'Pb'], [:PbShield, 'Pb'], [:FreeSpace, 'air'] ].each do |method, name| return name if send(method) end false end end $bob = Geometry.new posVect = Array.new posVect << 0 << 0 << 0 $bob.checkMaterial(posVect) while posVect < 25 do $bob.checkMaterial(posVect) puts "Xpos: " + posVect.to_s puts "Ypos: " + posVect.to_s puts "Zpos: " + posVect.to_s puts "polyCyl: " + $bob.polyCylinder.to_s puts "borpoly: " + $bob.borPolyBox.to_s puts "Cd: " + $bob.CdShield.to_s puts "Pb: " + $bob.PbShield.to_s puts "FreeSpace: " + $bob.FreeSpace.to_s puts "" posVect += 1 end
If you think this looks suspiciously like it is related to my c++ code you are correct, am writing two structurally different monte carlo's in Ruby and c++ (learning Ruby and the deepening c++ knowledge at the same time).
I would rewrite this entirely. You have a couple of problems that you want to solve. First, you want to define a region and see if a point is within that region. That should probably be one module with a method for defining regions and a method for placing a point within a defined region. You could, if you wished, define the regions in the module itself, or define them on the fly, whichever. That would give you the ability to pass a region name or definition and a point to a single method and get back whether the point is within that region. That would be much easier to test.
Second, you want to determine the material value: true or false, for every material. You might consider using a case statement for this. You write a method that returns values for your region test (like :poly, :box, whatever) and then use that as the test for your case statement:
case whatever(point) when (:foo) set some values when (:bar) set some other values end
If you set the default for every material value to false (a good plan) then you'll only have to update the trues, and it should be easy, based on the return value of your region check method, to decide what values need to be true or can be true.
Breaking the code apart this way--or some other way--will make it much easier to test.