Changeset 23205


Ignore:
Timestamp:
08/31/18 12:39:46 (7 years ago)
Author:
wester
Message:

CHG: Reduced SchurCG storage req. by storing preconditioner in Kff. Added adjusted routine to check for convergence.

Location:
issm/trunk-jpl/src/c/solutionsequences
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/c/solutionsequences/convergence.cpp

    r23167 r23205  
    77#include "../shared/shared.h"
    88
    9 void convergence(bool* pconverged, Matrix<IssmDouble>* Kff,Vector<IssmDouble>* pf,Vector<IssmDouble>* uf,Vector<IssmDouble>* old_uf,IssmDouble eps_res,IssmDouble eps_rel,IssmDouble eps_abs){
     9void convergence(bool* pconverged, Matrix<IssmDouble>* Kff,Vector<IssmDouble>* pf,Vector<IssmDouble>* uf,Vector<IssmDouble>* old_uf,IssmDouble eps_res,IssmDouble eps_rel,IssmDouble eps_abs){/*{{{*/
    1010
    1111        /*output*/
     
    3434        }
    3535
     36
    3637        /*Display solver caracteristics*/
    3738        if (VerboseConvergence()){
     39
     40       
    3841
    3942                /*compute KUF = KU - F = K*U - F*/
     
    136139        /*assign output*/
    137140        *pconverged=converged;
    138 }
     141}/*}}}*/
     142
     143
  • issm/trunk-jpl/src/c/solutionsequences/solutionsequence_schurcg.cpp

    r23204 r23205  
    1212
    1313#ifdef _HAVE_PETSC_
    14 void SchurCGSolver(Vector<IssmDouble>** puf,Mat Kff,Mat Iff,Vec pf, Vec uf0,Vec df,Parameters* parameters){/*{{{*/
     14
     15
     16void SchurCGSolver(Vector<IssmDouble>** puf,Mat Kff,Vec pf, Vec uf0,IS isv,IS isp,Parameters* parameters){/*{{{*/
    1517
    1618        Mat                  A, B, BT;                          /* Saddle point block matrices */
    1719        Mat                                             IP;                                             /* Preconditioner matrix */
    18         IS                   isv=NULL;                          /* Index set free velocity nodes */
    19         IS                   isp=NULL;                          /* Index set free pressure nodes */
     20        Mat                                             IP2;
    2021        int                  nu, np;                                    /* No of. free nodes in velocity / pressure space */
    2122   Vec                  p,uold,unew;                    /* Solution vectors for pressure / vel. */
     
    3839        Vector<IssmDouble>* out_uf=new Vector<IssmDouble>(uf0);
    3940       
    40         /* Get velocity and pressure index sets for extraction */
    41         #if _PETSC_MAJOR_==3
    42                 /*Make indices out of doftypes: */
    43                 if(!df)_error_("need doftypes for FS solver!\n");
    44            DofTypesToIndexSet(&isv,&isp,df,FSSolverEnum);
    45         #else
    46            _error_("Petsc 3.X required");
    47         #endif
    48 
    49 
    5041        /* Extract block matrices from the saddle point matrix */
    5142        /* [ A   B ] = Kff
     
    5748       
    5849        /* Extract preconditioner matrix on the pressure space*/
    59         MatGetSubMatrix(Iff,isp,isp,MAT_INITIAL_MATRIX,&IP);
    60        
     50        MatGetSubMatrix(Kff,isp,isp,MAT_INITIAL_MATRIX,&IP);
     51
    6152        /* Get number of velocity / pressure nodes */
    6253        MatGetSize(B,&nu,&np);
     
    230221                else if(rnorm > 100*initRnorm)
    231222                 _error_("Solver diverged. This shouldn't happen\n");
    232                 else
    233                  PetscPrintf(PETSC_COMM_WORLD,"rel. residual at step %d: %g, at TOL = %g\n",count,rnorm/initRnorm,TOL);
    234                
     223                //else
     224                // PetscPrintf(PETSC_COMM_WORLD,"rel. residual at step %d: %g, at TOL = %g\n",count,rnorm/initRnorm,TOL);
     225       
     226
     227
     228
    235229                if(count > np-1) break;
    236230       
     
    273267        VecDestroy(&thetanew);VecDestroy(&thetaold);
    274268
     269}/*}}}*/
     270void convergence_schurcg(bool* pconverged, Matrix<IssmDouble>* Kff,Vector<IssmDouble>* pf,Vector<IssmDouble>* uf,Vector<IssmDouble>* old_uf,IssmDouble eps_res,IssmDouble eps_rel,IssmDouble eps_abs,IS isv,IS isp){/*{{{*/
     271
     272        /*output*/
     273        bool converged=false;
     274
     275        /*intermediary*/
     276        //Vector<IssmDouble>* KU=NULL;
     277        //Vector<IssmDouble>* KUF=NULL;
     278        //Vector<IssmDouble>* KUold=NULL;
     279        //Vector<IssmDouble>* KUoldF=NULL;
     280        Vector<IssmDouble>* duf=NULL;
     281        IssmDouble ndu,nduinf,nu;
     282        IssmDouble nKUF;
     283        IssmDouble nKUoldF;
     284        IssmDouble nF;
     285        IssmDouble solver_residue,res;
     286        int analysis_type;
     287
     288        Mat A, B, BT;
     289        Vec u,p,uold,pold,f1,f2,tmp,res1,res2;
     290        int n_u,n_p;
     291        double rnorm1, rnorm2;
     292
     293
     294        if(VerboseModule()) _printf0_("   checking convergence\n");
     295
     296        /*If uf is NULL in input, f-set is nil, model is fully constrained, therefore converged from
     297         * the get go: */
     298        if(uf->IsEmpty()){
     299                *pconverged=true;
     300                return;
     301        }
     302
     303  /* Note: SchurCG also constructs the Schur preconditioner and stores it in the free block of Kff */
     304  /*                    [A    B]
     305        * Kff =  |      |
     306        *                       [B^T IP]
     307  /* To calculate the residual, only the necessary blocks need to be extracted */
     308
     309                /*Extract A, B, B^T */
     310                MatGetSubMatrix(Kff->pmatrix->matrix,isv,isv,MAT_INITIAL_MATRIX,&A);
     311                MatGetSubMatrix(Kff->pmatrix->matrix,isv,isp,MAT_INITIAL_MATRIX,&B);
     312                MatGetSubMatrix(Kff->pmatrix->matrix,isp,isv,MAT_INITIAL_MATRIX,&BT);
     313       
     314                /*no. of free nodes in velocity/pressure space*/
     315                MatGetSize(B,&n_u,&n_p);
     316
     317                /*Extract values corresponding to the free velocity/pressure nodes*/
     318                VecCreate(IssmComm::GetComm(),&p);VecSetSizes(p,PETSC_DECIDE,n_p);VecSetFromOptions(p);
     319                VecAssemblyBegin(p);VecAssemblyEnd(p);
     320                VecCreate(IssmComm::GetComm(),&u);VecSetSizes(u,PETSC_DECIDE,n_u);VecSetFromOptions(u);
     321                VecAssemblyBegin(u);VecAssemblyEnd(u);
     322
     323                VecGetSubVector(uf->pvector->vector,isv,&u);
     324                VecGetSubVector(uf->pvector->vector,isp,&p);
     325               
     326
     327                /*Extract values of the RHS corresponding to the first/second block*/
     328                VecDuplicate(u,&f1);VecSet(f1,1.0);
     329                VecDuplicate(p,&f2);VecSet(f2,1.0);
     330                VecGetSubVector(pf->pvector->vector,isv,&f1);
     331                VecGetSubVector(pf->pvector->vector,isp,&f2);
     332
     333                /*Allocate intermediaries*/
     334                VecDuplicate(u,&res1);VecSet(res1,1.0);
     335                VecDuplicate(u,&tmp);VecSet(tmp,1.0);
     336                VecDuplicate(p,&res2);VecSet(res2,1.0);
     337
     338
     339        /*Display solver caracteristics*/
     340        if (VerboseConvergence()){
     341               
     342                /*Calculate res1 = A*u + B*p - f1*/
     343                VecScale(f1,-1.);MatMultAdd(A,u,f1,tmp);MatMultAdd(B,p,tmp,res1);VecScale(f1,-1.);
     344                /*Calculate res2 = B^T * u - f2*/
     345                VecScale(f2,-1.);MatMultAdd(BT,u,f2,res2);VecScale(f2,-1.);
     346
     347
     348                /*compute norm(res1), norm(res2), norm(F) and residue*/
     349                VecNorm(res1,NORM_2,&rnorm1);VecNorm(res2,NORM_2,&rnorm2);
     350                nKUF=sqrt(rnorm1*rnorm1 + rnorm2*rnorm2);
     351                nF=pf->Norm(NORM_TWO);
     352                solver_residue=nKUF/nF;
     353                _printf0_("\n" << "   solver residue: norm(KU-F)/norm(F)=" << solver_residue << "\n");
     354                if(xIsNan<IssmDouble>(solver_residue)){
     355                        //Kff->Echo();
     356                }
     357
     358        }
     359        /*clean up*/
     360        VecRestoreSubVector(uf->pvector->vector,isv,&u);
     361        VecRestoreSubVector(uf->pvector->vector,isp,&p);
     362       
     363        /*Extract values corresponding to velocity/pressure on the old solution*/
     364        VecGetSubVector(old_uf->pvector->vector,isv,&uold);
     365        VecGetSubVector(old_uf->pvector->vector,isp,&pold);
     366               
     367
     368        /*Force equilibrium (Mandatory)*/
     369
     370        /*Calculate res1 = A*uold + B*pold - f1*/
     371        VecScale(f1,-1.);MatMultAdd(A,uold,f1,tmp);MatMultAdd(B,pold,tmp,res1);VecScale(f1,-1.);
     372        /*Calculate res2 = B^T * uold - f2*/
     373        VecScale(f2,-1.);MatMultAdd(BT,uold,f2,res2);VecScale(f2,-1.);
     374       
     375        /*compute norm(res1), norm(res2), norm(F) and residue*/
     376        VecNorm(res1,NORM_2,&rnorm1);VecNorm(res2,NORM_2,&rnorm2);
     377        nKUoldF=sqrt(rnorm1*rnorm1 + rnorm2*rnorm2);
     378        nF=pf->Norm(NORM_TWO);
     379        res=nKUoldF/nF;
     380        if (xIsNan<IssmDouble>(res)){
     381                _printf0_("norm nf = " << nF << "f and norm kuold = " << nKUoldF << "f\n");
     382                _error_("mechanical equilibrium convergence criterion is NaN!");
     383        }
     384
     385        MatDestroy(&A);MatDestroy(&B);MatDestroy(&BT);
     386        VecRestoreSubVector(pf->pvector->vector,isv,&f1);
     387        VecRestoreSubVector(pf->pvector->vector,isp,&f2);
     388        VecDestroy(&res1);VecDestroy(&res2);VecDestroy(&tmp);
     389        VecRestoreSubVector(old_uf->pvector->vector,isv,&uold);
     390        VecRestoreSubVector(old_uf->pvector->vector,isp,&pold);
     391       
     392
     393
     394        //print
     395        if(res<eps_res){
     396                if(VerboseConvergence()) _printf0_(setw(50)<<left<<"   mechanical equilibrium convergence criterion"<<res*100<< " < "<<eps_res*100<<" %\n");
     397                converged=true;
     398        }
     399        else{
     400                if(VerboseConvergence()) _printf0_(setw(50)<<left<<"   mechanical equilibrium convergence criterion"<<res*100<<" > "<<eps_res*100<<" %\n");
     401                converged=false;
     402        }
     403
     404        /*Relative criterion (optional)*/
     405        if (!xIsNan<IssmDouble>(eps_rel) || (VerboseConvergence())){
     406
     407                //compute norm(du)/norm(u)
     408                duf=old_uf->Duplicate(); old_uf->Copy(duf); duf->AYPX(uf,-1.0);
     409                ndu=duf->Norm(NORM_TWO); nu=old_uf->Norm(NORM_TWO);
     410
     411                if (xIsNan<IssmDouble>(ndu) || xIsNan<IssmDouble>(nu)) _error_("convergence criterion is NaN!");
     412
     413                //clean up
     414                delete duf;
     415
     416                //print
     417                if (!xIsNan<IssmDouble>(eps_rel)){
     418                        if((ndu/nu)<eps_rel){
     419                                if(VerboseConvergence()) _printf0_(setw(50) << left << "   Convergence criterion: norm(du)/norm(u)" << ndu/nu*100 << " < " << eps_rel*100 << " %\n");
     420                        }
     421                        else{
     422                                if(VerboseConvergence()) _printf0_(setw(50) << left << "   Convergence criterion: norm(du)/norm(u)" << ndu/nu*100 << " > " << eps_rel*100 << " %\n");
     423                                converged=false;
     424                        }
     425                }
     426                else _printf0_(setw(50) << left << "   Convergence criterion: norm(du)/norm(u)" << ndu/nu*100 << " %\n");
     427
     428        }
     429
     430        /*Absolute criterion (Optional) = max(du)*/
     431        if (!xIsNan<IssmDouble>(eps_abs) || (VerboseConvergence())){
     432
     433                //compute max(du)
     434                duf=old_uf->Duplicate(); old_uf->Copy(duf); duf->AYPX(uf,-1.0);
     435                ndu=duf->Norm(NORM_TWO); nduinf=duf->Norm(NORM_INF);
     436                if (xIsNan<IssmDouble>(ndu) || xIsNan<IssmDouble>(nu)) _error_("convergence criterion is NaN!");
     437
     438                //clean up
     439                delete duf;
     440
     441                //print
     442                if (!xIsNan<IssmDouble>(eps_abs)){
     443                        if ((nduinf)<eps_abs){
     444                                if(VerboseConvergence()) _printf0_(setw(50) << left << "   Convergence criterion: max(du)" << nduinf << " < " << eps_abs << "\n");
     445                        }
     446                        else{
     447                                if(VerboseConvergence()) _printf0_(setw(50) << left << "   Convergence criterion: max(du)" << nduinf << " > " << eps_abs << "\n");
     448                                converged=false;
     449                        }
     450                }
     451                else  _printf0_(setw(50) << left << "   Convergence criterion: max(du)" << nduinf << "\n");
     452
     453        }
     454
     455        /*assign output*/
     456        *pconverged=converged;
    275457}/*}}}*/
    276458void solutionsequence_schurcg(FemModel* femmodel){/*{{{*/
     
    285467        Vector<IssmDouble>* df  = NULL;
    286468        Vector<IssmDouble>* ys  = NULL;
    287         Matrix<IssmDouble>* Iff = NULL;
    288469
    289470
     
    324505
    325506                /*Create mass matrix*/
    326                 int fsize; Kff->GetSize(&fsize,&fsize);
    327                 Iff=new Matrix<IssmDouble>(fsize,fsize,300,4);
    328507                StressbalanceAnalysis* analysis = new StressbalanceAnalysis();
    329508                /*Get complete stiffness matrix without penalties*/
     
    331510                        Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i));
    332511                        ElementMatrix* Ie = analysis->CreateSchurPrecondMatrix(element);
    333                         if(Ie) Ie->AddToGlobal(Iff,NULL);
     512                        if(Ie) Ie->AddToGlobal(Kff,NULL);
    334513                        delete Ie;
    335514                }
    336                 Iff->Assemble();
     515                Kff->Assemble();
    337516                delete analysis;
     517
     518                /*Obtain index sets for velocity and pressure components */
     519                IS isv = NULL;
     520                IS isp = NULL;
     521                #if _PETSC_MAJOR_==3
     522                        /*Make indices out of doftypes: */
     523                        if(!(df->pvector->vector))_error_("need doftypes for FS solver!\n");
     524                        DofTypesToIndexSet(&isv,&isp,df->pvector->vector,FSSolverEnum);
     525                #else
     526                        _error_("Petsc 3.X required");
     527                #endif
     528
    338529
    339530                /*Solve*/
     
    343534                SchurCGSolver(&uf,
    344535                                        Kff->pmatrix->matrix,
    345                                         Iff->pmatrix->matrix,
    346536                                        pf->pvector->vector,
    347537                                        old_uf->pvector->vector,
    348                                         df->pvector->vector,
     538                                        isv,
     539                                        isp,
    349540                                        femmodel->parameters);
    350541                femmodel->profiler->Stop(SOLVER);
    351                 delete Iff;
    352                
     542       
     543
    353544                /*Merge solution from f set to g set*/
    354545                Mergesolutionfromftogx(&ug, uf,ys,femmodel->nodes,femmodel->parameters);delete ys;
    355546
    356547                /*Check for convergence and update inputs accordingly*/
    357                 convergence(&converged,Kff,pf,uf,old_uf,eps_res,eps_rel,eps_abs); delete Kff; delete pf; delete df;
     548                convergence_schurcg(&converged,Kff,pf,uf,old_uf,eps_res,eps_rel,eps_abs,isv,isp); delete Kff; delete pf; delete df;
    358549                count++;
    359550
     
    380571
    381572}/*}}}*/
     573
    382574#else
    383575void solutionsequence_schurcg(FemModel* femmodel){_error_("PETSc needs to be installed");}
Note: See TracChangeset for help on using the changeset viewer.