コード例 #1
0
ファイル: Evolver.cs プロジェクト: aarongrisez/TDSE
        /// <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
ファイル: VisscherWf.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Constructor. Initializes a Visscher wavefunction from an ordinary wavefunction.
        /// </summary>
        public VisscherWf(WaveFunction inputWf, float[][][] V, float mass, float dt, bool multiThread = true)
        {
            int sx = inputWf.GridSpec.SizeX;
            int sy = inputWf.GridSpec.SizeY;
            int sz = inputWf.GridSpec.SizeZ;

            LatticeSpacing = inputWf.LatticeSpacing;

            // Allocate the arrays
            RealPart  = TdseUtils.Misc.Allocate3DArray(sz, sy, sx);
            ImagPartM = TdseUtils.Misc.Allocate3DArray(sz, sy, sx);
            ImagPartP = TdseUtils.Misc.Allocate3DArray(sz, sy, sx);

            // For the real part, just copy the values from the input wavefunction.
            for (int z = 0; z < sz; z++)
            {
                for (int y = 0; y < sy; y++)
                {
                    float[] realPartZY = RealPart[z][y];
                    float[] inputWfZY  = inputWf.Data[z][y];
                    for (int x = 0; x < sx; x++)
                    {
                        realPartZY[x] = inputWfZY[2 * x];
                    }
                }
            }

            // For the imaginary parts, we need to compute the time evolutions.
            // We use a power series expansion of the time-evolution operator, accurate to 2nd order in H*dt
            WaveFunction H_PsiIn  = inputWf.ApplyH(V, mass, multiThread);
            WaveFunction H2_PsiIn = H_PsiIn.ApplyH(V, mass, multiThread);

            float halfDt    = dt / 2;
            float eighthDt2 = dt * dt / 8;

            TdseUtils.Misc.ForLoop(0, sz, (z) =>
            {
                for (int y = 0; y < sy; y++)
                {
                    float[] imPZY      = this.ImagPartP[z][y];
                    float[] imMZY      = this.ImagPartM[z][y];
                    float[] inputWfZY  = inputWf.Data[z][y];
                    float[] H_PsiInZY  = H_PsiIn.Data[z][y];
                    float[] H2_PsiInZY = H2_PsiIn.Data[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        int x2   = 2 * x;
                        int x2p1 = x2 + 1;

                        float dt0Term = inputWfZY[x2p1];
                        float dt1Term = halfDt * H_PsiInZY[x2];
                        float dt2Term = eighthDt2 * H2_PsiInZY[x2p1];

                        imPZY[x] = dt0Term - dt1Term - dt2Term; // [1 - i*H*(dt/2) - (1/2)H^2*(dt/2)^2] * Psi
                        imMZY[x] = dt0Term + dt1Term - dt2Term; // [1 + i*H*(dt/2) - (1/2)H^2*(dt/2)^2] * Psi
                    }
                }
            }, multiThread);
        }
コード例 #3
0
ファイル: SolverControl.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Evolves the wavefunction and saves keyframes to disk.
        /// </summary>
        private void CreateAnimationFrames()
        {
            // Get a fresh output directory
            m_outputDir = CreateOutputDir();

            // Write the run parameters to a file
            string paramsFile = Path.Combine(m_outputDir, "Params.txt");

            File.WriteAllText(paramsFile, m_params.ToString().Replace("\n", "\r\n"));


            // Create the initial wavefunction
            WaveFunction wf = WaveFunctionUtils.CreateGaussianWavePacket(
                m_params.GridSpec, m_params.LatticeSpacing, m_params.ParticleMass,
                m_params.InitialWavePacketCenter,
                m_params.InitialWavePacketSize,
                m_params.InitialWavePacketMomentum,
                m_params.MultiThread
                );

            // Save the initial wf as Frame 0
            wf.SaveToVtkFile(Path.Combine(m_outputDir, "Frame_0000.vtk"), m_params.SaveFormat);
            m_lastSavedFrame = 0;


            // Create an Evolver and run it in the background
            Evolver.VDelegate V = (x, y, z, t, m, sx, sy, sz) => { return(m_VBuilder.V(x, y, z, t, m, sx, sy, sz)); };

            m_evolver = new Evolver(wf, m_params.TotalTime, m_params.TimeStep, V, false, m_params.ParticleMass, 1,
                                    m_params.DampingBorderWidth, m_params.DampingFactor, m_params.MultiThread);
            m_evolver.ProgressEvent   += Evolver_ProgressEvent;
            m_evolver.CompletionEvent += Evolver_CompletionEvent;

            m_evolver.RunInBackground();
        }
