Exemple #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;
        }
Exemple #2
0
        /// <summary>
        /// Worker method.
        /// </summary>
        protected override void WorkerMethod()
        {
            // Reset counters
            m_currentTimeStepIndex = 0;
            m_lastSavedFrame       = -1;


            // Create a single-particle wf representing the incoming wavepacket
            WaveFunction2D1P initialWf1 = TdseSolver_2D1P.WaveFunctionUtils.CreateGaussianWavePacket(m_gridSizeX, m_gridSizeY, m_latticeSpacing,
                                                                                                     m_mass1, m_initialPosition1.ToPointF(), m_initialSize1.ToPointF(), m_initialMomentum1.ToPointF(), m_multiThread
                                                                                                     );

            // Create a single-particle wf representing the stationary bound state
            WaveFunction2D1P initialWf2 = WaveFunctionUtils.GetSHOWaveFunction(m_gridSizeX, m_gridSizeY, m_latticeSpacing,
                                                                               m_mass2, m_initialPosition2, m_sho_sigma, m_sho_N, m_sho_Lz, m_multiThread);

            // Precompute the potentials everywhere on the grid
            float[][] V1 = TdseUtils.Misc.Allocate2DArray(m_gridSizeY, m_gridSizeX);
            float[][] V2 = PrecomputeV2();

            // Create a VisscherWf from the direct product of the 1-particle wfs
            m_visscherWf = new VisscherWf(initialWf1, initialWf2, V1, V2, m_mass1, m_mass2, m_deltaT, m_multiThread);

            TimeStepCompleted();
            if (IsCancelled)
            {
                return;
            }

            float[][] Vrel = PrecomputeVrel();

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

                // Report progress to the client
                TimeStepCompleted();
                if (IsCancelled)
                {
                    return;
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Evolves the wavefunction by a single time step
        /// </summary>
        private void EvolveByOneTimeStep(VisscherWf wf, float[][] Vrel, float[][] V2)
        {
            // Initialize locals
            int sx   = m_gridSizeX;
            int sy   = m_gridSizeY;
            int sxm1 = sx - 1;
            int sym1 = sy - 1;

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

            float keFactor1 = 1.0f / (2 * m_mass1 * m_latticeSpacing * m_latticeSpacing);
            float keFactor2 = 1.0f / (2 * m_mass2 * m_latticeSpacing * m_latticeSpacing);


            // Compute the next real part in terms of the current imaginary part
            TdseUtils.Misc.ForLoop(0, sy, (y2) =>
            {
                int y2p  = (y2 < sym1) ?  y2 + 1 : 0;
                int y2pp = (y2p < sym1) ? y2p + 1 : 0;
                int y2m  = (y2 > 0) ?  y2 - 1 : sym1;
                int y2mm = (y2m > 0) ? y2m - 1 : sym1;

                for (int x2 = 0; x2 < sx; x2++)
                {
                    int x2p  = (x2 < sxm1) ?  x2 + 1 : 0;
                    int x2pp = (x2p < sxm1) ? x2p + 1 : 0;
                    int x2m  = (x2 > 0) ?  x2 - 1 : sxm1;
                    int x2mm = (x2m > 0) ? x2m - 1 : sxm1;

                    for (int y1 = 0; y1 < sy; y1++)
                    {
                        int y1p  = (y1 < sym1) ?  y1 + 1 : 0;
                        int y1pp = (y1p < sym1) ? y1p + 1 : 0;
                        int y1m  = (y1 > 0) ?  y1 - 1 : sym1;
                        int y1mm = (y1m > 0) ? y1m - 1 : sym1;

                        float[] wfi_y2_x2_y1   = wf.ImagPartP[y2][x2][y1];
                        float[] wfi_y2_x2_y1m  = wf.ImagPartP[y2][x2][y1m];
                        float[] wfi_y2_x2_y1p  = wf.ImagPartP[y2][x2][y1p];
                        float[] wfi_y2_x2_y1mm = wf.ImagPartP[y2][x2][y1mm];
                        float[] wfi_y2_x2_y1pp = wf.ImagPartP[y2][x2][y1pp];

                        float[] wfi_y2_x2p_y1  = wf.ImagPartP[y2][x2p][y1];
                        float[] wfi_y2_x2m_y1  = wf.ImagPartP[y2][x2m][y1];
                        float[] wfi_y2_x2mm_y1 = wf.ImagPartP[y2][x2mm][y1];
                        float[] wfi_y2_x2pp_y1 = wf.ImagPartP[y2][x2pp][y1];

                        float[] wfi_y2m_x2_y1  = wf.ImagPartP[y2m][x2][y1];
                        float[] wfi_y2p_x2_y1  = wf.ImagPartP[y2p][x2][y1];
                        float[] wfi_y2mm_x2_y1 = wf.ImagPartP[y2mm][x2][y1];
                        float[] wfi_y2pp_x2_y1 = wf.ImagPartP[y2pp][x2][y1];

                        float[] wfr_y2_x2_y1 = wf.RealPart[y2][x2][y1];

                        for (int x1 = 0; x1 < sx; x1++)
                        {
                            int x1p  = (x1 < sxm1) ?  x1 + 1 : 0;
                            int x1pp = (x1p < sxm1) ? x1p + 1 : 0;
                            int x1m  = (x1 > 0) ?  x1 - 1 : sxm1;
                            int x1mm = (x1m > 0) ? x1m - 1 : sxm1;

                            // Kinetic energy
                            float ke1 = keFactor1 * (
                                alpha * wfi_y2_x2_y1[x1] +
                                beta * (wfi_y2_x2_y1[x1m] + wfi_y2_x2_y1[x1p] + wfi_y2_x2_y1m[x1] + wfi_y2_x2_y1p[x1]) +
                                delta * (wfi_y2_x2_y1[x1mm] + wfi_y2_x2_y1[x1pp] + wfi_y2_x2_y1mm[x1] + wfi_y2_x2_y1pp[x1])
                                );

                            float ke2 = keFactor2 * (
                                alpha * wfi_y2_x2_y1[x1] +
                                beta * (wfi_y2_x2m_y1[x1] + wfi_y2_x2p_y1[x1] + wfi_y2m_x2_y1[x1] + wfi_y2p_x2_y1[x1]) +
                                delta * (wfi_y2_x2mm_y1[x1] + wfi_y2_x2pp_y1[x1] + wfi_y2mm_x2_y1[x1] + wfi_y2pp_x2_y1[x1])
                                );

                            // Potential energy
                            float pe = (V2[y2][x2] + Vrel[y2 - y1 + sym1][x2 - x1 + sxm1]) * wfi_y2_x2_y1[x1];

                            wfr_y2_x2_y1[x1] += m_deltaT * (ke1 + ke2 + 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, (y2) =>
            {
                int y2p  = (y2 < sym1) ?  y2 + 1 : 0;
                int y2pp = (y2p < sym1) ? y2p + 1 : 0;
                int y2m  = (y2 > 0) ?  y2 - 1 : sym1;
                int y2mm = (y2m > 0) ? y2m - 1 : sym1;

                for (int x2 = 0; x2 < sx; x2++)
                {
                    int x2p  = (x2 < sxm1) ?  x2 + 1 : 0;
                    int x2pp = (x2p < sxm1) ? x2p + 1 : 0;
                    int x2m  = (x2 > 0) ?  x2 - 1 : sxm1;
                    int x2mm = (x2m > 0) ? x2m - 1 : sxm1;

                    for (int y1 = 0; y1 < sy; y1++)
                    {
                        int y1p  = (y1 < sym1) ?  y1 + 1 : 0;
                        int y1pp = (y1p < sym1) ? y1p + 1 : 0;
                        int y1m  = (y1 > 0) ?  y1 - 1 : sym1;
                        int y1mm = (y1m > 0) ? y1m - 1 : sym1;

                        float[] wfr_y2_x2_y1   = wf.RealPart[y2][x2][y1];
                        float[] wfr_y2_x2_y1m  = wf.RealPart[y2][x2][y1m];
                        float[] wfr_y2_x2_y1p  = wf.RealPart[y2][x2][y1p];
                        float[] wfr_y2_x2_y1mm = wf.RealPart[y2][x2][y1mm];
                        float[] wfr_y2_x2_y1pp = wf.RealPart[y2][x2][y1pp];

                        float[] wfr_y2_x2p_y1  = wf.RealPart[y2][x2p][y1];
                        float[] wfr_y2_x2m_y1  = wf.RealPart[y2][x2m][y1];
                        float[] wfr_y2_x2mm_y1 = wf.RealPart[y2][x2mm][y1];
                        float[] wfr_y2_x2pp_y1 = wf.RealPart[y2][x2pp][y1];

                        float[] wfr_y2m_x2_y1  = wf.RealPart[y2m][x2][y1];
                        float[] wfr_y2p_x2_y1  = wf.RealPart[y2p][x2][y1];
                        float[] wfr_y2mm_x2_y1 = wf.RealPart[y2mm][x2][y1];
                        float[] wfr_y2pp_x2_y1 = wf.RealPart[y2pp][x2][y1];


                        for (int x1 = 0; x1 < sx; x1++)
                        {
                            int x1p  = (x1 < sxm1) ?  x1 + 1 : 0;
                            int x1pp = (x1p < sxm1) ? x1p + 1 : 0;
                            int x1m  = (x1 > 0) ?  x1 - 1 : sxm1;
                            int x1mm = (x1m > 0) ? x1m - 1 : sxm1;

                            // Kinetic energy
                            float ke1 = keFactor1 * (
                                alpha * wfr_y2_x2_y1[x1] +
                                beta * (wfr_y2_x2_y1[x1m] + wfr_y2_x2_y1[x1p] + wfr_y2_x2_y1m[x1] + wfr_y2_x2_y1p[x1]) +
                                delta * (wfr_y2_x2_y1[x1mm] + wfr_y2_x2_y1[x1pp] + wfr_y2_x2_y1mm[x1] + wfr_y2_x2_y1pp[x1])
                                );

                            float ke2 = keFactor2 * (
                                alpha * wfr_y2_x2_y1[x1] +
                                beta * (wfr_y2_x2m_y1[x1] + wfr_y2_x2p_y1[x1] + wfr_y2m_x2_y1[x1] + wfr_y2p_x2_y1[x1]) +
                                delta * (wfr_y2_x2mm_y1[x1] + wfr_y2_x2pp_y1[x1] + wfr_y2mm_x2_y1[x1] + wfr_y2pp_x2_y1[x1])
                                );

                            // Potential energy
                            float pe = (V2[y2][x2] + Vrel[y2 - y1 + sym1][x2 - x1 + sxm1]) * wfr_y2_x2_y1[x1];

                            wf.ImagPartP[y2][x2][y1][x1] = wf.ImagPartM[y2][x2][y1][x1] - m_deltaT * (ke1 + ke2 + pe);
                        }
                    }
                }
            }, m_multiThread);
        }