Exemple #1
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;
        }
Exemple #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
            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;
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Damps the wavefunction amplitude near the region boundary.
        /// </summary>
        private void ApplyDamping(VisscherWf wf)
        {
            int sx = wf.GridSpec.SizeX;
            int sy = wf.GridSpec.SizeY;
            int sz = wf.GridSpec.SizeZ;

            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)));
            }

            // Front Z border
            for (int z = 0; z < d; z++)
            {
                float f = factors[z];

                for (int y = 0; y < sy; y++)
                {
                    float[] wfDataIPzy = wf.ImagPartP[z][y];
                    float[] wfDataIMzy = wf.ImagPartM[z][y];
                    float[] wfDataRzy  = wf.RealPart[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }
                }
            }

            // Back Z border
            for (int z = sz - d; z < sz; z++)
            {
                float f = factors[sz - 1 - z];

                for (int y = 0; y < sy; y++)
                {
                    float[] wfDataIPzy = wf.ImagPartP[z][y];
                    float[] wfDataIMzy = wf.ImagPartM[z][y];
                    float[] wfDataRzy  = wf.RealPart[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }
                }
            }

            // Y borders
            for (int z = 0; z < sz; z++)
            {
                for (int y = 0; y < d; y++)
                {
                    float   f          = factors[y];
                    float[] wfDataIPzy = wf.ImagPartP[z][y];
                    float[] wfDataIMzy = wf.ImagPartM[z][y];
                    float[] wfDataRzy  = wf.RealPart[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }
                }
                for (int y = sy - d; y < sy; y++)
                {
                    float   f          = factors[sy - 1 - y];
                    float[] wfDataIPzy = wf.ImagPartP[z][y];
                    float[] wfDataIMzy = wf.ImagPartM[z][y];
                    float[] wfDataRzy  = wf.RealPart[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }
                }
            }


            // X borders
            for (int z = 0; z < sz; z++)
            {
                for (int y = 0; y < sy; y++)
                {
                    float[] wfDataIPzy = wf.ImagPartP[z][y];
                    float[] wfDataIMzy = wf.ImagPartM[z][y];
                    float[] wfDataRzy  = wf.RealPart[z][y];

                    for (int x = 0; x < d; x++)
                    {
                        float f = factors[x];
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }

                    for (int x = sx - d; x < sx; x++)
                    {
                        float f = factors[sx - 1 - x];
                        wfDataRzy[x]  *= f;
                        wfDataIPzy[x] *= f;
                        wfDataIMzy[x] *= f;
                    }
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Evolves the wavefunction by a single time step
        /// </summary>
        private void EvolveByOneTimeStep(VisscherWf wf, float[][][] V)
        {
            GridSpec wfGrid = wf.GridSpec;
            int      sx     = wfGrid.SizeX;
            int      sy     = wfGrid.SizeY;
            int      sz     = wfGrid.SizeZ;
            int      sxm1   = sx - 1;
            int      sym1   = sy - 1;
            int      szm1   = sz - 1;

            float keFactor = (1.0f / 12.0f) / (2 * m_reducedMass * wf.LatticeSpacing * wf.LatticeSpacing);


            // Compute the next real part in terms of the current imaginary part
            TdseUtils.Misc.ForLoop(0, sz, z =>
            {
                int zp  = (z < szm1) ?  z + 1 : 0;
                int zpp = (zp < szm1) ? zp + 1 : 0;
                int zm  = (z > 0) ?  z - 1 : szm1;
                int zmm = (zm > 0) ? zm - 1 : szm1;

                for (int y = 0; y < 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_z_y     = V[z][y];
                    float[] wfR_z_y   = wf.RealPart[z][y];
                    float[] wfI_z_y   = wf.ImagPartP[z][y];
                    float[] wfI_z_ym  = wf.ImagPartP[z][ym];
                    float[] wfI_z_yp  = wf.ImagPartP[z][yp];
                    float[] wfI_z_ymm = wf.ImagPartP[z][ymm];
                    float[] wfI_z_ypp = wf.ImagPartP[z][ypp];
                    float[] wfI_zm_y  = wf.ImagPartP[zm][y];
                    float[] wfI_zp_y  = wf.ImagPartP[zp][y];
                    float[] wfI_zmm_y = wf.ImagPartP[zmm][y];
                    float[] wfI_zpp_y = wf.ImagPartP[zpp][y];

                    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;

                        // Discretization of the 2nd derivative
                        float ke = keFactor * (
                            90.0f * wfI_z_y[x] -
                            16.0f * (wfI_zm_y[x] + wfI_zp_y[x] + wfI_z_yp[x] + wfI_z_ym[x] + wfI_z_y[xm] + wfI_z_y[xp]) +
                            (wfI_zmm_y[x] + wfI_zpp_y[x] + wfI_z_ypp[x] + wfI_z_ymm[x] + wfI_z_y[xmm] + wfI_z_y[xpp])
                            );

                        float pe = V_z_y[x] * wfI_z_y[x];

                        wfR_z_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, sz, z =>
            {
                int zp  = (z < szm1) ?  z + 1 : 0;
                int zpp = (zp < szm1) ? zp + 1 : 0;
                int zm  = (z > 0) ?  z - 1 : szm1;
                int zmm = (zm > 0) ? zm - 1 : szm1;

                for (int y = 0; y < 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_z_y     = V[z][y];
                    float[] wfIM_z_y  = wf.ImagPartM[z][y];
                    float[] wfIP_z_y  = wf.ImagPartP[z][y];
                    float[] wfR_z_y   = wf.RealPart[z][y];
                    float[] wfR_z_ym  = wf.RealPart[z][ym];
                    float[] wfR_z_yp  = wf.RealPart[z][yp];
                    float[] wfR_z_ymm = wf.RealPart[z][ymm];
                    float[] wfR_z_ypp = wf.RealPart[z][ypp];
                    float[] wfR_zm_y  = wf.RealPart[zm][y];
                    float[] wfR_zp_y  = wf.RealPart[zp][y];
                    float[] wfR_zmm_y = wf.RealPart[zmm][y];
                    float[] wfR_zpp_y = wf.RealPart[zpp][y];

                    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;

                        // Discretization of the 2nd derivative
                        float ke = keFactor * (
                            90.0f * wfR_z_y[x] -
                            16.0f * (wfR_zm_y[x] + wfR_zp_y[x] + wfR_z_yp[x] + wfR_z_ym[x] + wfR_z_y[xm] + wfR_z_y[xp]) +
                            (wfR_zmm_y[x] + wfR_zpp_y[x] + wfR_z_ypp[x] + wfR_z_ymm[x] + wfR_z_y[xmm] + wfR_z_y[xpp])
                            );

                        float pe = V_z_y[x] * wfR_z_y[x];

                        wfIP_z_y[x] = wfIM_z_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);
            }
        }