/// <summary>
        /// Reads density values from a vtk stream.
        /// </summary>
        private static ProbabilityDensity FromVtkStream(BinaryReader br, int sizeX, int sizeY, int sizeZ, float latticeSpacing)
        {
            ProbabilityDensity result = new ProbabilityDensity(new GridSpec(sizeX, sizeY, sizeZ), latticeSpacing);

            unsafe
            {
                // For performance, we keep a temporary float value with pointers to its bytes
                float floatVal    = 0.0f;
                byte *floatBytes0 = (byte *)(&floatVal);
                byte *floatBytes1 = floatBytes0 + 1;
                byte *floatBytes2 = floatBytes0 + 2;
                byte *floatBytes3 = floatBytes0 + 3;

                // Read the density values
                ReadTextLine(br);
                ReadTextLine(br);
                for (int z = 0; z < sizeZ; z++)
                {
                    byte[] bytePlane = br.ReadBytes(sizeX * sizeY * 4);

                    int n = 0;
                    for (int y = 0; y < sizeY; y++)
                    {
                        float[] dataZY = result.Data[z][y];
                        for (int x = 0; x < sizeX; x++)
                        {
                            *floatBytes3 = bytePlane[n];
                            *floatBytes2 = bytePlane[n + 1];
                            *floatBytes1 = bytePlane[n + 2];
                            *floatBytes0 = bytePlane[n + 3];
                            dataZY[x] = floatVal;
                            n        += 4;
                        }
                    }
                }
            }

            return(result);
        }
Exemple #2
0
        /// <summary>
        /// Saves the current probability densities to a vtk file.
        /// </summary>
        private void SaveOutputFile(string fileSpec)
        {
            float time = m_currentTimeStepIndex * m_deltaT;

            ProbabilityDensity prob1 = GetSingleParticleProbability(1, time);

            if (prob1 == null)
            {
                return;
            }
            System.Diagnostics.Trace.WriteLine(prob1.Norm().ToString());

            ProbabilityDensity prob2 = GetSingleParticleProbability(2, time);

            if (prob2 == null)
            {
                return;
            }
            System.Diagnostics.Trace.WriteLine("          " + prob2.Norm().ToString());

            ProbabilityDensity.SaveToVtkFile(new ProbabilityDensity[] { prob1, prob2 }, fileSpec);
        }
Exemple #3
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));
        }