コード例 #1
0
        /// <summary>
        /// Creates a Gaussian wavepacket with given properties.
        /// </summary>
        public static WaveFunction CreateGaussianWavePacket(
            int gridSizeX, int gridSizeY, float latticeSpacing, float mass,
            PointF packetCenter, PointF packetWidth, PointF avgMomentum, bool multiThread = true)
        {
            WaveFunction wf = new WaveFunction(gridSizeX, gridSizeY, latticeSpacing);

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

            TdseUtils.Misc.ForLoop(0, gridSizeY, (y) =>
            {
                float yf        = y * latticeSpacing;
                Complex expArgY = I * yf * avgMomentum.Y - (yf - packetCenter.Y) * (yf - packetCenter.Y) / (2 * sigmaYSq);

                float[] wfDataY = wf.Data[y];
                for (int x = 0; x < gridSizeX; x++)
                {
                    float xf = x * latticeSpacing;

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

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

            wf.Normalize();
            return(wf);
        }
コード例 #2
0
        /// <summary>
        /// Multiplication operator.
        /// </summary>
        public static WaveFunction operator *(TdseUtils.Complex s, WaveFunction A)
        {
            int   sx  = A.GridSizeX;
            int   sy  = A.GridSizeY;
            int   sx2 = 2 * sx;
            float sr  = s.Re;
            float si  = s.Im;

            WaveFunction result = new WaveFunction(sx, sy, A.LatticeSpacing);

            for (int y = 0; y < sy; y++)
            {
                float[] AdataY = A.m_data[y];
                float[] RdataY = result.m_data[y];

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

                    float ar = AdataY[x2];
                    float ai = AdataY[x2p];

                    RdataY[x2]  = sr * ar - si * ai;
                    RdataY[x2p] = sr * ai + si * ar;
                }
            }

            return(result);
        }
コード例 #3
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;
                    }
                }
            }
        }
コード例 #4
0
        /// <summary>
        /// Subtraction operator.
        /// </summary>
        public static WaveFunction operator -(WaveFunction A, WaveFunction B)
        {
            int sx  = A.GridSizeX;
            int sy  = A.GridSizeY;
            int sx2 = 2 * sx;

            if ((sx != B.GridSizeX) || (sy != B.GridSizeY) || Math.Abs(A.LatticeSpacing - B.LatticeSpacing) > 1.0e-5)
            {
                throw new ArgumentException("Incompatible WaveFunctions, in WaveFunction.operator+");
            }

            WaveFunction result = new WaveFunction(sx, sy, A.LatticeSpacing);

            for (int y = 0; y < sy; y++)
            {
                float[] AdataY = A.m_data[y];
                float[] BdataY = B.m_data[y];
                float[] RdataY = result.m_data[y];

                for (int nx = 0; nx < sx2; nx++)
                {
                    RdataY[nx] = AdataY[nx] - BdataY[nx];
                }
            }

            return(result);
        }
コード例 #5
0
        /// <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.GridSizeX, m_params.GridSizeY, 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, t, m, sx, sy) => { return(m_VBuilder.V(x, y, t, m, sx, sy)); };

            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();
        }
コード例 #6
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.GridSizeX;
            int sy = inputWf.GridSizeY;

            LatticeSpacing = inputWf.LatticeSpacing;

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

            // For the real part, just copy the values from the input wavefunction.
            for (int y = 0; y < sy; y++)
            {
                float[] realPartY = RealPart[y];
                float[] inputWfY  = inputWf.Data[y];
                for (int x = 0; x < sx; x++)
                {
                    realPartY[x] = inputWfY[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, sy, (y) =>
            {
                float[] imPY      = this.ImagPartP[y];
                float[] imMY      = this.ImagPartM[y];
                float[] inputWfY  = inputWf.Data[y];
                float[] H_PsiInY  = H_PsiIn.Data[y];
                float[] H2_PsiInY = H2_PsiIn.Data[y];

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

                    float dt0Term = inputWfY[x2p1];
                    float dt1Term = halfDt * H_PsiInY[x2];
                    float dt2Term = eighthDt2 * H2_PsiInY[x2p1];

                    imPY[x] = dt0Term - dt1Term - dt2Term; // [1 - i*H*(dt/2) - (1/2)H^2*(dt/2)^2] * Psi
                    imMY[x] = dt0Term + dt1Term - dt2Term; // [1 + i*H*(dt/2) - (1/2)H^2*(dt/2)^2] * Psi
                }
            }, multiThread);
        }
