Example #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_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;
        }
Example #2
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;
                }
            }
        }
Example #3
0
        /// <summary>
        /// Damps the wavefunction amplitude near the region boundary.
        /// </summary>
        private void ApplyDamping(VisscherWf wf)
        {
            int sx = wf.GridSizeX;
            int sy = wf.GridSizeY;
            int d  = m_dampingBorderWidth;

            float[] factors = new float[d];
            for (int i = 0; i < d; i++)
            {
                factors[i] = (float)(1.0 - m_dampingFactor * m_deltaT * (1.0 - Math.Sin(((Math.PI / 2) * i) / d)));
            }

            // Top border
            for (int y = 0; y < d; y++)
            {
                float[] wfDataIPy = wf.ImagPartP[y];
                float[] wfDataIMy = wf.ImagPartM[y];
                float[] wfDataRy  = wf.RealPart[y];
                float   f         = factors[y];

                for (int x = 0; x < sx; x++)
                {
                    wfDataRy[x]  *= f;
                    wfDataIPy[x] *= f;
                    wfDataIMy[x] *= f;
                }
            }

            // Bottom border
            for (int y = sy - d; y < sy; y++)
            {
                float[] wfDataIPy = wf.ImagPartP[y];
                float[] wfDataIMy = wf.ImagPartM[y];
                float[] wfDataRy  = wf.RealPart[y];
                float   f         = factors[sy - 1 - y];

                for (int x = 0; x < sx; x++)
                {
                    wfDataRy[x]  *= f;
                    wfDataIPy[x] *= f;
                    wfDataIMy[x] *= f;
                }
            }

            // Left and right borders
            for (int y = 0; y < sy; y++)
            {
                float[] wfDataIPy = wf.ImagPartP[y];
                float[] wfDataIMy = wf.ImagPartM[y];
                float[] wfDataRy  = wf.RealPart[y];

                for (int x = 0; x < d; x++)
                {
                    float f = factors[x];
                    wfDataRy[x]  *= f;
                    wfDataIPy[x] *= f;
                    wfDataIMy[x] *= f;
                }
                for (int x = sx - d; x < sx; x++)
                {
                    float f = factors[sx - 1 - x];
                    wfDataRy[x]  *= f;
                    wfDataIPy[x] *= f;
                    wfDataIMy[x] *= f;
                }
            }
        }
Example #4
0
        /// <summary>
        /// Evolves the wavefunction by a single time step
        /// </summary>
        private void EvolveByOneTimeStep(VisscherWf wf, float[][] V)
        {
            int   sx       = wf.GridSizeX;
            int   sy       = wf.GridSizeY;
            int   sxm1     = sx - 1;
            int   sym1     = sy - 1;
            float keFactor = 1.0f / (2 * m_reducedMass * wf.LatticeSpacing * wf.LatticeSpacing);

            float alpha = 5.0f;
            float beta  = -4.0f / 3.0f;
            float delta = 1.0f / 12.0f;

            // Compute the next real part in terms of the current imaginary part
            TdseUtils.Misc.ForLoop(0, sy, y =>
            {
                int yp  = (y < sym1) ?  y + 1 : 0;
                int ypp = (yp < sym1) ? yp + 1 : 0;
                int ym  = (y > 0) ?  y - 1 : sym1;
                int ymm = (ym > 0) ? ym - 1 : sym1;

                float[] V_y     = V[y];
                float[] wfR_y   = wf.RealPart[y];
                float[] wfI_y   = wf.ImagPartP[y];
                float[] wfI_ym  = wf.ImagPartP[ym];
                float[] wfI_yp  = wf.ImagPartP[yp];
                float[] wfI_ymm = wf.ImagPartP[ymm];
                float[] wfI_ypp = wf.ImagPartP[ypp];

                for (int x = 0; x < sx; x++)
                {
                    int xp  = (x < sxm1) ?  x + 1 : 0;
                    int xpp = (xp < sxm1) ? xp + 1 : 0;
                    int xm  = (x > 0) ?  x - 1 : sxm1;
                    int xmm = (xm > 0) ? xm - 1 : sxm1;

                    // A discretization of the 2nd derivative, whose error term is O(a^6)
                    float ke = keFactor * (
                        alpha * wfI_y[x] +
                        beta * (wfI_y[xm] + wfI_y[xp] + wfI_ym[x] + wfI_yp[x]) +
                        delta * (wfI_y[xmm] + wfI_y[xpp] + wfI_ymm[x] + wfI_ypp[x])
                        );

                    float pe = V_y[x] * wfI_y[x];

                    wfR_y[x] += m_deltaT * (ke + pe);
                }
            }, m_multiThread);


            // Swap prev and post imaginary parts
            float[][] temp = wf.ImagPartM;
            wf.ImagPartM = wf.ImagPartP;
            wf.ImagPartP = temp;


            // Compute the next imaginary part in terms of the current real part
            TdseUtils.Misc.ForLoop(0, sy, y =>
            {
                int yp  = (y < sym1) ?  y + 1 : 0;
                int ypp = (yp < sym1) ? yp + 1 : 0;
                int ym  = (y > 0) ?  y - 1 : sym1;
                int ymm = (ym > 0) ? ym - 1 : sym1;

                float[] V_y     = V[y];
                float[] wfIM_y  = wf.ImagPartM[y];
                float[] wfIP_y  = wf.ImagPartP[y];
                float[] wfR_y   = wf.RealPart[y];
                float[] wfR_ym  = wf.RealPart[ym];
                float[] wfR_yp  = wf.RealPart[yp];
                float[] wfR_ymm = wf.RealPart[ymm];
                float[] wfR_ypp = wf.RealPart[ypp];

                for (int x = 0; x < sx; x++)
                {
                    int xp  = (x < sxm1) ?  x + 1 : 0;
                    int xpp = (xp < sxm1) ? xp + 1 : 0;
                    int xm  = (x > 0) ?  x - 1 : sxm1;
                    int xmm = (xm > 0) ? xm - 1 : sxm1;

                    // A discretization of the 2nd derivative, whose error term is O(a^6)
                    float ke = keFactor * (
                        alpha * wfR_y[x] +
                        beta * (wfR_y[xm] + wfR_y[xp] + wfR_ym[x] + wfR_yp[x]) +
                        delta * (wfR_y[xmm] + wfR_y[xpp] + wfR_ymm[x] + wfR_ypp[x])
                        );

                    float pe = V_y[x] * wfR_y[x];

                    wfIP_y[x] = wfIM_y[x] - m_deltaT * (ke + pe);
                }
            }, m_multiThread);


            // Optionally perform damping to suppress reflection and transmission at the borders.
            if ((m_dampingBorderWidth > 0) && (m_dampingFactor > 0.0f))
            {
                ApplyDamping(wf);
            }
        }