コード例 #4
0
ファイル: VisscherWf.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Converts a Visscher wavefunction to a regular wavefunction.
        /// </summary>
        public WaveFunction ToRegularWavefunction(bool multiThread = true)
        {
            int sx = GridSpec.SizeX;
            int sy = GridSpec.SizeY;
            int sz = GridSpec.SizeZ;

            WaveFunction result = new WaveFunction(GridSpec, LatticeSpacing);

            TdseUtils.Misc.ForLoop(0, sz, (z) =>
            {
                for (int y = 0; y < sy; y++)
                {
                    float[] thisRzy  = RealPart[z][y];
                    float[] thisIMzy = ImagPartM[z][y];
                    float[] thisIPzy = ImagPartP[z][y];
                    float[] outWfzy  = result.Data[z][y];

                    for (int x = 0; x < sx; x++)
                    {
                        outWfzy[2 * x] = thisRzy[x];

                        // Take the square root of Im(t-dt/2) * I(t+dt/2), as this is the quantity that gives a conserved probability.
                        float IM       = thisIMzy[x];
                        float IP       = thisIPzy[x];
                        float Iproduct = IM * IP;

                        float Iout;
                        if (Iproduct > 0.0f)
                        {
                            Iout = (float)Math.Sqrt(Iproduct);
                            if (IM < 0.0f)
                            {
                                Iout = -Iout;
                            }
                        }
                        else
                        {
                            Iout = 0.0f;
                        }

                        outWfzy[2 * x + 1] = Iout;
                    }
                }
            }, multiThread);

            return(result);
        }
コード例 #5
0
ファイル: Evolver.cs プロジェクト: aarongrisez/TDSE
 /// <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;
 }
コード例 #6
0
        /// <summary>
        /// Creates a Gaussian wavepacket with given properties.
        /// </summary>
        public static WaveFunction CreateGaussianWavePacket(
            GridSpec gridSpec, float latticeSpacing, float mass, Vec3 packetCenter, Vec3 packetWidth, Vec3 avgMomentum, bool multiThread = true)
        {
            WaveFunction wf = new WaveFunction(gridSpec, latticeSpacing);

            int sx = gridSpec.SizeX;
            int sy = gridSpec.SizeY;
            int sz = gridSpec.SizeZ;

            float[][][] wfData = wf.Data;

            Complex I        = Complex.I;
            float   rootPi   = (float)Math.Sqrt(Math.PI);
            float   sigmaXSq = packetWidth.X * packetWidth.X;
            float   sigmaYSq = packetWidth.Y * packetWidth.Y;
            float   sigmaZSq = packetWidth.Z * packetWidth.Z;
            float   norm     = (float)Math.Sqrt((packetWidth.X / (rootPi * sigmaXSq)) * (packetWidth.Y / (rootPi * sigmaYSq)) * (packetWidth.Z / (rootPi * sigmaZSq)));

            TdseUtils.Misc.ForLoop(0, sz, (z) =>
            {
                float zf        = z * latticeSpacing;
                Complex expArgZ = I * zf * avgMomentum.Z - (zf - packetCenter.Z) * (zf - packetCenter.Z) / (2 * sigmaZSq);

                for (int y = 0; y < sy; y++)
                {
                    float yf         = y * latticeSpacing;
                    Complex expArgZY = expArgZ + I * yf * avgMomentum.Y - (yf - packetCenter.Y) * (yf - packetCenter.Y) / (2 * sigmaYSq);

                    float[] wfDataZY = wfData[z][y];
                    for (int x = 0; x < sx; x++)
                    {
                        float xf = x * latticeSpacing;

                        Complex expArgZYX = expArgZY + I * xf * avgMomentum.X - (xf - packetCenter.X) * (xf - packetCenter.X) / (2 * sigmaXSq);
                        Complex wfVal     = norm * Complex.Exp(expArgZYX);

                        wfDataZY[2 * x]     = wfVal.Re;
                        wfDataZY[2 * x + 1] = wfVal.Im;
                    }
                }
            }, multiThread);

            wf.Normalize();
            return(wf);
        }
