Esempio n. 1
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public Evolver(RunParams parms, VDelegate V, string outputDir)
        {
            m_gridSizeX            = parms.GridSize.Width;
            m_gridSizeY            = parms.GridSize.Height;
            m_latticeSpacing       = parms.LatticeSpacing;
            m_totalTime            = parms.TotalTime;
            m_deltaT               = parms.TimeStep;
            m_totalNumTimeSteps    = (int)Math.Round(parms.TotalTime / parms.TimeStep) + 1;
            m_currentTimeStepIndex = 0;

            m_mass1     = parms.Mass1;
            m_mass2     = parms.Mass2;
            m_potential = V;

            m_initialMomentum1 = new Vec2(parms.InitialWavePacketMomentum1);
            m_initialPosition1 = new Vec2(parms.InitialWavePacketCenter1);
            m_initialSize1     = new Vec2(parms.InitialWavePacketSize);

            m_initialPosition2 = new Vec2(parms.AtomCenter);
            m_sho_sigma        = parms.AtomSize;
            m_sho_N            = parms.Atom_N;
            m_sho_Lz           = parms.Atom_Lz;

            m_numFramesToSave = parms.NumFramesToSave;
            m_lastSavedFrame  = -1;
            m_outputDir       = outputDir;
            m_multiThread     = parms.MultiThread;

            m_visscherWf = null;
        }
Esempio n. 2
0
        /// <summary>
        /// Creates a Gaussian wavepacket with given properties.
        /// </summary>
        public static WaveFunction CreateGaussianWavePacket(
            int gridSizeX, int gridSizeY, float latticeSpacing, bool originAtLatticeCenter, float mass,
            Vec2 packetCenter, Vec2 packetWidth, Vec2 avgMomentum, bool multiThread = true)
        {
            WaveFunction wf = new WaveFunction(gridSizeX, gridSizeY, latticeSpacing);

            Complex I             = Complex.I;
            float   rootPi        = (float)Math.Sqrt(Math.PI);
            float   sigmaXSq      = packetWidth.X * packetWidth.X;
            float   sigmaYSq      = packetWidth.Y * packetWidth.Y;
            float   norm          = (float)Math.Sqrt((packetWidth.X / (rootPi * sigmaXSq)) * (packetWidth.Y / (rootPi * sigmaYSq)));
            int     halfGridSizeX = (gridSizeX - 1) / 2;
            int     halfGridSizeY = (gridSizeY - 1) / 2;

            TdseUtils.Misc.ForLoop(0, gridSizeY, (y) =>
            {
                float yf        = (originAtLatticeCenter) ? (y - halfGridSizeY) * latticeSpacing : (y * latticeSpacing);
                Complex expArgY = I * yf * avgMomentum.Y - (yf - packetCenter.Y) * (yf - packetCenter.Y) / (2 * sigmaYSq);

                float[] wfDataY = wf.Data[y];
                for (int x = 0; x < gridSizeX; x++)
                {
                    float xf = (originAtLatticeCenter) ? (x - halfGridSizeX) * latticeSpacing : (x * latticeSpacing);

                    Complex expArgYX = expArgY + I * xf * avgMomentum.X - (xf - packetCenter.X) * (xf - packetCenter.X) / (2 * sigmaXSq);
                    Complex wfVal    = norm * Complex.Exp(expArgYX);

                    wfDataY[2 * x]     = wfVal.Re;
                    wfDataY[2 * x + 1] = wfVal.Im;
                }
            }, multiThread);

            wf.Normalize();
            return(wf);
        }
