int FAMGSystem::ConstructSimple( FAMGMatrixAlg* stiffmat, FAMGVector* tvA, FAMGVector* tvB ) { #ifdef ModelP assert(0); // not for parallel because of Mat/ConMat #endif FAMGMarkHeap(FAMG_FROM_BOTTOM); matrix = stiffmat; #ifdef FAMG_REORDERCOLUMN if(matrix->OrderColumns(colmap)) RETURN(1); #endif char *solver = FAMGGetParameter()->Getsolver(); SolverPtr = &FAMGSystem::BiCGStab; if(strcmp(solver,"bicgstab") == 0) { SolverPtr = &FAMGSystem::BiCGStab; } else if(strcmp(solver,"linit") == 0) { SolverPtr = &FAMGSystem::LinIt; } else if(strcmp(solver,"gmres") == 0) { SolverPtr = &FAMGSystem::GMRES; } else { ostrstream ostr; ostr << __FILE__ << __LINE__ << "solver = bicgstab" << endl; FAMGWarning(ostr); } // mg0 supposed to be constructed FAMGMultiGrid *mg0 = mg[0]; if(mg0 == NULL) RETURN(1); #ifdef FAMG_REORDERCOLUMN if(mg0->Order()) RETURN(1); #endif return 0; }
void MarkStrongLinks(const MT &A, const FAMGGrid &grid) { typedef typename MT::Vector VT; const typename MT::GridVector& gridvec = (typename MT::GridVector&)grid.GetGridVector(); typename MT::MatrixEntry matij; typename VT::VectorEntry vi; typename VT::Iterator viter(gridvec); double rlist[20], llist[20], mij, mji, rmax, lmax; int z, y; const double sigma = FAMGGetParameter()->Getsigma(); const int minsl = 2 - 1; while (viter(vi)) { for(z = 0; z <= minsl; z++) { rlist[z] = llist[z] = 0.0; } typename MT::Iterator mij_iter(A,vi); mij_iter(matij); // skip diagonal while( mij_iter(matij) ) { mij = Abs(A[matij]); mji = Abs(A.GetAdjData(matij)); for(z = minsl; z >= 0; z--) { if (mij < rlist[z]) break; } for(y = minsl; y > z+1; y--) { rlist[y] = rlist[y-1]; } if(z+1 <= minsl) rlist[z+1] = mij; for(z = minsl; z >= 0; z--) { if (mji < llist[z]) break; } for(y = minsl; y > z+1; y--) { llist[y] = llist[y-1]; } if(z+1 <= minsl) llist[z+1] = mji; } rmax = rlist[minsl]*sigma; lmax = llist[minsl]*sigma; mij_iter.reset(); mij_iter(matij); matij.set_strong(1); while( mij_iter(matij) ) { mij = Abs(A[matij]); mji = Abs(A.GetAdjData(matij)); if((mij > rmax) || (mji > lmax)) { matij.set_strong(1); } else matij.set_strong(0); } } return; }
int FAMGMultiGrid::Step(int level) { // Input: right hand side, initial guess and defect // Output: right hand side, new solution and new defect FAMGGrid *g, *cg; int i,n1,n2,gamma; n1 = FAMGGetParameter()->Getn1(); n2 = FAMGGetParameter()->Getn2(); gamma = FAMGGetParameter()->Getgamma(); g = grid[level]; if(gamma < 1) { for(i = 0; i < n1; i++) { g->PreSmooth(); // not necessary any more: g->AddVector(FAMGDEFECT,FAMGUNKNOWN); g->Defect(); } for(i = 0; i < n2; i++) { g->PostSmooth(); // not necessary any more: g->AddVector(FAMGDEFECT,FAMGUNKNOWN); g->Defect(); } return 0; } if(level == (n-1)) { if(g->SolveCoarseGrid()) RETURN(1); } else { cg = grid[level+1]; for(i = 0; i < n1; i++) { g->PreSmooth(); // not necessary any more: g->AddVector(FAMGDEFECT,FAMGUNKNOWN); g->Defect(); } // g->DevideFGDefect(); included in the new restriction g->Restriction(*(g->GetVector(FAMGUNKNOWN)), *(g->GetVector(FAMGDEFECT)), *(cg->GetVector(FAMGDEFECT)), *(g->GetVector(FAMGUNKNOWN))/*only as dummy!*/ ); *(cg->GetVector(FAMGUNKNOWN)) = 0.0; *(cg->GetVector(FAMGRHS)) = *(cg->GetVector(FAMGDEFECT)); for(i = 0; i < gamma; i++) if(Step(level+1)) RETURN(1); g->Prolongation(cg, *(cg->GetVector(FAMGUNKNOWN)), *(g->GetVector(FAMGUNKNOWN)), *(g->GetVector(FAMGDEFECT)), NULL); // g->Defect(); included in the new restriction for(i = 0; i < n2; i++) { g->PostSmooth(); // not necessary any more: g->AddVector(FAMGDEFECT,FAMGUNKNOWN); g->Defect(); } } return 0; }
int FAMGMultiGrid::Construct() { FAMGGrid *g, *cg; int level, nnc, nn, ilu, cgilu, leave; DOUBLE coarsefrac = 0.0, t, time, cgtime; FAMGLeaveInfo myleaveinfo; // read parameter const int cgnodes = FAMGGetParameter()->Getcgnodes(); #ifdef ModelP const int cgminnodespe = FAMGGetParameter()->Getcgminnodespe(); #endif const int cglevels = FAMGGetParameter()->Getcglevels(); const double mincoarse = FAMGGetParameter()->Getmincoarse(); const int gamma = FAMGGetParameter()->Getgamma(); if ((strcmp("ilut",FAMGGetParameter()->Getpresmoother()) == 0) || (strcmp("ilut",FAMGGetParameter()->Getpostsmoother()) == 0)) { ilu = 1; } else ilu = 0; if (strcmp("ilut",FAMGGetParameter()->Getcgsmoother()) == 0) { cgilu = 1; } else cgilu = 0; g = grid[0]; #ifdef FAMG_SPARSE_BLOCK g->SmoothTV(); #else g->SmoothTV(); #endif FAMGMarkHeap(FAMG_FROM_TOP); // release in Deconstruct for(level = 0; level < FAMGMAXGRIDS-1; level++) { time = CURRENT_TIME; // g->SmoothTV(); #ifdef ModelP nn = g->GetNrMasterVectors(); // we are interested only in the master vectors #else nn = g->GetN(); #endif leave = 0; myleaveinfo.coarsefrac = coarsefrac; myleaveinfo.cgnodes = nn; #ifdef ModelP myleaveinfo.cgminnodespe = nn; GlobalLeave( &myleaveinfo ); #endif #ifdef XFERTIMING XFERTIMING_algtime = 0.0; XFERTIMING_algtime_start = CURRENT_TIME; #endif if( myleaveinfo.coarsefrac > mincoarse ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; coarsening rate " << 1.0/myleaveinfo.coarsefrac << " < " << 1.0/mincoarse << endl; } if( level >= cglevels ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; levels " << level << " >= " << cglevels << endl; } if( myleaveinfo.cgnodes <= cgnodes ) { leave = 1; #ifdef ModelP if( me==master ) #endif cout << "FAMG finished; cg nodes " << myleaveinfo.cgnodes << " <= " << cgnodes << endl; } #ifdef ModelP if( myleaveinfo.cgminnodespe < cgminnodespe ) { leave = 1; if( me==master ) cout << "FAMG finished; min cg nodes per PE " << myleaveinfo.cgminnodespe << " <= " << cgminnodespe << endl; } #endif if (leave) break; if (gamma < 1) return 0; // ModelP: simple return because gamma is known to all processors #ifdef ModelP //prv(-level,0); g->ConstructOverlap(); //prv(-level,0); assert(g->GetNrMasterVectors() == nn ); #endif g->Stencil(); #ifdef FAMG_ILU if(ilu) { if (g->ILUTDecomp(0)) RETURN(1); } #endif #ifdef FAMG_SPARSE_BLOCK if (g->ConstructDiagonalInverse()) RETURN(1); #endif if (g->ConstructTransfer()) RETURN(1); #ifdef FAMG_SPARSE_BLOCK // if (g->ConstructDiagonalLump()) // RETURN(1); #endif cgtime = CURRENT_TIME; nnc = (g->GetN())-(g->GetNF()); cg = (FAMGGrid *) FAMGGetMem(sizeof(FAMGGrid),FAMG_FROM_TOP); if(cg == NULL) RETURN(1); if(cg->Init(nnc,*g)) RETURN(1); if(cg->Construct(g)) RETURN(1); grid[n] = cg; g = cg; n++; //printf("after Galerkin:\n"); //prm(0,0);prm(0,1); prim(0); //prm(-1,0); //prv(-level-1,0); // for debugging: print some consistent and inconsistent matrices: //GRID *tmpgrid = cg->GetugGrid(); //int tmplevel = GLEVEL(tmpgrid); //MATDATA_DESC *tmpA = ((FAMGugMatrix*)cg->GetMatrix())->GetMatDesc(); //MATDATA_DESC *tmpACons = ((FAMGugMatrix*)cg->GetConsMatrix())->GetMatDesc(); //prvGeom(tmplevel,0); primGeom(tmplevel+1); prmGeom(tmplevel,MD_SCALCMP(tmpA)); //if (dmatcopy(MYMG(tmpgrid),tmplevel,tmplevel,ALL_VECTORS,tmpACons,tmpA) != NUM_OK) assert(0); //if (l_matrix_consistent(tmpgrid,tmpACons,MAT_CONS) != NUM_OK) assert(0); //prvGeom(tmplevel,0); primGeom(tmplevel+1); prmGeom(tmplevel,MD_SCALCMP(tmpACons)); t = CURRENT_TIME; time = t - time; cgtime = t - cgtime; #ifdef XFERTIMING XFERTIMING_algtime += t - XFERTIMING_algtime_start; #endif #ifdef ModelP cout << me << ": "; nnc = cg->GetNrMasterVectors(); // we are interested only in the master vectors #endif coarsefrac = (double)nnc/nn; if( nnc <= 0 ) coarsefrac = 0.000000999; // dummy cout << "amglevel " << -level << " coarsening rate " << 1.0/coarsefrac << " time "<<time<<' '<<cgtime; #ifdef XFERTIMING cout << ' '<<XFERTIMING_algtime; #endif cout << endl; } if(level == FAMGMAXGRIDS-1) { ostrstream ostr; ostr << __FILE__ << ", line " << __LINE__ << ": maximum number of levels reached. " << endl; FAMGWarning(ostr); } g->Stencil(); #ifdef FAMG_ILU if(cgilu) { if (g->ILUTDecomp(1)) RETURN(1); } #endif return 0; }
int FAMGSystem::Construct( FAMGGridVector *gridvector, FAMGMatrixAlg* stiffmat, FAMGMatrixAlg* Consstiffmat, FAMGMatrixAlg* diagmatrix, FAMGVector *vectors[FAMGMAXVECTORS] ) { FAMGMarkHeap(FAMG_FROM_TOP); FAMGMarkHeap(FAMG_FROM_BOTTOM); int i; SetGridVector(gridvector); if (mygridvector == NULL) { ostrstream ostr; ostr << __FILE__ << __LINE__ << "you must provide a gridvector" << endl; FAMGError(ostr); RETURN(1); } #ifdef USE_UG_DS SetFineGrid(((FAMGugGridVector*)gridvector)->GetGrid()); #endif SetMatrix(stiffmat); if (GetMatrix() == NULL) { ostrstream ostr; ostr << __FILE__ << __LINE__ << "you must provide a matrix" << endl; FAMGError(ostr); RETURN(1); } #ifdef FAMG_SPARSE_BLOCK SetDiagMatrix(diagmatrix); if (GetDiagMatrix() == NULL) { ostrstream ostr; ostr << __FILE__ << __LINE__ << "you must provide a diagonal help matrix" << endl; FAMGError(ostr); RETURN(1); } #endif SetConsMatrix(Consstiffmat); if (GetConsMatrix() == NULL) { ostrstream ostr; ostr << __FILE__ << __LINE__ << "you must provide a consistent matrix" << endl; FAMGError(ostr); RETURN(1); } #ifdef FAMG_REORDERCOLUMN // only for reorder column colmap = (int*) FAMGGetMem(famg_interface->n*sizeof(int),FAMG_FROM_TOP); if (colmap == NULL) RETURN(1); if(GetMatrix()->OrderColumns(colmap)) RETURN(1); #endif for ( i=0; i<FAMGMAXVECTORS; i++ ) { if(vectors[i] == NULL) { ostrstream ostr; ostr << __FILE__ << __LINE__ << "you must provide vector " << i << endl; FAMGError(ostr); RETURN(1); } vector[i] = vectors[i]; } char *solver = FAMGGetParameter()->Getsolver(); SolverPtr = &FAMGSystem::BiCGStab; if(strcmp(solver,"bicgstab") == 0) { SolverPtr = &FAMGSystem::BiCGStab; } else if(strcmp(solver,"linit") == 0) { SolverPtr = &FAMGSystem::LinIt; } else if(strcmp(solver,"gmres") == 0) { SolverPtr = &FAMGSystem::GMRES; } else { ostrstream ostr; ostr << __FILE__ << __LINE__ << "solver = bicgstab" << endl; FAMGWarning(ostr); } FAMGMultiGrid *mg0 = CreateMultiGrid(); if(mg0 == NULL) RETURN(1); if (mg0->Init(*this)) RETURN(1); if (mg0->Construct()) RETURN(1); return 0; }