コード例 #7
0
        /// <summary>
        /// Processes a single input file.
        /// </summary>
        private void ProcessFile(string inFile, string outFile, WaveFunction.ColorDelegate colorFunc)
        {
            unsafe
            {
                int    sx             = -1;
                int    sy             = -1;
                int    sz             = -1;
                string inFormat       = "";
                float  latticeSpacing = 0.0f;
                long   inDataStartPos = 0;
                string nl             = Environment.NewLine;

                float fa = 0.0f, fb = 0.0f;
                byte *fa0 = (byte *)(&fa);
                byte *fa1 = fa0 + 1;
                byte *fa2 = fa0 + 2;
                byte *fa3 = fa0 + 3;
                byte *fb0 = (byte *)(&fb);
                byte *fb1 = fb0 + 1;
                byte *fb2 = fb0 + 2;
                byte *fb3 = fb0 + 3;


                using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open)))
                {
                    // Parse the header of the input file
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        string textLine = WaveFunction.ReadTextLine(br);

                        if (textLine.StartsWith("Wavefunction3D"))
                        {
                            string[] comps = textLine.Split(null);
                            inFormat       = comps[1];
                            latticeSpacing = Single.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("DIMENSIONS"))
                        {
                            string[] comps = textLine.Split(null);
                            sx = Int32.Parse(comps[1]);
                            sy = Int32.Parse(comps[2]);
                            sz = Int32.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("LOOKUP_TABLE default"))
                        {
                            break;
                        }
                    }
                    // Bail out if the header was not what we expected
                    if (string.IsNullOrEmpty(inFormat) || (sx < 0) || (sy < 0) || (sz < 0))
                    {
                        throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile.");
                    }
                    if (inFormat != "REAL_AND_IMAG")
                    {
                        throw new ArgumentException("Unsupported Wavefunction format, in Colorer.ProcessFile. " + "(" + inFormat + ")");
                    }
                    inDataStartPos = br.BaseStream.Position;



                    // Create output file
                    using (FileStream fileStream = File.Create(outFile))
                    {
                        using (BinaryWriter bw = new BinaryWriter(fileStream))
                        {
                            // Write the output header
                            string outFormat = (colorFunc == null) ? "AMPLITUDE_ONLY" : "AMPLITUDE_AND_COLOR";
                            bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + outFormat.ToString() + " " + "spacing: " + latticeSpacing.ToString() + nl));
                            bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sx + " " + sy + " " + sz + nl));
                            bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sx * sy * sz + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SCALARS amplitude float" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));


                            // Read {re,im} pairs from the input file, and write the corresponding ampl values to the output file
                            // (Avoid reading-in the whole input file up-front, as it may be extremely large.)
                            byte[] outPlane = new byte[sx * sy * 4];
                            float  maxAmpl  = 0.0f;
                            for (int z = 0; z < sz; z++)
                            {
                                byte[] inPlane = br.ReadBytes(sx * sy * 8);
                                int    ni = 0, no = 0;;
                                for (int y = 0; y < sy; y++)
                                {
                                    for (int x = 0; x < sx; x++)
                                    {
                                        *fa3 = inPlane[ni];   // Reverse the byte order
                                        *fa2 = inPlane[ni + 1];
                                        *fa1 = inPlane[ni + 2];
                                        *fa0 = inPlane[ni + 3];

                                        *fb3 = inPlane[ni + 4];
                                        *fb2 = inPlane[ni + 5];
                                        *fb1 = inPlane[ni + 6];
                                        *fb0 = inPlane[ni + 7];
                                        ni  += 8;

                                        fa = (float)Math.Sqrt(fa * fa + fb * fb);
                                        if (fa > maxAmpl)
                                        {
                                            maxAmpl = fa;
                                        }
                                        outPlane[no]     = *fa3;
                                        outPlane[no + 1] = *fa2;
                                        outPlane[no + 2] = *fa1;
                                        outPlane[no + 3] = *fa0;
                                        no += 4;
                                    }
                                }
                                bw.Write(outPlane);
                            }


                            // Now write the colors
                            if (colorFunc != null)
                            {
                                bw.Write(Encoding.ASCII.GetBytes("SCALARS colors unsigned_char 3" + nl));
                                bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));
                                br.BaseStream.Seek(inDataStartPos, SeekOrigin.Begin);
                                byte[] colorPlane = new byte[sx * sy * 3];
                                for (int z = 0; z < sz; z++)
                                {
                                    byte[] inPlane = br.ReadBytes(sx * sy * 8);
                                    int    ni = 0, no = 0;;
                                    for (int y = 0; y < sy; y++)
                                    {
                                        for (int x = 0; x < sx; x++)
                                        {
                                            *fa3 = inPlane[ni];    // Real part
                                            *fa2 = inPlane[ni + 1];
                                            *fa1 = inPlane[ni + 2];
                                            *fa0 = inPlane[ni + 3];

                                            *fb3 = inPlane[ni + 4];  // Imaginary part
                                            *fb2 = inPlane[ni + 5];
                                            *fb1 = inPlane[ni + 6];
                                            *fb0 = inPlane[ni + 7];
                                            ni  += 8;

                                            Color color = (colorFunc == null) ? Color.Blue : colorFunc(fb, fa, maxAmpl);
                                            colorPlane[no]     = color.R;
                                            colorPlane[no + 1] = color.G;
                                            colorPlane[no + 2] = color.B;
                                            no += 3;
                                        }
                                    }
                                    bw.Write(colorPlane);
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Processes a single input file.
        /// </summary>
        private void ProcessFile(string inFile, string outFile)
        {
            unsafe
            {
                int    sx = -1, sy = -1, sz = -1;
                string format         = "";
                float  latticeSpacing = 0.0f;
                string nl             = Environment.NewLine;

                using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open)))
                {
                    // Parse the header of the input file
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        string textLine = WaveFunction.ReadTextLine(br);

                        if (textLine.StartsWith("Wavefunction3D"))
                        {
                            string[] comps = textLine.Split(null);
                            format         = comps[1];
                            latticeSpacing = (float)(Single.Parse(comps[3]) / m_upsampFactor);
                        }
                        else if (textLine.StartsWith("DIMENSIONS"))
                        {
                            string[] comps = textLine.Split(null);
                            sx = Int32.Parse(comps[1]);
                            sy = Int32.Parse(comps[2]);
                            sz = Int32.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("LOOKUP_TABLE default"))
                        {
                            break;
                        }
                    }
                    // Bail out if the header was not what we expected
                    if (string.IsNullOrEmpty(format) || (sx < 0) || (sy < 0) || (sz < 0))
                    {
                        throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile.");
                    }
                    if (format != "REAL_AND_IMAG")
                    {
                        throw new ArgumentException("Unsupported Wavefunction format, in Smoother.ProcessFile. " + "(" + format + ")");
                    }

                    // Allocate some storage
                    int       sxu       = (int)Math.Max(1, sx * m_upsampFactor);
                    int       syu       = (int)Math.Max(1, sy * m_upsampFactor);
                    int       szu       = (int)Math.Max(1, sz * m_upsampFactor);
                    int       sxu2      = 2 * sxu;
                    float[][] workSpace = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx);
                    float[][] outPlane  = TdseUtils.Misc.Allocate2DArray(syu, sxu2);

                    // Read the initial few xy planes
                    float[][][] iXYPlanes = new float[sz][][];
                    for (int zIn = 0; zIn < 4; zIn++)
                    {
                        iXYPlanes[zIn] = TdseUtils.Misc.Allocate2DArray(syu, sxu2);
                        GetNextXYPlane(br, iXYPlanes[zIn], workSpace, m_upsampFactor);
                    }

                    // Precalculate the z-weights and indices
                    int[]   zInm2, zInm1, zInp1, zInp2;
                    float[] wzm2, wzm1, wzp1, wzp2;
                    GetUpsampleArrays(sz, m_upsampFactor, out zInm2, out zInm1, out zInp1, out zInp2, out wzm2, out wzm1, out wzp1, out wzp2);


                    // Create and open the output file
                    using (FileStream fileStream = File.Create(outFile))
                    {
                        using (BinaryWriter bw = new BinaryWriter(fileStream))
                        {
                            // Write the output header
                            bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + "REAL_AND_IMAG" + " " + "spacing: " + latticeSpacing.ToString() + nl));
                            bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sxu + " " + syu + " " + szu + nl));
                            bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sxu * syu * szu + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));


                            // Loop over the output z-planes
                            for (int zOut = 0; zOut < szu; zOut++)
                            {
                                // Cache z-weights and offsets
                                float Wzm2 = wzm2[zOut];
                                float Wzm1 = wzm1[zOut];
                                float Wzp1 = wzp1[zOut];
                                float Wzp2 = wzp2[zOut];

                                float[][] pixValsZInm2 = iXYPlanes[zInm2[zOut]];
                                float[][] pixValsZInm1 = iXYPlanes[zInm1[zOut]];
                                float[][] pixValsZInp1 = iXYPlanes[zInp1[zOut]];
                                float[][] pixValsZInp2 = iXYPlanes[zInp2[zOut]];
                                if (pixValsZInp2 == null)
                                {
                                    // Load (and upsample) the next xy plane
                                    float[][] temp = iXYPlanes[zInp2[zOut] - 4];
                                    iXYPlanes[zInp2[zOut] - 4] = null;
                                    GetNextXYPlane(br, temp, workSpace, m_upsampFactor);
                                    pixValsZInp2 = iXYPlanes[zInp2[zOut]] = temp;
                                }

                                for (int yOut = 0; yOut < syu; yOut++)
                                {
                                    float[] pixValsZInm2Y = pixValsZInm2[yOut];
                                    float[] pixValsZInm1Y = pixValsZInm1[yOut];
                                    float[] pixValsZInp1Y = pixValsZInp1[yOut];
                                    float[] pixValsZInp2Y = pixValsZInp2[yOut];
                                    float[] outPlaneY     = outPlane[yOut];

                                    for (int xOut = 0; xOut < sxu2; xOut++)
                                    {
                                        outPlaneY[xOut] = Wzm2 * pixValsZInm2Y[xOut] + Wzm1 * pixValsZInm1Y[xOut] + Wzp1 * pixValsZInp1Y[xOut] + Wzp2 * pixValsZInp2Y[xOut];
                                    }
                                }
                                WriteXYPlane(bw, outPlane);
                            }
                        }
                    }
                }
            }
        }
