Esempio n. 1
0
        protected override void InternalInteract(ElectronBeam electronBeam)
        {
            if (this.HighVoltageSupplyOn.Value == 0)
            {
                this.HighVoltageSupplyMeasured.Value = 0;
                return;
            }

            // Increase/decrease measured high voltage with respect to time delta and gradient
            if (this.HighVoltageSupplyPreset.Value < this.HighVoltageSupplyMeasured.Value)
            {
                // Up gradient
                var voltage = this.HighVoltageSupplyMeasured.Value + (this.HighVoltageSupplyPreset.Value * HighVoltageGradient * this.LastInteractionTimeDelta);
                this.HighVoltageSupplyMeasured.Value = voltage <= this.HighVoltageSupplyPreset.Value ? this.HighVoltageSupplyPreset.Value : voltage;
            }
            else if (this.HighVoltageSupplyPreset.Value > this.HighVoltageSupplyMeasured.Value)
            {
                // Down gradient
                var voltage = this.HighVoltageSupplyMeasured.Value - ((-350E3 - this.HighVoltageSupplyPreset.Value) * HighVoltageGradient * this.LastInteractionTimeDelta);
                this.HighVoltageSupplyMeasured.Value = voltage >= this.HighVoltageSupplyPreset.Value ? this.HighVoltageSupplyPreset.Value : voltage;
            }

            // Calculating the new velocity of the accelerated electron beam using F=qE=mA & E=Volt/d & V^2=Vo^2+2Ax => V=Sqrt(2.q.Volt/m + Vo^2)
            var velocity = Math.Round(Math.Sqrt(Math.Pow(electronBeam.Velocity.Dz, 2) + (2 * Electron.Charge * -this.HighVoltageSupplyMeasured.Value / Electron.Mass)));

            // Electron beam density decreases as much as the beam speed increases thus keeping beam current constant
            // ToDo: Electron speed exceeds the speed of light in case of V = -350kV so something is wrong
            // electronBeam.ElectronDensity = Math.Round(electronBeam.ElectronDensity * (electronBeam.Velocity.Dz / velocity));
            // electronBeam.Velocity = new Velocity(0, 0, velocity);
        }
Esempio n. 2
0
        protected override void InternalInteract(ElectronBeam electronBeam)
        {
            // Using Joule heating equation to calculate filament temperature: I2.R.t = m.c.Delta(T) => Delta(T) = I2.R.t / m.c
            var tempDelta = (Math.Pow(this.CathodeCurrent.Value, 2) * FilamentResistivity * this.LastInteractionTimeDelta) / (FilamentMass * FilamentSpecificHeatCapacity);
            var newTemp   = this.CathodeTemperature.Value + tempDelta;

            // Some of the heat is radiated away each second, proportionally to the current filament temperature and the cooling constant
            // Formula for cooling is T(t) = TA + (To - TA)e^(-kt) ; T(t) = temp delta, TA = ambient temperature, To = object's temperature @ t=0, k = positive constant (should be around 0.00351 water - 0.00481 tube weld)
            this.CathodeTemperature.Value = Parameters.AmbientTemperature + ((newTemp - Parameters.AmbientTemperature) * Math.Pow(Math.E, -1 * 0.00205 * this.LastInteractionTimeDelta));

            if (this.BeamOn.Value == 0)
            {
                // Beam is cut-off
                electronBeam.Velocity = new Velocity(0, 0, 0);
            }
            else
            {
                // ToDo: Calculating thermionic emission density using Richardson/Dushman equation
                electronBeam.ElectronDensity = this.CathodeTemperature.Value * 45E11;

                // Same as the drift tube (in meters)
                electronBeam.Radius = Parameters.DriftTubeRadius;

                // ToDO: This should actually use tugnsten metal's work function to calculate leaving electrons' intial velocity
                electronBeam.Velocity = new Velocity(0, 0, this.CathodeTemperature.Value * 3);

                // ToDo: Set 100V barrier to 77ns interval & 500ps lenght (also set the 100V bias control)
                // Uses X = v.t formula to calculate the lenght in meters
                electronBeam.Length = electronBeam.Velocity.Dz * 77E-9;
            }
        }
