public void Print_Matrix(alglib.sparsematrix A, int rows, int col) { for (int i = 0; i < rows; i++) { string output = ""; for (int j = 0; j < col; j++) { output += alglib.sparseget(A, i, j).ToString("E2") + " "; } Console.WriteLine(output); } }
static public void normalize(this alglib.sparsematrix M, IList <int> ids, int k) { foreach (int id in ids) { double[] wrow = new double[k]; int[] colids = new int[k]; int tmp; alglib.sparsegetcompressedrow(M, id, ref colids, ref wrow, out tmp); double sum = wrow.Sum(); IList <double> wrowl = wrow.ToList(); wrowl = wrowl.Divide(sum); int i = 0; foreach (int id2 in colids) { try{ alglib.sparserewriteexisting(M, id, id2, wrowl [i]); }catch (alglib.alglibexception e) { Console.WriteLine(e.msg); } i++; } } }
public double[] LinearSolver_LU(alglib.sparsematrix K, double[] F) { Stopwatch sw = new Stopwatch(); sw.Start(); Console.Write(" Solving linear system... "); // Sparse LU decomposition with column pivoting for sparsity and row pivoting // for stability. Input must be square sparse matrix stored in CRS format. // // The algorithm computes LU decomposition of a general square matrix // (rectangular ones are not supported). The result of an algorithm is a // representation of A as A = P*L*U*Q, where: // * L is lower unitriangular matrix // * U is upper triangular matrix // * P = P0*P1*...*PK, K=N-1, Pi - permutation matrix for I and P[I] // * Q = QK*...*Q1*Q0, K=N-1, Qi - permutation matrix for I and Q[I] // // This function pivots columns for higher sparsity, and then pivots rows for // stability (larger element at the diagonal). // // INPUT PARAMETERS: // A - sparse NxN matrix in CRS format. An exception is generated // if matrix is non-CRS or non-square. // PivotType- pivoting strategy: // * 0 for best pivoting available (2 in current version) // * 1 for row-only pivoting (NOT RECOMMENDED) // * 2 for complete pivoting which produces most sparse outputs // // OUTPUT PARAMETERS: // A - the result of factorization, matrices L and U stored in // compact form using CRS sparse storage format: // * lower unitriangular L is stored strictly under main diagonal // * upper triangilar U is stored ON and ABOVE main diagonal // P - row permutation matrix in compact form, array[N] // Q - col permutation matrix in compact form, array[N] // // This function always succeeds, i.e. it ALWAYS returns valid factorization, // but for your convenience it also returns boolean value which helps to // detect symbolically degenerate matrices: // * function returns TRUE, if the matrix was factorized AND symbolically // non-degenerate // * function returns FALSE, if the matrix was factorized but U has strictly // zero elements at the diagonal (the factorization is returned anyway). alglib.sparseconverttocrs(K); alglib.sparselu(K, 0, out int[] P, out int[] Q); // Sparse linear solver for A*x=b with general (nonsymmetric) N*N sparse real // matrix A given by its LU factorization, N * 1 vectors x and b. // // IMPORTANT: this solver requires input matrix to be in the CRS sparse // storage format. An exception will be generated if you pass // matrix in some other format (HASH or SKS). // // INPUT PARAMETERS // A - LU factorization of the sparse matrix, must be NxN exactly // in CRS storage format // P, Q - pivot indexes from LU factorization // N - size of A, N>0 // B - array[0..N-1], right part alglib.sparselusolve(K, P, Q, alglib.sparsegetnrows(K), F, out double[] U, out alglib.sparsesolverreport report); // Termination type (>0 - solution; -3 - error (filled by zeros)) if (report.terminationtype > 0) { Console.Write("NORMAL TERMINATION"); } else { Console.Write("ERROR TERMINATION"); } Console.Write(" (type " + report.terminationtype + ")"); sw.Stop(); Console.WriteLine(" in " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + "s"); return(U); }
public double[] LinearSolver_Cholesky(alglib.sparsematrix K, double[] F) { Stopwatch sw = new Stopwatch(); sw.Start(); // From ALGLIB manual - sparsecholeskyskyline function // // /************************************************************************* // Sparse Cholesky decomposition for skyline matrixm using in-place algorithm // without allocating additional storage. // // The algorithm computes Cholesky decomposition of a symmetric positive- // definite sparse matrix. The result of an algorithm is a representation of // A as A=U^T*U or A=L*L^T // // This function is a more efficient alternative to general, but slower // SparseCholeskyX(), because it does not create temporary copies of the // target. It performs factorization in-place, which gives best performance // on low-profile matrices. Its drawback, however, is that it can not perform // profile-reducing permutation of input matrix. // // INPUT PARAMETERS: // A - sparse matrix in skyline storage (SKS) format. // N - size of matrix A (can be smaller than actual size of A) // IsUpper - if IsUpper=True, then factorization is performed on upper // triangle. Another triangle is ignored (it may contant some // data, but it is not changed). // // // OUTPUT PARAMETERS: // A - the result of factorization, stored in SKS. If IsUpper=True, // then the upper triangle contains matrix U, such that // A = U^T*U. Lower triangle is not changed. // Similarly, if IsUpper = False. In this case L is returned, // and we have A = L*(L^T). // Note that THIS function does not perform permutation of // rows to reduce bandwidth. // // RESULT: // If the matrix is positive-definite, the function returns True. // Otherwise, the function returns False. Contents of A is not determined // in such case. // // NOTE: for performance reasons this function does NOT check that input // matrix includes only finite values. It is your responsibility to // make sure that there are no infinite or NAN values in the matrix. // // -- ALGLIB routine -- // 16.01.2014 // Bochkanov Sergey // *************************************************************************/ Console.WriteLine(" Linear system K*U=F:"); alglib.sparseconverttosks(K); Console.Write(" - Cholesky decomposition:"); bool Result = alglib.sparsecholeskyskyline(K, alglib.sparsegetnrows(K), true); if (Result == true) { Console.WriteLine(" Done"); } else { Console.WriteLine(" ERROR"); } // From ALGLIB manual - sparsecholeskysolvesks function // // /************************************************************************* // Sparse linear solver for A*x=b with N*N real symmetric positive definite // matrix A given by its Cholesky decomposition, and N*1 vectors x and b. // // IMPORTANT: this solver requires input matrix to be in the SKS (Skyline) // sparse storage format. An exception will be generated if you // pass matrix in some other format (HASH or CRS). // // INPUT PARAMETERS // A - sparse NxN matrix stored in SKS format, must be NxN exactly // N - size of A, N>0 // IsUpper - which half of A is provided (another half is ignored) // B - array[N], right part // // OUTPUT PARAMETERS // Rep - solver report, following fields are set: // * rep.terminationtype - solver status; >0 for success, // set to -3 on failure (degenerate or non-SPD system). // X - array[N], it contains: // * rep.terminationtype>0 => solution // * rep.terminationtype=-3 => filled by zeros // // -- ALGLIB -- // Copyright 26.12.2017 by Bochkanov Sergey // *************************************************************************/ Console.Write(" - Solving:"); alglib.sparsecholeskysolvesks(K, alglib.sparsegetnrows(K), true, F, out alglib.sparsesolverreport report, out double[] U); // Termination type (>0 - solution; -3 - error (filled by zeros)) if (report.terminationtype > 0) { Console.Write(" NORMAL termination"); } else { Console.Write(" ERROR termination"); } Console.WriteLine(" (type " + report.terminationtype + ")"); sw.Stop(); Console.WriteLine(" Total time to solve K*U=F: " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + "s"); return(U); }
// Linear system of equation solvers ----------------------------- public double[] LinearSolver_CG(alglib.sparsematrix K, double[] F, Analysis AnalysisLib) { Stopwatch sw = new Stopwatch(); sw.Start(); Console.Write(" Solving linear system... "); alglib.sparseconverttocrs(K); alglib.lincgcreate(alglib.sparsegetnrows(K), out alglib.lincgstate s); // From ALGLIB manual - lincgsetcond function // // ************************************************************************* // This function sets stopping criteria. // // INPUT PARAMETERS: // EpsF - algorithm will be stopped if norm of residual is less than // EpsF*||b||. // MaxIts - algorithm will be stopped if number of iterations is more // than MaxIts. // // OUTPUT PARAMETERS: // State - structure which stores algorithm state // // NOTES: // If both EpsF and MaxIts are zero then small EpsF will be set to small // value. // // -- ALGLIB -- // Copyright 14.11.2011 by Bochkanov Sergey // ************************************************************************* double tolerance = AnalysisLib.GetLinSolverTolerance(); int IterMax = AnalysisLib.GetLinSolverMaxIter(); alglib.lincgsetcond(s, tolerance, IterMax); alglib.lincgsolvesparse(s, K, true, F); alglib.lincgresults(s, out double[] U, out alglib.lincgreport report); // OUTPUT PARAMETERS: // X - array[N], solution // Rep - optimization report: // * Rep.TerminationType completetion code: // * -5 input matrix is either not positive definite, // too large or too small // * -4 overflow/underflow during solution // (ill conditioned problem) // * 1 ||residual||<=EpsF*||b|| // * 5 MaxIts steps was taken // * 7 rounding errors prevent further progress, // best point found is returned // * Rep.IterationsCount contains iterations count // * NMV countains number of matrix-vector calculations if (report.terminationtype == 1 || report.terminationtype == 7) { Console.Write(" NORMAL "); } else { Console.Write(" ERROR "); } Console.Write(" (type " + report.terminationtype + ")"); sw.Stop(); Console.WriteLine(" in " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + "s"); return(U); }
private static void SolverNonlinearStatics() { SolverFunctions Fun = new SolverFunctions(); Stopwatch sw = new Stopwatch(); sw.Start(); // Analysis settings double tolerance = 0.001; // Others string separator = " ========================================================== "; // Initialize time 0 and time 1 foreach (Node N in DB.NodeLib.Values) { N.Initialize_StepZero(); } foreach (Element E in DB.ElemLib.Values) { E.Initialize_StepZero(DB.FELib); } // Console paragraph Console.WriteLine("\n" + separator); if (DB.AnalysisLib.GetAnalysisType().StartsWith("Linear")) { Console.WriteLine(" LINEAR STATIC ANALYSIS "); } if (DB.AnalysisLib.GetAnalysisType().StartsWith("Nonlinear")) { Console.WriteLine(" NONLINEAR STATIC ANALYSIS "); } Console.WriteLine(separator); // ***************************************************************************** // ========================= MAIN FINITE ELEMENT CODE ========================== // ***************************************************************************** // ============================ Essential boundary conditions ====================================== // DoF list with kinematic BC List <int> Fix_DOF = new List <int>(); foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "SPC")) { foreach (int NID in BC.NodalValues.Keys) { if (BC.NodalValues[NID].Get(0, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[0]); } if (BC.NodalValues[NID].Get(1, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[1]); } if (BC.NodalValues[NID].Get(2, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[2]); } } } // Sort and remove duplicates of kinematic BC Fix_DOF = Fix_DOF.Distinct().ToList(); Fix_DOF.Sort(); // Define Row index reduction - rows and columns related to Dirichlet BC are removed from K matrix and F vector int[] nDOF_reduction = new int[DB.nDOF]; for (int i = 0; i < Fix_DOF.Count; i++) { nDOF_reduction[Fix_DOF[i]] = -1; } int reduc = 0; for (int i = 0; i < DB.nDOF; i++) { if (nDOF_reduction[i] == -1) { reduc++; } else { nDOF_reduction[i] = reduc; } } // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> INCREMENTAL ANALYSIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< for (int inc = 1; inc <= DB.AnalysisLib.GetIncNumb(); inc++) { Console.WriteLine("\n" + separator); Console.WriteLine(" INCREMENT " + inc); Console.WriteLine(separator); // Initialize Nodal displacements for new increment foreach (Node n in DB.NodeLib.Values) { n.Initialize_NewDisp(inc); } // Initialize Element Strain and Stress for new increment foreach (Element Elem in DB.ElemLib.Values) { Elem.Initialize_Increment(inc); } // ============================ F (Right hand side) Vector ========================================= double[] F = new double[DB.nDOF - Fix_DOF.Count]; foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "PointLoad")) { foreach (int NID in BC.NodalValues.Keys) { for (int dir = 0; dir < 3; dir++) { if (nDOF_reduction[DB.NodeLib[NID].DOF[dir]] != -1) { if (inc == 1) { F[DB.NodeLib[NID].DOF[dir] - nDOF_reduction[DB.NodeLib[NID].DOF[dir]]] += BC.NodalValues[NID].Get(dir, 0) * inc / DB.AnalysisLib.GetIncNumb(); } } } } } // ================================ NEWTON-RAPHSON ITERATION ===================================== int iter = 0; double NormF = Fun.Vector_Norm(F); double NormRes = 1; // Iteration zero: Console.WriteLine(" ITERATION 0: "); alglib.sparsematrix K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Initial"); // Newton loop while (NormRes > tolerance) //while (iter<1) { if (iter > 0) { Console.WriteLine(" ITERATION " + iter + ": "); K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Tangent"); Fun.Print_Matrix(K, 6, 8); } // ============================== SOLVING LINEAR SYSTEM =================================== double[] U = new double[DB.nDOF - Fix_DOF.Count]; alglib.sparsematrix K1 = (alglib.sparsematrix)K.make_copy(); if (DB.AnalysisLib.GetLinSolver() == "CG") { U = Fun.LinearSolver_CG(K1, F, DB.AnalysisLib); } if (DB.AnalysisLib.GetLinSolver() == "Cholesky") { U = Fun.LinearSolver_Cholesky(K1, F); } if (DB.AnalysisLib.GetLinSolver() == "LU") { U = Fun.LinearSolver_LU(K1, F); } // ================== U (Left hand side) vector reconstruction ===================================== double[] U_Full = Fun.Include_BC_DOF(U, nDOF_reduction); // Assign displacements to nodes (replace dU vector and update dU Buffer) foreach (Node n in DB.NodeLib.Values) { n.dU[0] = U_Full[n.DOF[0]]; n.dU_buffer[0] += U_Full[n.DOF[0]]; n.dU[1] = U_Full[n.DOF[1]]; n.dU_buffer[1] += U_Full[n.DOF[1]]; n.dU[2] = U_Full[n.DOF[2]]; n.dU_buffer[2] += U_Full[n.DOF[2]]; //Console.Write("Node " + n.ID + " disp: "); Fun.Print_Vector(n.dU_buffer, 3); } // Internal Forces vector double[] R = new double[DB.nDOF]; Console.Write(" Stress recovery: "); Parallel.ForEach(DB.ElemLib.Values, Elem => { Elem.Recovery_Stress(DB); Elem.Compute_NodalForces(DB); // Assembly Nodal Forces vector for (int i = 0; i < Elem.NList.Count; i++) { for (int j = 0; j < 3; j++) { R[DB.NodeLib[Elem.NList[i]].DOF[j]] += Elem.NodalForces.GetFast(3 * i + j, 0); } } }); R = Fun.Exclude_BC_DOF(R, nDOF_reduction); Console.WriteLine(" Done"); Fun.Print_MatrixST(DB.ElemLib[1].dS[0].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[1].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[2].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[3].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[4].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[5].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[6].Transpose(), 1, 6); Fun.Print_MatrixST(DB.ElemLib[1].dS[7].Transpose(), 1, 6); Console.WriteLine("\n Nodal forces:"); Fun.Print_Vector(R, R.Length); Console.WriteLine("\n"); // Calculate Residual Forces double[] Residual = new double[DB.nDOF - Fix_DOF.Count]; for (int i = 0; i < F.Length; i++) { Residual[i] = F[i] - R[i]; } // Calculate Residual Forces norm and extreme value NormRes = Fun.Vector_Norm(Residual) / NormF; double ExtremeResidual = Math.Max(Residual.Max(), Math.Abs(Residual.Min())); Console.WriteLine(" Residual norm: " + NormRes.ToString("F4")); Console.WriteLine(" Max residual force: " + ExtremeResidual.ToString("#0.0e+0") + "\n"); //Console.WriteLine("\nOut of balance forces:\n" + string.Join("\n", F.Where(x => x != 0)) + "\n"); // Next iteration F = Residual; iter++; } Console.WriteLine(" INCREMENT CONVERGED in " + iter + " iterations\n"); // Update nodal displacement, element stress and strain foreach (Node N in DB.NodeLib.Values) { N.Update_Displacement(inc); } foreach (Element E in DB.ElemLib.Values) { E.Update_StrainStress(inc); } } sw.Stop(); Console.WriteLine("\n" + separator); Console.WriteLine(" Total CPU time: " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + " s"); Console.WriteLine(separator); }
private static void SolverLinearStatics() { SolverFunctions Fun = new SolverFunctions(); Stopwatch sw = new Stopwatch(); sw.Start(); // Others int inc = 1; string separator = " ========================================================== "; // Initialize time 0 and time 1 foreach (Node N in DB.NodeLib.Values) { N.Initialize_StepZero(); N.Initialize_NewDisp(inc); } foreach (Element E in DB.ElemLib.Values) { E.Initialize_StepZero(DB.FELib); E.Initialize_Increment(inc); } // Console paragraph Console.WriteLine("\n" + separator); Console.WriteLine(" LINEAR STATIC ANALYSIS "); Console.WriteLine(separator); // ***************************************************************************** // ========================= MAIN FINITE ELEMENT CODE ========================== // ***************************************************************************** // ============================ Essential boundary conditions ====================================== // DoF list with kinematic BC List <int> Fix_DOF = new List <int>(); foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "SPC")) { foreach (int NID in BC.NodalValues.Keys) { if (BC.NodalValues[NID].Get(0, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[0]); } if (BC.NodalValues[NID].Get(1, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[1]); } if (BC.NodalValues[NID].Get(2, 0) == 1) { Fix_DOF.Add(DB.NodeLib[NID].DOF[2]); } } } // Sort and remove duplicates of kinematic BC Fix_DOF = Fix_DOF.Distinct().ToList(); Fix_DOF.Sort(); // Define Row index reduction - rows and columns related to Dirichlet BC are removed from K matrix and F vector int[] nDOF_reduction = new int[DB.nDOF]; for (int i = 0; i < Fix_DOF.Count; i++) { nDOF_reduction[Fix_DOF[i]] = -1; } int reduc = 0; for (int i = 0; i < DB.nDOF; i++) { if (nDOF_reduction[i] == -1) { reduc++; } else { nDOF_reduction[i] = reduc; } } // ============================ F (Right hand side) Vector ========================================= double[] F = new double[DB.nDOF - Fix_DOF.Count]; foreach (BoundaryCondition BC in DB.BCLib.Values.Where(x => x.Type == "PointLoad")) { foreach (int NID in BC.NodalValues.Keys) { for (int dir = 0; dir < 3; dir++) { if (nDOF_reduction[DB.NodeLib[NID].DOF[dir]] != -1) { if (inc == 1) { F[DB.NodeLib[NID].DOF[dir] - nDOF_reduction[DB.NodeLib[NID].DOF[dir]]] += BC.NodalValues[NID].Get(dir, 0); } } } } } // ============================== GLOBAL STIFFNESS MATRIX =================================== alglib.sparsematrix K = Fun.ParallelAssembly_K(DB, nDOF_reduction, inc, "Initial"); // ============================== SOLVING LINEAR SYSTEM =================================== double[] U = new double[DB.nDOF - Fix_DOF.Count]; if (DB.AnalysisLib.GetLinSolver() == "CG") { U = Fun.LinearSolver_CG(K, F, DB.AnalysisLib); } if (DB.AnalysisLib.GetLinSolver() == "Cholesky") { U = Fun.LinearSolver_Cholesky(K, F); } if (DB.AnalysisLib.GetLinSolver() == "LU") { U = Fun.LinearSolver_LU(K, F); } // ================== U (Left hand side) vector reconstruction ===================================== double[] U_Full = Fun.Include_BC_DOF(U, nDOF_reduction); // Assign displacements to nodes (replace dU vector and update dU Buffer) foreach (Node n in DB.NodeLib.Values) { n.dU_buffer[0] = U_Full[n.DOF[0]]; n.dU_buffer[1] = U_Full[n.DOF[1]]; n.dU_buffer[2] = U_Full[n.DOF[2]]; //Console.Write("Node " + n.ID + " disp: "); Fun.Print_Vector(n.dU_buffer, 3); } // Internal Forces vector double[] R = new double[DB.nDOF]; Console.Write(" Stress recovery: "); Parallel.ForEach(DB.ElemLib.Values, Elem => { Elem.Recovery_Stress(DB); Elem.Compute_NodalForces(DB); // Assembly Nodal Forces vector for (int i = 0; i < Elem.NList.Count; i++) { for (int j = 0; j < 3; j++) { R[DB.NodeLib[Elem.NList[i]].DOF[j]] += Elem.NodalForces.GetFast(3 * i + j, 0); } } }); R = Fun.Exclude_BC_DOF(R, nDOF_reduction); Console.WriteLine(" Done"); // Update nodal displacement, element stress and strain foreach (Node n in DB.NodeLib.Values) { n.Update_Displacement(inc); } foreach (Element E in DB.ElemLib.Values) { E.Update_StrainStress(inc); } // Print CPU time summary sw.Stop(); Console.WriteLine("\n" + separator); Console.WriteLine(" Total CPU time: " + sw.Elapsed.TotalSeconds.ToString("F2", CultureInfo.InvariantCulture) + " s"); Console.WriteLine(separator); }
/// <summary> /// Call this to build matrices. /// </summary> public void Initialize(bool clearSources = true) { float time = Time.realtimeSinceStartup; float time0 = time; Debug.Log("Initializing matrices..."); if (clearSources) { s = new List<Vertex>(); } bool multiSource = useAccurateMultisource && s.Count > 1; int n = g.vertices.Count; // Heat matrix (Neumann condition) A1 = g.CalculateLcMatrixSparse(- Settings.tFactor * g.h * g.h, false, multiSource ? s : null); if (multiSource) { modif1 = g.modification; } for (int i = 0; i < n; i++) { alglib.sparseadd(A1, i, i, g.vertices[i].CalculateVertexAreaTri()); } if (useCholesky) { alglib.sparseconverttosks(A1); alglib.sparsecholeskyskyline(A1, n, true); } else { alglib.sparseconverttocrs(A1); } Debug.Log("Heat equation matrix built, time = " + (Time.realtimeSinceStartup - time) * 1000 + "ms"); time = Time.realtimeSinceStartup; if (g.hasBorder && Settings.boundaryCondition > 0) { // Dirichlet condition heat matrix A1b = g.CalculateLcMatrixSparse(- Settings.tFactor * g.h * g.h, true, multiSource ? s : null); if (multiSource) { modif1b = g.modification; } for (int i = 0; i < n; i++) { alglib.sparseadd(A1b, i, i, g.vertices[i].CalculateVertexAreaTri()); } if (useCholesky) { alglib.sparseconverttosks(A1b); alglib.sparsecholeskyskyline(A1b, n, true); } else { alglib.sparseconverttocrs(A1b); } Debug.Log("Additional heat equation matrix built (dirichlet), time = " + (Time.realtimeSinceStartup - time) * 1000 + "ms"); time = Time.realtimeSinceStartup; } // Laplacien matrix A2 = g.CalculateLcMatrixSparse(-1, false, multiSource ? s : null); if (multiSource) { foreach (Vertex src in s) { alglib.sparseadd(A2, src.index, src.index, 1); } } if (useCholesky) { for (int i = 0; i < n; i++) { alglib.sparseadd(A2, i, i, 0.000000001); // To make it positive definite } alglib.sparseconverttosks(A2); alglib.sparsecholeskyskyline(A2, n, true); } else { alglib.sparseconverttocrs(A2); } Debug.Log("Laplacien matrix built, time = " + (Time.realtimeSinceStartup - time) * 1000 + "ms"); time = Time.realtimeSinceStartup; // Tables of Cotangent value * edge vectors div = g.CalculateDivData(); Debug.Log("Cotangent table built, time = " + (Time.realtimeSinceStartup - time) * 1000 + "ms"); GameObject.Find("Timer2").GetComponent<Text>().text = "Precalculation time = " + (Time.realtimeSinceStartup - time0) * 1000 + "ms"; }
/// <summary> /// Generates a list of alglib sparsematrix objects where the first is the diagonal elements and the remaining ones are for D and K for each mode and then the matrices for the cross terms. /// </summary> /// <param name="basisVectorsByJ"> /// List of JBasisVectors sorted by J. /// </param> /// <param name="isQuad"> /// True means a quadratic basis set is used and quadratic terms will be calculated. /// </param> /// <param name="input"> /// FileInfo object containing input information. /// </param> /// <param name="nColumns"> /// Integer with order of A. /// </param> /// <param name="par"> /// Value indicating max degree of parallelism for matrix generation loop. /// </param> /// <param name="diagOnly"> /// Boolean to see if only the diagonal elements should be generated /// </param> /// <returns> /// List of sparsematrix objects corresponding to different parameters. /// </returns> public static List<alglib.sparsematrix> GenMatrixHash(List<BasisFunction> basisVectorsByJ, bool isQuad, FileInfo input, out int nColumns, int par, bool diagOnly, int position) { int matSize = basisVectorsByJ.Count; nColumns = matSize; bool bilinear = false; int nModes = input.nModes; //Lists to store the positions of the A and E vecs with cross-terms coupling List<int> biAVecPos = new List<int>(); List<int> biEVecPos = new List<int>(); List<int> eVecPos = new List<int>(); List<int> aVecPos = new List<int>(); //List to store the alglib sparse matrices for each variable var matList = new List<alglib.sparsematrix>(); //The Tuple stores the row and column of the matrix element in the two int values and the value at that matrix element as the double //order of row and column is unimportant since the matrix is symmetric List<ConcurrentBag<Tuple<int, int, double>>> matrixPos = new List<ConcurrentBag<Tuple<int, int, double>>>(); //this array stores the v and l values for each mode for each basis function as well as Lambda and J //all v values are stored in elements 0 through nmodes - 1 and l is in nmodes through 2*nmodes - 1 //Lambda is stored in element 2*nmodes and J is stored as an int as (J - 0.5) in 2 * nmodes + 1 //the nested loops initialize the vlLambda arrays for each basis function //This is ugly but makes the matrix generation much faster than accessing the objects in the matrix generation and saves me a ton of re-coding int[,] vlLambda = new int[matSize, nModes * 2 + 2]; int[] hashStorage = new int[nModes * 2 + 1]; //Dictionary<string, int> basisPositions = new Dictionary<string, int>(); //basisPositions[position] = new Dictionary<string, int>(); for (int i = 0; i < matSize; i++) { for (int j = 0; j < nModes; j++) { vlLambda[i, j] = hashStorage[j] = basisVectorsByJ[i].modesInVec[j].V; vlLambda[i, j + nModes] = hashStorage[j + nModes] = basisVectorsByJ[i].modesInVec[j].L; } vlLambda[i, nModes * 2] = hashStorage[nModes * 2] = basisVectorsByJ[i].Lambda; vlLambda[i, nModes * 2 + 1] = (int)(basisVectorsByJ[i].J - 0.5M); basisPositions[position].Add(BasisFunction.GenerateHashCode(hashStorage, nModes), i); }//end loop to make vlLambda //generate an array to store omega, omegaExe, D, K and degeneracy of each mode //only one copy of this is needed since those values are the same across all basis functions var modeVals = new double[nModes, 5]; for (int i = 0; i < nModes; i++) { modeVals[i, 0] = basisVectorsByJ[0].modesInVec[i].ModeOmega; modeVals[i, 1] = basisVectorsByJ[0].modesInVec[i].Anharmonicity; modeVals[i, 2] = basisVectorsByJ[0].modesInVec[i].DBasis; modeVals[i, 3] = basisVectorsByJ[0].modesInVec[i].KBasis; modeVals[i, 4] = 2.0;//degeneracy = 2 by default if (basisVectorsByJ[0].modesInVec[i].SymmetryIsA) { modeVals[i, 4] = 1.0; aVecPos.Add(i); } else { modeVals[i, 4] = 2.0; eVecPos.Add(i); } }//end loop to make modeVals[,] array #region HO Terms //just the harmonic oscillator terms. Here only the diagonal elements are generated var diag = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, matSize, out diag); //loop through all diagonal elements for (int n = 0; n < matSize; n++) { //one mode harmonic and anharmonic terms for (int i = 0; i < input.nModes; i++) { double temp = modeVals[i, 0] * ((double)vlLambda[n, i] + (double)modeVals[i, 4] / 2.0) - modeVals[i, 1] * Math.Pow((vlLambda[n, i] + (double)modeVals[i, 4] / 2.0), 2.0); alglib.sparseadd(diag, n, n, temp); }//end loop over modes continue; }//end HO loop //add diagonal matrix elements to matList as element [0] matList.Add(diag); #endregion //if this is not the first call to the Hamiltonian generation function then only the diagonal elements are needed //therefore, if diagOnly is true, just return matList with only the diagonal portion of the matrix. if (diagOnly) { return matList; } //loop through each mode to see if a sparse matrix is needed for D and K for (int i = 0; i < nModes; i++) { if (!basisVectorsByJ[0].modesInVec[i].SymmetryIsA || basisVectorsByJ[0].modesInVec[i].DBasis != 0.0) { //means this mode is degenerate, add matrices for D and K alglib.sparsematrix tempMat = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, matSize * (nModes + 1), out tempMat); matList.Add(tempMat); alglib.sparsematrix tempMat2 = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, matSize * (nModes + 1), out tempMat2); matList.Add(tempMat2); } else { //add empty matrices for D and K for non degenerate modes. Probably not a huge deal but saves some memory alglib.sparsematrix tempMat = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, 0, out tempMat); matList.Add(tempMat); alglib.sparsematrix tempMat2 = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, 0, out tempMat2); matList.Add(tempMat2); } } //initialize cross-terms and generate biAVecPos and biEVecPos lists BilinearInitialization(basisVectorsByJ[0].modesInVec, nModes, out bilinear, out biAVecPos, out biEVecPos, input.CrossTermMatrix); bool crossQuad = false; var crossQuadPos = CrossQuadraticInitialization(eVecPos, out crossQuad, input.CrossTermMatrix); //add any matrices needed for cross-terms if (input.CrossTermMatrix != null) { for (int i = 0; i < nModes; i++) { for (int j = 0; j < nModes; j++) { //add a new sparsematrix for each nonzero cross-term element if (input.CrossTermMatrix[i, j] != 0.0) { alglib.sparsematrix tempMat = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, matSize * (nModes + 1), out tempMat); matList.Add(tempMat); } } } }//enf if crossTermMatrix == null //initialize the concurrentBags for each matrix being generated. -1 in loop bounds because diagonal already done for (int n = 0; n < matList.Count - 1; n++) { matrixPos.Add(new ConcurrentBag<Tuple<int, int, double>>()); } //set up the settings for the parallel foreach loop var rangePartitioner = Partitioner.Create(0, matSize); ParallelOptions parOp = new ParallelOptions(); parOp.MaxDegreeOfParallelism = par; Parallel.ForEach(rangePartitioner, parOp, (range, loopState) => { //indexes n and m are for the rows and columns of the matrix respectively for (int n = range.Item1; n < range.Item2; n++) { int[] hashInt = new int[nModes * 2 + 1]; for (int a = 0; a < hashInt.Length; a++) { hashInt[a] = vlLambda[n, a]; } int[] tempInt; int m; double temp; string hashCode; for (int aModes = 0; aModes < aVecPos.Count; aModes++) { #region SymmetricGradient for (int deltaV = -1; deltaV < 2; deltaV += 2) { tempInt = (int[])hashInt.Clone(); DeltaVL(ref tempInt, aVecPos[aModes], deltaV, 0, nModes, false); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); if (basisPositions[position].TryGetValue(hashCode, out m)) { //assign temp here. double oneORnone = 0.0; if (deltaV == 1) { oneORnone = 1.0; } temp = Math.Sqrt(((double)vlLambda[n, aVecPos[aModes]] + oneORnone)); Tuple<int, int, double> ttTemp = new Tuple<int, int, double>(n, m, temp);// basisVectorsByJ[n].modesInVec[mode].v basisVectorsByJ[n].modesInVec[mode].l matrixPos[2 * aVecPos[aModes]].Add(ttTemp); } } #endregion } for (int eModes = 0; eModes < eVecPos.Count; eModes++) { #region Linear //linear portion //now check each EVecPos mode for a linear element by taking vlLambda[n, ] and changing the values appropriately to find a linear element. Store in tempint //tempInt = (int[])hashInt.Clone(); for(int deltal = -1; deltal < 2; deltal += 2) { for (int deltaV = -1; deltaV < 2; deltaV += 2) { tempInt = (int[])hashInt.Clone(); DeltaVL(ref tempInt, eVecPos[eModes], deltaV, deltal, nModes); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); //if it exists, then assign it to the linear value if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = LinearMatrixElement(vlLambda, n, eVecPos[eModes], nModes, deltal, deltaV); Tuple<int, int, double> ttTemp = new Tuple<int, int, double>(n, m, temp);// basisVectorsByJ[n].modesInVec[mode].v basisVectorsByJ[n].modesInVec[mode].l matrixPos[2 * eVecPos[eModes]].Add(ttTemp); } } }//end loop over deltaV }//end loop over linear l values #endregion #region Quadratic //check for all quadratic elements //reset tempInt values for Quadratic elements for (int ll = -2; ll < 3; ll += 4) { tempInt = (int[])hashInt.Clone(); //for bottom matrix element on page DeltaVL(ref tempInt, eVecPos[eModes], 2, ll, nModes); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = (1 / 4D * Math.Sqrt((vlLambda[n, eVecPos[eModes]] + (ll / 2) * vlLambda[n, nModes + eVecPos[eModes]] + 4D) * (vlLambda[n, eVecPos[eModes]] + (ll / 2) * vlLambda[n, nModes + eVecPos[eModes]] + 2))); Tuple<int, int, double> tTemp = new Tuple<int, int, double>(n, m, temp); matrixPos[eVecPos[eModes] * 2 + 1].Add(tTemp); } } //reset tempInt values for Quadratic elements tempInt = (int[])hashInt.Clone(); //for middle matrix element on page DeltaVL(ref tempInt, eVecPos[eModes], 0, ll, nModes); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = (1D / 2D * Math.Sqrt((vlLambda[n, eVecPos[eModes]] + (ll / 2) * vlLambda[n, nModes + eVecPos[eModes]] + 2) * (vlLambda[n, eVecPos[eModes]] - (ll / 2) * vlLambda[n, eVecPos[eModes] + nModes]))); Tuple<int, int, double> tTemp = new Tuple<int, int, double>(n, m, temp); matrixPos[eVecPos[eModes] * 2 + 1].Add(tTemp); } } tempInt = (int[])hashInt.Clone(); //for top matrix element on page DeltaVL(ref tempInt, eVecPos[eModes], -2, ll, nModes); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = (1 / 4D * Math.Sqrt((vlLambda[n, eVecPos[eModes]] - (ll / 2) * vlLambda[n, nModes + eVecPos[eModes]]) * (vlLambda[n, eVecPos[eModes]] - (ll / 2) * vlLambda[n, nModes + eVecPos[eModes]] - 2))); Tuple<int, int, double> tTemp = new Tuple<int, int, double>(n, m, temp); matrixPos[eVecPos[eModes] * 2 + 1].Add(tTemp); } } }//end quadratic loop over l values #endregion }//end loop over E-modes int crossCount = 0; #region Bilinear if (bilinear) { //loop through A and E vecs with possible coupling for (int a = 0; a < biAVecPos.Count; a++) { for (int e = 0; e < biEVecPos.Count; e++) { //value to keep track of which cross-term matrix we're on. crossCount = a + e; //this is because the cross-term couplings for JT terms are stored in the upper-diagonal of the cross-term matrix int row; int column; if (biAVecPos[a] > biEVecPos[e]) { column = biAVecPos[a]; row = biEVecPos[e]; } else { column = biEVecPos[e]; row = biAVecPos[a]; } for (int ll = -1; ll < 2; ll += 2) { for (int dve = -1; dve < 2; dve += 2) { for (int dva = -1; dva < 2; dva += 2) { double oneORnone = 0.0; if (dva == 1) { oneORnone = 1.0; } double twoORnone = 0.0; int pre = -1; if (dve == 1) { twoORnone = 2.0; pre = 1; } tempInt = (int[])hashInt.Clone(); //delta vl for e mode DeltaVL(ref tempInt, biEVecPos[e], dve, ll, nModes); //delta vl for a mode DeltaVL(ref tempInt, biAVecPos[a], dva, 0, nModes, false); hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); //formula for bilinear matrix element if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = 0.5 * Math.Sqrt(((double)vlLambda[n, biAVecPos[a]] + oneORnone) * ((double)vlLambda[n, biEVecPos[e]] + ll * pre * vlLambda[n, nModes + biEVecPos[e]] + twoORnone));//ll * (double)vlLambda[n, EVecPos[eModes] + nModes] + 2D)) Tuple<int, int, double> tTemp = new Tuple<int, int, double>(n, m, temp); matrixPos[2 * nModes + crossCount].Add(tTemp); } } }//end loop over delta v values for a mode }//end loop over delta v values for e mode }//end loop over l values for e mode }//end for loop over evec positions }//end for loop over a vec positions }//end bilinear if #endregion #region Cross-Quadratic if (crossQuad) { for (int crossTerm = 0; crossTerm < crossQuadPos.Count; crossTerm += 2) { crossCount++; // Moved this up since without it, the matrix was adding onto the last one. if (!bilinear && crossTerm == 0) // If bilinear matrices were not generated, then start at 0. { crossCount = 0; } for (int deltal = -1; deltal < 2; deltal += 2) { for (int deltaV = -1; deltaV < 2; deltaV += 2) { for (int deltal2 = -1; deltal2 < 2; deltal2 += 2) { for (int deltaV2 = -1; deltaV2 < 2; deltaV2 += 2) { for (int changeLambda = 0; changeLambda < 2; changeLambda++) { //tbool makes it so that every other iteration of changeLambda is electronically off-diagonal bool tbool = false; if (changeLambda == 0) { tbool = true; continue; } tempInt = (int[])hashInt.Clone(); //get DeltaVL for the first mode //DeltaVL(ref tempInt, eVecPos[crossQuadPos[crossTerm]], deltaV, deltal, nModes, tbool); DeltaVL(ref tempInt, crossQuadPos[crossTerm], deltaV, deltal, nModes, tbool); //get DeltaVL for the second mode //DeltaVL(ref tempInt, eVecPos[crossQuadPos[crossTerm + 1]], deltaV2, deltal2, nModes); DeltaVL(ref tempInt, crossQuadPos[crossTerm + 1], deltaV2, deltal2, nModes); //generate the hashcode hashCode = BasisFunction.GenerateHashCode(tempInt, nModes); //if it exists, then assign it to the linear value if (basisPositions[position].TryGetValue(hashCode, out m)) { if (m > n) { temp = LinearMatrixElement(vlLambda, n, crossQuadPos[crossTerm], nModes, deltal, deltaV); temp *= LinearMatrixElement(vlLambda, n, crossQuadPos[crossTerm + 1], nModes, deltal2, deltaV2); temp *= 0.5; Tuple<int, int, double> ttTemp = new Tuple<int, int, double>(n, m, temp);// basisVectorsByJ[n].modesInVec[mode].v basisVectorsByJ[n].modesInVec[mode].l matrixPos[2 * nModes + crossCount].Add(ttTemp); } } }//end loop over change lambda }//end loop over deltaV }//end loop over linear l values }//end loop over deltaV }//end loop over linear l values // crossCount++; }//end loop over cross quadratic terms } #endregion }//row for loop }//end anonymous function in parallel for loop );//end parallel for //actually add all of the matrix elements to the matrices //Start at 0 because matrixPos only has off diagonal elements. Add elements to matList[i + 1] because matList already has diagonal elements in position 0. for (int i = 0; i < matrixPos.Count; i++) { //add all calculated matrix elements to the appropriate sparsematrices foreach (Tuple<int, int, double> spot in matrixPos[i]) { alglib.sparseadd(matList[i + 1], spot.Item1, spot.Item2, spot.Item3); } } return matList; }
/// <summary> /// Takes a list of alglib.sparsematrix objects and combines them. /// </summary> /// <param name="mat"> /// List of alglib.sparsematrix objects to be combined /// </param> /// <returns> /// alglib.sparsematrix object which contains all elements of all alglib.sparsematrix objects in the List mat. /// </returns> private static alglib.sparsematrix aggregator(List<alglib.sparsematrix> mat) { int i; int j; double oldVal; alglib.sparsematrix B = new alglib.sparsematrix(); alglib.sparsecreate(mat[0].innerobj.m, mat[0].innerobj.n, out B); for (int m = 0; m < mat.Count; m++) { int t0 = 0; int t1 = 0; while (alglib.sparseenumerate(mat[m], ref t0, ref t1, out i, out j, out oldVal)) { alglib.sparseadd(B, i, j, oldVal); //adds lower diagonal matrix elements for all off-diagonal matrices (first element in mat is the diagonal elements so don't do this for it). if (m != 0) { alglib.sparseadd(B, j, i, oldVal); } } } return B; }
public List<string> SOCJTroutine(List<ModeInfo> Modes, bool isQuad, string[] inputFile, FileInfo input) { //Sets minimum and maximum j values. Stopwatch measurer = new Stopwatch(); long howMuchTime; decimal jMin; decimal jMax; //If is quadratic makes sure that the maxJ is at least 7.5 if (isQuad == true) { if (input.maxJ < 7.5M) { input.maxJ = 7.5M; } } if (isQuad == true) { jMax = input.maxJ; jMin = -input.maxJ; }//end if else { jMax = input.maxJ; if (input.MinJBool == true) { jMin = input.minJ; } else { jMin = 0.5M; } }//end if //Makes a List of Lists of Basis objects with each List of Basis objects being for one mode. List<List<BasisByMode>> basisByMode = new List<List<BasisByMode>>(); for (int i = 0; i < input.nModes; i++) { basisByMode.Add(new List<BasisByMode>()); basisByMode[i] = BasisByMode.GenVLCombinations(Modes[i], i); }//end for //Generates all of the JBasisVectors to be used in calculation. List<BasisFunction> hamiltonianVecs = BasisFunction.GenJVecs(basisByMode, input.nModes, jMin, jMax); //hamiltonianVecs are the total list of all J vectors in the Hamiltonian //Sorts the hamiltonianVecs by J and puts them into a List of Lists of JBasisVectors. List<List<BasisFunction>> jBasisVecsByJ = new List<List<BasisFunction>>(); for (decimal i = jMin; i <= jMax; i++) { jBasisVecsByJ.Add(GenHamMat.SortByJ(hamiltonianVecs, i)); }//end for loop //Initializes Lists to hold the Hamiltonian matrices, eigenvectors, eigenvalues, basis vectors for the output file and number of columns for each j matrix respectively. //Also initializes the Dictionary list for storing the positions of the basis functions List<double[,]> zMatrices = new List<double[,]>(); List<double[]> eigenvalues = new List<double[]>(); List<List<BasisFunction>> JvecsForOutuput = new List<List<BasisFunction>>(); List<BasisFunction>[] jbasisoutA = new List<BasisFunction>[0]; List<int> numColumns = new List<int>(); GenHamMat.basisPositions = new List<Dictionary<string, int>>(); #region Hamiltonian List<alglib.sparsematrix> sHamMatrix = new List<alglib.sparsematrix>(); alglib.sparsematrix[] array1; int[] numcolumnsA; //smallMat = false; //Creates the Hamiltonian matrices for linear cases int numQuadMatrix = 0; List<int> a = new List<int>(); if (input.M > input.NumberOfIts) { throw new BasisSetTooSmallException(false); } if (isQuad == false) { #region LinearHamiltonian measurer.Reset(); measurer.Start(); int h = 0; array1 = new alglib.sparsematrix[jBasisVecsByJ.Count]; List<int> basisSize = new List<int>(); basisSet = jBasisVecsByJ; if (!matricesMade) { fitHamList = new List<List<alglib.sparsematrix>>(); for (int m = 0; m < jBasisVecsByJ.Count; m++) { fitHamList.Add(new List<alglib.sparsematrix>()); } //check here to see if matrix file should be used, if so then read from file and make them, set matricesMade to true //matricesMade = matReadFunction(input); basisSize = matReadFunction(input, ref matricesMade); } numcolumnsA = new int[jBasisVecsByJ.Count]; //put items up to length in here for (int i = (int)(jMin - 0.5M); i < (int)(jMax + 0.5M); i++) { GenHamMat.basisPositions.Add(new Dictionary<string, int>()); } ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = input.ParJ; try { Parallel.For((int)(jMin - 0.5M), (int)(jMax + 0.5M), options, i => { int nColumns; if (jBasisVecsByJ[i].Count != 0)//changed from h to i { //this checks if the matrix was read from file, and if so if the basis set is the correct size if (basisSize.Count != 0) { if (basisSize[i] != jBasisVecsByJ[i].Count) { throw new MatrixFileError(); } } if (!matricesMade)//if matrices not made then generate all matrices { fitHamList[i] = GenHamMat.GenMatrixHash(jBasisVecsByJ[i], isQuad, input, out nColumns, input.ParMatrix, false, i); } else//this makes sure that the diagonal portion is regenerated on each call. { fitHamList[i][0] = GenHamMat.GenMatrixHash(jBasisVecsByJ[i], isQuad, input, out nColumns, input.ParMatrix, true, i)[0]; } numcolumnsA[i] = nColumns; if (numcolumnsA[i] < input.M) { a.Add(0); } h++; } else { a.Add(0); } }//end for loop ); } catch (AggregateException ae) { foreach (var e in ae.InnerExceptions) { if (e is MatrixFileError) { throw new MatrixFileError(); } else { throw; } } } measurer.Stop(); howMuchTime = measurer.ElapsedMilliseconds; input.MatrixGenerationTime = (double)howMuchTime / 1000D; for (int i = (int)(jMin - 0.5M); i < (int)(jMax + 0.5M); i++) { zMatrices.Add(new double[0, 0]); eigenvalues.Add(new double[0]); } matricesMade = true; //handles errors where the basis set is too small if (a.Count > 0) { throw new BasisSetTooSmallException(true); } #endregion }//end if //Creates the Hamiltonian matrices for quadratic cases. else { #region QuadraticHamiltonian measurer.Reset(); measurer.Start(); int dynVar1 = (int)(jMax - 1.5M); int dynVar2 = dynVar1 / 3; List<int> basisSize = new List<int>(); array1 = new alglib.sparsematrix[jBasisVecsByJ.Count - dynVar1 - jBasisVecsByJ.Count / 2];//changed to dynVar1 from 6 if (!matricesMade) { fitHamList = new List<List<alglib.sparsematrix>>(); for (int m = 0; m < jBasisVecsByJ.Count - dynVar1 - jBasisVecsByJ.Count / 2; m++) { fitHamList.Add(new List<alglib.sparsematrix>()); } //check here to see if matrix file should be used, if so then read from file and make them, set matricesMade to true basisSize = matReadFunction(input, ref matricesMade); } numcolumnsA = new int[jBasisVecsByJ.Count - dynVar1 - jBasisVecsByJ.Count / 2];//changed to dynVar1 from 6 jbasisoutA = new List<BasisFunction>[jBasisVecsByJ.Count - dynVar1 - jBasisVecsByJ.Count / 2];//changed to dynVar1 from 6 for (int i = jBasisVecsByJ.Count / 2; i < jBasisVecsByJ.Count - dynVar1; i++) { GenHamMat.basisPositions.Add(new Dictionary<string, int>()); } ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = input.ParJ; try { Parallel.For(jBasisVecsByJ.Count / 2, jBasisVecsByJ.Count - dynVar1, options, i =>//changed to dynVar1 from 6 { List<BasisFunction> quadVecs = new List<BasisFunction>(); int nColumns; for (int v = -dynVar2 - 1; v <= dynVar2; v++) { if (i + v * 3 >= 0) { quadVecs.AddRange(jBasisVecsByJ[i + v * 3]); } } //this checks if the matrix was read from file, and if so if the basis set is the correct size if (basisSize.Count != 0) { if (basisSize[i - jBasisVecsByJ.Count / 2] != quadVecs.Count) { throw new MatrixFileError(); } } //if matrices aren't made then generate all of them if (!matricesMade) { fitHamList[i - jBasisVecsByJ.Count / 2] = GenHamMat.GenMatrixHash(quadVecs, isQuad, input, out nColumns, input.ParMatrix, false, i - jBasisVecsByJ.Count / 2); } else//If they are made then just generate the diagonal elements. { fitHamList[i - jBasisVecsByJ.Count / 2][0] = GenHamMat.GenMatrixHash(quadVecs, isQuad, input, out nColumns, input.ParMatrix, true, i - jBasisVecsByJ.Count / 2)[0]; } jbasisoutA[i - jBasisVecsByJ.Count / 2] = quadVecs; numcolumnsA[i - jBasisVecsByJ.Count / 2] = nColumns; if (numcolumnsA[i - jBasisVecsByJ.Count / 2] < input.M) { a.Add(0); } numQuadMatrix++; } ); } catch (AggregateException ae) { foreach (var e in ae.InnerExceptions) { if (e is MatrixFileError) { throw new MatrixFileError(); } else { throw; } } } basisSet = new List<List<BasisFunction>>(); for (int jj = 0; jj < jbasisoutA.Length; jj++) { basisSet.Add(jbasisoutA[jj]); } matricesMade = true; measurer.Stop(); howMuchTime = measurer.ElapsedMilliseconds; input.MatrixGenerationTime = (double)howMuchTime / 1000D; if (a.Count > 0) { throw new BasisSetTooSmallException(true); } for (int i = 0; i < 2; i++) { zMatrices.Add(new double[0, 0]); eigenvalues.Add(new double[0]); } #endregion }//end else #endregion //list where each element of mat is a list of alglib.sparsematrix objects. One for each off-diagonal parameter (D, K, B) var mat = new List<List<alglib.sparsematrix>>(); bool bilinear = false; var biAVecPos = new List<int>(); var biEVecPos = new List<int>(); GenHamMat.BilinearInitialization(jBasisVecsByJ[0][0].modesInVec, input.nModes, out bilinear, out biAVecPos, out biEVecPos, input.CrossTermMatrix); //code here to convert the alglib matrices to matrices for each j block for (int i = 0; i < fitHamList.Count; i++) { int whichCrossMatrix = 0; mat.Add(new List<alglib.sparsematrix>()); int count; int DorK; double val = 0.0; //this adds the diagonal elements to the list mat[i].Add(fitHamList[i][0]); //go through each member of the list and multiply it by the appropriate value, combine them all //skip the first one which is the diagonal elements and isn't multiplied by anything. for (int j = 1; j < fitHamList[i].Count; j++) { count = (j - 1) / 2; DorK = (j - 1) % 2; if (count < input.nModes) { if (DorK == 0) { if (!Modes[count].IsAType) { val = Math.Sqrt(Modes[count].D) * Modes[count].modeOmega; } else { //val = Math.Sqrt(Modes[count].D); val = Modes[count].D; } } else { val = Modes[count].K * Modes[count].modeOmega; } } else//means it's a cross term. loop over relevant E and A terms in same order as in genFitMatrix function { int crossMatrixCounter = 0; for (int blOrNot = 0; blOrNot < 2; blOrNot++) { for (int row = 0; row < input.CrossTermMatrix.GetLength(0); row++) { for (int column = row + 1; column < input.CrossTermMatrix.GetLength(0); column++) { if (input.CrossTermMatrix[row, column] != 0.0) { //now test to see if this is a bilinear or cross quadratic term. do bilinear first, then cross quadratic. //then can get the value //use blOrNot to see if we should be doing bilinear or not //if this is a bilinear term, only add it if blOrNot == 0 //crossMatrixCounter will keep going if ((biAVecPos.Exists(x => x == row) || biAVecPos.Exists(x => x == column)) && blOrNot == 0) { //means this is a bilinear term if (crossMatrixCounter == whichCrossMatrix) { val = input.CrossTermMatrix[row, column]; }//end conditional to see if this is the cross-term element we want crossMatrixCounter++; } if (!(biAVecPos.Exists(x => x == row) || biAVecPos.Exists(x => x == column)) && blOrNot == 1) { //means this is a cross-quadratic term if (crossMatrixCounter == whichCrossMatrix) { val = input.CrossTermMatrix[row, column]; }//end conditional to see if this is the cross-term element we want crossMatrixCounter++; } }//end conditional to see if this matrix element is 0 }//end loop over columns of cross-term matrix }//end loop over rows of cross-term matrix }//end loop to go through the cross-term matrix twice whichCrossMatrix++; }//end else for counting if it's D / K or cross-Term mat[i].Add(cTimesSparse(fitHamList[i][j], val)); }//end loop over fitHamList } //now need to convert the lists of matrices in each mat element into a single object //here convert the alglib matrices to the appropriate things. for (int i = 0; i < array1.Length; i++) { array1[i] = aggregator(mat[i]);//some functio to put in aggregate of mat[i] sparsematrices } //move this to after genFitMatricss are treated so that SO code does not need to be changed #region Spin Orbit //add SO stuff here if (input.IncludeSO == true) { //Jvecs for output // //var tempBasisList = new List<List<BasisFunction>>(); decimal minS = input.S * -1M; List<alglib.sparsematrix> tempMatList = new List<alglib.sparsematrix>(); List<int> tempNumbColumns = new List<int>(); for (int i = 0; i < array1.Length; i++) { for (decimal j = minS; j <= input.S; j++) { alglib.sparsematrix tempMat = new alglib.sparsematrix(); alglib.sparsecopy(array1[i], out tempMat); tempMatList.Add(tempMat); if (isQuad) { JvecsForOutuput.Add(jbasisoutA[i]); } else { JvecsForOutuput.Add(jBasisVecsByJ[i]); } //jbasisoutA for quadratic //jBasisVecsByJ for linear //tempBasisList.Add(JvecsForOutuput[i]); for (int k = 0; k < numcolumnsA[i]; k++) { double temp = input.Azeta * (double)JvecsForOutuput[i][k].Lambda * (double)j; alglib.sparseadd(tempMatList[tempMatList.Count - 1], k, k, temp); }//end loop over diagonal matrix elements tempNumbColumns.Add(numcolumnsA[i]); //means SO only in j = 0.5 block for quadratic cases //if (i > 0 && isQuad) //means SO only in degenerate blocks if ((i - 1) % 3 == 0) { break; } }//end loop over values of S }//end loop over all previouly made sparseMatrices numcolumnsA = null; numcolumnsA = tempNumbColumns.ToArray(); array1 = null; array1 = tempMatList.ToArray(); //JvecsForOutuput.Clear(); //JvecsForOutuput = tempBasisList; zMatrices.Clear(); eigenvalues.Clear(); for (int i = 0; i < array1.Length; i++) { zMatrices.Add(new double[0, 0]); eigenvalues.Add(new double[0]); } }//end if inclSO == true #endregion for (int i = 0; i < array1.Length; i++) { alglib.sparseconverttocrs(array1[i]); } #region Seed // Makes an Array of List where the first index is Floor(j) and the second index are all elements in the seed vector to be non zero. // The Lanczos routine is parallelized by j, and the routine takes the list at [j] to implement the seed vector. Empty list will indicate that no seed is being used. var SeedPositionsByJ = new List<int>[GenHamMat.basisPositions.Count]; var SeedCoefficientsByJ = new List<double>[GenHamMat.basisPositions.Count]; var isAbyJ = new List<bool>[GenHamMat.basisPositions.Count]; // Array of Lists where the first index is Floor(j) and the second index are booleans indicating A1 (T) or Not A1 (F) for (int i = 0; i < GenHamMat.basisPositions.Count; i++) { SeedPositionsByJ[i] = new List<int>(); // Initialize seed position list for each j SeedCoefficientsByJ[i] = new List<double>(); isAbyJ[i] = new List<bool>(); } if (input.useSeed) { SeedPositionsByJ = GenerateSeedPositions(input.SeedFile, input.nModes, isQuad, ref SeedCoefficientsByJ); } #endregion #region Lanczos int[] IECODE = new int[array1.Length]; int[] ITER = new int[array1.Length]; //actually diagonalizes the Hamiltonian matrix measurer.Reset(); measurer.Start(); //if the evecs of the lanczos matrices will need to be stored then save the lanczos matrices. if (input.PrintVector && !input.BlockLanczos && array1[0].innerobj.m >= Lanczos.basisSetLimit) { lanczosEVectors = new List<double[,]>(); for (int i = 0; i < array1.Length; i++) { lanczosEVectors.Add(new double[0, 0]); } } ParallelOptions options2 = new ParallelOptions(); options2.MaxDegreeOfParallelism = input.ParJ; try { Parallel.For(0, array1.Length, options2, i =>//changed to array1.count from sHamMatrix.count { double[] evs; double[,] temp; IECODE[i] = -1; //add a parameter to count Lanczos iterations to set possible stopping criteria that way //call MINVAL from here if (!input.BlockLanczos)//means use naiveLanczos routine { ITER[i] = input.NumberOfIts; evs = new double[input.M + 1]; temp = new double[numcolumnsA[i], input.M + 1]; Lanczos.NaiveLanczos(ref evs, ref temp, ref isAbyJ[i], array1[i], input.NumberOfIts, input.Tolerance, input.PrintVector, SeedPositionsByJ[i], SeedCoefficientsByJ[i], i, input.FilePath); } else//means use block Lanczos from SOCJT { evs = new double[input.M + 1]; temp = new double[numcolumnsA[i], input.M + 1];//changed here to numcolumnsA IECODE[i] = -1; ITER[i] = Lanczos.MINVAL(numcolumnsA[i], input.M + 1, input.kFactor, input.M, input.NumberOfIts, input.Tolerance, 0, ref evs, ref temp, ref IECODE[i], array1[i], input.ParVectorMultiplication); } //initialize eigenvalues to have a length. eigenvalues[i] = new double[evs.Length - 1]; for (int j = 0; j < evs.Length - 1; j++) { eigenvalues[i][j] = evs[j]; } //I think this should be only for if block lanczos or naive lanczos with already calculated eigenvectors if (input.BlockLanczos) // || (!input.BlockLanczos && array1[i].innerobj.m * input.NumberOfIts < Lanczos.basisSetLimit)) // I don't know what this second condition is for. { zMatrices[i] = new double[numcolumnsA[i], evs.Length - 1];//changed input.M to evs.Length - 1 for (int j = 0; j < numcolumnsA[i]; j++) { for (int k = 0; k < evs.Length - 1; k++)//changed input.M to evs.Length - 1 { zMatrices[i][j, k] = temp[j, k]; } } } //here if evectors are needed and hamiltonian is too large assign the lanczosEVectors to the if (!input.BlockLanczos && array1[0].innerobj.m >= Lanczos.basisSetLimit && input.PrintVector) { //assign the evecs of the lanczos matrices to the lanczosEVectors list. lanczosEVectors[i] = new double[temp.GetLength(0), temp.GetLength(1)]; for (int j = 0; j < temp.GetLength(0); j++) { for (int k = 0; k < temp.GetLength(1); k++) { lanczosEVectors[i][j, k] = temp[j, k]; } } } temp = null; evs = null; }//end for ); }//end try catch (AggregateException ae) { foreach (var e in ae.InnerExceptions) { if (e is RepeaterError) { throw new RepeaterError(); } else { throw; } } }//end catch if (input.CheckEigenvector) { //LanczosChecker(input, array1, zMatrices, eigenvalues); int jBlock = (int)(input.JBlockEigenvector.Item1 - 0.5M); CheckJohnEigenvector(input, array1[jBlock], eigenvalues[jBlock][input.JBlockEigenvector.Item2 - 1]); } if (!input.BlockLanczos && array1[0].innerobj.m * input.NumberOfIts >= Lanczos.basisSetLimit && input.PrintVector) { //make it so that the output file generator does not try to print the values in the zmatrices which will be the eigenvectors of the lanczos matrix, not the hamiltonian input.PrintVector = false; } measurer.Stop(); howMuchTime = measurer.ElapsedMilliseconds; input.DiagonalizationTime = (double)howMuchTime / 1000D; #endregion if (input.IncludeSO == false) { if (isQuad == false) { JvecsForOutuput = jBasisVecsByJ; }//end if else { for (int i = 0; i < jbasisoutA.Length; i++) { JvecsForOutuput.Add(jbasisoutA[i]); } }//end else } //writes the eigenvectors to disk if that has been requested //if NTooBig == true then the separate eigenvector file will be made after the eigenvectors are calculated if (input.EVectorFile && (input.BlockLanczos || input.PrintVector)) { writeVecFile(input, zMatrices, JvecsForOutuput, 0.0); }//end if //put code here to write eigenvectors to file with entire basis set. //do this by writing function to use jbasisvecsbyj which has all basis functions and //go through that list, where a basis function is in it and JvecsForOutput, pull the appropriate coefficient //from the zmatrices, otherwise just put in a 0. if (input.VectorFileComplete) { writeVecComplete(jBasisVecsByJ, JvecsForOutuput, zMatrices, input, eigenvalues, isQuad); } //this is where the intensity or overlap will be checked if necessary var overlaps = new List<double[]>(eigenvalues.Count); for (int count = 0; count < eigenvalues.Count; count++) { overlaps.Add(new double[eigenvalues[count].Length]); } if (input.Intensity && input.PrintVector) { //code here to read vector and take dot product double[] vector; if (input.JSInten) { for (int jIndex = 0; jIndex < eigenvalues.Count(); jIndex++) { vector = EigenvectorReader(input.FilePath + input.VectorName, jIndex); Lanczos.normalize(vector); overlaps[jIndex] = Overlap(zMatrices[jIndex], vector); } } else { vector = ReadSOCJT2Vector(input.VectorName, input.VectorIndex, input.VectorJBlock, input.Special); Lanczos.normalize(vector); for (int jIndex = 0; jIndex < eigenvalues.Count(); jIndex++) { if (jIndex == (int)(input.VectorJBlock - 0.5M)) { overlaps[jIndex] = Overlap(zMatrices[jIndex], vector); } else { overlaps[jIndex] = new double[zMatrices[jIndex].GetLength(0)]; } } } foreach (double[] overlap in overlaps) { Lanczos.normalize(overlap); } } List<string> linesToWrite = new List<string>(); finalList = setAndSortEVs(eigenvalues, isAbyJ, input.S, input.IncludeSO, zMatrices, JvecsForOutuput, input, overlaps);//add the eigenvectors so that the symmetry can be included as well linesToWrite = OutputFile.makeOutput(input, zMatrices, array1, JvecsForOutuput, eigenvalues, isQuad, finalList, IECODE, ITER); outp = linesToWrite; return linesToWrite; }
/// <summary> /// Function that reads a matrix file from file and initializes hamiltonian matrices. /// </summary> /// <param name="input"> /// initialized FileInfo object. /// </param> /// <param name="matricesMade"> /// Set to true if the matrices are generated after this function call. /// </param> /// <returns> /// Boolean indicating whether or not the fitHamList matrices have been initialized from matFile. /// </returns> private static List<int> matReadFunction(FileInfo input, ref bool matricesMade) { matricesMade = false; List<int> basisSizeList = new List<int>(); if (input.UseMatrixFile && input.MatrixMade) { string[] matFile = { }; try { matFile = FileInfo.FileRead(input.MatrixFilePath); } catch (FileNotFoundException) { throw new FileNotFoundException("The matrix file does not exist."); } catch { throw new Exception("Matrix File Error." + "\r" + "Please check the matrix file and try again."); } matricesMade = true; //read the matrix into memory int index = 0, basisSize = 0; for (int i = 0; i < matFile.Length; i++) { if (matFile[i] == "List") { index = Convert.ToInt32(matFile[i + 1]); basisSize = Convert.ToInt32(matFile[i + 2]); basisSizeList.Add(basisSize); //this is the matrix for the diagonal elements. These are added seperately. var B = new alglib.sparsematrix(); alglib.sparsecreate(basisSize, basisSize, out B); fitHamList[index].Add(B); continue; }//end if matFile[i] == List if (matFile[i] == "Matrix") { var B = new alglib.sparsematrix(); alglib.sparsecreate(basisSize, basisSize, out B); i += 2; while (matFile[i] != "List" && matFile[i] != "Matrix") { alglib.sparseadd(B, Convert.ToInt32(matFile[i]), Convert.ToInt32(matFile[i + 1]), FileInfo.ParseDouble(matFile[i + 2])); i += 3; if (i >= matFile.Length) { break; } } i--; fitHamList[index].Add(B); }//end if matFile[i] == Matrix }//end for loop over entire matrix file }//end if //return matricesMade; return basisSizeList; }
/// <summary> /// Used to multiply all elements in a sparse matrix A by the value val /// </summary> /// <param name="A"> /// Sparse matrix to be multiplied. /// </param> /// <param name="val"> /// Value to be multiplied /// </param> /// <returns> /// Sparesmatrix containing the original matrix A times the double val. /// </returns> private static alglib.sparsematrix cTimesSparse(alglib.sparsematrix A, double val) { int i; int j; double oldVal; int t0 = 0; int t1 = 0; alglib.sparsematrix B = new alglib.sparsematrix(); alglib.sparsecreate(A.innerobj.m, A.innerobj.n, out B); while (alglib.sparseenumerate(A, ref t0, ref t1, out i, out j, out oldVal)) { alglib.sparseadd(B, i, j, oldVal * val); } return B; }
/// <summary> /// Generates an alglib sparsematrix object to be used in Lanczos diagonalization. /// </summary> /// <param name="basisVectorsByJ"> /// List of JBasisVectors sorted by J. /// </param> /// <param name="isQuad"> /// True means a quadratic basis set is used and quadratic terms will be calculated. /// </param> /// <param name="input"> /// FileInfo object containing input information. /// </param> /// <param name="nColumns"> /// Integer with order of A. /// </param> /// <param name="Large"> /// boolean value so that genMatrix method could be overloaded. /// </param> /// <returns></returns> public static alglib.sparsematrix genMatrix(List<JBasisVector> basisVectorsByJ, bool isQuad, FileInfo input, out int nColumns, bool Large, int par) { int matSize = basisVectorsByJ.Count; nColumns = matSize; int r = 0; double temp = 0; alglib.sparsematrix A = new alglib.sparsematrix(); alglib.sparsecreate(matSize, matSize, 10, out A); bool containsAVecs = false; List<int> AVecPos = new List<int>(); List<int> EVecPos = new List<int>(); List<int> biAVecPos = new List<int>(); List<int> biEVecPos = new List<int>(); int[] change = new int[3]; #region CrossTermInitializationStuff if (input.includeCrossTerms == true) { for (int i = 0; i < input.nModes; i++) { if (basisVectorsByJ[0].modesInVec[i].symmetryIsA == true) { AVecPos.Add(i); containsAVecs = true; continue; } else { EVecPos.Add(i); } }//end for //for bilinear coupling if (containsAVecs == true) { //new lists just for bilinear coupling biAVecPos = AVecPos; biEVecPos = EVecPos; //loop to eliminate any A vectors that have no cross-coupling for (int i = 0; i < biAVecPos.Count; i++) { for (int j = 0; j < biEVecPos.Count; j++) { if (biAVecPos[i] > biEVecPos[j]) { if (input.crossTermMatrix[biEVecPos[j], biAVecPos[i]] != 0) { break; } } else { if (input.crossTermMatrix[biAVecPos[i], biEVecPos[j]] != 0) { break; } } if (j == biEVecPos.Count - 1) { biAVecPos.RemoveAt(i); i--; break; } } } //loop to eliminate any E vectors that have no cross-coupling for (int i = 0; i < biEVecPos.Count; i++) { for (int j = 0; j < biAVecPos.Count; j++) { if (biAVecPos[j] > biEVecPos[i]) { if (input.crossTermMatrix[biEVecPos[i], biAVecPos[j]] != 0) { break; } } else { if (input.crossTermMatrix[biAVecPos[j], biEVecPos[i]] != 0) { break; } } if (j == biAVecPos.Count - 1) { biEVecPos.RemoveAt(i); i--; break; } } } } //stuff for cross quadratic for (int i = 0; i < EVecPos.Count; i++) { for (int j = i + 1; j < EVecPos.Count; j++) { if (input.crossTermMatrix[EVecPos[i], EVecPos[j]] != 0) { break; } if (j == EVecPos.Count - 1) { EVecPos.RemoveAt(i); i--; break; } } } }//end if CrossTerms == true #endregion //generates the Hamiltonian Matrix //this checks to make sure that any cross anharmonic terms are only between two A type modes if (input.includeCrossTerms == true) { for (int i = 1; i < input.nModes; i++) { for (int j = 0; j < i; j++) { if (input.crossTermMatrix[i, j] > 0.0000001 || input.crossTermMatrix[i, j] < -0.0000001) { if (basisVectorsByJ[0].modesInVec[i].symmetryIsA == false || basisVectorsByJ[0].modesInVec[j].symmetryIsA == false) { throw new AEAnharmonicTermException(); } } } } } //just the HO terms if (input.AT == true) { for (int n = 0; n < matSize; n++) { #region HO Terms + Cross //one mode harmonic and anharmonic terms for (int i = 0; i < input.nModes; i++) { int degeneracy = 2; if (basisVectorsByJ[n].modesInVec[i].symmetryIsA) { degeneracy = 1; } temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].v + (double)degeneracy / 2D) - basisVectorsByJ[n].modesInVec[i].anharmonicity * Math.Pow((basisVectorsByJ[n].modesInVec[i].v + (double)degeneracy / 2), 2);//I deleted the (double) from the degeneracy / 2 alglib.sparseadd(A, n, n, temp);//changed from (A, n, m, temp) temp = 0; } //Not wrong, just incomplete. These are the diagonal terms. Off diagonal terms are later. //cross anharmonic terms if (input.AT == true) { for (int i = 1; i < input.nModes; i++) { for (int j = 0; j < i; j++) { if (input.crossTermMatrix[i, j] > 0.0000001 || input.crossTermMatrix[j, i] < -0.0000001) { //added the *4 to this temp = input.crossTermMatrix[i, j] * 4D * ((double)basisVectorsByJ[n].modesInVec[i].v + (double)1 / 2) * ((double)basisVectorsByJ[n].modesInVec[j].v + (double)1 / 2);//took off the -1 alglib.sparseadd(A, n, n, temp);//changed from (A, n, m, temp) temp = 0; }//end if }//end j for loop }//end i for loop }//end if AT == true continue; #endregion } }//end for if AT = true else { for (int n = 0; n < matSize; n++) { #region HO Terms //one mode harmonic and anharmonic terms for (int i = 0; i < input.nModes; i++) { int degeneracy = 2; if (basisVectorsByJ[n].modesInVec[i].symmetryIsA) { degeneracy = 1; } temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].v + (double)degeneracy / 2D) - basisVectorsByJ[n].modesInVec[i].anharmonicity * Math.Pow((basisVectorsByJ[n].modesInVec[i].v + (double)degeneracy / 2), 2);//I deleted the (double) from the degeneracy / 2 alglib.sparseadd(A, n, n, temp);//changed from (A, n, m, temp) temp = 0; }//end if AT == true continue; #endregion } } //now the JT terms //Parallel.For(0, par, hh => //{ //for (int n = hh * (matSize / par); n < ((hh + 1) * matSize) / par; n++) for(int n = 0; n < matSize; n++) { for (int m = n + 1; m < matSize; m++)//changed from r + 1 { //double temp; int numberOfChanges = modeChangeCounter(basisVectorsByJ, input.nModes, n, m); //makes it skip any places where matrix elements are 0. if (numberOfChanges > 2) { continue; } //indexes n and m are for the rows and columns of the matrix respectively if (basisVectorsByJ[n].Lambda == basisVectorsByJ[m].Lambda && input.Special == false && input.AT == false)//checks to see if it can have an off diagonal term { continue; } if (input.Special == true && numberOfChanges <= 2 && basisVectorsByJ[n].Lambda == basisVectorsByJ[m].Lambda) { #region Special if (numberOfChanges == 1) { if (basisVectorsByJ[n].modesInVec[0].v + 1 == basisVectorsByJ[m].modesInVec[0].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[0].v + 1D) * (2D * (double)basisVectorsByJ[n].modesInVec[1].v + 1D);//mode two stuff alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } /* if (basisVectorsByJ[n].modesInVec[0].v - 1 == basisVectorsByJ[m].modesInVec[0].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt(basisVectorsByJ[n].modesInVec[0].modeOmega * (double)basisVectorsByJ[n].modesInVec[0].v) * basisVectorsByJ[n].modesInVec[1].modeOmega * (2D * (double)basisVectorsByJ[n].modesInVec[1].v + 1D);//mode two stuff alglib.sparseadd(A, n, m, temp); temp = 0; continue; } */ } if (numberOfChanges == 2) { if (basisVectorsByJ[n].modesInVec[0].v + 1 == basisVectorsByJ[m].modesInVec[0].v) { /* if (basisVectorsByJ[n].modesInVec[1].v - 2 == basisVectorsByJ[m].modesInVec[1].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt(basisVectorsByJ[n].modesInVec[0].modeOmega * (double)basisVectorsByJ[n].modesInVec[0].v + 1D) * basisVectorsByJ[n].modesInVec[1].modeOmega * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[1].v - 1D) * (double)basisVectorsByJ[n].modesInVec[1].v); alglib.sparseadd(A, n, m, temp); temp = 0; continue; } */ if (basisVectorsByJ[n].modesInVec[1].v + 2 == basisVectorsByJ[m].modesInVec[1].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[0].v + 1D) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[1].v + 2D) * ((double)basisVectorsByJ[n].modesInVec[1].v + 1D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } } if (basisVectorsByJ[n].modesInVec[0].v - 1 == basisVectorsByJ[m].modesInVec[0].v) { if (basisVectorsByJ[n].modesInVec[1].v + 2 == basisVectorsByJ[m].modesInVec[1].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[0].v) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[1].v + 2D) * ((double)basisVectorsByJ[n].modesInVec[1].v + 1D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } /* if (basisVectorsByJ[n].modesInVec[1].v - 2 == basisVectorsByJ[m].modesInVec[1].v) { temp = input.crossTermMatrix[0, 0] * Math.Sqrt(basisVectorsByJ[n].modesInVec[0].modeOmega * (double)basisVectorsByJ[n].modesInVec[0].v) * basisVectorsByJ[n].modesInVec[1].modeOmega * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[1].v - 1D) * (double)basisVectorsByJ[n].modesInVec[1].v); alglib.sparseadd(A, n, m, temp); temp = 0; continue; } */ } continue; } #endregion } if (input.AT == true && basisVectorsByJ[n].Lambda == basisVectorsByJ[m].Lambda && numberOfChanges <= 2) { #region Cross-AT //also, add an exception so that if one of these modes is an e type mode it throws an error for (int i = 1; i < input.nModes; i++)//rows { for (int j = 0; j < i; j++)//columns { if (input.crossTermMatrix[i, j] > 0.0000001 || input.crossTermMatrix[i, j] < -0.00000001) { if (basisVectorsByJ[n].modesInVec[i].v + 2 == basisVectorsByJ[m].modesInVec[i].v) { if (basisVectorsByJ[n].modesInVec[j].v + 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v + 3D * (double)basisVectorsByJ[n].modesInVec[i].v + 2D) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v + 3D * (double)basisVectorsByJ[n].modesInVec[j].v + 2D); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } if (basisVectorsByJ[n].modesInVec[j].v == basisVectorsByJ[m].modesInVec[j].v && numberOfChanges == 1) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v + 3D * (double)basisVectorsByJ[n].modesInVec[i].v + 2D) * 2D * ((double)basisVectorsByJ[n].modesInVec[j].v + 0.5); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } if (basisVectorsByJ[n].modesInVec[j].v - 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v + 3D * (double)basisVectorsByJ[n].modesInVec[i].v + 2D) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v - (double)basisVectorsByJ[n].modesInVec[j].v); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } } if (basisVectorsByJ[n].modesInVec[i].v == basisVectorsByJ[m].modesInVec[i].v && numberOfChanges == 1) { if (basisVectorsByJ[n].modesInVec[j].v + 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * 2D * ((double)basisVectorsByJ[n].modesInVec[i].v + 0.5) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v + 3D * (double)basisVectorsByJ[n].modesInVec[j].v + 2D); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } /* if (basisVectorsByJ[n].modesInVec[j].v == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * 4D * ((double)basisVectorsByJ[n].modesInVec[i].v + 0.5) * ((double)basisVectorsByJ[n].modesInVec[j].v + 0.5); alglib.sparseadd(A, n, m, temp); temp = 0; } */ if (basisVectorsByJ[n].modesInVec[j].v - 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * 2D * ((double)basisVectorsByJ[n].modesInVec[i].v + 0.5) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v - (double)basisVectorsByJ[n].modesInVec[j].v); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } } if (basisVectorsByJ[n].modesInVec[i].v - 2 == basisVectorsByJ[m].modesInVec[i].v) { if (basisVectorsByJ[n].modesInVec[j].v + 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v - (double)basisVectorsByJ[n].modesInVec[i].v) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v + 3D * (double)basisVectorsByJ[n].modesInVec[j].v + 2D); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } if (basisVectorsByJ[n].modesInVec[j].v == basisVectorsByJ[m].modesInVec[j].v && numberOfChanges == 1) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v - (double)basisVectorsByJ[n].modesInVec[i].v) * 2D * ((double)basisVectorsByJ[n].modesInVec[j].v + 0.5); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } if (basisVectorsByJ[n].modesInVec[j].v - 2 == basisVectorsByJ[m].modesInVec[j].v) { temp = input.crossTermMatrix[i, j] * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[i].v * (double)basisVectorsByJ[n].modesInVec[i].v - (double)basisVectorsByJ[n].modesInVec[i].v) * Math.Sqrt((double)basisVectorsByJ[n].modesInVec[j].v * (double)basisVectorsByJ[n].modesInVec[j].v - (double)basisVectorsByJ[n].modesInVec[j].v); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; } } //go through possible nonzero terms } } } #endregion } //calculate JT terms if (numberOfChanges == 1)//changed this to one from zero { for (int i = 0; i < input.nModes; i++) { if (basisVectorsByJ[n].modesInVec[i].v == basisVectorsByJ[m].modesInVec[i].v && basisVectorsByJ[n].modesInVec[i].l == basisVectorsByJ[m].modesInVec[i].l) { continue; }//this just makes it skip the extra conditionals if it's not the mode with the potential JT term #region linear terms if (basisVectorsByJ[n].modesInVec[i].v + 1 == basisVectorsByJ[m].modesInVec[i].v && basisVectorsByJ[n].modesInVec[i].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * Math.Sqrt(basisVectorsByJ[n].modesInVec[i].DBasis * ((double)basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[i].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; break;//I think I can do this }//end first if if (basisVectorsByJ[n].modesInVec[i].v + 1 == basisVectorsByJ[m].modesInVec[i].v && basisVectorsByJ[n].modesInVec[i].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * Math.Sqrt(basisVectorsByJ[n].modesInVec[i].DBasis * ((double)basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[i].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; break; }//end second if //I don't think this code is ever used since I only have the upper triangle of the matrix being used /* if (basisVectorsByJ[n].modesInVec[i].v - 1 == basisVectorsByJ[m].modesInVec[i].v && basisVectorsByJ[n].modesInVec[i].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[i].l) { matrix[n, m] += basisVectorsByJ[n].modesInVec[i].modeOmega * Math.Sqrt(basisVectorsByJ[n].modesInVec[i].DBasis * ((double)basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[i].l));//don't think this 2 should be here break; }//end third if if (basisVectorsByJ[n].modesInVec[i].v - 1 == basisVectorsByJ[m].modesInVec[i].v && basisVectorsByJ[n].modesInVec[i].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[i].l) { matrix[n, m] += basisVectorsByJ[n].modesInVec[i].modeOmega * Math.Sqrt(basisVectorsByJ[n].modesInVec[i].DBasis * ((double)basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[i].l));//don't think this 2 should be here break; }//end fourth if */ #endregion if (isQuad == true) { #region quadratic terms if (basisVectorsByJ[n].modesInVec[i].v - 2 == basisVectorsByJ[m].modesInVec[i].v) { if (basisVectorsByJ[n].modesInVec[i].l + 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 4D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l) * (basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l - 2))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for top terms in +/- if (basisVectorsByJ[n].modesInVec[i].l - 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 4D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l) * (basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l - 2))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for bottom terms in +/- break; }//end if for top quadratic term (1 of 3) if (basisVectorsByJ[n].modesInVec[i].v == basisVectorsByJ[m].modesInVec[i].v) { if (basisVectorsByJ[n].modesInVec[i].l + 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 2D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 2) * (basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for top terms in +/- if (basisVectorsByJ[n].modesInVec[i].l - 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 2D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 2) * (basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for bottom terms in +/- break; }//end if for top quadratic term (2 of 3) if (basisVectorsByJ[n].modesInVec[i].v + 2 == basisVectorsByJ[m].modesInVec[i].v) { if (basisVectorsByJ[n].modesInVec[i].l + 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 4D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 4D) * (basisVectorsByJ[n].modesInVec[i].v + Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 2))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for top terms in +/- if (basisVectorsByJ[n].modesInVec[i].l - 2 * Math.Pow(-1D, input.S2) == basisVectorsByJ[m].modesInVec[i].l) { temp = basisVectorsByJ[n].modesInVec[i].modeOmega * (basisVectorsByJ[n].modesInVec[i].KBasis / 4D * Math.Sqrt((basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 4D) * (basisVectorsByJ[n].modesInVec[i].v - Math.Pow(-1, input.S2) * basisVectorsByJ[n].modesInVec[i].l + 2))); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; }//end if for bottom terms in +/- break; }//end if for top quadratic term (3 of 3) #endregion }//end if }//end for loop }//end of JT terms part #region Cross Terms if (input.includeCrossTerms == true && numberOfChanges == 2) { //bilinear stuff if (containsAVecs == true) { #region Bilinear for (int a = 0; a < biAVecPos.Count; a++) { for (int e = 0; e < biEVecPos.Count; e++) { int row; int column; if (biAVecPos[a] > biEVecPos[e]) { column = biAVecPos[a]; row = biEVecPos[e]; } else { column = biEVecPos[e]; row = biAVecPos[a]; } if (basisVectorsByJ[n].modesInVec[biAVecPos[a]].v + 1 == basisVectorsByJ[m].modesInVec[biAVecPos[a]].v) { ////* if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v + 1D) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue;//I think I can do this }//end first if if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v + 1D) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if //*/ if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v + 1D) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v + 1D) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if } if (basisVectorsByJ[n].modesInVec[biAVecPos[a]].v - 1 == basisVectorsByJ[m].modesInVec[biAVecPos[a]].v) { if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue;//I think I can do this }//end first if if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if ////* if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l - (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v + Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - 1 == basisVectorsByJ[m].modesInVec[biEVecPos[e]].v && basisVectorsByJ[n].modesInVec[biEVecPos[e]].l + (int)Math.Pow(-1D, (double)input.S1) == basisVectorsByJ[m].modesInVec[biEVecPos[e]].l) { temp = input.crossTermMatrix[row, column] * Math.Sqrt(basisVectorsByJ[n].modesInVec[biAVecPos[a]].modeOmega * basisVectorsByJ[n].modesInVec[biEVecPos[e]].modeOmega) * Math.Sqrt(((double)basisVectorsByJ[n].modesInVec[biAVecPos[a]].v) * ((double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].v - Math.Pow(-1D, (double)input.S1) * (double)basisVectorsByJ[n].modesInVec[biEVecPos[e]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if //*/ } //if statements for A mode with if statements for e mode within //here is where to put the if conditions for the matrix } } #endregion }//end bilinear stuff if (EVecPos.Count > 1) { #region Cross-Quadratic int ps = -1; if (input.S1 == 0) { ps = 1; } for (int i = 0; i < EVecPos.Count; i++) { for (int j = i + 1; j < EVecPos.Count; j++) { if (basisVectorsByJ[n].modesInVec[EVecPos[i]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[i]].v && basisVectorsByJ[n].modesInVec[EVecPos[i]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[i]].l) { if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end first if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if }//end first if if (basisVectorsByJ[n].modesInVec[EVecPos[i]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[i]].v && basisVectorsByJ[n].modesInVec[EVecPos[i]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[i]].l) { if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end first if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l + 2D)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if }//end second if if (basisVectorsByJ[n].modesInVec[EVecPos[i]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[i]].v && basisVectorsByJ[n].modesInVec[EVecPos[i]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[i]].l) { if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end first if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if }//end third if if (basisVectorsByJ[n].modesInVec[EVecPos[i]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[i]].v && basisVectorsByJ[n].modesInVec[EVecPos[i]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[i]].l) { if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end first if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v + 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l + 2D)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end second if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l - ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v + (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end third if if (basisVectorsByJ[n].modesInVec[EVecPos[j]].v - 1 == basisVectorsByJ[m].modesInVec[EVecPos[j]].v && basisVectorsByJ[n].modesInVec[EVecPos[j]].l + ps == basisVectorsByJ[m].modesInVec[EVecPos[j]].l) { temp = input.crossTermMatrix[EVecPos[i], EVecPos[j]] * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[i]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[i]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[i]].l)) * Math.Sqrt(basisVectorsByJ[n].modesInVec[EVecPos[j]].modeOmega * ((double)basisVectorsByJ[n].modesInVec[EVecPos[j]].v - (double)ps * (double)basisVectorsByJ[n].modesInVec[EVecPos[j]].l)); alglib.sparseadd(A, n, m, temp); alglib.sparseadd(A, m, n, temp); temp = 0; continue; }//end fourth if }//end fourth if } } #endregion }//end Cross-quadratic }//end if CrossTerms = true #endregion }//column for loop r++; }//row for loop //} //);//end parallel for //end the parallel loop here alglib.sparseconverttocrs(A); return A; }