Vector *BPXPrecond(int NoLevels, QMatrix *A, Vector *y, Vector *c, Matrix *R, Matrix *P, int Level, IterProcType SmoothProc, int Nu, PrecondProcType PrecondProc, double Omega, IterProcType SmoothProcC, int NuC, PrecondProcType PrecondProcC, double OmegaC) /* BPX preconditioner (recursively defined) */ { if (Level == 0) { /* smoothing on the coarsest grid - NuC iterations */ V_SetAllCmp(&y[Level], 0.0); (*SmoothProcC)(&A[Level], &y[Level], &c[Level], NuC, PrecondProcC, OmegaC); } else { /* smoothing - Nu iterations */ V_SetAllCmp(&y[Level], 0.0); (*SmoothProc)(&A[Level], &y[Level], &c[Level], Nu, PrecondProc, Omega); /* restiction of the residual to the coarser grid */ Asgn_VV(&c[Level - 1], Mul_MV(&R[Level - 1], &c[Level])); /* smoothing on the coarser grid */ BPXPrecond(NoLevels, A, y, c, R, P, Level - 1, SmoothProc, Nu, PrecondProc, Omega, SmoothProcC, NuC, PrecondProcC, OmegaC); /* interpolation of the solution from coarser grid */ if (P != NULL) AddAsgn_VV(&y[Level], Mul_MV(&P[Level], &y[Level - 1])); else AddAsgn_VV(&y[Level], Mul_MV(Transp_M(&R[Level - 1]), &y[Level - 1])); } return(&y[Level]); }
NumericVector<T> & LaspackVector<T>::operator = (const T s) { libmesh_assert (this->initialized()); libmesh_assert (this->closed()); V_SetAllCmp (&_vec, s); return *this; }
Vector *MGStep(int NoLevels, QMatrix *A, Vector *x, Vector *b, Matrix *R, Matrix *P, int Level, int Gamma, IterProcType SmoothProc, int Nu1, int Nu2, PrecondProcType PrecondProc, double Omega, IterProcType SolvProc, int NuC, PrecondProcType PrecondProcC, double OmegaC) /* one multigrid iteration */ { int CoarseMGIter; /* multi grid iteration counter for coarser grid */ if (Level == 0) { /* solving of system of equations for the residual on the coarsest grid */ (*SolvProc)(&A[Level], &x[Level], &b[Level], NuC, PrecondProcC, OmegaC); } else { /* pre-smoothing - Nu1 iterations */ (*SmoothProc)(&A[Level], &x[Level], &b[Level], Nu1, PrecondProc, Omega); /* restiction of the residual to the coarser grid */ Asgn_VV(&b[Level - 1], Mul_MV(&R[Level - 1], Sub_VV(&b[Level], Mul_QV(&A[Level], &x[Level])))); /* initialisation of vector of unknowns on the coarser grid */ V_SetAllCmp(&x[Level - 1], 0.0); /* solving of system of equations for the residual on the coarser grid */ for (CoarseMGIter = 1; CoarseMGIter <= Gamma; CoarseMGIter++) MGStep(NoLevels, A, x, b, R, P, Level - 1, Gamma, SmoothProc, Nu1, Nu2, PrecondProc, Omega, SolvProc, NuC, PrecondProcC, OmegaC); /* interpolation of the solution from the coarser grid */ if (P != NULL) AddAsgn_VV(&x[Level], Mul_MV(&P[Level], &x[Level - 1])); else AddAsgn_VV(&x[Level], Mul_MV(Transp_M(&R[Level - 1]), &x[Level - 1])); /* post-smoothing - Nu2 iterations */ (*SmoothProc)(&A[Level], &x[Level], &b[Level], Nu2, PrecondProc, Omega); } return(&x[Level]); }
Vector *NestedMGIter(int NoLevels, QMatrix *A, Vector *x, Vector *b, Matrix *R, Matrix *P, int Gamma, IterProcType SmoothProc, int Nu1, int Nu2, PrecondProcType PrecondProc, double Omega, IterProcType SolvProc, int NuC, PrecondProcType PrecondProcC, double OmegaC) /* nested multigrid method */ { int Level; /* solution of system of equations on coarsest grid */ V_SetAllCmp(&x[0], 0.0); MGStep(NoLevels, A, x, b, R, P, 0, Gamma, SmoothProc, Nu1, Nu2, PrecondProc, Omega, SolvProc, NuC, PrecondProcC, OmegaC); for (Level = 1; Level < NoLevels; Level++) { /* prolongation of solution to finer grid */ if (P != NULL) Asgn_VV(&x[Level], Mul_MV(&P[Level], &x[Level - 1])); else Asgn_VV(&x[Level], Mul_MV(Transp_M(&R[Level - 1]), &x[Level - 1])); /* solution of system of equations on finer grid with multigrid method */ MGStep(NoLevels, A, x, b, R, P, Level, Gamma, SmoothProc, Nu1, Nu2, PrecondProc, Omega, SolvProc, NuC, PrecondProcC, OmegaC); } /* submission of reached accuracy to RTC */ RTCResult(1, l2Norm_V(Sub_VV(&b[NoLevels - 1], Mul_QV(&A[NoLevels - 1], &x[NoLevels - 1]))), l2Norm_V(&b[NoLevels - 1]), NestedMGIterId); return(&x[NoLevels - 1]); }
Vector *MGPCGIter(int NoLevels, QMatrix *A, Vector *z, Vector *r, Matrix *R, Matrix *P, int MaxIter, int NoMGIter, int Gamma, IterProcType SmoothProc, int Nu1, int Nu2, PrecondProcType PrecondProc, double Omega, IterProcType SolvProc, int NuC, PrecondProcType PrecondProcC, double OmegaC)/* multigrid preconditioned CG method */ { int Iter, MGIter; double Alpha, Beta, Rho, RhoOld = 0.0; double bNorm; size_t Dim; Vector x, p, q, b; Dim = Q_GetDim(&A[NoLevels - 1]); V_Constr(&x, "x", Dim, Normal, True); V_Constr(&p, "p", Dim, Normal, True); V_Constr(&q, "q", Dim, Normal, True); V_Constr(&b, "b", Dim, Normal, True); if (LASResult() == LASOK) { /* copy solution and right hand side stored in parameters z and r */ Asgn_VV(&x, &z[NoLevels - 1]); Asgn_VV(&b, &r[NoLevels - 1]); bNorm = l2Norm_V(&b); Iter = 0; Asgn_VV(&r[NoLevels - 1], Sub_VV(&b, Mul_QV(&A[NoLevels - 1], &x))); while (!RTCResult(Iter, l2Norm_V(&r[NoLevels - 1]), bNorm, MGPCGIterId) && Iter < MaxIter) { Iter++; /* multigrid preconditioner */ V_SetAllCmp(&z[NoLevels - 1], 0.0); for (MGIter = 1; MGIter <= NoMGIter; MGIter++) MGStep(NoLevels, A, z, r, R, P, NoLevels - 1, Gamma, SmoothProc, Nu1, Nu2, PrecondProc, Omega, SolvProc, NuC, PrecondProcC, OmegaC); Rho = Mul_VV(&r[NoLevels - 1], &z[NoLevels - 1]); if (Iter == 1) { Asgn_VV(&p, &z[NoLevels - 1]); } else { Beta = Rho / RhoOld; Asgn_VV(&p, Add_VV(&z[NoLevels - 1], Mul_SV(Beta, &p))); } Asgn_VV(&q, Mul_QV(&A[NoLevels - 1], &p)); Alpha = Rho / Mul_VV(&p, &q); AddAsgn_VV(&x, Mul_SV(Alpha, &p)); SubAsgn_VV(&r[NoLevels - 1], Mul_SV(Alpha, &q)); RhoOld = Rho; } /* put solution and right hand side vectors back */ Asgn_VV(&z[NoLevels - 1], &x); Asgn_VV(&r[NoLevels - 1], &b); } V_Destr(&x); V_Destr(&p); V_Destr(&q); V_Destr(&b); return(&z[NoLevels - 1]); }
Vector *Test4_QV(QMatrix *Q, Vector *V) /* VRes = Q * V ... implementation using local variables and pointers, descended counting of matrix elements */ { Vector *VRes; char *VResName; size_t Dim, Row, Clm, Len, ElCount; size_t *QLen; ElType **QEl, *PtrEl; Real Sum, Cmp; Real *VCmp, *VResCmp; if (LASResult() == LASOK) { if (Q->Dim == V->Dim) { Dim = Q->Dim; VRes = (Vector *)malloc(sizeof(Vector)); VResName = (char *)malloc((strlen(Q_GetName(Q)) + strlen(V_GetName(V)) + 10) * sizeof(char)); if (VRes != NULL && VResName != NULL) { sprintf(VResName, "(%s) * (%s)", Q_GetName(Q), V_GetName(V)); V_Constr(VRes, VResName, Dim, Tempor, True); if (LASResult() == LASOK) { /* initialisation of vector VRes */ if (Q->Symmetry || Q->ElOrder == Clmws) V_SetAllCmp(VRes, 0.0); /* analysis of multipliers of matrix Q and vector V is not implemented yet */ /* multiplication of matrix elements by vector components */ VCmp = V->Cmp; VResCmp = VRes->Cmp; QLen = Q->Len; QEl = Q->El; if (!Q->Symmetry) { if (Q->ElOrder == Rowws) { for (Row = Dim; Row > 0; Row--) { Len = QLen[Row]; PtrEl = QEl[Row] + Len - 1; Sum = 0.0; for (ElCount = Len; ElCount > 0; ElCount--) { Sum += (*PtrEl).Val * VCmp[(*PtrEl).Pos]; PtrEl--; } VResCmp[Row] = Sum; } } if (Q->ElOrder == Clmws) { for (Clm = Dim; Clm > 0; Clm--) { Len = QLen[Clm]; PtrEl = QEl[Clm] + Len - 1; Cmp = VCmp[Clm]; for (ElCount = Len; ElCount > 0; ElCount--) { VResCmp[(*PtrEl).Pos] += (*PtrEl).Val * Cmp; PtrEl--;; } } } } else { /* multiplication by symmetric matrix is not implemented yet */ V_SetAllCmp(VRes, 0.0); } } } else { LASError(LASMemAllocErr, "Mul_QV", Q_GetName(Q), V_GetName(V), NULL); if (VRes != NULL) free(VRes); if (VResName != NULL) free(VResName); } } else { LASError(LASDimErr, "Mul_QV", Q_GetName(Q), V_GetName(V), NULL); VRes = NULL; } } else { VRes = NULL; } if (Q != NULL) { if (Q->Instance == Tempor) { Q_Destr(Q); free(Q); } } if (V != NULL) { if (V->Instance == Tempor) { V_Destr(V); free(V); } } return(VRes); }
Vector *Test1_QV(QMatrix *Q, Vector *V) /* VRes = Q * V ... very simple implementation */ { Vector *VRes; char *VResName; size_t Dim, Row, Clm, ElCount; ElType **QEl; if (LASResult() == LASOK) { if (Q->Dim == V->Dim) { Dim = Q->Dim; QEl = Q->El; VRes = (Vector *)malloc(sizeof(Vector)); VResName = (char *)malloc((strlen(Q_GetName(Q)) + strlen(V_GetName(V)) + 10) * sizeof(char)); if (VRes != NULL && VResName != NULL) { sprintf(VResName, "(%s) * (%s)", Q_GetName(Q), V_GetName(V)); V_Constr(VRes, VResName, Dim, Tempor, True); if (LASResult() == LASOK) { /* initialisation of vector VRes */ V_SetAllCmp(VRes, 0.0); /* analysis of multipliers of matrix Q and vector V is not implemented yet */ /* multiplication of matrix elements by vector components */ if (!Q->Symmetry) { if (Q->ElOrder == Rowws) { for (Row = 1; Row <= Dim; Row++) { for (ElCount = 0; ElCount < Q->Len[Row]; ElCount++) { Clm = QEl[Row][ElCount].Pos; VRes->Cmp[Row] += QEl[Row][ElCount].Val * V->Cmp[Clm]; } } } if (Q->ElOrder == Clmws) { for (Clm = 1; Clm <= Dim; Clm++) { for (ElCount = 0; ElCount < Q->Len[Clm]; ElCount++) { Row = QEl[Clm][ElCount].Pos; VRes->Cmp[Row] += QEl[Clm][ElCount].Val * V->Cmp[Clm]; } } } } else { /* multiplication by symmetric matrix is not implemented yet */ V_SetAllCmp(VRes, 0.0); } } } else { LASError(LASMemAllocErr, "Mul_QV", Q_GetName(Q), V_GetName(V), NULL); if (VRes != NULL) free(VRes); if (VResName != NULL) free(VResName); } } else { LASError(LASDimErr, "Mul_QV", Q_GetName(Q), V_GetName(V), NULL); VRes = NULL; } } else { VRes = NULL; } if (Q != NULL) { if (Q->Instance == Tempor) { Q_Destr(Q); free(Q); } } if (V != NULL) { if (V->Instance == Tempor) { V_Destr(V); free(V); } } return(VRes); }
static void EstimEigenvals(QMatrix *A, PrecondProcType PrecondProc, double OmegaPrecond) /* estimates extremal eigenvalues of the matrix A by means of the Lanczos method */ { /* * for details to the Lanczos algorithm see * * G. H. Golub, Ch. F. van Loan: * Matrix Computations; * North Oxford Academic, Oxford, 1986 * * (for modification for preconditioned matrices compare with sec. 10.3) * */ double LambdaMin = 0.0, LambdaMax = 0.0; double LambdaMinOld, LambdaMaxOld; double GershBoundMin = 0.0, GershBoundMax = 0.0; double *Alpha, *Beta; size_t Dim, j; Boolean Found; Vector q, qOld, h, p; Q_Lock(A); Dim = Q_GetDim(A); V_Constr(&q, "q", Dim, Normal, True); V_Constr(&qOld, "qOld", Dim, Normal, True); V_Constr(&h, "h", Dim, Normal, True); if (PrecondProc != NULL) V_Constr(&p, "p", Dim, Normal, True); if (LASResult() == LASOK) { Alpha = (double *)malloc((Dim + 1) * sizeof(double)); Beta = (double *)malloc((Dim + 1) * sizeof(double)); if (Alpha != NULL && Beta != NULL) { j = 0; V_SetAllCmp(&qOld, 0.0); V_SetRndCmp(&q); if (Q_KerDefined(A)) OrthoRightKer_VQ(&q, A); if (Q_GetSymmetry(A) && PrecondProc != NULL) { (*PrecondProc)(A, &p, &q, OmegaPrecond); MulAsgn_VS(&q, 1.0 / sqrt(Mul_VV(&q, &p))); } else { MulAsgn_VS(&q, 1.0 / l2Norm_V(&q)); } Beta[0] = 1.0; do { j++; if (Q_GetSymmetry(A) && PrecondProc != NULL) { /* p = M^(-1) q */ (*PrecondProc)(A, &p, &q, OmegaPrecond); /* h = A p */ Asgn_VV(&h, Mul_QV(A, &p)); if (Q_KerDefined(A)) OrthoRightKer_VQ(&h, A); /* Alpha = p . h */ Alpha[j] = Mul_VV(&p, &h); /* r = h - Alpha q - Beta qOld */ SubAsgn_VV(&h, Add_VV(Mul_SV(Alpha[j], &q), Mul_SV(Beta[j-1], &qOld))); /* z = M^(-1) r */ (*PrecondProc)(A, &p, &h, OmegaPrecond); /* Beta = sqrt(r . z) */ Beta[j] = sqrt(Mul_VV(&h, &p)); Asgn_VV(&qOld, &q); /* q = r / Beta */ Asgn_VV(&q, Mul_SV(1.0 / Beta[j], &h)); } else { /* h = A p */ if (Q_GetSymmetry(A)) { Asgn_VV(&h, Mul_QV(A, &q)); } else { if (PrecondProc != NULL) { (*PrecondProc)(A, &h, Mul_QV(A, &q), OmegaPrecond); (*PrecondProc)(Transp_Q(A), &h, &h, OmegaPrecond); Asgn_VV(&h, Mul_QV(Transp_Q(A), &h)); } else { Asgn_VV(&h, Mul_QV(Transp_Q(A), Mul_QV(A, &q))); } } if (Q_KerDefined(A)) OrthoRightKer_VQ(&h, A); /* Alpha = q . h */ Alpha[j] = Mul_VV(&q, &h); /* r = h - Alpha q - Beta qOld */ SubAsgn_VV(&h, Add_VV(Mul_SV(Alpha[j], &q), Mul_SV(Beta[j-1], &qOld))); /* Beta = || r || */ Beta[j] = l2Norm_V(&h); Asgn_VV(&qOld, &q); /* q = r / Beta */ Asgn_VV(&q, Mul_SV(1.0 / Beta[j], &h)); } LambdaMaxOld = LambdaMax; LambdaMinOld = LambdaMin; /* determination of extremal eigenvalues of the tridiagonal matrix (Beta[i-1] Alpha[i] Beta[i]) (where 1 <= i <= j) by means of the method of bisection; bounds for eigenvalues are determined after Gershgorin circle theorem */ if (j == 1) { GershBoundMin = Alpha[1] - fabs(Beta[1]); GershBoundMax = Alpha[1] + fabs(Beta[1]); LambdaMin = Alpha[1]; LambdaMax = Alpha[1]; } else { GershBoundMin = min(Alpha[j] - fabs(Beta[j]) - fabs(Beta[j - 1]), GershBoundMin); GershBoundMax = max(Alpha[j] + fabs(Beta[j]) + fabs(Beta[j - 1]), GershBoundMax); SearchEigenval(j, Alpha, Beta, 1, GershBoundMin, LambdaMin, &Found, &LambdaMin); if (!Found) SearchEigenval(j, Alpha, Beta, 1, GershBoundMin, GershBoundMax, &Found, &LambdaMin); SearchEigenval(j, Alpha, Beta, j, LambdaMax, GershBoundMax, &Found, &LambdaMax); if (!Found) SearchEigenval(j, Alpha, Beta, j, GershBoundMin, GershBoundMax, &Found, &LambdaMax); } } while (!IsZero(Beta[j]) && j < Dim && (fabs(LambdaMin - LambdaMinOld) > EigenvalEps * LambdaMin || fabs(LambdaMax - LambdaMaxOld) > EigenvalEps * LambdaMax) && LASResult() == LASOK); if (Q_GetSymmetry(A)) { LambdaMin = (1.0 - j * EigenvalEps) * LambdaMin; } else { LambdaMin = (1.0 - sqrt(j) * EigenvalEps) * sqrt(LambdaMin); } if (Alpha != NULL) free(Alpha); if (Beta != NULL) free(Beta); } else { LASError(LASMemAllocErr, "EstimEigenvals", Q_GetName(A), NULL, NULL); } } V_Destr(&q); V_Destr(&qOld); V_Destr(&h); if (PrecondProc != NULL) V_Destr(&p); if (LASResult() == LASOK) { ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MinEigenval = LambdaMin; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MaxEigenval = LambdaMax; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->PrecondProcUsed = PrecondProc; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->OmegaPrecondUsed = OmegaPrecond; } else { ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MinEigenval = 1.0; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->MaxEigenval = 1.0; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->PrecondProcUsed = NULL; ((EigenvalInfoType *)*(Q_EigenvalInfo(A)))->OmegaPrecondUsed = 1.0; } Q_Unlock(A); }