コード例 #7
0
        /// <summary>
        /// Worker method.
        /// </summary>
        protected override void WorkerMethod()
        {
            string[] vtkFiles = Directory.GetFiles(m_inputDir, "*.vtk");
            if ((vtkFiles == null) || (vtkFiles.Length == 0))
            {
                return;
            }

            // Write the color parameters to a file
            string outputDir       = CreateOutputDir(m_inputDir);
            string colorParamsFile = Path.Combine(outputDir, "ColorParams.txt");

            File.WriteAllText(colorParamsFile, m_colorBuilder.GetLastSavedCode().Replace("\n", "\r\n"));

            string paramsFile = Path.Combine(m_inputDir, "Params.txt");

            if (File.Exists(paramsFile))
            {
                File.Copy(paramsFile, Path.Combine(outputDir, Path.GetFileName(paramsFile)));
            }

            WaveFunction.ColorDelegate colorFunc = (re, im, maxAmpl) => { return(m_colorBuilder.CalcColor(re, im, maxAmpl)); };
            if (colorFunc(1, 1, 1) == Color.Empty)
            {
                colorFunc = null;
            }

            m_numFilesToProcess = vtkFiles.Length;
            int chunkSize = Environment.ProcessorCount;

            for (int iStart = 0; iStart < m_numFilesToProcess; iStart += chunkSize)
            {
                int iEnd = Math.Min(iStart + chunkSize, m_numFilesToProcess);
                Parallel.For(iStart, iEnd, i =>
                {
                    // Re-color one file
                    string inputFile = vtkFiles[i];
                    WaveFunction wf  = WaveFunction.ReadFromVtkFile(inputFile);

                    string outFile = Path.Combine(outputDir, Path.GetFileName(inputFile));
                    wf.SaveToVtkFile(outFile, WaveFunction.WfSaveFormat.AMPLITUDE_AND_COLOR, colorFunc);
                });

                // Report progress to the caller
                m_currentFileIndex = iEnd - 1;
                ReportProgress();
                if (IsCancelled)
                {
                    return;
                }
            }
        }
コード例 #8
0
ファイル: Upsampler.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Resamples a wavefunction to a higher resolution.
        /// </summary>
        public static WaveFunction Upsample(WaveFunction inputWf, double factor)
        {
            float[][] modData = UpsampleBicubic(inputWf.Data, factor);

            WaveFunction outputWf = new WaveFunction(modData, (float)(inputWf.LatticeSpacing / factor));

            // Match the normalization of the input wavefunction
            float normFactor = (float)Math.Sqrt(inputWf.NormSq() / outputWf.NormSq());

            outputWf.ScaleBy(normFactor);

            return(outputWf);
        }
コード例 #9
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_totalTime          = totalTime;
     m_deltaT             = timeStep;
     m_totalNumTimeSteps  = (int)Math.Round(totalTime / timeStep) + 1;
     m_potential          = V;
     m_isTimeDependentV   = isVTimeDependent;
     m_particleMass       = particleMass;
     m_reportInterval     = progressReportInterval;
     m_dampingBorderWidth = dampingBorderWidth;
     m_dampingFactor      = dampingFactor;
     m_multiThread        = multiThread;
 }