コード例 #9
0
        /// <summary>
        /// Processes a single input file.
        /// </summary>
        private void ProcessFile(string inFile, string outFile)
        {
            unsafe
            {
                int    sx = -1, sy = -1, sz = -1;
                string format         = "";
                float  latticeSpacing = 0.0f;
                string nl             = Environment.NewLine;

                float[] kernel = CreateGaussianKernel(m_smoothingFactor);
                int     sk     = kernel.Length;
                int     hsk    = (sk - 1) / 2;

                using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open)))
                {
                    // Parse the header of the input file
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        string textLine = WaveFunction.ReadTextLine(br);

                        if (textLine.StartsWith("Wavefunction3D"))
                        {
                            string[] comps = textLine.Split(null);
                            format         = comps[1];
                            latticeSpacing = Single.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("DIMENSIONS"))
                        {
                            string[] comps = textLine.Split(null);
                            sx = Int32.Parse(comps[1]);
                            sy = Int32.Parse(comps[2]);
                            sz = Int32.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("LOOKUP_TABLE default"))
                        {
                            break;
                        }
                    }
                    // Bail out if the header was not what we expected
                    if (string.IsNullOrEmpty(format) || (sx < 0) || (sy < 0) || (sz < 0))
                    {
                        throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile.");
                    }
                    if (format != "REAL_AND_IMAG")
                    {
                        throw new ArgumentException("Unsupported Wavefunction format, in Smoother.ProcessFile. " + "(" + format + ")");
                    }

                    // Allocate some storage
                    float[][][] slab      = TdseUtils.Misc.Allocate3DArray(sk, sy, 2 * sx);
                    float[][]   outPlane  = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx);
                    float[][]   workSpace = TdseUtils.Misc.Allocate2DArray(sy, 2 * sx);


                    // Create and open the output file
                    using (FileStream fileStream = File.Create(outFile))
                    {
                        using (BinaryWriter bw = new BinaryWriter(fileStream))
                        {
                            // Write the output header
                            bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + "REAL_AND_IMAG" + " " + "spacing: " + latticeSpacing.ToString() + nl));
                            bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sx + " " + sy + " " + sz + nl));
                            bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sx * sy * sz + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));

                            // Read the initial few planes
                            for (int i = hsk; i < sk; i++)
                            {
                                GetNextXYPlane(br, kernel, workSpace, slab[i]);
                            }
                            for (int i = 0; i < hsk; i++)
                            {
                                TdseUtils.Misc.Copy2DArray(slab[sk - 1 - i], slab[i]); // Mirror boundary conditions on z
                            }
                            // Smooth along z, and write-out the result
                            SmoothAlongZ(slab, kernel, outPlane);
                            WriteXYPlane(bw, outPlane);


                            // Loop over remaining planes
                            for (int z = 1; z < sz; z++)
                            {
                                // Cycle the z-planes, and read-in a new one
                                float[][] temp = slab[0];
                                for (int i = 0; i < sk - 1; i++)
                                {
                                    slab[i] = slab[i + 1];
                                }
                                slab[sk - 1] = temp;
                                if (z < sz - hsk)
                                {
                                    GetNextXYPlane(br, kernel, workSpace, slab[sk - 1]);
                                }
                                else
                                {
                                    TdseUtils.Misc.Copy2DArray(slab[2 * (sz - 1 - z)], slab[sk - 1]); // Mirror boundary conditions on z
                                }

                                // Smooth along z, and write-out the result
                                SmoothAlongZ(slab, kernel, outPlane);
                                WriteXYPlane(bw, outPlane);
                            }
                        }
                    }
                }
            }
        }
