Esempio n. 1
0
 public void Initialize(SOCJT nSocjt, FileInfo input, List<ModeInfo> Modes, string[] inputFile, bool isQuad, Eigenvalue[] fitFile)
 {
     nSoc = nSocjt;
     nInput = input;
     nModes = Modes;
     nInputFile = inputFile;
     nIsQuad = isQuad;
     nFitFile = fitFile;
 }
Esempio n. 2
0
        public List<string> fit(List<ModeInfo> Modes, bool isQuad, string[] inputFile, FileInfo input, String filepath)
        {
            //string to return
            List<string> output = new List<string>();

            //reads and parses fit file
            string[] fitF = {};
            try
            {
                fitF = FileInfo.FileRead(filepath);
            }
            catch(FileNotFoundException)
            {
                throw new FileNotFoundException("The fit file does not exist.");
            }

            //assign number of eigenvalues to be fit from fitFile
            int nToFit = Convert.ToInt16(fitF[0]);

            //create new Eigenvalue array to store the values from the fit file for each value being fit
            Eigenvalue[] userInput = new Eigenvalue[nToFit];

            //initialize the Eigenvalue array for the fit values from the fit file
            for (int i = 0; i < nToFit; i++)
            {
                if (input.useSeed)
                {
                    userInput[i] = new Eigenvalue(Convert.ToDecimal(fitF[i * 5 + 2]), Convert.ToInt16(fitF[i * 5 + 3]), Convert.ToDecimal(fitF[i * 5 + 4]), Convert.ToDouble(fitF[i * 5 + 1]), FileInfo.TorF(fitF[i * 5 + 5]));
                }
                else // if the seed switch is off, all Lanczos eigenvalues will be labelled as not A1, so we will label all fit file values as not A1
                {
                    userInput[i] = new Eigenvalue(Convert.ToDecimal(fitF[i * 5 + 2]), Convert.ToInt16(fitF[i * 5 + 3]), Convert.ToDecimal(fitF[i * 5 + 4]), Convert.ToDouble(fitF[i * 5 + 1]), false);
                }
            }

            //initializes the X vector, boundary conditions and variable scales
            //xList will contain each parameter being fit
            List<double> xList = new List<double>();

            //the lower bounds for each variable being fit, these are hardcoded
            List<double> bndL = new List<double>();

            //the upper bounds for each variable being fit, these are hardcoded
            List<double> bndU = new List<double>();

            //the scaling values for each variable being fit, these are hardcoded
            List<double> lScale = new List<double>();

            //here I initialize the xList, upper and lower boundaries, and scales for each parameter being fit.
            //for Azeta
            if (input.FitAzeta == true)
            {
                xList.Add(input.Azeta);
                bndL.Add(double.NegativeInfinity);
                bndU.Add(double.PositiveInfinity);
                lScale.Add(1.0);
            }
            //for the origin
            if (input.FitOrigin == true)
            {
                xList.Add(0.0);
                bndL.Add(double.NegativeInfinity);
                bndU.Add(double.PositiveInfinity);
                lScale.Add(50.0);//changed from 200
            }
            //for each mode
            for (int i = 0; i < input.nModes; i++)
            {
                //for Omega
                if (Modes[i].fitOmega == true)
                {
                    xList.Add(Modes[i].modeOmega);
                    bndL.Add(0.0);
                    bndU.Add(double.PositiveInfinity);
                    lScale.Add(50.0);//changed from 100
                }
                //for D
                if (Modes[i].fitD == true)
                {
                    xList.Add(Modes[i].D);
                    bndL.Add(0.0);
                    bndU.Add(double.PositiveInfinity);
                    lScale.Add(3.0);//changed from 10
                }
                //for K
                if (Modes[i].fitK == true)
                {
                    xList.Add(Modes[i].K);
                    bndL.Add(double.NegativeInfinity);
                    bndU.Add(double.PositiveInfinity);
                    lScale.Add(0.5);//changed from 1
                }
                //for wexe
                if (Modes[i].fitWEXE == true)
                {
                    xList.Add(Modes[i].wExe);
                    bndL.Add(double.NegativeInfinity);
                    bndU.Add(double.PositiveInfinity);
                    lScale.Add(10.0);//change from 50
                }
            }
            //then for cross-terms
            if (input.IncludeCrossTerms == true)
            {
                for (int i = 0; i < input.nModes; i++)
                {
                    for (int j = 0; j < input.nModes; j++)
                    {
                        if (input.CrossTermFit[i, j] == true)
                        {
                            xList.Add(input.CrossTermMatrix[i, j]);
                            bndL.Add(double.NegativeInfinity);
                            bndU.Add(double.PositiveInfinity);
                            if (j > i)
                            {
                                lScale.Add(500.0);//scale for bilinear coupling + cross quadratic, changed from 100
                            }
                            if (j == i)
                            {
                                lScale.Add(50.0);//change from 250
                            }
                            else
                            {
                                lScale.Add(50.0);//scale for cross anharmonic, change from 250
                            }
                        }
                    }
                }
            }

            //xVec for minLM optimizer
            double[] xVec = xList.ToArray();

            //Upper/lower boundary arrays for minLM optimizer
            double[] lowBound = bndL.ToArray();
            double[] upBound = bndU.ToArray();

            //scaling array for minLM optimizer
            double[] scale = lScale.ToArray();

            //Generate new Master Object
            //this is an ugly solution to the problem of using the ALGLIB routines since I need to pass a large amount of information
            //to this routine but can only include one object in the arguments.  Therefore, I created the MasterObject just to store
            //this information which I pass to the ALGLIB routine.  Where it's used, it is cast from object to a MasterObject.
            SOCJT run = new SOCJT();
            MasterObject Masterly = new MasterObject();

            //here, if using simple lanczos and wanting evecs, set pVector to false so that they are not calculated each step of the fit
            bool evecs = false;
            if (input.PrintVector && !input.BlockLanczos)
            {
                evecs = true;
                input.PrintVector = false;
            }
            Masterly.Initialize(run, input, Modes, inputFile, isQuad, userInput);

            //initialize and run MinLM algorithm
            double epsg = input.GTol;
            double epsf = input.FTol;
            double epsx = input.XTol;
            int maxits = input.MaxOptimizerSteps;
            alglib.minlmstate state;
            alglib.minlmreport rep;
            //alglib.ndimensional_func func;
            //alglib.ndimensional_grad gradient;
            //alglib.ndimensional_hess hessian;

            alglib.minlmcreatev(userInput.Length, xVec, input.Factor, out state);
            //if (input.calcHessian)
            //{
            //    state.needfgh = true;
            //    //alglib.ndimensional_func func;
            //    //alglib.ndimensional_grad grad;
            //    //alglib.ndimensional_hess HessianMat;
            //    //alglib.minlmoptimize(state, function, null, null, state.repnhess, Masterly);
            //}
            alglib.minlmsetbc(state, lowBound, upBound);
            alglib.minlmsetscale(state, scale);
            alglib.minlmsetcond(state, epsg, epsf, epsx, maxits);
            alglib.minlmsetxrep(state, true);
            //acc = 1, meaning it's on by default.  Just leave that.
            //alglib.minlmsetacctype(state, 0);

            //if (input.calcHessian)
            //{
            //    alglib.minlmoptimize(state, func, gradient, hessian, null, Masterly);
            //}
            alglib.minlmoptimize(state, function, null, Masterly);
            alglib.minlmresults(state, out xVec, out rep);
            int report = rep.terminationtype;
            int iter = rep.iterationscount;

            //this calculates the covariance matrix from the Jacobian using cov[,] = {J^T * J}^-1
            //initialize covariance matrix
            double[,] resultM = new double[state.x.Length, state.x.Length];
            for (int u = 0; u < state.x.Length; u++)
            {
                for (int uu = 0; uu < state.x.Length; uu++)
                {
                    resultM[u, uu] = 0.0;
                }
            }
            //calculate J^T * J and store in resultM
            alglib.rmatrixgemm(state.j.GetLength(1), state.j.GetLength(1), state.j.GetLength(0), 1.0, state.j, 0, 0, 1, state.j, 0, 0, 0, 0.0, ref resultM, 0, 0);
            //take inverse of resultM, replaces resultM
            int invInfo;
            alglib.matinvreport invReport = new alglib.matinvreport();
            alglib.rmatrixinverse(ref resultM, out invInfo, out invReport);
            //now make correlation coefficient matrix
            double[,] corMat = new double[resultM.GetLength(0), resultM.GetLength(0)];
            for (int i = 0; i < resultM.GetLength(0); i++)
            {
                for (int j = 0; j < resultM.GetLength(0); j++)
                {
                    corMat[i, j] = resultM[i, j] / (Math.Sqrt(resultM[i, i] * resultM[j, j]));
                }
            }

            //if eigenvectors are needed when using naive lanczos, run SOCJT routine one more time to calculate them.
            if (evecs && !input.BlockLanczos)
            {
                Console.WriteLine("Calculating eigenvectors.");
                Masterly.nInput.PrintVector = true;
                Masterly.nSoc.SOCJTroutine(Masterly.nModes, Masterly.nIsQuad, Masterly.nInputFile, Masterly.nInput);
                //now assign the lanczosEVectors to those from the SOCJT routine
                lanczosEVectors = Masterly.nSoc.lanczosEVectors;
                basisSet = Masterly.nSoc.basisSet;
            }
            //make output
            soc = Masterly.nSoc;
            output = Masterly.nSoc.outp;
            //add something showing RMS error and parameters for each JT mode
            double[] error = ComparerVec(userInput, Masterly.nSoc.finalList, Masterly.nInput.Origin, true);

            StringBuilder file = new StringBuilder();
            file.AppendLine("Fit report below...");
            file.AppendLine("Termination Type: ");
            if (report == -9)
            {
                file.Append("Derivative correctness check failed");
            }
            if (report == 1)
            {
                file.Append("Relative function improvement is no more than EpsF");
            }
            if (report == 2)
            {
                file.Append("Relative step is no more than EpsX");
            }
            if (report == 4)
            {
                file.Append("Gradient is no more than EpsG");
            }
            if (report == 5)
            {
                file.Append("Maximum number of iterations was exceeded");
            }
            if (report == 7)
            {
                file.Append("Stopping conditions are too stringent, further improvement is impossible");
            }

            file.AppendLine(" ");

            file.AppendLine("Number of iterations: " + Convert.ToString(iter));
            file.AppendLine("Number of times the eigenvalues were calculated: " + Convert.ToString(rep.nfunc));

            file.AppendLine(" ");

            file.AppendLine("A * zeta e = " + Convert.ToString(Masterly.nInput.Azeta));

            /* This is written for data analysis with the NFG program */
            if (input.useNFG == true)
            {
                file.Append("\n" + "NFG_OUTPUT" + "\t");
                for (int ii = 0; ii < Masterly.nInput.nModes; ii++)
                {
                    double JTSE;
                    if (Masterly.nModes[ii].IsAType == true)
                    {
                        JTSE = 0.0;
                    }
                    else
                    {
                        JTSE = Masterly.nModes[ii].D * Masterly.nModes[ii].modeOmega * (Masterly.nModes[ii].K + 1.0);
                    }
                    file.Append(String.Format("{0,7:0.00}", Masterly.nModes[ii].modeOmega) + "\t" + String.Format("{0,4:0.00}", Masterly.nModes[ii].wExe) + "\t" + String.Format("{0,5:0.0000}", Masterly.nModes[ii].D) + "\t" + String.Format("{0,5:0.0000}", Masterly.nModes[ii].K) + "\t" + String.Format("{0,4:0.00}", JTSE) + "\t");
                }
                if (input.IncludeCrossTerms == true)
                {
                    for (int i = 0; i < input.nModes; i++)
                    {
                        for (int j = 0; j < input.nModes; j++)
                        {
                            if (input.CrossTermMatrix[i, j] != 0.0 || input.CrossTermFit[i, j] == true)
                            {
                                if (i < j)
                                {
                                    file.Append(String.Format("{0,10:0.0000}", input.CrossTermMatrix[i, j]) + "\t");
                                }
                                else
                                {
                                    file.Append(String.Format("{0,10:0.0000}", input.CrossTermMatrix[i, j]) + "\t");
                                }
                            }
                        }
                    }
                }
                for (int ll = 0; ll < resultM.GetLength(0); ll++)
                {
                    file.Append(String.Format("{0,10:0.0000}", Math.Sqrt(resultM[ll, ll])) + "\t");
                }
                file.Append(String.Format("{0,10:0.000}", (Math.Sqrt(FitSOCJT.Comparer(userInput, Masterly.nSoc.finalList, Masterly.nInput.Origin) / userInput.Length))));

                file.Append("\n" + "ELEVEL");
                for (int ii = 0; ii < Masterly.nSoc.finalList.Length; ii++)
                {
                    if (Masterly.nSoc.finalList[ii].JBlock == 0.5M)
                    {
                        file.Append("\t" + String.Format("{0,9:0.0000}", Masterly.nSoc.finalList[ii].Evalue));
                    }
                }
                file.Append("\n" + "A1LEVEL");
                for (int ii = 0; ii < Masterly.nSoc.finalList.Length; ii++)
                {
                    if (Masterly.nSoc.finalList[ii].JBlock == 1.5M && Masterly.nSoc.finalList[ii].IsA1 == true)
                    {
                        file.Append("\t" + String.Format("{0,9:0.0000}", Masterly.nSoc.finalList[ii].Evalue));
                    }
                }
                file.Append("\n" + "A2LEVEL");
                for (int ii = 0; ii < Masterly.nSoc.finalList.Length; ii++)
                {
                    if (Masterly.nSoc.finalList[ii].JBlock == 1.5M && Masterly.nSoc.finalList[ii].IsA1 == false)
                    {
                        file.Append("\t" + String.Format("{0,9:0.0000}", Masterly.nSoc.finalList[ii].Evalue));
                    }
                }
                file.AppendLine("\n");
            } // end if useNFG == true

            file.AppendLine("Final Parameters for Each Mode:");
            file.AppendLine("Mode #" + "\t" + "V(min)" + "\t" + "V(max)" + "\t" + "Omega(E)" + "\t" + "wexe" + "\t" + "D" + "\t" + "K" + "\t" + "JTSE" + "\t" + "Omega(A)" + "\t" + "A Type?");
            for (int i = 0; i < Masterly.nInput.nModes; i++)
            {
                double JTSE;
                if (Masterly.nModes[i].IsAType == true)
                {
                    JTSE = 0.0;
                }
                else
                {
                    JTSE = Masterly.nModes[i].D * Masterly.nModes[i].modeOmega * (Masterly.nModes[i].K + 1.0);
                }
                file.AppendLine(Convert.ToString(i + 1) + "\t" + String.Format("{0,4:0}", 0) + "\t" + String.Format("{0,4:0}", Masterly.nModes[i].modeVMax) + "\t" + String.Format("{0,7:0.00}", Masterly.nModes[i].modeOmega) + "\t" + "\t" + String.Format("{0,4:0.00}", Masterly.nModes[i].wExe) + "\t" + String.Format("{0,5:0.0000}", Masterly.nModes[i].D) + "\t" + String.Format("{0,5:0.0000}", Masterly.nModes[i].K) + "\t" + String.Format("{0,4:0.00}", JTSE) + "\t" + String.Format("{0,7:0.00}", Masterly.nModes[i].modeAOmega) + "\t" + "\t" + Convert.ToString(Masterly.nModes[i].IsAType));
            }
            file.AppendLine("  ");
            if (input.FitOrigin == true)
            {
                file.AppendLine("Origin Shift = " + String.Format("{0,8:0.000}", -1.0 * Masterly.nInput.Origin));
            }
            file.AppendLine("  ");
            if (input.IncludeCrossTerms == true)
            {
                for (int i = 0; i < input.nModes; i++)
                {
                    for (int j = 0; j < input.nModes; j++)
                    {
                        if (input.CrossTermMatrix[i, j] != 0.0 || input.CrossTermFit[i, j] == true)
                        {
                            if (i < j)
                            {
                                file.AppendLine("Mode " + Convert.ToString(i + 1) + " Mode " + Convert.ToString(j + 1) + " JT cross-term = " + String.Format("{0,10:0.0000}", input.CrossTermMatrix[i, j]));
                            }
                            else
                            {
                                file.AppendLine("Mode " + Convert.ToString(j + 1) + " Mode " + Convert.ToString(i + 1) + " AT cross-term = " + String.Format("{0,10:0.00}", input.CrossTermMatrix[i, j]));
                            }
                        }
                    }
                }
                file.AppendLine(" ");
            }

            file.AppendLine("Fitting Results:");
            if (input.FitOrigin == true)
            {
                file.AppendLine("Experimental values are shifted by " + String.Format("{0,8:0.000}", Masterly.nInput.Origin) + " wavenumbers.");
            }
            file.AppendLine("FitFile Value" + "\t" + "Calculated Value" + "\t" + "Exp - Calc" + "\t" + "(Exp - Calc)^2");
            for (int i = 0; i < error.Length; i++)
            {
                file.AppendLine(String.Format("{0,13:0.000}", userInput[i].Evalue + Masterly.nInput.Origin) + "\t" + String.Format("{0,13:0.000}", userInput[i].Evalue + Masterly.nInput.Origin - error[i]) + "\t" + "\t" + String.Format("{0,9:0.000}", error[i]) + "\t" + String.Format("{0,11:0.000}", Math.Pow(error[i], 2D)));
            }
            file.AppendLine("  ");
            file.AppendLine("RMS Error = " + String.Format("{0,10:0.000}", (Math.Sqrt(FitSOCJT.Comparer(userInput, Masterly.nSoc.finalList, Masterly.nInput.Origin) / userInput.Length))));
            file.AppendLine("  ");

            int l = 0;
            if (Masterly.nInput.FitAzeta == true)
            {
                file.AppendLine("Azeta StdDev = " + String.Format("{0,10:0.000000}", Math.Sqrt(resultM[l, l])));
                l++;
            }
            if (Masterly.nInput.FitOrigin == true)
            {
                file.AppendLine("Origin StdDev = " + String.Format("{0,10:0.00}", Math.Sqrt(resultM[l, l])));
                l++;
            }
            for (int i = 0; i < Masterly.nInput.nModes; i++)
            {
                if (Masterly.nModes[i].fitOmega == true)
                {
                    file.AppendLine("Mode " + Convert.ToString(i + 1) + " Omega StdDev = " + String.Format("{0,10:0.00}", Math.Sqrt(resultM[l, l])));
                    l++;
                }
                if (Masterly.nModes[i].fitD == true)
                {
                    file.AppendLine("Mode " + Convert.ToString(i + 1) + " D StdDev = " + String.Format("{0,10:0.0000}", Math.Sqrt(resultM[l, l])));
                    l++;
                }
                if (Masterly.nModes[i].fitK == true)
                {
                    file.AppendLine("Mode " + Convert.ToString(i + 1) + " K StdDev = " + String.Format("{0,10:0.0000}", Math.Sqrt(resultM[l, l])));
                    l++;
                }
                if (Masterly.nModes[i].fitWEXE == true)
                {
                    file.AppendLine("Mode " + Convert.ToString(i + 1) + " wexe StdDev = " + String.Format("{0,10:0.00}", Math.Sqrt(resultM[l, l])));
                    l++;
                }
            }
            if (Masterly.nInput.IncludeCrossTerms == true)
            {
                for (int i = 0; i < Masterly.nInput.nModes; i++)
                {
                    for (int h = 0; h < Masterly.nInput.nModes; h++)
                    {
                        if (Masterly.nInput.CrossTermFit[i, h] == true)
                        {
                            if (i < h)
                            {
                                file.AppendLine("Mode " + Convert.ToString(i + 1) + " Mode " + Convert.ToString(h + 1) + " JT Term StdDev = " + String.Format("{0,10:0.0000}", Math.Sqrt(resultM[l, l])));
                                l++;
                            }
                            else
                            {
                                file.AppendLine("Mode " + Convert.ToString(h + 1) + " Mode " + Convert.ToString(i + 1) + " AT Term StdDev = " + String.Format("{0,10:0.00}", Math.Sqrt(resultM[l, l])));
                                l++;
                            }
                        }
                    }
                }
            }
            file.AppendLine(" ");
            file.AppendLine("Correlation coefficient matrix:");
            for (int i = 0; i < resultM.GetLength(0); i++)
            {
                file.AppendLine("");
                file.Append("(");
                for (int j = 0; j < resultM.GetLength(0); j++)
                {
                    if (j != 0)
                    {
                        file.Append(",  ");
                    }
                    file.Append(String.Format("{0,8:0.000}", corMat[i, j]));
                }
                file.Append(")");
            }
            file.AppendLine(" ");
            file.AppendLine(" ");

            output.Add(file.ToString());

            output.AddRange(OutputFile.inputFileMaker(Masterly.nInput, Masterly.nModes));
            return output;
        }