コード例 #10
0
ファイル: Upsampler.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Worker method.
        /// </summary>
        protected override void WorkerMethod()
        {
            string[] vtkFiles = Directory.GetFiles(m_inputDir, "*.vtk");
            if ((vtkFiles == null) || (vtkFiles.Length == 0))
            {
                return;
            }

            m_outputDir = CreateOutputDir(m_inputDir);
            string paramsFile = Path.Combine(m_inputDir, "Params.txt");

            if (File.Exists(paramsFile))
            {
                File.Copy(paramsFile, Path.Combine(m_outputDir, Path.GetFileName(paramsFile)));
            }


            m_numFilesToProcess = vtkFiles.Length;
            int chunkSize = Environment.ProcessorCount;

            for (int iStart = 0; iStart < m_numFilesToProcess; iStart += chunkSize)
            {
                int iEnd = Math.Min(iStart + chunkSize, m_numFilesToProcess);
                Parallel.For(iStart, iEnd, i =>
                {
                    // Upsample one file, and save the result
                    string inputFile = vtkFiles[i];
                    WaveFunction wf  = WaveFunction.ReadFromVtkFile(inputFile);
                    wf = Upsample(wf, m_upsampFactor);

                    string outFile = Path.Combine(m_outputDir, Path.GetFileName(inputFile));
                    wf.SaveToVtkFile(outFile, WaveFunction.WfSaveFormat.REAL_AND_IMAG);
                });

                // Report progress to the caller
                m_currentFileIndex = iEnd - 1;
                ReportProgress();
                if (IsCancelled)
                {
                    return;
                }
            }
        }
コード例 #11
0
ファイル: VisscherWf.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Converts a Visscher wavefunction to a regular wavefunction.
        /// </summary>
        public WaveFunction ToRegularWavefunction(bool multiThread = true)
        {
            int sx = GridSizeX;
            int sy = GridSizeY;

            WaveFunction result = new WaveFunction(sx, sy, LatticeSpacing);

            TdseUtils.Misc.ForLoop(0, sy, (y) =>
            {
                float[] thisRy  = RealPart[y];
                float[] thisIMy = ImagPartM[y];
                float[] thisIPy = ImagPartP[y];
                float[] outWfy  = result.Data[y];

                for (int x = 0; x < sx; x++)
                {
                    outWfy[2 * x] = thisRy[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       = thisIMy[x];
                    float IP       = thisIPy[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;
                    }

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

            return(result);
        }
コード例 #12
0
        /// <summary>
        /// Multiplication operator.
        /// </summary>
        public static WaveFunction operator *(double s, WaveFunction A)
        {
            int   sx  = A.GridSizeX;
            int   sy  = A.GridSizeY;
            int   sx2 = 2 * sx;
            float fs  = (float)s;

            WaveFunction result = new WaveFunction(sx, sy, A.LatticeSpacing);

            for (int y = 0; y < sy; y++)
            {
                float[] AdataY = A.m_data[y];
                float[] RdataY = result.m_data[y];

                for (int nx = 0; nx < sx2; nx++)
                {
                    RdataY[nx] = AdataY[nx] * fs;
                }
            }

            return(result);
        }
コード例 #13
0
ファイル: Smoother.cs プロジェクト: aarongrisez/TDSE
        /// <summary>
        /// Processes a single input file.
        /// </summary>
        private void ProcessFile(string inFile, string outFile)
        {
            unsafe
            {
                int    sx = -1, sy = -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("Wavefunction2D"))
                        {
                            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]);
                        }
                        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))
                    {
                        throw new ArgumentException("Invalid Wavefunction file, in Colorer.ProcessFile.");
                    }
                    if ((format != "AMPLITUDE_ONLY") && (format != "AMPLITUDE_AND_COLOR"))
                    {
                        throw new ArgumentException("Unsupported Wavefunction format, in Smoother.ProcessFile. " + "(" + format + ")");
                    }

                    // Read the amplitude values
                    byte[]    bytePlane  = br.ReadBytes(sx * sy * 4);
                    float[][] amplitudes = TdseUtils.Misc.Allocate2DArray(sy, sx);

                    float floatVal    = 0.0f;
                    byte *floatBytes0 = (byte *)(&floatVal);
                    byte *floatBytes1 = floatBytes0 + 1;
                    byte *floatBytes2 = floatBytes0 + 2;
                    byte *floatBytes3 = floatBytes0 + 3;

                    int n = 0;
                    for (int y = 0; y < sy; y++)
                    {
                        float[] amplitudesY = amplitudes[y];
                        for (int x = 0; x < sx; x++)
                        {
                            *floatBytes3   = bytePlane[n];
                            *floatBytes2   = bytePlane[n + 1];
                            *floatBytes1   = bytePlane[n + 2];
                            *floatBytes0   = bytePlane[n + 3];
                            amplitudesY[x] = floatVal;
                            n += 4;
                        }
                    }

                    // Smooth the amplitudes
                    float[][] smoothedAmplitudes = Smooth(amplitudes, m_smoothingFactor, true);

                    // 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("Wavefunction2D " + format + " " + "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 + " 1" + 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 + nl));

                            // Write out the smoothed amplitudes
                            bw.Write(Encoding.ASCII.GetBytes("SCALARS amplitude float" + nl));
                            bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));

                            n = 0;
                            for (int y = 0; y < sy; y++)
                            {
                                float[] smY = smoothedAmplitudes[y];

                                for (int x = 0; x < sx; x++)
                                {
                                    floatVal         = smY[x];
                                    bytePlane[n]     = *floatBytes3;
                                    bytePlane[n + 1] = *floatBytes2;
                                    bytePlane[n + 2] = *floatBytes1;
                                    bytePlane[n + 3] = *floatBytes0;
                                    n += 4;
                                }
                            }
                            bw.Write(bytePlane);

                            // Copy the color data from input to output
                            if (format == "AMPLITUDE_AND_COLOR")
                            {
                                WaveFunction.ReadTextLine(br);
                                WaveFunction.ReadTextLine(br);
                                bw.Write(Encoding.ASCII.GetBytes("SCALARS colors unsigned_char 3" + nl));
                                bw.Write(Encoding.ASCII.GetBytes("LOOKUP_TABLE default" + nl));
                                bw.Write(br.ReadBytes(sx * sy * 3));
                            }
                        }
                    }
                }
            }
        }