コード例 #10
0
        /// <summary>
        /// Processes a single input file.
        /// </summary>
        private void ProcessFile(string inFile, string outFile)
        {
            unsafe
            {
                int    sxIn = -1, syIn = -1, szIn = -1;
                int    sxOut = -1, syOut = -1, szOut = -1;
                string format         = "";
                float  latticeSpacing = 0.0f;
                string nl             = Environment.NewLine;

                using (BinaryReader br = new BinaryReader(File.Open(inFile, FileMode.Open)))
                {
                    // Parse the header of the input file
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        string textLine = WaveFunction.ReadTextLine(br);

                        if (textLine.StartsWith("Wavefunction3D"))
                        {
                            string[] comps = textLine.Split(null);
                            format         = comps[1];
                            latticeSpacing = Single.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("DIMENSIONS"))
                        {
                            string[] comps = textLine.Split(null);
                            sxIn = Int32.Parse(comps[1]);
                            syIn = Int32.Parse(comps[2]);
                            szIn = Int32.Parse(comps[3]);
                        }
                        else if (textLine.StartsWith("LOOKUP_TABLE default"))
                        {
                            break;
                        }
                    }
                    // Bail out if the header was not what we expected
                    if (string.IsNullOrEmpty(format) || (sxIn < 0) || (syIn < 0) || (szIn < 0))
                    {
                        throw new ArgumentException("Invalid Wavefunction file, in Cropper.ProcessFile.");
                    }



                    // Create output file
                    sxOut = sxIn - m_xCrop1 - m_xCrop2;
                    syOut = syIn - m_yCrop1 - m_yCrop2;
                    szOut = szIn - m_zCrop1 - m_zCrop2;

                    using (FileStream fileStream = File.Create(outFile))
                    {
                        using (BinaryWriter bw = new BinaryWriter(fileStream))
                        {
                            // Write the output header
                            bw.Write(Encoding.ASCII.GetBytes("# vtk DataFile Version 3.0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("Wavefunction3D " + format.ToString() + " " + "spacing: " + latticeSpacing.ToString() + nl));
                            bw.Write(Encoding.ASCII.GetBytes("BINARY" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DATASET STRUCTURED_POINTS" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("DIMENSIONS " + sxOut + " " + syOut + " " + szOut + nl));
                            bw.Write(Encoding.ASCII.GetBytes("ORIGIN 0 0 0" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("SPACING 1 1 1" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("POINT_DATA " + sxOut * syOut * szOut + nl));


                            // Read values from the input file, and write (some of) them to the output file.
                            // (Avoid reading-in the whole input file up-front, as it may be extremely large.)
                            if (format == "REAL_AND_IMAG")
                            {
                                bw.Write(Encoding.ASCII.GetBytes("SCALARS wf float 2" + nl));
                                bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));

                                byte[] outPlane = new byte[sxOut * syOut * 8];
                                for (int z = 0; z < szIn - m_zCrop2; z++)
                                {
                                    byte[] inPlane = br.ReadBytes(sxIn * syIn * 8);

                                    if (z < m_zCrop1)
                                    {
                                        continue;
                                    }

                                    for (int y = m_yCrop1; y < syIn - m_yCrop2; y++)
                                    {
                                        Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 8, outPlane, (y - m_yCrop1) * sxOut * 8, sxOut * 8);
                                    }
                                    bw.Write(outPlane);
                                }
                            }
                            else if ((format == "AMPLITUDE_ONLY") || (format == "AMPLITUDE_AND_COLOR"))
                            {
                                bw.Write(Encoding.ASCII.GetBytes("SCALARS amplitude float" + nl));
                                bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));

                                byte[] outPlane = new byte[sxOut * syOut * 4];
                                for (int z = 0; z < szIn; z++)
                                {
                                    byte[] inPlane = br.ReadBytes(sxIn * syIn * 4);

                                    if ((z < m_zCrop1) || (z > szIn - m_zCrop2 - 1))
                                    {
                                        continue;
                                    }

                                    for (int y = m_yCrop1; y < syIn - m_yCrop2; y++)
                                    {
                                        Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 4, outPlane, (y - m_yCrop1) * sxOut * 4, sxOut * 4);
                                    }
                                    bw.Write(outPlane);
                                }

                                if (format == "AMPLITUDE_AND_COLOR")
                                {
                                    bw.Write(Encoding.ASCII.GetBytes("SCALARS colors unsigned_char 3" + nl));
                                    bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));

                                    outPlane = new byte[sxOut * syOut * 3];
                                    for (int z = 0; z < szIn - m_zCrop2; z++)
                                    {
                                        byte[] inPlane = br.ReadBytes(sxIn * syIn * 3);

                                        if (z < m_zCrop1)
                                        {
                                            continue;
                                        }

                                        for (int y = m_yCrop1; y < syIn - m_yCrop2; y++)
                                        {
                                            Buffer.BlockCopy(inPlane, (y * sxIn + m_xCrop1) * 3, outPlane, (y - m_yCrop1) * sxOut * 3, sxOut * 3);
                                        }
                                        bw.Write(outPlane);
                                    }
                                }
                            }
                            else
                            {
                                throw new ArgumentException("Unsupported Wavefunction format, in Cropper.ProcessFile. " + "(" + format + ")");
                            }
                        }
                    }
                }
            }
        }