Esempio n. 3
0
        static void Main(string[] args)
        {
            try
            {
                string fileDirectory;
            #if DEBUG
                //prompt user for input directory.  Default value is C:\SOCJT 2
                Console.WriteLine("Enter file directory or press enter to use C:\\SOCJT 2");
                fileDirectory = Console.ReadLine();
                if (fileDirectory == "")
                {
                    fileDirectory = "C:\\SOCJT 2\\";
                }

                if (Directory.Exists(fileDirectory) == false)
                {
                    throw new DirectoryNotFoundException();
                }
            #else

                fileDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            #endif

                Directory.SetCurrentDirectory(fileDirectory);

                string inFileName;
                string outFile;

                if (args == null || args.Length == 0)
                {
                    Console.WriteLine("Enter file name including extension:");
                    inFileName = Console.ReadLine();

                    //obtain output file name.  If blank, default value of input + .out is used
                    Console.WriteLine("Enter output file name or press enter to use " + inFileName + ".out:");
                    outFile = Console.ReadLine();
                    if (outFile == "" || outFile == " ")
                    {
                        outFile = string.Concat(inFileName, ".out");
                    }
                }
                else
                {
                    inFileName = args[0];
                    outFile = args[1];
                }

                //Original Input
                //prompt user to enter input file name
                /*Console.WriteLine("Enter file name including extension:");
                string inFileName = Console.ReadLine();

                //obtain output file name.  If blank, default value of input + .out is used
                Console.WriteLine("Enter output file name or press enter to use " + inFileName + ".out:");
                string outFile = Console.ReadLine();
                if (outFile == "" || outFile == " ")
                {
                    outFile = string.Concat(inFileName, ".out");
                }*/

                //start timer for overall program execution
                Stopwatch totalTime = new Stopwatch();
                totalTime.Start();

                //set input, output, and fit file values.
                string filepath = string.Concat(fileDirectory);
                //filepath += "/"; // FOR THE CLUSTER
                filepath += "\\";
                string filepathIN = string.Copy(filepath);
                string filepathOUT = string.Copy(filepath);
                string filepathFIT = string.Copy(filepath);
                filepathIN += inFileName;
                filepathOUT += outFile;
                if (filepathOUT == filepathIN)
                {
                    throw new FileNameError("outFile");
                }

                //read and parse input file, then initialize FileInfo object
                string[] inputFile = FileInfo.FileRead(filepathIN);
                FileInfo input = new FileInfo();
                input.SetFileInfo(inputFile, filepath);
                input.FilePath = filepath;

                //make the fitfile point to something
                filepathFIT = string.Concat(input.FitFile);

                //see if matFile is true, and if so if the matfile exists or not.
                if (input.UseMatrixFile)
                {
                    input.MatrixFilePath = string.Copy(filepath);
                    input.MatrixFilePath += input.MatrixFile;
                    //check that the mat file has a valid path
                    if (input.MatrixFilePath == filepathIN || input.MatrixFilePath == filepathOUT || input.MatrixFilePath == filepathFIT)
                    {
                        throw new FileNameError("matFile");
                    }
                    //if this file already exists, then use it for the matrix generation
                    if (File.Exists(input.MatrixFilePath))
                    {
                        input.MatrixMade = true;
                    }
                }

                //initialize the modes
                List<ModeInfo> Modes = ModeInitialization(inputFile, input);

                //Determines if the quadratic basis set should be used
                bool isQuad = IsQuad(input, Modes);

                //Determines if any values are being fit
                bool fit = IsFit(input, Modes);

                //main subroutine execution when not running a scan
                if (input.Scan == false)
                {
                    List<string> linesToWrite = new List<string>();
                    linesToWrite = OutputFile.inputFileMaker(input, Modes);

                    if (!fit)
                    {
                        SOCJT runner = new SOCJT();
                        linesToWrite.AddRange(runner.SOCJTroutine(Modes, isQuad, inputFile, input));
                        WriteOutputFile(totalTime, filepathOUT, linesToWrite);
                        //Here, if necessary, the eigenvectors for very large matrices are calculated after the rest of the calculations have been done.
                        //This is done because this process may take a large amount of time
                        if (runner.lanczosEVectors != null)
                        {
                            CalcLargeEvecs(filepath, input, runner.lanczosEVectors, runner.basisSet);
                        }
                    }
                    else
                    {
                        FitSOCJT fitt = new FitSOCJT();
                        linesToWrite.AddRange(fitt.fit(Modes, isQuad, inputFile, input, filepathFIT));
                        WriteOutputFile(totalTime, filepathOUT, linesToWrite);
                        if (fitt.lanczosEVectors != null)
                        {
                            CalcLargeEvecs(filepath, input, fitt.lanczosEVectors, fitt.basisSet);
                        }
                    }
                    //WriteOutputFile(totalTime, filepathOUT, linesToWrite);
                }//end no scan

                else//means a scan is being run
                {
                    #region SCAN
                    SOCJT runner = new SOCJT();
                    List<Eigenvalue[]> scanList = new List<Eigenvalue[]>();
                    List<string> finalOut = new List<string>();

                    for (int h = 0; h < input.ScanSteps; h++)
                    {
                        List<string> linesToWrite = new List<string>();

                        //run loop over each variable to be scanned and increment by step size times loop iteration.
                        for (int n = 0; n < input.ScanList.Count; n++)
                        {
                            if (input.ScanList[n].varToFit.ToUpper() == "OMEGA")
                            {
                                Modes[input.ScanList[n].Mode - 1].modeOmega = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "WEXE")
                            {
                                Modes[input.ScanList[n].Mode - 1].wExe = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "D")
                            {
                                Modes[input.ScanList[n].Mode - 1].D = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "K")
                            {
                                Modes[input.ScanList[n].Mode - 1].K = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "B" || input.ScanList[n].varToFit.ToUpper() == "C")
                            {
                                int tRow = input.ScanList[n].Mode;
                                int tCol = input.ScanList[n].Cross;
                                int temp;
                                if (tRow > tCol)
                                {
                                    temp = tRow;
                                    tRow = tCol;
                                    tCol = temp;
                                }
                                input.CrossTermMatrix[tRow - 1, tCol - 1] = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "SPECIAL")
                            {
                                input.CrossTermMatrix[0, 0] = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "AT")
                            {
                                int tRow = input.ScanList[n].Mode;
                                int tCol = input.ScanList[n].Cross;
                                int temp;
                                if (tRow < tCol)
                                {
                                    temp = tRow;
                                    tRow = tCol;
                                    tCol = temp;
                                }
                                input.CrossTermMatrix[tRow - 1, tCol - 1] = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                            if (input.ScanList[n].varToFit.ToUpper() == "JT")
                            {
                                int tRow = input.ScanList[n].Mode;
                                int tCol = input.ScanList[n].Cross;
                                int temp;
                                if (tRow > tCol)
                                {
                                    temp = tRow;
                                    tRow = tCol;
                                    tCol = temp;
                                }
                                input.CrossTermMatrix[tRow - 1, tCol - 1] = input.ScanList[n].Start + input.ScanList[n].Step * (double)h;
                            }
                        }//end adjust each variable to fit

                        //now make output file for each step
                        linesToWrite = OutputFile.inputFileMaker(input, Modes);
                        linesToWrite.AddRange(runner.SOCJTroutine(Modes, isQuad, inputFile, input));

                        string stepFile = filepathOUT + "_step_" + Convert.ToString(h + 1) + ".out";
                        File.WriteAllLines(stepFile, linesToWrite);

                        //add this steps eigenvalues to the scan output file
                        scanList.Add(runner.finalList);

                        linesToWrite = null;
                        stepFile = null;
                    }//end of steps loop

                    //write scan output file including total elapsed time
                    List<string> scanOut = OutputFile.ScanOutput(scanList);
                    totalTime.Stop();
                    double TIME = totalTime.ElapsedMilliseconds / 1000D;
                    scanOut.Add(" ");
                    scanOut.Add("SOCJT 2 has completed. Total time elapsed = " + String.Format("{0,11:0.0000}", TIME) + " seconds.");
                    File.WriteAllLines(filepathOUT, scanOut);
                    #endregion
                }//end else for scan

                //Writes the matrix to file if needed
                if (input.UseMatrixFile && !input.MatrixMade)
                {
                    OutputFile.writeMatFile(input);
                }//end if to write matrix to file
            }//end try block

            //Exception handling
            catch (DirectoryNotFoundException)
            {
                Console.WriteLine("The directory does not exist");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            catch (FileNotFoundException a)
            {
                Console.WriteLine(a.Message);
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            catch (InvalidInput a)
            {
                Console.WriteLine(a.EMessage);
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            #if !DEBUG
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("An index out of range exception has occurred");
                Console.WriteLine("Check to make sure that NMODES is correct and");
                Console.WriteLine("that any CROSS_TERM arguments are correct.");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            catch (BasisSetTooSmallException a)
            {
                Console.Write(a.EMessage);
                Console.ReadLine();
            }
            catch (AEAnharmonicTermException)
            {
                Console.WriteLine("Cross anharmonic terms can only be included between two A modes.");
                Console.WriteLine("Take out any cross anharmonic terms between A and E modes.");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            catch (RepeaterError)
            {
                Console.WriteLine("NaN Error in Naive Lanczos routine.");
                Console.WriteLine("Try decreasing NOITS or using Block Lanczos instead.");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            catch (FileNameError err)
            {
                Console.WriteLine(err.EMessage);
                Console.ReadLine();
            }
            catch (MatrixFileError)
            {
                Console.WriteLine("The basis sets of the input file and matrix file are different sizes.");
                Console.WriteLine("Try regenerating the matrix.");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }

            catch (Exception ex)
            {
                Console.WriteLine("An exception has occurred: " + ex.Message);
                Console.WriteLine("Check your input file and try again.");
                Console.WriteLine("Press enter to terminate the program.");
                Console.ReadLine();
            }
            #endif
        }