// End Initialize() in MDSLinearAlgebra // MaxIndicator = 0 Find Maximum Eigenvalue of Matrix // MaxIndicator = 1 Find Maximum Eigenvalue of (Maximizr - Matrix) public static int PowerIterate(Desertwind Solution, int MaxIndicator, double Maximizer, out double PowerEigenvalue) { if (DistributedNewIteratedVector == null) { Initialize(); } Hotsun.UseDiagonalScaling = true; Hotsun.AddMarquardtQDynamically = false; // Set up Initial Power Vectors SetInitialPowerVector(DistributedNewIteratedVector); double AdotA = SALSABLAS.VectorScalarProduct(DistributedNewIteratedVector, DistributedNewIteratedVector); int somethingtodo = 0; int PowerIterationCount = 0; PowerEigenvalue = -1.0; while (true) { // Iterate over Power Multiplications by Chisq Matrix // Normalize Current A and move from New to Old double OldNorm = 1.0 / Math.Sqrt(AdotA); SALSABLAS.LinearCombineVector(DistributedOldIteratedVector, OldNorm, DistributedNewIteratedVector, 0.0, DistributedNewIteratedVector); // Make a Global Vector of DistributedOldIteratedVector ManxcatCentral.MakeVectorGlobal(DistributedOldIteratedVector, GlobalOldIteratedVector); // Form Chisq Matrix Product with Old Vector if (Hotsun.FullSecondDerivative) { UserRoutines.GlobalMatrixVectorProduct(DistributedNewIteratedVector, Solution, true, Hotsun.GlobalParameter, GlobalOldIteratedVector); } else { UserRoutines.GlobalMatrixVectorProduct(DistributedNewIteratedVector, Solution, false, Hotsun.GlobalParameter, GlobalOldIteratedVector); } // Correct case MaxIndicator = 1 if (MaxIndicator > 0) { SALSABLAS.LinearCombineVector(DistributedNewIteratedVector, -1.0, DistributedNewIteratedVector, Maximizer, DistributedOldIteratedVector); } SALSABLAS.LinearCombineVector(DistributedNewIteratedVector, 1.0, DistributedNewIteratedVector, Hotsun.addonforQcomputation, DistributedOldIteratedVector); // Form Scalar Products double NewEigenvalue = SALSABLAS.VectorScalarProduct(DistributedNewIteratedVector, DistributedOldIteratedVector); AdotA = SALSABLAS.VectorScalarProduct(DistributedNewIteratedVector, DistributedNewIteratedVector); ++PowerIterationCount; somethingtodo = -1; if (SALSAUtility.MPI_Rank == 0) { if (PowerIterationCount > 10 && (NewEigenvalue > 0.0)) { // Arbitary criteria for starting +tests somethingtodo = 0; double scaleit = 1.0; if (MaxIndicator > 0) { scaleit = Hotsun.extraprecision; } if (Math.Abs(NewEigenvalue - PowerEigenvalue) > PowerEigenvalue * scaleit * Hotsun.eigenvaluechange) { ++somethingtodo; } double delta = AdotA - NewEigenvalue * NewEigenvalue; // (Ax- Eigenvalue*Axold)**2 if (Math.Abs(delta) > NewEigenvalue * NewEigenvalue * scaleit * Hotsun.eigenvectorchange) { ++somethingtodo; } } } PowerEigenvalue = NewEigenvalue; if (SALSAUtility.MPI_Size > 1) { SALSAUtility.StartSubTimer(SALSAUtility.MPIBROADCASTTiming); SALSAUtility.MPI_communicator.Broadcast(ref somethingtodo, 0); SALSAUtility.StopSubTimer(SALSAUtility.MPIBROADCASTTiming); } if (PowerIterationCount >= Hotsun.PowerIterationLimit) { somethingtodo = -2; break; } if (somethingtodo == 0) { somethingtodo = PowerIterationCount; break; } } // End while over PowerIterationCounts return(somethingtodo); }
// End PowerIterate() // Solve for Distributed Answer = (Matrix-1) First // Note RealMatrixSize takes account of forced zero parameters which does not crop up in explicit // algorithm as implemented in Matrix Vector Multiplier public static bool ConjugateGradientSolver(double[][] Answer, Desertwind Solution, bool useexact, double[][] GlobalxVector, double[][] DistributedRHS, ref int NumberofIterations, int RealMatrixSize, double LimitonNormofR) { bool matrixsuccess = true; // Initialize SALSABLAS.zrword(Answer); // Zero Solution x called xshift in Manxcat and stored in Answer SALSABLAS.CopyVector(DistributedCGVector_R, DistributedRHS, 0, SALSAUtility.PointCount_Process); // Set R(0) = RHS double InitialRNorm = SALSABLAS.VectorScalarProduct(DistributedCGVector_R, DistributedCGVector_R); double RNormTest = InitialRNorm * LimitonNormofR; // Limit for Test on Iteration of Norm of R var SaveRNorm = new double[RealMatrixSize + 1]; SaveRNorm[0] = InitialRNorm; int CountSteps = 0; double lastrho = 1.0; double currentrho = 1.0; // Loop over Conjugate Gradient Steps while (true) { // Set value of rho lastrho = currentrho; currentrho = SALSABLAS.VectorScalarProduct(DistributedCGVector_R, DistributedCGVector_R); // Set Vector P ++CountSteps; if (CountSteps == 1) { SALSABLAS.CopyVector(DistributedCGVector_P, DistributedCGVector_R, 0, SALSAUtility.PointCount_Process); } else { SALSABLAS.LinearCombineVector(DistributedCGVector_P, currentrho / lastrho, DistributedCGVector_P, 1.0, DistributedCGVector_R); } // Make a Global Vector of DistributedCGVector_P ManxcatCentral.MakeVectorGlobal(DistributedCGVector_P, GlobalCGVector_P); // Distributed Q = Matrix . Global P UserRoutines.GlobalMatrixVectorProduct(DistributedCGVector_Q, Solution, useexact, Hotsun.GlobalParameter, GlobalCGVector_P); // New Answer is Old answer + (Current Rho / (P dot Q)) Vector P double PdotQ = SALSABLAS.VectorScalarProduct(DistributedCGVector_P, DistributedCGVector_Q); double alpha = currentrho / PdotQ; SALSABLAS.LinearCombineVector(Answer, alpha, DistributedCGVector_P, 1.0, Answer); // New residual R = Old Residual - (Current Rho / (P dot Q)) Vector Q SALSABLAS.LinearCombineVector(DistributedCGVector_R, -alpha, DistributedCGVector_Q, 1.0, DistributedCGVector_R); // See if we can or should End double CurrentRNorm = SALSABLAS.VectorScalarProduct(DistributedCGVector_R, DistributedCGVector_R); SaveRNorm[CountSteps] = CurrentRNorm; bool TestRNorm = CurrentRNorm <= RNormTest; SALSAUtility.SynchronizeMPIvariable(ref TestRNorm); if (TestRNorm) { matrixsuccess = true; break; } // Singular Matrix if (CountSteps >= RealMatrixSize) { matrixsuccess = false; ManxcatCentral.MakeVectorGlobal(DistributedCGVector_R, GlobalCGVector_R); if (SALSAUtility.MPI_Rank == 0) { SALSAUtility.SALSAPrint(0, " CG Failure after " + RealMatrixSize.ToString() + " Steps"); string ListofNorms = ""; int Normindex = CountSteps; for (int inorm = 0; inorm < 10; inorm++) { ListofNorms += " " + SaveRNorm[Normindex].ToString("E4"); --Normindex; if (Normindex < 0) { break; } } SALSAUtility.SALSAPrint(0, "Last 10 Norms " + ListofNorms); string fname = ManxcatCentral.ResultDirectoryName + "\\BadCGVector" + Hotsun.TotalCGFailures.ToString(); var sw = new StreamWriter(fname, false, Encoding.UTF8); double fractionnorm = 1.0 / Math.Sqrt(CurrentRNorm); try { for (int GlobalPointIndex = 0; GlobalPointIndex < SALSAUtility.PointCount_Global; GlobalPointIndex++) { string Coordinates = ""; int UsedPointIndex = SALSAUtility.NaivetoActualUsedOrder[GlobalPointIndex]; double pointsize = 0.0; for (int LocalVectorIndex = 0; LocalVectorIndex < Hotsun.ParameterVectorDimension; LocalVectorIndex++) { Coordinates += GlobalCGVector_R[UsedPointIndex][LocalVectorIndex].ToString("E4") + "\t"; pointsize += GlobalCGVector_R[UsedPointIndex][LocalVectorIndex] * GlobalCGVector_R[UsedPointIndex][LocalVectorIndex]; } pointsize = Math.Sqrt(pointsize) * fractionnorm; sw.WriteLine( String.Format((GlobalPointIndex).ToString() + "\t" + Coordinates + " " + pointsize.ToString("E4"))); } sw.Flush(); sw.Close(); } catch (Exception e) { Console.WriteLine("Failed writing data in CG Solver " + e); throw (e); } } break; } } // End Loop over Conjugate Gradient Steps NumberofIterations = CountSteps; return(matrixsuccess); }