public static bool ComplexSolveBiCGSTABWithPivoting( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B, int fillinLevel, double convRatioTolerance) { int t; t = System.Environment.TickCount; ComplexSparseMatrix LU; int[] pivot; ComplexCalcILUWithPivoting(out LU, out pivot, A, fillinLevel); ComplexSparseMatrix pivotingA = new ComplexSparseMatrix(A.RowLength, A.ColumnLength); for (int i = 0; i < pivotingA.RowLength; i++) { pivotingA.RowColIndexValues[i] = A.RowColIndexValues[pivot[i]]; } System.Numerics.Complex[] pivotingB = new System.Numerics.Complex[B.Length]; for (int i = 0; i < B.Length; i++) { pivotingB[i] = B[pivot[i]]; } A = null; B = null; System.Diagnostics.Debug.WriteLine("ComplexSolveBiCGStab 1: t= " + (System.Environment.TickCount - t)); t = System.Environment.TickCount; bool success = IvyFEM.Linear.Functions.ComplexSolvePreconditionedBiCGSTAB(out X, pivotingA, pivotingB, LU, convRatioTolerance); System.Diagnostics.Debug.WriteLine("ComplexSolveBiCGSTAB 2: t= " + (System.Environment.TickCount - t)); return(success); }
private bool ComplexSolveBiCGSTABWithPivoting( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { int t; X = null; //t = System.Environment.TickCount; //bool success = IvyFEM.Linear.Functions.ComplexSolveBiCGSTABWithPivoting(out X, A, B, ILUFillinLevel, // ConvRatioTolerance); //System.Diagnostics.Debug.Assert(success); //System.Diagnostics.Debug.WriteLine(" ComplexSolveCGWithPivoting t = " + (System.Environment.TickCount - t)); // Nativeを使う bool success = false; { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; int[] APtrs; int[] AIndexs; System.Numerics.Complex[] AValues; t = System.Environment.TickCount; A.GetCSR(out APtrs, out AIndexs, out AValues); System.Diagnostics.Debug.WriteLine(" GetCSR t = " + (System.Environment.TickCount - t)); t = System.Environment.TickCount; success = IvyFEM.Native.Functions.ComplexSolveBiCGSTABWithPivoting( out X, n, APtrs, AIndexs, AValues, B, ILUFillinLevel, ConvRatioTolerance); System.Diagnostics.Debug.Assert(success); System.Diagnostics.Debug.WriteLine(" ComplexSolveCGWithPivoting t = " + (System.Environment.TickCount - t)); } return(success); }
public bool ComplexSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { bool success = false; using (IvyFEM.Lis.LisInitializer LisInitializer = new IvyFEM.Lis.LisInitializer()) using (IvyFEM.Lis.LisMatrix lisA = (IvyFEM.Lis.LisMatrix)A) using (IvyFEM.Lis.LisVector lisB = (IvyFEM.Lis.LisVector)B) using (IvyFEM.Lis.LisVector lisX = new IvyFEM.Lis.LisVector()) using (IvyFEM.Lis.LisSolver lisSolver = new IvyFEM.Lis.LisSolver()) { int ret; int n = B.Length; lisX.SetSize(0, n); A = null; ret = lisSolver.SetOption(GetOption()); System.Diagnostics.Debug.Assert(ret == 0); ret = lisSolver.SetOptionC(); System.Diagnostics.Debug.Assert(ret == 0); ret = lisSolver.Solve(lisA, lisB, lisX); System.Diagnostics.Debug.Assert(ret == 0); success = (ret == 0); int iter; ret = lisSolver.GetIter(out iter); System.Diagnostics.Debug.Assert(ret == 0); System.Diagnostics.Debug.WriteLine("Lis Solve iter = " + iter); X = new System.Numerics.Complex[n]; ret = lisX.GetValues(0, n, X); System.Diagnostics.Debug.Assert(ret == 0); } return(success); }
public bool ComplexSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { bool success = false; X = null; switch (Method) { case LapackEquationSolverMethod.Dense: success = ComplexDenseSolve(out X, A, B); break; case LapackEquationSolverMethod.Default: case LapackEquationSolverMethod.Band: success = ComplexBandSolve(out X, A, B); break; case LapackEquationSolverMethod.PositiveDefiniteBand: success = ComplexPositiveDefiniteBandSolve(out X, A, B); break; default: throw new NotImplementedException(); //break; } return(success); }
private bool ComplexPositiveDefiniteBandSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { X = null; bool isHermitian = A.IsHermitian(); System.Diagnostics.Debug.Assert(isHermitian); if (!isHermitian) { return(false); } bool success = false; IvyFEM.Lapack.ComplexHermitianBandMatrix pbA = (IvyFEM.Lapack.ComplexHermitianBandMatrix)A; A = null; int xRow; int xCol; int ret = IvyFEM.Lapack.Functions.zpbsv(out X, out xRow, out xCol, pbA.Buffer, pbA.RowLength, pbA.ColumnLength, pbA.SuperdiaLength, B, B.Length, 1); System.Diagnostics.Debug.Assert(ret == 0); success = (ret == 0); return(success); }
///////////////////////////////////////////////////////////////////////////////// // complex // LU : Lii = 1 Lij (i=1...n -1 j=0...i-1) Uij (i=0...n-1 j=i...n-1) // Note: M = L * U public static ComplexSparseMatrix ComplexCalcILU(ComplexSparseMatrix A, int fillinLevel) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; ComplexSparseMatrix LU = new ComplexSparseMatrix(A); int[,] level = new int[n, n]; for (int row = 0; row < n; row++) { for (int col = 0; col < n; col++) { level[row, col] = (A[row, col].Magnitude >= IvyFEM.Constants.PrecisionLowerLimit) ? 0 : (fillinLevel + 1); } } for (int i = 1; i < n; i++) { for (int k = 0; k <= (i - 1); k++) { //if (!LU.RowColIndexValues[i].ContainsKey(k)) //{ // continue; //} if (level[i, k] > fillinLevel) { continue; } LU[i, k] /= LU[k, k]; System.Numerics.Complex LUik = LU[i, k]; foreach (var pair in LU.RowColIndexValues[k]) { int j = pair.Key; System.Numerics.Complex LUkj = pair.Value; if (j >= k + 1 && j < n) { // } else { continue; } level[i, j] = Math.Min(level[i, j], level[i, k] + level[k, j] + 1); if (level[i, j] <= fillinLevel) { LU[i, j] -= LUik * LUkj; } } } } return(LU); }
public void Copy(ComplexSparseMatrix src) { Resize(src.RowLength, src.ColumnLength); for (int row = 0; row < src.RowLength; row++) { var srcColIndexValues = src.RowColIndexValues[row]; foreach (var pair in srcColIndexValues) { int col = pair.Key; System.Numerics.Complex value = pair.Value; RowColIndexValues[row].Add(col, value); } } }
public bool ComplexSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { bool success = false; X = null; switch (Method) { case IvyFEMEquationSolverMethod.CG: // エルミート行列の場合はCG // 必要なケースがでてくれば実装する throw new NotImplementedException(); //break; case IvyFEMEquationSolverMethod.Default: case IvyFEMEquationSolverMethod.NoPreconCOCG: success = ComplexSolveNoPreconCOCG(out X, A, B); break; case IvyFEMEquationSolverMethod.COCG: // 複素対称行列の場合はCOCG success = ComplexSolveCOCG(out X, A, B); break; case IvyFEMEquationSolverMethod.ICCOCG: success = ComplexSolveICCOCG(out X, A, B); break; case IvyFEMEquationSolverMethod.NoPreconBiCGSTAB: success = ComplexSolveNoPreconBiCGSTAB(out X, A, B); break; case IvyFEMEquationSolverMethod.BiCGSTAB: success = ComplexSolveBiCGSTAB(out X, A, B); break; case IvyFEMEquationSolverMethod.BiCGSTABWithPivoting: success = ComplexSolveBiCGSTABWithPivoting(out X, A, B); break; default: throw new NotImplementedException(); //break; } return(success); }
private static bool[,] GetComplexMatrixNonzeroPattern(ComplexSparseMatrix A) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; bool[,] nonzeroPattern = new bool[n, n]; for (int row = 0; row < n; row++) { foreach (var pair in A.RowColIndexValues[row]) { int col = pair.Key; nonzeroPattern[row, col] = true; } } return(nonzeroPattern); }
public static bool ComplexSolveICCOCG( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B, double convRatioTolerance) { int t; t = System.Environment.TickCount; ComplexSparseMatrix LU = IvyFEM.Linear.Functions.ComplexCalcIC(A); System.Diagnostics.Debug.WriteLine("ComplexSolveICCOCG 1: t= " + (System.Environment.TickCount - t)); t = System.Environment.TickCount; bool success = IvyFEM.Linear.Functions.ComplexSolvePreconditionedCOCG(out X, A, B, LU, convRatioTolerance); System.Diagnostics.Debug.WriteLine("ComplexSolveICCG 2: t= " + (System.Environment.TickCount - t)); return(success); }
private bool ComplexDenseSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { bool success = false; IvyFEM.Lapack.ComplexMatrix denseA = (IvyFEM.Lapack.ComplexMatrix)A; int xRow; int xCol; int ret = IvyFEM.Lapack.Functions.zgesv(out X, out xRow, out xCol, denseA.Buffer, denseA.RowLength, denseA.ColumnLength, B, B.Length, 1); System.Diagnostics.Debug.Assert(ret == 0); success = (ret == 0); return(success); }
public static bool ComplexSolveBiCGSTAB( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B, int fillinLevel, double convRatioTolerance) { int t; t = System.Environment.TickCount; ComplexSparseMatrix LU = IvyFEM.Linear.Functions.ComplexCalcILU(A, fillinLevel); System.Diagnostics.Debug.WriteLine("ComplexSolveBiCGSTAB 1: t= " + (System.Environment.TickCount - t)); t = System.Environment.TickCount; bool success = IvyFEM.Linear.Functions.ComplexSolvePreconditionedBiCGSTAB(out X, A, B, LU, convRatioTolerance); System.Diagnostics.Debug.WriteLine("ComplexSolveBiCGSTAB 2: t= " + (System.Environment.TickCount - t)); return(success); }
private bool __ComplexBandSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { bool success = false; IvyFEM.Lapack.ComplexBandMatrix bandA = (IvyFEM.Lapack.ComplexBandMatrix)A; A = null; int xRow; int xCol; int ret = IvyFEM.Lapack.Functions.zgbsv(out X, out xRow, out xCol, bandA.Buffer, bandA.RowLength, bandA.ColumnLength, bandA.SubdiaLength, bandA.SuperdiaLength, B, B.Length, 1); System.Diagnostics.Debug.Assert(ret == 0); success = (ret == 0); return(success); }
////////////////////////////////////////////////////////////////////////////////////// // complex private bool ComplexSolveNoPreconCOCG( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { int t; X = null; //t = System.Environment.TickCount; //bool isSymmetric = A.IsSymmetric(); //System.Diagnostics.Debug.Assert(isSymmetric); //System.Diagnostics.Debug.WriteLine(" IsSymmetric t = " + (System.Environment.TickCount - t)); //if (!isSymmetric) //{ // return false; //} //t = System.Environment.TickCount; //bool success = IvyFEM.Linear.Functions.ComplexSolveNoPreconCOCG(out X, A, B, // ConvRatioTolerance); //System.Diagnostics.Debug.Assert(success); //System.Diagnostics.Debug.WriteLine(" ComplexSolveNoPreconCOCG t = " + (System.Environment.TickCount - t)); // Nativeを使う bool success = false; { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; int[] APtrs; int[] AIndexs; System.Numerics.Complex[] AValues; t = System.Environment.TickCount; A.GetCSR(out APtrs, out AIndexs, out AValues); System.Diagnostics.Debug.WriteLine(" GetCSR t = " + (System.Environment.TickCount - t)); t = System.Environment.TickCount; success = IvyFEM.Native.Functions.ComplexSolveNoPreconCOCG( out X, n, APtrs, AIndexs, AValues, B, ConvRatioTolerance); System.Diagnostics.Debug.Assert(success); System.Diagnostics.Debug.WriteLine(" ComplexSolveNoPreconCOCG t = " + (System.Environment.TickCount - t)); } return(success); }
private bool ComplexBandSolve( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B) { X = null; ComplexSparseMatrix AToSolve; System.Numerics.Complex[] BToSolve; int[] indexs; if (IsOrderingToBandMatrix) { bool successOrder = IvyFEM.Linear.Utils.OrderToComplexBandMatrix( out AToSolve, out BToSolve, out indexs, A, B); System.Diagnostics.Debug.Assert(successOrder); if (!successOrder) { return(false); } } else { AToSolve = A; BToSolve = B; indexs = null; } System.Numerics.Complex[] XToSolve; bool success = __ComplexBandSolve(out XToSolve, AToSolve, BToSolve); if (IsOrderingToBandMatrix) { X = new System.Numerics.Complex[XToSolve.Length]; for (int row = 0; row < XToSolve.Length; row++) { X[indexs[row]] = XToSolve[row]; } } else { X = XToSolve; } return(success); }
public static void ComplexSolveLU( out System.Numerics.Complex[] X, ComplexSparseMatrix LU, System.Numerics.Complex[] B) { System.Diagnostics.Debug.Assert(LU.RowLength == LU.ColumnLength); int n = LU.RowLength; X = new System.Numerics.Complex[n]; B.CopyTo(X, 0); // Ly = b for (int row = 1; row < n; row++) { foreach (var pair in LU.RowColIndexValues[row]) { int col = pair.Key; System.Numerics.Complex value = pair.Value; if (col >= 0 && col < row) { X[row] -= value * X[col]; // LU[row, col] } } } // Ux = y for (int row = n - 2; row >= 0; row--) { foreach (var pair in LU.RowColIndexValues[row]) { int col = pair.Key; System.Numerics.Complex value = pair.Value; if (col >= row + 1 && col < n) { X[row] -= value * X[col]; // LU[row, col] } } X[row] /= LU[row, row]; } }
/* * public void Transpose() * { * throw new NotImplementedException(); * } */ public static ComplexSparseMatrix operator *(ComplexSparseMatrix A, ComplexSparseMatrix B) { int aRow = A.RowLength; int aCol = A.ColumnLength; int bRow = B.RowLength; int bCol = B.ColumnLength; if (aCol != bRow) { throw new ArgumentException("Mismatched size: aCol != bRow(" + aCol + " != " + bRow + ")"); } int cRow = aRow; int cCol = bCol; ComplexSparseMatrix C = new ComplexSparseMatrix(cRow, cCol); for (int i = 0; i < aRow; i++) { var colIndexValues1 = A.RowColIndexValues[i]; for (int j = 0; j < bCol; j++) { foreach (var pair1 in colIndexValues1) { int k = pair1.Key; System.Numerics.Complex value1 = pair1.Value; // Aik if (B.RowColIndexValues[k].ContainsKey(j)) { System.Numerics.Complex value2 = B.RowColIndexValues[k][j]; // Bkj C[i, j] += value1 * value2; } } } } return(C); }
// Incomplete Cholesky Factorization public static ComplexSparseMatrix ComplexCalcIC(ComplexSparseMatrix A) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; ComplexSparseMatrix LU = new ComplexSparseMatrix(n, n); System.Numerics.Complex[] D = new System.Numerics.Complex[n]; D[0] = A[0, 0]; LU[0, 0] = 1.0; // L for (int i = 1; i < n; i++) { for (int j = 0; j <= (i - 1); j++) { if (!A.RowColIndexValues[i].ContainsKey(j)) { continue; } System.Numerics.Complex tmp = A[i, j]; foreach (var pair in LU.RowColIndexValues[i]) { int k = pair.Key; System.Numerics.Complex LUik = pair.Value; if (k >= 0 && k <= (j - 1)) { // } else { continue; } tmp -= LUik * LU[j, k] * D[k]; // LU[i, k] } LU[i, j] = (1.0 / D[j]) * tmp; } // i == jのとき { System.Numerics.Complex tmp = A[i, i]; foreach (var pair in LU.RowColIndexValues[i]) { int k = pair.Key; System.Numerics.Complex LUik = pair.Value; if (k >= 0 && k <= (i - 1)) { // } else { continue; } tmp -= LUik * LUik * D[k]; // LU[i, k] } D[i] = tmp; LU[i, i] = 1.0; } } // DL^T for (int i = 0; i < n; i++) { foreach (var pair in LU.RowColIndexValues[i]) { int j = pair.Key; System.Numerics.Complex LUij = pair.Value; if (j >= 0 && j <= (i - 1)) { // } else { continue; } LU[j, i] = D[j] * LUij; // LU[i, j] } LU[i, i] = D[i]; } return(LU); }
public static bool OrderToComplexBandMatrix( out ComplexSparseMatrix orderedA, out System.Numerics.Complex[] orderedB, out int[] indexs, ComplexSparseMatrix A, System.Numerics.Complex[] B) { orderedA = null; orderedB = null; indexs = null; // バンド幅を縮小する // 非0要素のパターンを取得 bool[,] matPattern = GetComplexMatrixNonzeroPattern(A); int n = matPattern.GetLength(0); // subdiagonal、superdiagonalのサイズを取得する int iniSubdiaLength = 0; int iniSuperdiaLength = 0; { System.Diagnostics.Debug.WriteLine("/////initial Band Matrix info///////"); int rowcolLength; int subdiaLength; int superdiaLength; GetBandMatrixSubDiaSuperDia(matPattern, out rowcolLength, out subdiaLength, out superdiaLength); iniSubdiaLength = subdiaLength; iniSuperdiaLength = superdiaLength; } // 非0要素出現順に節点番号を格納 IList <int> newIndexs = new List <int>(); Queue <int> check = new Queue <int>(); int[] remain = new int[matPattern.GetLength(0)]; for (int i = 0; i < matPattern.GetLength(0); i++) { remain[i] = i; } while (newIndexs.Count < n) { for (int iRemain = 0; iRemain < remain.Length; iRemain++) { int i = remain[iRemain]; if (i == -1) { continue; } check.Enqueue(i); remain[iRemain] = -1; break; } while (check.Count > 0) { int i = check.Dequeue(); newIndexs.Add(i); for (int iRemain = 0; iRemain < remain.Length; iRemain++) { int j = remain[iRemain]; if (j == -1) { continue; } if (matPattern[i, j]) { check.Enqueue(j); remain[iRemain] = -1; } } } } System.Diagnostics.Debug.Assert(newIndexs.Count == n); ComplexSparseMatrix newA = new ComplexSparseMatrix(n, n); // 遅い //for (int row = 0; row < n; row++) //{ // for (int col = 0; col < n; col++) // { // newA[row, col] = A[newIndexs[row], newIndexs[col]]; // } //} int[] oldIndexs = new int[n]; for (int i = 0; i < n; i++) { oldIndexs[newIndexs[i]] = i; } for (int row = 0; row < n; row++) { foreach (var pair in A.RowColIndexValues[row]) { int col = pair.Key; System.Numerics.Complex value = pair.Value; newA[oldIndexs[row], oldIndexs[col]] = value; } } // 改善できないこともあるのでチェックする bool improved = false; // 非0パターンを取得 bool[,] newMatPattern = GetComplexMatrixNonzeroPattern(newA); // check { System.Diagnostics.Debug.WriteLine("///// orderd Band Matrix info ///////"); int rowcolLength; int subdiaLength; int superdiaLength; GetBandMatrixSubDiaSuperDia(newMatPattern, out rowcolLength, out subdiaLength, out superdiaLength); if (subdiaLength <= iniSubdiaLength && superdiaLength <= iniSuperdiaLength) { improved = true; } } if (improved) { // 置き換え orderedA = newA; indexs = newIndexs.ToArray(); orderedB = new System.Numerics.Complex[n]; for (int row = 0; row < n; row++) { orderedB[row] = B[newIndexs[row]]; } } else { System.Diagnostics.Debug.WriteLine("band with not optimized!"); } return(improved); }
public static void ComplexCalcILUWithPivoting( out ComplexSparseMatrix LU, out int[] pivot, ComplexSparseMatrix A, int fillinLevel) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; LU = new ComplexSparseMatrix(A); pivot = new int[n]; for (int row = 0; row < n; row++) { pivot[row] = row; } int[,] level = new int[n, n]; for (int row = 0; row < n; row++) { for (int col = 0; col < n; col++) { level[row, col] = (A[row, col].Magnitude >= IvyFEM.Constants.PrecisionLowerLimit) ? 0 : (fillinLevel + 1); } } for (int k = 0; k < (n - 1); k++) { int p = k; { double max = LU[k, k].Magnitude; for (int i = k + 1; i < n; i++) { double abs = LU[i, k].Magnitude; if (abs > max) { max = abs; p = i; } } } if (k != p) { { int tmp = pivot[k]; pivot[k] = pivot[p]; pivot[p] = tmp; } { var tmp = LU.RowColIndexValues[k]; LU.RowColIndexValues[k] = LU.RowColIndexValues[p]; LU.RowColIndexValues[p] = tmp; } for (int j = 0; j < n; j++) { int tmp = level[k, j]; level[k, j] = level[p, j]; level[p, j] = tmp; } } for (int i = k + 1; i < n; i++) { if (level[i, k] > fillinLevel) { continue; } System.Diagnostics.Debug.Assert(LU.RowColIndexValues[k].ContainsKey(k)); LU[i, k] /= LU[k, k]; System.Numerics.Complex LUik = LU[i, k]; foreach (var pair in LU.RowColIndexValues[k]) { int j = pair.Key; System.Numerics.Complex LUkj = pair.Value; if (j >= k + 1 && j < n) { } else { continue; } level[i, j] = Math.Min(level[i, j], level[i, k] + level[k, j] + 1); if (level[i, j] <= fillinLevel) { LU[i, j] -= LUik * LUkj; // LU[i, k] LU[k, j] } } } } for (int i = 0; i < n; i++) { System.Diagnostics.Debug.Assert(LU.RowColIndexValues[i].ContainsKey(i)); } }
public static bool ComplexSolvePreconditionedBiCGSTAB( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B, ComplexSparseMatrix LU, double convRatioTolerance) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; System.Diagnostics.Debug.Assert(B.Length == n); double convRatio = convRatioTolerance; double tolerance = convRatio; const int maxIter = IvyFEM.Linear.Constants.MaxIter; System.Numerics.Complex[] r = new System.Numerics.Complex[n]; System.Numerics.Complex[] r0 = new System.Numerics.Complex[n]; System.Numerics.Complex[] x = new System.Numerics.Complex[n]; System.Numerics.Complex[] p = new System.Numerics.Complex[n]; System.Numerics.Complex[] s = new System.Numerics.Complex[n]; System.Numerics.Complex[] Mp = new System.Numerics.Complex[n]; System.Numerics.Complex[] Ms = new System.Numerics.Complex[n]; int iter = 0; B.CopyTo(r, 0); double sqInvNorm0; { double sqNorm0 = IvyFEM.Lapack.Functions.zdotc(r, r).Real; if (sqNorm0 < IvyFEM.Constants.PrecisionLowerLimit) { convRatio = 0; X = x; System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); return(true); } sqInvNorm0 = 1.0 / sqNorm0; } r.CopyTo(r0, 0); r.CopyTo(p, 0); for (iter = 0; iter < maxIter; iter++) { ComplexSolveLU(out Mp, LU, p); System.Numerics.Complex r0r = IvyFEM.Lapack.Functions.zdotc(r0, r); System.Numerics.Complex[] AMp = A * Mp; System.Numerics.Complex alpha; { System.Numerics.Complex denominator = IvyFEM.Lapack.Functions.zdotc(r0, AMp); alpha = r0r / denominator; } s = IvyFEM.Lapack.Functions.zaxpy(-alpha, AMp, r); ComplexSolveLU(out Ms, LU, s); System.Numerics.Complex[] AMs = A * Ms; System.Numerics.Complex omega; { System.Numerics.Complex denominator = IvyFEM.Lapack.Functions.zdotc(AMs, AMs); System.Numerics.Complex numerator = IvyFEM.Lapack.Functions.zdotc(s, AMs); omega = numerator / denominator; } x = IvyFEM.Lapack.Functions.zaxpy(alpha, Mp, x); x = IvyFEM.Lapack.Functions.zaxpy(omega, Ms, x); r = IvyFEM.Lapack.Functions.zaxpy(-omega, AMs, s); { double sqNorm = IvyFEM.Lapack.Functions.zdotc(r, r).Real; if (sqNorm * sqInvNorm0 < tolerance * tolerance) { convRatio = Math.Sqrt(sqNorm * sqInvNorm0); X = x; System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); return(true); } } System.Numerics.Complex beta; { System.Numerics.Complex r0rPrev = r0r; r0r = IvyFEM.Lapack.Functions.zdotc(r0, r); beta = (r0r * alpha) / (r0rPrev * omega); } p = IvyFEM.Lapack.Functions.zaxpy(beta, p, r); p = IvyFEM.Lapack.Functions.zaxpy(-beta * omega, AMp, p); } { double sqNormRes = IvyFEM.Lapack.Functions.zdotc(r, r).Real; convRatio = Math.Sqrt(sqNormRes * sqInvNorm0); System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); X = x; } System.Diagnostics.Debug.WriteLine("Not converged"); return(false); }
public ComplexSparseMatrix(ComplexSparseMatrix src) { Copy(src); }
public static bool ComplexSolveNoPreconCOCG( out System.Numerics.Complex[] X, ComplexSparseMatrix A, System.Numerics.Complex[] B, double convRatioTolerance) { System.Diagnostics.Debug.Assert(A.RowLength == A.ColumnLength); int n = A.RowLength; System.Diagnostics.Debug.Assert(B.Length == n); double convRatio = convRatioTolerance; double convRatioTol = convRatio; const int maxIter = IvyFEM.Linear.Constants.MaxIter; System.Numerics.Complex[] r = new System.Numerics.Complex[n]; System.Numerics.Complex[] x = new System.Numerics.Complex[n]; System.Numerics.Complex[] p = new System.Numerics.Complex[n]; int iter = 0; B.CopyTo(r, 0); double sqInvNorm0; { double sqNorm0 = IvyFEM.Lapack.Functions.zdotc(r, r).Real; if (sqNorm0 < IvyFEM.Constants.PrecisionLowerLimit) { convRatio = 0; X = x; System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); return(true); } sqInvNorm0 = 1.0 / sqNorm0; } r.CopyTo(p, 0); System.Numerics.Complex rr = IvyFEM.Lapack.Functions.zdotu(r, r); for (iter = 0; iter < maxIter; iter++) { System.Numerics.Complex[] Ap = A * p; System.Numerics.Complex alpha; { System.Numerics.Complex pAp = IvyFEM.Lapack.Functions.zdotu(p, Ap); alpha = rr / pAp; } r = IvyFEM.Lapack.Functions.zaxpy(-alpha, Ap, r); x = IvyFEM.Lapack.Functions.zaxpy(alpha, p, x); { double sqNorm = IvyFEM.Lapack.Functions.zdotc(r, r).Real; if (sqNorm * sqInvNorm0 < convRatioTol * convRatioTol) { convRatio = Math.Sqrt(sqNorm * sqInvNorm0); X = x; System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); return(true); } } System.Numerics.Complex rrPrev = rr; rr = IvyFEM.Lapack.Functions.zdotu(r, r); System.Numerics.Complex beta = rr / rrPrev; p = IvyFEM.Lapack.Functions.zaxpy(beta, p, r); } { double sqNormRes = IvyFEM.Lapack.Functions.zdotc(r, r).Real; convRatio = Math.Sqrt(sqNormRes * sqInvNorm0); System.Diagnostics.Debug.WriteLine("iter = " + iter + " norm: " + convRatio); X = x; } System.Diagnostics.Debug.WriteLine("Not converged"); return(false); }