Esempio n. 3
0
 protected override void InternalInteract(ElectronBeam electronBeam)
 {
     if (this.In.Value == 1)
     {
         // Aperture cuts the beam radius down to the aperture size
         electronBeam.Radius = this.Radius.Value;
     }
 }
Esempio n. 4
0
 protected override void InternalInteract(ElectronBeam electronBeam)
 {
     if (this.Closed.Value == 1)
     {
         // Cut the beam if the valve is closed
         electronBeam.ElectronDensity = 0;
         //electronBeam.Velocity = new Velocity(0, 0, 0);
     }
 }
Esempio n. 5
0
 protected override void InternalInteract(ElectronBeam electronBeam)
 {
     if (this.CurrentOn.Value == 1)
     {
         // Focus the beam (narrow down the beam radius while increasing the density thus keeping electron flow constant)
         // Using solenoid focal lenght formula: 1/f = q^2/8Tm . Integral(Bz^2, dz) ; T=longitudinal kinetic energy, Bz=Field strength
         // ToDo: Now simply assuming f=25cm with 400G magnetic field @300keV beam energy or else calculating I->G->Bz/T->f will take ages
         electronBeam.Divergence = -(Math.PI * this.Current.Value) / (4 * 2E4);
     }
 }
Esempio n. 6
0
 protected override void InternalInteract(ElectronBeam electronBeam)
 {
     // If the current is lower than that of the previous blm measurement by a predefined limit, there is a beam loss
     // ToDo: Below is a temporary solution, rather use previous beamLoss measurement & Parameters.BeamLossThreshold
     if (electronBeam.ElectronDensity == 0)
     {
         this.BeamLoss.Value = 1;
     }
     else
     {
         this.BeamLoss.Value = 0;
     }
 }
