// 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 VectorSum(double[] VTotal, double[] V2, double sign, double[] V1) public static void InitializeParameters(Desertwind Solution, int CountStartingPoints) { // Inversion InvertSolution = false; if ((CountStartingPoints / 2) * 2 != CountStartingPoints) { InvertSolution = true; } for (int LocalVectorIndex1 = 0; LocalVectorIndex1 < PointVectorDimension; LocalVectorIndex1++) { for (int LocalVectorIndex2 = 0; LocalVectorIndex2 < PointVectorDimension; LocalVectorIndex2++) { CurrentCosmicScaling[LocalVectorIndex1, LocalVectorIndex2] = 0.0; } CurrentCosmicScaling[LocalVectorIndex1, LocalVectorIndex1] = 1.0; } if (InvertSolution) { for (int LocalVectorIndex1 = 0; LocalVectorIndex1 < PointVectorDimension; LocalVectorIndex1++) { CurrentCosmicScaling[LocalVectorIndex1, LocalVectorIndex1] = -1.0; } if (PointVectorDimension == 2) { CurrentCosmicScaling[0, 0] = 1.0; } } for (int LocalVectorIndex1 = 0; LocalVectorIndex1 < PointVectorDimension; LocalVectorIndex1++) { for (int LocalVectorIndex2 = 0; LocalVectorIndex2 < PointVectorDimension; LocalVectorIndex2++) { SavedCosmicScaling[CountStartingPoints][LocalVectorIndex1, LocalVectorIndex2] = CurrentCosmicScaling[LocalVectorIndex1, LocalVectorIndex2]; } } // Scaling double Scale = FirstScale / SecondScale; if (ScaleOption == 0) { Solution.param[ScalePosition][0] = Scale; } else { ScaleA1 = 0.5 * (ScaleAlpha + 1.0 / ScaleAlpha); ScaleA2 = 0.5 * Math.Abs(ScaleAlpha - 1.0 / ScaleAlpha); Solution.param[ScalePosition][0] = Math.Asin((ScaleA1 - 1.0) / ScaleA2); ScaleA1 *= Scale; ScaleA2 *= Scale; } var Randobject = new Random(); var RandomAngles = new double[3]; if (SALSAUtility.MPI_Rank == 0) { for (int irand = 0; irand < 3; irand++) { RandomAngles[irand] = Randobject.NextDouble(); } } if (SALSAUtility.MPI_Size > 1) { SALSAUtility.StartSubTimer(SALSAUtility.MPIBROADCASTTiming); SALSAUtility.MPI_communicator.Broadcast(ref RandomAngles, 0); SALSAUtility.StopSubTimer(SALSAUtility.MPIBROADCASTTiming); } // Translation and Rotation for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { Solution.param[LocalVectorIndex][0] = FirstMean[LocalVectorIndex] - Scale * CurrentCosmicScaling[LocalVectorIndex, LocalVectorIndex] * SecondMean[LocalVectorIndex]; if (PointVectorDimension == 3) { Solution.param[LocalVectorIndex + PointVectorDimension][0] = 0.0; if (CountStartingPoints > 1) { Solution.param[LocalVectorIndex + PointVectorDimension][0] = Math.PI * RandomAngles[LocalVectorIndex]; } } } if (PointVectorDimension == 2) { Solution.param[2][0] = 0.0; if (CountStartingPoints > 1) { Solution.param[2][0] = Math.PI * RandomAngles[0]; } } }
// 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); }
// End SetupRotateMDS() public static bool Calcfg(Desertwind Solution) { // call Accum with value and derivative for each point bool violat = false; double Scale = 1.0; double DerivScale = 1.0; if (ScaleOption == 0) { if ((Solution.param[ScalePosition][0] < 0.0) && (RotationOption_invert == 0)) { violat = true; Solution.param[ScalePosition][0] = -Solution.param[ScalePosition][0]; } Solution.param[ScalePosition][0] = Math.Max(ScaleAlpha * FirstScale / SecondScale, Solution.param[ScalePosition][0]); Scale = Solution.param[ScalePosition][0]; } else { Solution.param[ScalePosition][0] = ProperAngle(Solution.param[ScalePosition][0]); Scale = CalculateScale(Solution.param[ScalePosition][0]); DerivScale = DifferentiateScale(Solution.param[ScalePosition][0]); // SALSAUtility.SALSAPrint(0, "Scale DerivScale " + Scale.ToString("E4") + " " + DerivScale.ToString("E4")); } // Force Angles between -PI and PI if (PointVectorDimension == 3) { for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { Solution.param[LocalVectorIndex + PointVectorDimension][0] = ProperAngle(Solution.param[LocalVectorIndex + PointVectorDimension][0]); } } if (PointVectorDimension == 2) { Solution.param[2][0] = ProperAngle(Solution.param[2][0]); } // End Force Angles between -PI and PI // Each Value is weight * (Scaling * Cosmic * Rotation * Second Vector + Translation - First Vector) // Each Derivative is weight * ( Scaling * Cosmic * Rotation Term * Second Vectot + Treanslation Term ) // Rotation, Rotation Term, Translation, Translation Term are independent of Point // weight depends on Option Used var Translation = new double[PointVectorDimension]; var Rotation = new double[PointVectorDimension, PointVectorDimension]; var DerivTranslation = new double[Hotsun.npar][]; var DerivRotationScale = new double[Hotsun.npar][, ]; var SubRotation = new double[NumberSubRotations][, ]; var SubDeriveRotation = new double[NumberSubRotations][, ]; for (int ipar = 0; ipar < Hotsun.npar; ipar++) { DerivTranslation[ipar] = new double[PointVectorDimension]; DerivRotationScale[ipar] = new double[PointVectorDimension, PointVectorDimension]; for (int LocalVectorIndex1 = 0; LocalVectorIndex1 < PointVectorDimension; LocalVectorIndex1++) { DerivTranslation[ipar][LocalVectorIndex1] = 0.0; for (int LocalVectorIndex2 = 0; LocalVectorIndex2 < PointVectorDimension; LocalVectorIndex2++) { if (ipar < PointVectorDimension) { DerivRotationScale[ipar][LocalVectorIndex1, LocalVectorIndex2] = 0.0; } // Rotation Matrix Zero for Translations } } } for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { Translation[LocalVectorIndex] = Solution.param[LocalVectorIndex][0]; // Translations DerivTranslation[LocalVectorIndex][LocalVectorIndex] = 1.0; // Deriv of Translation } for (int SubRotationIndex = 0; SubRotationIndex < NumberSubRotations; SubRotationIndex++) { SubRotation[SubRotationIndex] = new double[PointVectorDimension, PointVectorDimension]; SubDeriveRotation[SubRotationIndex] = new double[PointVectorDimension, PointVectorDimension]; for (int LocalVectorIndex1 = 0; LocalVectorIndex1 < PointVectorDimension; LocalVectorIndex1++) { for (int LocalVectorIndex2 = 0; LocalVectorIndex2 < PointVectorDimension; LocalVectorIndex2++) { SubDeriveRotation[SubRotationIndex][LocalVectorIndex1, LocalVectorIndex2] = 0.0; SubRotation[SubRotationIndex][LocalVectorIndex1, LocalVectorIndex2] = 0.0; } } SetRotationMatrix(SubRotation[SubRotationIndex], SubRotationIndex, Solution.param[PointVectorDimension + SubRotationIndex][0], false); SetRotationMatrix(SubDeriveRotation[SubRotationIndex], SubRotationIndex, Solution.param[PointVectorDimension + SubRotationIndex][0], true); } if (PointVectorDimension == 3) { SetTotalRotation(Rotation, Scale, CurrentCosmicScaling, SubRotation[2], SubRotation[1], SubRotation[0]); SetTotalRotation(DerivRotationScale[PointVectorDimension], Scale, CurrentCosmicScaling, SubRotation[2], SubRotation[1], SubDeriveRotation[0]); // Rotation for First Angle SetTotalRotation(DerivRotationScale[PointVectorDimension + 1], Scale, CurrentCosmicScaling, SubRotation[2], SubDeriveRotation[1], SubRotation[0]); // Rotation for Second Angle SetTotalRotation(DerivRotationScale[PointVectorDimension + 2], Scale, CurrentCosmicScaling, SubDeriveRotation[2], SubRotation[1], SubRotation[0]); // Rotation for Third Angle SetTotalRotation(DerivRotationScale[ScalePosition], DerivScale, CurrentCosmicScaling, SubRotation[2], SubRotation[1], SubRotation[0]); // Rotation for Scale } if (PointVectorDimension == 2) { SetTotalRotation(Rotation, Scale, CurrentCosmicScaling, SubRotation[0]); SetTotalRotation(DerivRotationScale[PointVectorDimension], Scale, CurrentCosmicScaling, SubDeriveRotation[0]); // Rotation for First Angle SetTotalRotation(DerivRotationScale[ScalePosition], DerivScale, CurrentCosmicScaling, SubRotation[0]); // Rotation for Scale } // Set up Accum GenericManxcat.ReInitializeAccum(); // Finally Loop over entries in Chisq Parallel.For(0, SALSAUtility.ParallelOptions.MaxDegreeOfParallelism, SALSAUtility.ParallelOptions, (ThreadNo) => { var DerivativeFl = new double[PointVectorDimension][]; for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { DerivativeFl[LocalVectorIndex] = new double[Hotsun.npar]; } int indexlen = SALSAUtility.PointsperThread[ThreadNo]; int beginpoint = SALSAUtility.StartPointperThread[ThreadNo] - SALSAUtility.PointStart_Process; for (int DistributedPointIndex = beginpoint; DistributedPointIndex < indexlen + beginpoint; DistributedPointIndex++) { int GlobalIndex = SALSAUtility.PointStart_Process + DistributedPointIndex; // Setting weight to Math.Sqrt(1.0/SALSAUtility.PointCount_Global)* Fudge Factor/FirstScale double weight = Math.Sqrt(1.0 / SALSAUtility.PointCount_Global) * ManxcatCentral.ChisqFunctionCalcMultiplier / FirstScale; // RotationOption =0 is simple least squares sum; RotationOption = 1 implies use fractional errors if (RotationOption == 1) { double size = 0.0; for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { size += FirstData[GlobalIndex][LocalVectorIndex] * FirstData[GlobalIndex][LocalVectorIndex]; } size = Math.Sqrt(size); size = Math.Max(MinimumDistance, size); weight *= FirstScale / size; } var ValueFl = new double[PointVectorDimension]; MatrixVectorProduct(ValueFl, Rotation, SecondData[GlobalIndex]); VectorSum(ValueFl, Translation, +1.0, ValueFl); VectorSum(ValueFl, ValueFl, -1.0, FirstData[GlobalIndex]); for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { ValueFl[LocalVectorIndex] *= weight; } for (int ipar = 0; ipar < Hotsun.npar; ipar++) { if (ipar < PointVectorDimension) { // Translation Derivatives for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { DerivativeFl[LocalVectorIndex][ipar] = weight * DerivTranslation[ipar][ LocalVectorIndex]; } } else { var tempvector = new double[PointVectorDimension]; MatrixVectorProduct(tempvector, DerivRotationScale[ipar], SecondData[GlobalIndex]); for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { DerivativeFl[LocalVectorIndex][ipar] = weight * tempvector[LocalVectorIndex]; } } } for (int LocalVectorIndex = 0; LocalVectorIndex < PointVectorDimension; LocalVectorIndex++) { GenericManxcat.Accum(ThreadNo, ValueFl[LocalVectorIndex], DerivativeFl[LocalVectorIndex]); if (GlobalIndex <= 0) { string deriv = ""; for (int ipar = 0; ipar < Hotsun.npar; ipar++) { deriv += DerivativeFl[LocalVectorIndex][ipar].ToString("E4") + " "; } // SALSAUtility.SALSAPrint(0, "Val " + ValueFl[LocalVectorIndex].ToString("f4") + " Drv " + deriv); GenericManxcat.AccumDebug(GlobalIndex); } if (GlobalIndex > (SALSAUtility.PointCount_Global - 2)) { GenericManxcat.AccumDebug(GlobalIndex); } } } // End loop over points in this thread }); // End loop initialing Point dependent quantities // Add up MPI and Thread Contributions GenericManxcat.AddupChisqContributions(Solution); return(violat); }