示例#1
0
        /// <summary>
        /// Worker method.
        /// </summary>
        protected override void WorkerMethod()
        {
            // Precompute the potential everywhere on the grid
            float[][][] V = PrecomputeV(0);

            // Create a Visscher wf from the input wf
            m_visscherWf = new VisscherWf(m_intialWf, V, m_particleMass, m_deltaT, m_multiThread);
            m_intialWf   = null; // Allow m_initialWf to be garbage collected

            // Main loop
            m_currentTimeStepIndex = 0;
            while (m_currentTimeStepIndex < m_totalNumTimeSteps)
            {
                // Compute the potential at the current time, if necessary
                if (m_isTimeDependentV && (m_currentTimeStepIndex > 0))
                {
                    V = PrecomputeV(m_currentTimeStepIndex * m_deltaT);
                }

                // Evolve the wavefunction by one timestep
                EvolveByOneTimeStep(m_visscherWf, V);
                m_currentTimeStepIndex++;

                // Report progress to the caller
                if (m_currentTimeStepIndex % m_reportInterval == 0)
                {
                    ReportProgress();
                    if (IsCancelled)
                    {
                        return;
                    }
                }
            }
        }
示例#2
0
 /// <summary>
 /// Constructor.
 /// </summary>
 public Evolver(WaveFunction initialWf, float totalTime, float timeStep, VDelegate V, bool isVTimeDependent, float particleMass, int progressReportInterval,
                int dampingBorderWidth = 0, float dampingFactor = 0.0f, bool multiThread = true)
 {
     m_intialWf             = initialWf;
     m_visscherWf           = null;
     m_potential            = V;
     m_isTimeDependentV     = isVTimeDependent;
     m_particleMass         = particleMass;
     m_totalTime            = totalTime;
     m_deltaT               = timeStep;
     m_currentTimeStepIndex = 0;
     m_totalNumTimeSteps    = (int)Math.Round(totalTime / timeStep) + 1;
     m_reportInterval       = progressReportInterval;
     m_dampingBorderWidth   = dampingBorderWidth;
     m_dampingFactor        = dampingFactor;
     m_multiThread          = multiThread;
 }
示例#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;
                    }
                }
            }
        }
示例#4
0
        /// <summary>
        /// Evolves the wavefunction by a single timestep
        /// </summary>
        private void EvolveByOneTimeStep(VisscherWf wf, float[][][] V)
        {
            int sx = wf.GridSpec.SizeX;
            int sy = wf.GridSpec.SizeY;
            int sz = wf.GridSpec.SizeZ;

            int sxm1 = sx - 1;
            int sym1 = sy - 1;
            int szm1 = sz - 1;

            float keFactor = (1.0f / 12.0f) / (2 * m_particleMass * 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);
            }
        }