Example #1
0
        /// <summary>
        /// Calculates the value of a (freely evolving) Gaussian wavepacket at a given location and time.
        /// </summary>
        public static Complex FreeGaussianWavePacketValue(float x, float y, float z, float t,
                                                          Vec3 initialCenter, Vec3 initialWidth, Vec3 avgMomentum, float mass)
        {
            Complex I = Complex.I;

            Complex effSigmaXSq = initialWidth.X * initialWidth.X + I * (t / mass);
            Complex effSigmaYSq = initialWidth.Y * initialWidth.Y + I * (t / mass);
            Complex effSigmaZSq = initialWidth.Z * initialWidth.Z + I * (t / mass);

            float xRel = x - initialCenter.X - avgMomentum.X * t / mass;
            float yRel = y - initialCenter.Y - avgMomentum.Y * t / mass;
            float zRel = z - initialCenter.Z - avgMomentum.Z * t / mass;

            float avgMomentumSq = avgMomentum.NormSq();

            Complex expArg = I * (x * avgMomentum.X + y * avgMomentum.Y + z * avgMomentum.Z) - I * t * avgMomentumSq / (2 * mass) -
                             (xRel * xRel) / (2 * effSigmaXSq) - (yRel * yRel) / (2 * effSigmaYSq) - (zRel * zRel) / (2 * effSigmaZSq);

            float   rootPi = (float)Math.Sqrt(Math.PI);
            Complex normX  = Complex.Sqrt(initialWidth.X / (rootPi * effSigmaXSq));
            Complex normY  = Complex.Sqrt(initialWidth.Y / (rootPi * effSigmaYSq));
            Complex normZ  = Complex.Sqrt(initialWidth.Z / (rootPi * effSigmaZSq));

            Complex wfVal = normX * normY * normZ * Complex.Exp(expArg);

            return(wfVal);
        }