Esempio n. 3
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public Evolver(RunParams parms, VDelegate V, string outputDir)
        {
            m_gridSizeX            = parms.GridSize.Width;
            m_gridSizeY            = parms.GridSize.Height;
            m_latticeSpacing       = parms.LatticeSpacing;
            m_totalTime            = parms.TotalTime;
            m_deltaT               = parms.TimeStep;
            m_totalNumTimeSteps    = (int)Math.Round(parms.TotalTime / parms.TimeStep) + 1;
            m_currentTimeStepIndex = 0;

            m_mass1       = parms.Mass1;
            m_mass2       = parms.Mass2;
            m_totalMass   = (parms.Mass1 + parms.Mass2);
            m_reducedMass = (parms.Mass1 * parms.Mass2) / m_totalMass;
            m_potential   = V;

            m_initialMomentum1 = new Vec2(parms.InitialWavePacketMomentum1);
            m_initialMomentum2 = new Vec2(parms.InitialWavePacketMomentum2);
            m_initialPosition1 = new Vec2(parms.InitialWavePacketCenter1);
            m_initialPosition2 = new Vec2(parms.InitialWavePacketCenter2);
            m_sigmaRel         = parms.InitialWavePacketSize * Math.Sqrt(m_totalMass / m_mass2);
            m_sigmaCm          = parms.InitialWavePacketSize * Math.Sqrt(m_mass1 / m_totalMass);

            m_dampingBorderWidth = parms.DampingBorderWidth;
            m_dampingFactor      = parms.DampingFactor;

            m_numFramesToSave = parms.NumFramesToSave;
            m_lastSavedFrame  = -1;
            m_outputDir       = outputDir;
            m_multiThread     = parms.MultiThread;

            m_visscherWf = null;
        }
