Changeset 23205
- Timestamp:
- 08/31/18 12:39:46 (7 years ago)
- Location:
- issm/trunk-jpl/src/c/solutionsequences
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
issm/trunk-jpl/src/c/solutionsequences/convergence.cpp
r23167 r23205 7 7 #include "../shared/shared.h" 8 8 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){ 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){/*{{{*/ 10 10 11 11 /*output*/ … … 34 34 } 35 35 36 36 37 /*Display solver caracteristics*/ 37 38 if (VerboseConvergence()){ 39 40 38 41 39 42 /*compute KUF = KU - F = K*U - F*/ … … 136 139 /*assign output*/ 137 140 *pconverged=converged; 138 } 141 }/*}}}*/ 142 143 -
issm/trunk-jpl/src/c/solutionsequences/solutionsequence_schurcg.cpp
r23204 r23205 12 12 13 13 #ifdef _HAVE_PETSC_ 14 void SchurCGSolver(Vector<IssmDouble>** puf,Mat Kff,Mat Iff,Vec pf, Vec uf0,Vec df,Parameters* parameters){/*{{{*/ 14 15 16 void SchurCGSolver(Vector<IssmDouble>** puf,Mat Kff,Vec pf, Vec uf0,IS isv,IS isp,Parameters* parameters){/*{{{*/ 15 17 16 18 Mat A, B, BT; /* Saddle point block matrices */ 17 19 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; 20 21 int nu, np; /* No of. free nodes in velocity / pressure space */ 21 22 Vec p,uold,unew; /* Solution vectors for pressure / vel. */ … … 38 39 Vector<IssmDouble>* out_uf=new Vector<IssmDouble>(uf0); 39 40 40 /* Get velocity and pressure index sets for extraction */41 #if _PETSC_MAJOR_==342 /*Make indices out of doftypes: */43 if(!df)_error_("need doftypes for FS solver!\n");44 DofTypesToIndexSet(&isv,&isp,df,FSSolverEnum);45 #else46 _error_("Petsc 3.X required");47 #endif48 49 50 41 /* Extract block matrices from the saddle point matrix */ 51 42 /* [ A B ] = Kff … … 57 48 58 49 /* 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 61 52 /* Get number of velocity / pressure nodes */ 62 53 MatGetSize(B,&nu,&np); … … 230 221 else if(rnorm > 100*initRnorm) 231 222 _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 235 229 if(count > np-1) break; 236 230 … … 273 267 VecDestroy(&thetanew);VecDestroy(&thetaold); 274 268 269 }/*}}}*/ 270 void 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; 275 457 }/*}}}*/ 276 458 void solutionsequence_schurcg(FemModel* femmodel){/*{{{*/ … … 285 467 Vector<IssmDouble>* df = NULL; 286 468 Vector<IssmDouble>* ys = NULL; 287 Matrix<IssmDouble>* Iff = NULL;288 469 289 470 … … 324 505 325 506 /*Create mass matrix*/ 326 int fsize; Kff->GetSize(&fsize,&fsize);327 Iff=new Matrix<IssmDouble>(fsize,fsize,300,4);328 507 StressbalanceAnalysis* analysis = new StressbalanceAnalysis(); 329 508 /*Get complete stiffness matrix without penalties*/ … … 331 510 Element* element=xDynamicCast<Element*>(femmodel->elements->GetObjectByOffset(i)); 332 511 ElementMatrix* Ie = analysis->CreateSchurPrecondMatrix(element); 333 if(Ie) Ie->AddToGlobal( Iff,NULL);512 if(Ie) Ie->AddToGlobal(Kff,NULL); 334 513 delete Ie; 335 514 } 336 Iff->Assemble();515 Kff->Assemble(); 337 516 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 338 529 339 530 /*Solve*/ … … 343 534 SchurCGSolver(&uf, 344 535 Kff->pmatrix->matrix, 345 Iff->pmatrix->matrix,346 536 pf->pvector->vector, 347 537 old_uf->pvector->vector, 348 df->pvector->vector, 538 isv, 539 isp, 349 540 femmodel->parameters); 350 541 femmodel->profiler->Stop(SOLVER); 351 delete Iff;352 542 543 353 544 /*Merge solution from f set to g set*/ 354 545 Mergesolutionfromftogx(&ug, uf,ys,femmodel->nodes,femmodel->parameters);delete ys; 355 546 356 547 /*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; 358 549 count++; 359 550 … … 380 571 381 572 }/*}}}*/ 573 382 574 #else 383 575 void solutionsequence_schurcg(FemModel* femmodel){_error_("PETSc needs to be installed");}
Note:
See TracChangeset
for help on using the changeset viewer.