コード例 #14
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    = GridSizeX;
            int sy    = GridSizeY;
            int sxm1  = sx - 1;
            int sym1  = sy - 1;
            int sxm2  = sx - 2;
            int sym2  = sy - 2;
            int sx2   = 2 * sx;
            int sx2m2 = sx2 - 2;

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

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

            WaveFunction outWf = new WaveFunction(sx, sy, m_latticeSpacing);


            // Compute H * Wf
            TdseUtils.Misc.ForLoop(0, 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_y   = m_data[y];
                float[] inWf_ym  = m_data[ym];
                float[] inWf_yp  = m_data[yp];
                float[] inWf_ymm = m_data[ymm];
                float[] inWf_ypp = m_data[ypp];
                float[] outWf_y  = outWf.m_data[y];
                float[] V_y      = V[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 * (
                        alpha * inWf_y[rx] +
                        beta * (inWf_y[rxm] + inWf_y[rxp] + inWf_ym[rx] + inWf_yp[rx]) +
                        delta * (inWf_y[rxmm] + inWf_y[rxpp] + inWf_ymm[rx] + inWf_ypp[rx])
                        );

                    int ix   = rx + 1;
                    float kI = keFactor * (
                        alpha * inWf_y[ix] +
                        beta * (inWf_y[rxm + 1] + inWf_y[rxp + 1] + inWf_ym[ix] + inWf_yp[ix]) +
                        delta * (inWf_y[rxmm + 1] + inWf_y[rxpp + 1] + inWf_ymm[ix] + inWf_ypp[ix])
                        );

                    // Potential energy terms
                    float vR = V_y[x] * inWf_y[rx];
                    float vI = V_y[x] * inWf_y[ix];

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

            return(outWf);
        }
コード例 #15
0
        /// <summary>
        /// Crops a wavefunction.
        /// </summary>
        public static WaveFunction Crop(WaveFunction wf, int xminCrop, int xmaxCrop, int yminCrop, int ymaxCrop)
        {
            float[][] modData = Crop(wf.Data, xminCrop, xmaxCrop, yminCrop, ymaxCrop);

            return(new WaveFunction(modData, wf.LatticeSpacing));
        }