Esempio n. 4
0
        /// <summary>
        /// Worker method.
        /// </summary>
        protected override void WorkerMethod()
        {
            // Reset counters
            m_currentTimeStepIndex = 0;
            m_lastSavedFrame       = -1;

            // Precompute the potential everywhere on the grid
            float[][] V = PrecomputeV();

            // Create the initial relative wavefunction
            Vec2 r0 = m_initialPosition1 - m_initialPosition2;
            Vec2 p0 = (m_mass2 / m_totalMass) * m_initialMomentum1 - (m_mass1 / m_totalMass) * m_initialMomentum2;
            int  sx = 2 * m_gridSizeX - 1; // The range of r = r1-r2 is twice the range of r1, r2
            int  sy = 2 * m_gridSizeY - 1;

            WaveFunction initialWf = WaveFunctionUtils.CreateGaussianWavePacket(
                sx, sy, m_latticeSpacing, true, m_reducedMass, r0, m_sigmaRel, p0, m_multiThread
                );

            m_visscherWf = new VisscherWf(initialWf, V, m_reducedMass, m_deltaT, m_multiThread);
            initialWf    = null; // Allow initialWf to be garbage collected
            TimeStepCompleted();
            if (IsCancelled)
            {
                return;
            }


            // Main loop: Evolve the relative wavefunction
            while (m_currentTimeStepIndex < m_totalNumTimeSteps)
            {
                // Evolve the wavefunction by one timestep
                EvolveByOneTimeStep(m_visscherWf, V);
                m_currentTimeStepIndex++;

                // Report progress to the client
                TimeStepCompleted();
                if (IsCancelled)
                {
                    return;
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Computes a single particle probability density by integrating over one of the particle coordinates.
        /// </summary>
        private ProbabilityDensity GetSingleParticleProbability(int particleIndex, double time)
        {
            int psx = m_gridSizeX;
            int psy = m_gridSizeY;

            // Precompute some constants we'll need
            double fm1            = m_mass1 / m_totalMass;
            double fm2            = m_mass2 / m_totalMass;
            double sigmaCmFactorX = Math.Pow(m_sigmaCm.X, 4) + (time * time) / (m_totalMass * m_totalMass);
            double sigmaCmFactorY = Math.Pow(m_sigmaCm.Y, 4) + (time * time) / (m_totalMass * m_totalMass);
            double RnormX         = m_sigmaCm.X / Math.Sqrt(Math.PI * sigmaCmFactorX);
            double RnormY         = m_sigmaCm.Y / Math.Sqrt(Math.PI * sigmaCmFactorY);
            Vec2   R0             = fm1 * m_initialPosition1 + fm2 * m_initialPosition2;
            Vec2   P0             = (m_initialMomentum1 + m_initialMomentum2);
            double RxOffset       = R0.X + time * (P0.X / m_totalMass);
            double RyOffset       = R0.Y + time * (P0.Y / m_totalMass);
            double RxScale        = -(m_sigmaCm.X * m_sigmaCm.X) / sigmaCmFactorX;
            double RyScale        = -(m_sigmaCm.Y * m_sigmaCm.Y) / sigmaCmFactorY;


            // Precompute the relative wavefunction probabilities
            ProbabilityDensity relDensity = m_visscherWf.ToRegularWavefunction().GetProbabilityDensity();


            // Get a one-particle probability by marginalizing over the joint probability
            float[][] oneParticleProbs = TdseUtils.Misc.Allocate2DArray(psy, psx);

            if (particleIndex == 1)
            {
                for (int y1 = 0; y1 < psy; y1++)
                {
                    // Precompute the center-of-mass wavefunction probabilities
                    float[] YExp = new float[psy];
                    for (int y2 = 0; y2 < psy; y2++)
                    {
                        double RyArg = (fm1 * y1 + fm2 * y2) * m_latticeSpacing - RyOffset;
                        YExp[y2] = (float)(RnormY * Math.Exp(RyScale * RyArg * RyArg));
                    }

                    TdseUtils.Misc.ForLoop(0, psx, x1 =>
                    {
                        float[] XExp = new float[psx];
                        for (int x2 = 0; x2 < psx; x2++)
                        {
                            double RxArg = (fm1 * x1 + fm2 * x2) * m_latticeSpacing - RxOffset;
                            XExp[x2]     = (float)(RnormX * Math.Exp(RxScale * RxArg * RxArg));
                        }

                        float prob = 0.0f;
                        for (int y2 = 0; y2 < psy; y2++)
                        {
                            float[] relProbsY = relDensity.Data[(y1 - y2) + psy - 1];

                            int xOffset = x1 + psx - 1;
                            float sum   = 0.0f;
                            for (int x2 = 0; x2 < psx; x2++)
                            {
                                sum += XExp[x2] * relProbsY[xOffset - x2];
                            }
                            prob += sum * YExp[y2];
                        }
                        oneParticleProbs[y1][x1] = prob * (m_latticeSpacing * m_latticeSpacing);
                    }, m_multiThread);

                    CheckForPause();
                    if (IsCancelled)
                    {
                        return(null);
                    }
                }
            }
            else
            {
                for (int y2 = 0; y2 < psy; y2++)
                {
                    // Precompute the center-of-mass wavefunction probabilities
                    float[] YExp = new float[psy];
                    for (int y1 = 0; y1 < psy; y1++)
                    {
                        double RyArg = (fm1 * y1 + fm2 * y2) * m_latticeSpacing - RyOffset;
                        YExp[y1] = (float)(RnormY * Math.Exp(RyScale * RyArg * RyArg));
                    }

                    TdseUtils.Misc.ForLoop(0, psx, x2 =>
                    {
                        float[] XExp = new float[psx];
                        for (int x1 = 0; x1 < psx; x1++)
                        {
                            double RxArg = (fm1 * x1 + fm2 * x2) * m_latticeSpacing - RxOffset;
                            XExp[x1]     = (float)(RnormX * Math.Exp(RxScale * RxArg * RxArg));
                        }

                        float prob = 0.0f;
                        for (int y1 = 0; y1 < psy; y1++)
                        {
                            float[] relProbsY = relDensity.Data[(y1 - y2) + psy - 1];

                            int xOffset = -x2 + psx - 1;
                            float sum   = 0.0f;
                            for (int x1 = 0; x1 < psx; x1++)
                            {
                                sum += XExp[x1] * relProbsY[x1 + xOffset];
                            }
                            prob += sum * YExp[y1];
                        }
                        oneParticleProbs[y2][x2] = prob * (m_latticeSpacing * m_latticeSpacing);
                    }, m_multiThread);

                    CheckForPause();
                    if (IsCancelled)
                    {
                        return(null);
                    }
                }
            }

            return(new ProbabilityDensity(oneParticleProbs, m_visscherWf.LatticeSpacing));
        }