Esempio n. 7
0
        protected override void InternalInteract(ElectronBeam electronBeam)
        {
            if (this.XCurrentOn.Value == 1)
            {
                // Steering magnet has no effect on drift velocity
                electronBeam.Velocity = new Velocity(electronBeam.Velocity.Dx + (this.XCurrent.Value * 5), electronBeam.Velocity.Dy, electronBeam.Velocity.Dz);
            }

            if (this.YCurrentOn.Value == 1)
            {
                electronBeam.Velocity = new Velocity(electronBeam.Velocity.Dx, electronBeam.Velocity.Dy + (this.YCurrent.Value * 5), electronBeam.Velocity.Dz);
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Initiates electron beam - components interactions where the electron beam may come out with a simple measurement
        /// or may be affected by the component in one way or the other.
        /// </summary>
        /// <param name="electronBeam">Electron beam going through the beam line components.</param>
        public void Interact(ElectronBeam electronBeam)
        {
            // Calculate the time delta (seconds) from forward movement (Z) distance and speed
            // This measures the time elapsed during the electron beam's travel from one component to the next
            var locationDelta = this.Location.Z - electronBeam.Location.Z;
            var timeDelta     = locationDelta / electronBeam.Velocity.Dz;

            if (!double.IsNaN(timeDelta))
            {
                SimulatorTime += timeDelta;
            }

            this.LastInteractionTimeDelta = SimulatorTime - this.lastInteractionTime;

            /* 1 tick is 100 nanoseconds
             * Stopwatch _stopwatch = Stopwatch.StartNew();
             * DateTime highresDT = _starttime.AddTicks(_stopwatch.Elapsed.Ticks);
             * Synchronization & last interaction time
             */

            // Beam velocity and density fades away as the beam gets farther away from the source (0.05% per meter of distance)
            // ToDo: electronBeam.Velocity = new Velocity(electronBeam.Velocity.Dx, electronBeam.Velocity.Dy, electronBeam.Velocity.Dz - ??);
            electronBeam.ElectronDensity = electronBeam.ElectronDensity * (1 - (locationDelta / 2000));

            // Update beam radius with respect to beam divergence while keeping electron flow constant
            if (electronBeam.Divergence != 0)
            {
                var oldRadius = electronBeam.Radius;
                electronBeam.Radius         += locationDelta * Math.Sin(electronBeam.Divergence);
                electronBeam.ElectronDensity = electronBeam.ElectronDensity * Math.Pow(oldRadius, 2) / Math.Pow(electronBeam.Radius, 2);
            }

            // Update beam location))
            if (!double.IsNaN(timeDelta))
            {
                electronBeam.Location = new Location(
                    electronBeam.Location.X + (electronBeam.Velocity.Dx * timeDelta),
                    electronBeam.Location.Y + (electronBeam.Velocity.Dy * timeDelta),
                    this.Location.Z);
            }
            else
            {
                electronBeam.Location = new Location(electronBeam.Location.X, electronBeam.Location.Y, this.Location.Z);
            }

            // Component specific interactions
            this.InternalInteract(electronBeam);

            // Update last interaction time
            this.lastInteractionTime = SimulatorTime;
        }
Esempio n. 9
0
        /// <summary>
        /// Takes measurements on the electron beam.
        /// </summary>
        /// <param name="electronBeam">Electron beam going through the beam position monitor.</param>
        protected override void InternalInteract(ElectronBeam electronBeam)
        {
            // Check to see if the beams are getting dangerously close to the drift tube walls and if so, correct the beam path
            this.XPosition.Value = electronBeam.Location.X - this.Location.X;
            if (this.xCurrent != null)
            {
                if (this.XPosition.Value >= Parameters.DesiredBeamPositionRange)
                {
                    // Directly putting the current on value to prevent I/O overhead for checking if it is already on (which EPICS does already)
                    this.xCurrentOn.Value = 1;
                    this.xCurrent.Value  += this.XPosition.Value * -2;
                }
                else if (this.XPosition.Value <= -Parameters.DesiredBeamPositionRange)
                {
                    this.xCurrentOn.Value = 1;
                    this.xCurrent.Value  += this.XPosition.Value * -2;
                }
            }

            this.YPosition.Value = electronBeam.Location.Y - this.Location.Y;
            if (this.yCurrent != null)
            {
                if (this.YPosition.Value >= Parameters.DesiredBeamPositionRange)
                {
                    // Directly putting the current on value to prevent I/O overhead for checking if it is already on (which EPICS does already)
                    this.yCurrentOn.Value = 1;
                    this.yCurrent.Value  += this.YPosition.Value * -2;
                }
                else if (this.YPosition.Value <= -Parameters.DesiredBeamPositionRange)
                {
                    this.yCurrentOn.Value = 1;
                    this.yCurrent.Value  += this.YPosition.Value * -2;
                }
            }

            // Calculate beam loss and make adjustments. If the beam path overflows, electron density drops to zero
            if (this.XPosition.Value >= Parameters.DriftTubeRadius || this.XPosition.Value <= -Parameters.DriftTubeRadius ||
                this.YPosition.Value >= Parameters.DriftTubeRadius || this.YPosition.Value <= -Parameters.DriftTubeRadius)
            {
                electronBeam.ElectronDensity = 0;
            }

            // Measure electron beam current using I=nAvQ (http://en.wikipedia.org/wiki/Electric_current#Drift_speed)
            this.Current.Value = electronBeam.ElectronDensity * (Math.PI * Math.Pow(electronBeam.Radius, 2)) * electronBeam.Velocity.Dz * Electron.Charge;
        }
Esempio n. 10
0
 protected override void InternalInteract(ElectronBeam electronBeam)
 {
     if (this.Pressure.Value <= DesiredPressure * this.vacuumRest)
     {
         this.On.Value        = 0;
         this.vacuumRest      = VacuumRestFactor;
         this.Pressure.Value += this.Pressure.Value * VacuumGradient * 0.1 * this.LastInteractionTimeDelta;
     }
     else if (this.Pressure.Value > CriticalPressure)
     {
         this.On.Value = 2;
         var pressure = this.Pressure.Value - (this.Pressure.Value * VacuumGradient * 2 * this.LastInteractionTimeDelta);
         this.Pressure.Value = pressure < DesiredPressure ? DesiredPressure : pressure;
     }
     else if (this.Pressure.Value > DesiredPressure * this.vacuumRest)
     {
         this.On.Value   = 1;
         this.vacuumRest = 1;
         var pressure = this.Pressure.Value - (this.Pressure.Value * VacuumGradient * this.LastInteractionTimeDelta);
         this.Pressure.Value = pressure < DesiredPressure ? DesiredPressure : pressure;
     }
 }
Esempio n. 11
0
        protected override void InternalInteract(ElectronBeam electronBeam)
        {
            if (this.CameraOn.Value == 1)
            {
                if (!this.stopwatch.IsRunning)
                {
                    this.stopwatch.Start();
                }
                else if (this.ViewScreenIn.Value == 0)
                {
                    // Serialize then publish the new beam profile image
                    using (var stream = new MemoryStream())
                    {
                        this.bitmap = new Bitmap(ImageSide, ImageSide, PixelFormat.Format24bppRgb);
                        this.bitmap.Save(stream, ImageFormat.Gif);
                        this.Image.Value = Convert.ToBase64String(stream.ToArray());
                        this.stopwatch.Restart();
                    }
                }
                else if (this.stopwatch.ElapsedMilliseconds > 1000)
                {
                    // Take a snapshot of the beam profile once every second
                    this.bitmap                     = new Bitmap(ImageSide, ImageSide, PixelFormat.Format24bppRgb);
                    this.beamImageRadius            = (int)((electronBeam.Radius * ImageSide) / (Parameters.DriftTubeRadius * 2));
                    this.beamImageDensity           = (int)(10000 * electronBeam.ElectronDensity / 2E15);
                    this.imageCenterXOffset         = (int)(((electronBeam.Location.X - this.Location.X) * ImageSide) / (Parameters.DriftTubeRadius * 2));
                    this.imageCenterYOffset         = (int)(((electronBeam.Location.Y - this.Location.Y) * ImageSide) / (Parameters.DriftTubeRadius * 2));
                    this.beamImageCenterXCoordinate = (ImageSide / 2) + this.imageCenterXOffset;
                    this.beamImageCenterYCoordinate = (ImageSide / 2) + this.imageCenterYOffset;

                    for (var i = 0; i < this.beamImageDensity; i++)
                    {
                        this.imageXCoordinate = this.random.Next(0, ImageSide);
                        this.imageYCoordinate = this.random.Next(0, ImageSide);
                        this.randomRadius     = (int)
                                                Math.Sqrt(
                            ((this.imageXCoordinate - this.beamImageCenterXCoordinate) * (this.imageXCoordinate - this.beamImageCenterXCoordinate))
                            + ((this.imageYCoordinate - this.beamImageCenterYCoordinate) * (this.imageYCoordinate - this.beamImageCenterYCoordinate)));

                        if (this.LaserOn.Value == 1 && this.randomRadius < 5)
                        {
                            this.bitmap.SetPixel(this.imageXCoordinate, this.imageYCoordinate, Color.Red);
                        }
                        else if (this.randomRadius < this.beamImageRadius)
                        {
                            // ToDo: Performance can be improved via LockBits method (http://www.bobpowell.net/lockingbits.htm)
                            this.bitmap.SetPixel(this.imageXCoordinate, this.imageYCoordinate, Color.Blue);
                        }
                        else
                        {
                            if (++this.imageOverflowScatter > 15)
                            {
                                this.imageOverflowScatter = 0;
                                this.bitmap.SetPixel(this.imageXCoordinate, this.imageYCoordinate, Color.Blue);
                            }
                        }
                    }

                    // Serialize then publish the new beam profile image
                    using (var stream = new MemoryStream())
                    {
                        this.bitmap.Save(stream, ImageFormat.Gif);
                        this.Image.Value = Convert.ToBase64String(stream.ToArray());
                        this.stopwatch.Restart();
                    }
                }
            }
            else
            {
                if (this.stopwatch.IsRunning)
                {
                    this.stopwatch.Stop();
                }
            }
        }
Esempio n. 12
0
 protected abstract void InternalInteract(ElectronBeam electronBeam);
Esempio n. 13
0
        private void InternalInitiate(Action <double> simulatorTime)
        {
            // Optional 6 seconds of waittime (for proper initialization)
            // Thread.Sleep(6000);

            // Create the beam line and fill it with components
            this.BeamLine = new List <BeamLineComponent>
            {
                // ToDo: Appoint component numbers automatically via reflection
                new Cathode(1, new Location(0, 0, 0)),
                new HighVoltageSupply(1, new Location(0, 0, 10)),
                new Vacuum(1, new Location(0, 0, 15)),
                new SteeringMagnet(1, new Location(0, 0, 20)),
                new BeamPositionMonitor(1, new Location(0, 0, 30)),
                new BeamLossMonitor(1, new Location(0, 0, 31)),
                new Aperture(1, new Location(0, 0, 31)),
                new BeamProfileMonitor(1, new Location(0, 0, 32)),
                new GateValve(1, new Location(0, 0, 33)),
                new Solenoid(1, new Location(0, 0, 38)),
                new SteeringMagnet(2, new Location(0, 0, 40)),
                new BeamPositionMonitor(2, new Location(0, 0, 50)),
                new BeamLossMonitor(2, new Location(0, 0, 51)),
                new Aperture(2, new Location(0, 0, 51)),
                new BeamProfileMonitor(2, new Location(0, 0, 52)),
                new GateValve(2, new Location(0, 0, 53)),
                new Vacuum(2, new Location(0, 0, 55)),
                new Solenoid(2, new Location(0, 0, 58)),
                new SteeringMagnet(3, new Location(0, 0, 60)),
                new BeamPositionMonitor(3, new Location(0, 0, 70)),
                new BeamLossMonitor(3, new Location(0, 0, 71)),
                new Aperture(3, new Location(0, 0, 71)),
                new BeamProfileMonitor(3, new Location(0, 0, 72)),
                new GateValve(3, new Location(0, 0, 73)),
                new Vacuum(3, new Location(0, 0, 75)),
                new Solenoid(3, new Location(0, 0, 78)),
                new SteeringMagnet(4, new Location(0, 0, 80)),
                new BeamPositionMonitor(4, new Location(0, 0, 90)),
                new BeamLossMonitor(4, new Location(0, 0, 931)),
                new Aperture(4, new Location(0, 0, 91)),
                new BeamProfileMonitor(4, new Location(0, 0, 92)),
                new GateValve(4, new Location(0, 0, 93)),
                new Solenoid(4, new Location(0, 0, 98)),
                new SteeringMagnet(5, new Location(0, 0, 100)),
                new BeamPositionMonitor(5, new Location(0, 0, 110)),
                new BeamLossMonitor(5, new Location(0, 0, 110)),
                new BeamProfileMonitor(5, new Location(0, 0, 112)),
                new Solenoid(5, new Location(0, 0, 118))
            };

            this.ResolveLinks(this.BeamLine);

            // ToDo: Timer is better suited for this job! var timer = new Timer(o => {}, null, 0, 0);

            // Start sending electron beams through the beam line
            var componentCount = this.BeamLine.Count;

            while (true)
            {
                // If the simulator is terminated, break out of the loop
                if (this.simulatorTerminated)
                {
                    BeamLineComponent.SimulatorTime = 0;
                    break;
                }

                // Initially the electron beam is a null beam which gets shaped by the initial component on the beamline: the electron gun
                var electronBeam = new ElectronBeam();

                foreach (var beamLineComponent in this.BeamLine)
                {
                    beamLineComponent.Interact(electronBeam);
                }

                // Update simulator time display after every beamline transversal
                simulatorTime(BeamLineComponent.SimulatorTime);
                Thread.Sleep(80);
            }
        }