Example #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public Evolver(RunParams parms, VDelegate V, string outputDir)
        {
            m_gridSizeX            = parms.GridSpec.SizeX;
            m_gridSizeY            = parms.GridSpec.SizeY;
            m_gridSizeZ            = parms.GridSpec.SizeZ;
            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 Vec3(parms.InitialWavePacketMomentum1);
            m_initialMomentum2 = new Vec3(parms.InitialWavePacketMomentum2);
            m_initialPosition1 = new Vec3(parms.InitialWavePacketCenter1);
            m_initialPosition2 = new Vec3(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;
        }
Example #3
0
        /// <summary>
        /// Creates a Gaussian wavepacket with given properties.
        /// </summary>
        public static WaveFunction CreateGaussianWavePacket(
            GridSpec gridSpec, float latticeSpacing, bool originAtLatticeCenter, float mass,
            Vec3 packetCenter, Vec3 packetWidth, Vec3 avgMomentum, bool multiThread = true)
        {
            WaveFunction wf = new WaveFunction(gridSpec, latticeSpacing);

            int sx = gridSpec.SizeX;
            int sy = gridSpec.SizeY;
            int sz = gridSpec.SizeZ;

            float[][][] wfData = wf.Data;


            Complex I             = Complex.I;
            float   rootPi        = (float)Math.Sqrt(Math.PI);
            float   sigmaXSq      = packetWidth.X * packetWidth.X;
            float   sigmaYSq      = packetWidth.Y * packetWidth.Y;
            float   sigmaZSq      = packetWidth.Z * packetWidth.Z;
            float   norm          = (float)Math.Sqrt(1.0 / (rootPi * packetWidth.X * rootPi * packetWidth.Y * rootPi * packetWidth.Z));
            int     halfGridSizeX = (sx - 1) / 2;
            int     halfGridSizeY = (sy - 1) / 2;
            int     halfGridSizeZ = (sz - 1) / 2;

            TdseUtils.Misc.ForLoop(0, sz, (z) =>
            {
                float zf        = (originAtLatticeCenter) ? (z - halfGridSizeZ) * latticeSpacing : (z * latticeSpacing);
                Complex expArgZ = I * zf * avgMomentum.Z - (zf - packetCenter.Z) * (zf - packetCenter.Z) / (2 * sigmaZSq);

                for (int y = 0; y < sy; y++)
                {
                    float yf         = (originAtLatticeCenter) ? (y - halfGridSizeY) * latticeSpacing : (y * latticeSpacing);
                    Complex expArgZY = expArgZ + I * yf * avgMomentum.Y - (yf - packetCenter.Y) * (yf - packetCenter.Y) / (2 * sigmaYSq);

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

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

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

            wf.Normalize();
            return(wf);
        }
Example #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
            Vec3 r0 = m_initialPosition1 - m_initialPosition2;
            Vec3 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;
            int  sz = 2 * m_gridSizeZ - 1;

            WaveFunction initialWf = WaveFunctionUtils.CreateGaussianWavePacket(
                new GridSpec(sx, sy, sz), 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;
                }
            }
        }
Example #5
0
        /// <summary>
        /// Computes a single particle probability density by integrating over one of the particle coordinates.
        /// </summary>
        private unsafe ProbabilityDensity GetSingleParticleProbability(int particleIndex, double time)
        {
            int psx = m_gridSizeX;
            int psy = m_gridSizeY;
            int psz = m_gridSizeZ;

            // 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 sigmaCmFactorZ = Math.Pow(m_sigmaCm.Z, 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);
            double RnormZ         = m_sigmaCm.Z / Math.Sqrt(Math.PI * sigmaCmFactorZ);
            Vec3   R0             = fm1 * m_initialPosition1 + fm2 * m_initialPosition2;
            Vec3   P0             = (m_initialMomentum1 + m_initialMomentum2);
            double RxOffset       = R0.X + time * (P0.X / m_totalMass);
            double RyOffset       = R0.Y + time * (P0.Y / m_totalMass);
            double RzOffset       = R0.Z + time * (P0.Z / m_totalMass);
            double RxScale        = -(m_sigmaCm.X * m_sigmaCm.X) / sigmaCmFactorX;
            double RyScale        = -(m_sigmaCm.Y * m_sigmaCm.Y) / sigmaCmFactorY;
            double RzScale        = -(m_sigmaCm.Z * m_sigmaCm.Z) / sigmaCmFactorZ;


            // 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.Allocate3DArray(psz, psy, psx);

            if (particleIndex == 1)
            {
                for (int z1 = 0; z1 < psz; z1++)
                {
                    // Precompute the center-of-mass wavefunction probabilities
                    float[] ZExp = new float[psz];
                    for (int z2 = 0; z2 < psz; z2++)
                    {
                        double RzArg = (fm1 * z1 + fm2 * z2) * m_latticeSpacing - RzOffset;
                        ZExp[z2] = (float)(RnormZ * Math.Exp(RzScale * RzArg * RzArg));
                    }

                    TdseUtils.Misc.ForLoop(0, 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));
                        }

                        for (int x1 = 0; x1 < 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));
                            }
                            fixed(float *pXExp = XExp)
                            {
                                float prob = 0.0f;
                                for (int z2 = 0; z2 < psz; z2++)
                                {
                                    int xOffset         = x1 + psx - 1;
                                    float[][] relProbsZ = relDensity.Data[(z1 - z2) + psz - 1];

                                    for (int y2 = 0; y2 < psy; y2++)
                                    {
                                        float yzExpFactor        = YExp[y2] * ZExp[z2];
                                        fixed(float *pRelProbsZY = &(relProbsZ[(y1 - y2) + psy - 1][xOffset]))
                                        {
                                            float sum = 0.0f;
                                            for (int x2 = 0; x2 < psx; x2++)
                                            {
                                                sum += pXExp[x2] * pRelProbsZY[-x2];
                                            }
                                            prob += sum * yzExpFactor;
                                        }
                                    }
                                }
                                oneParticleProbs[z1][y1][x1] = prob * (m_latticeSpacing * m_latticeSpacing * m_latticeSpacing);
                            }
                        }
                    }, m_multiThread);

                    CheckForPause();
                    if (IsCancelled)
                    {
                        return(null);
                    }
                }
            }
            else
            {
                for (int z2 = 0; z2 < psz; z2++)
                {
                    // Precompute the center-of-mass wavefunction probabilities
                    float[] ZExp = new float[psz];
                    for (int z1 = 0; z1 < psz; z1++)
                    {
                        double RzArg = (fm1 * z1 + fm2 * z2) * m_latticeSpacing - RzOffset;
                        ZExp[z1] = (float)(RnormZ * Math.Exp(RzScale * RzArg * RzArg));
                    }

                    TdseUtils.Misc.ForLoop(0, 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));
                        }

                        for (int x2 = 0; x2 < 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));
                            }
                            fixed(float *pXExp = XExp)
                            {
                                float prob = 0.0f;
                                for (int z1 = 0; z1 < psz; z1++)
                                {
                                    float[][] relProbsZ = relDensity.Data[(z1 - z2) + psz - 1];

                                    int xOffset = -x2 + psx - 1;
                                    for (int y1 = 0; y1 < psy; y1++)
                                    {
                                        float yzExpFactor        = YExp[y1] * ZExp[z1];
                                        fixed(float *pRelProbsZY = &(relProbsZ[(y1 - y2) + psy - 1][xOffset]))
                                        {
                                            float sum = 0.0f;
                                            for (int x1 = 0; x1 < psx; x1++)
                                            {
                                                sum += pXExp[x1] * pRelProbsZY[x1];
                                            }
                                            prob += sum * yzExpFactor;
                                        }
                                    }
                                }
                                oneParticleProbs[z2][y2][x2] = prob * (m_latticeSpacing * m_latticeSpacing * m_latticeSpacing);
                            }
                        }
                    }, m_multiThread);

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

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