コード例 #11
0
        /// <summary>
        /// Computes the result of applying a given Hamiltonian operator to this wavefunction.
        /// </summary>
        public WaveFunction ApplyH(float[][][] V, float mass, bool multiThread = true)
        {
            // Initialize locals
            int sx  = GridSpec.SizeX;
            int sy  = GridSpec.SizeY;
            int sz  = GridSpec.SizeZ;
            int sx2 = 2 * sx;

            int sx2m2 = sx2 - 2;
            int sym1  = sy - 1;
            int szm1  = sz - 1;

            float keFactor = (1.0f / 12.0f) / (2 * mass * m_latticeSpacing * m_latticeSpacing);

            WaveFunction outWf = new WaveFunction(GridSpec, m_latticeSpacing);


            // Compute H * Wf
            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[] inWf_z_y   = m_data[z][y];
                    float[] inWf_z_ym  = m_data[z][ym];
                    float[] inWf_z_yp  = m_data[z][yp];
                    float[] inWf_z_ymm = m_data[z][ymm];
                    float[] inWf_z_ypp = m_data[z][ypp];
                    float[] inWf_zm_y  = m_data[zm][y];
                    float[] inWf_zp_y  = m_data[zp][y];
                    float[] inWf_zmm_y = m_data[zmm][y];
                    float[] inWf_zpp_y = m_data[zpp][y];
                    float[] outWf_z_y  = outWf.m_data[z][y];
                    float[] V_z_y      = V[z][y];

                    for (int rx = 0; rx < sx2; rx += 2)
                    {
                        int rxp  = (rx < sx2m2) ?  rx + 2  : 0;
                        int rxpp = (rxp < sx2m2) ?  rxp + 2 : 0;
                        int rxm  = (rx > 0) ?  rx - 2 : sx2m2;
                        int rxmm = (rxm > 0) ? rxm - 2 : sx2m2;
                        int x    = rx / 2;

                        // Kinetic energy terms.
                        float kR = keFactor * (
                            90.0f * inWf_z_y[rx] -
                            16.0f * (inWf_zm_y[rx] + inWf_zp_y[rx] + inWf_z_yp[rx] + inWf_z_ym[rx] + inWf_z_y[rxm] + inWf_z_y[rxp]) +
                            (inWf_zmm_y[rx] + inWf_zpp_y[rx] + inWf_z_ypp[rx] + inWf_z_ymm[rx] + inWf_z_y[rxmm] + inWf_z_y[rxpp])
                            );

                        int ix   = rx + 1;
                        float kI = keFactor * (
                            90.0f * inWf_z_y[ix] -
                            16.0f * (inWf_zm_y[ix] + inWf_zp_y[ix] + inWf_z_yp[ix] + inWf_z_ym[ix] + inWf_z_y[rxm + 1] + inWf_z_y[rxp + 1]) +
                            (inWf_zmm_y[ix] + inWf_zpp_y[ix] + inWf_z_ypp[ix] + inWf_z_ymm[ix] + inWf_z_y[rxmm + 1] + inWf_z_y[rxpp + 1])
                            );

                        // Potential energy terms
                        float vR = V_z_y[x] * inWf_z_y[rx];
                        float vI = V_z_y[x] * inWf_z_y[ix];

                        outWf_z_y[rx] = kR + vR;
                        outWf_z_y[ix] = kI + vI;
                    }
                }
            }, multiThread);

            return(outWf);
        }