Pourquoi mon solveur linéaire itératif ne converge-t-il pas?

26

Qu'est-ce qui peut mal tourner lors de l'utilisation de méthodes Krylov précondonifiées du KSP ( package de solveur linéaire de PETSc ) pour résoudre un système linéaire clairsemé tel que ceux obtenus en discrétisant et en linéarisant des équations différentielles partielles?

Quelles mesures puis-je prendre pour déterminer ce qui ne va pas pour mon problème?

Quels changements puis-je apporter pour résoudre avec succès et efficacité mon système linéaire?

Jed Brown
la source
Avez-vous l'intention que cette question soit une question sur les solveurs linéaires itératifs spécifiquement dans PETSc (qui est ce que j'aurais recueilli à partir du texte du corps de la question), ou d'être une question sur les défaillances algorithmiques potentielles des solveurs linéaires itératifs dans un logiciel principalement- contexte agnostique (qu'est-ce que j'aurais compris en regardant le titre seul)?
Geoff Oxberry
4
Il a la petscbalise. La méthodologie est générale, mais je pense que la réponse serait moins utile si chaque "essayez ceci" n'incluait pas également le "comment". Alternativement, le "comment" devrait être beaucoup plus long (et plus sujet aux erreurs pour le spectateur) s'il devait être expliqué de manière indépendante du logiciel. Si quelqu'un veut expliquer comment faire toutes ces choses en utilisant un package différent, je serai ravi de rendre la question indépendante du logiciel et de changer ma réponse pour indiquer qu'elle décrit ce qu'il faut faire dans PETSc. Remarque: J'ai ajouté ceci, qui est une version améliorée d'une FAQ, donc je pourrais aimer les gens sur ce site.
Jed Brown

Réponses:

26

Conseil initial

  • Exécutez toujours avec -ksp_converged_reason -ksp_monitor_true_residuallorsque vous essayez de comprendre pourquoi une méthode ne converge pas.
  • Réduisez la taille du problème et le nombre de processus pour démontrer l'échec. Vous obtenez souvent un aperçu en déterminant quels petits problèmes présentent le comportement qui provoque la panne de votre méthode et le temps d'exécution est réduit. De plus, certaines techniques d'investigation ne peuvent être utilisées que pour les petits systèmes.
  • Si le problème ne survient qu'après un grand nombre d'étapes de temps, d'étapes de continuation ou d'étapes de résolution non linéaire, envisagez d'écrire l'état du modèle en cas d'échec afin de pouvoir expérimenter rapidement.
  • Alternativement, surtout si votre logiciel n'a pas de capacité de point de contrôle, utilisez -ksp_view_binaryou MatView()pour enregistrer le système linéaire, puis utilisez le code à $PETSC_DIR/src/ksp/ksp/examples/tutorials/ex10.cpour lire dans la matrice et le résoudre (éventuellement avec un nombre différent de processus). Cela nécessite une matrice assemblée, donc son utilité peut être quelque peu limitée.
  • Il existe de nombreux choix de solveurs possibles (par exemple, un nombre infini disponible sur la ligne de commande dans PETSc en raison d'un nombre arbitraire de niveaux de composition), voir cette question pour des conseils généraux sur le choix de solveurs linéaires.

Raisons courantes pour lesquelles KSP ne converge pas

  • Les équations sont singulières par accident (par exemple, ont oublié d'imposer des conditions aux limites). Vérifiez ceci pour un petit problème d'utilisation -pc_type svd -pc_svd_monitor. Essayez également un solveur direct avec -pc_type lu(via un package tiers en parallèle, par exemple -pc_type lu -pc_factor_mat_solver_package superlu_dist).
  • Les équations sont intentionnellement singulières (par exemple un espace nul constant), mais la méthode de Krylov n'a pas été informée, voir KSPSetNullSpace().
  • Les équations sont intentionnellement singulières et ont KSPSetNullSpace()été utilisées, mais le côté droit n'est pas cohérent. Vous devrez peut-être appeler MatNullSpaceRemove()sur le côté droit avant d'appeler KSPSolve().
  • Les équations sont indéfinies afin que les préconditionneurs standard ne fonctionnent pas. Habituellement, vous le saurez par la physique, mais vous pouvez vérifier avec -ksp_compute_eigenvalues -ksp_gmres_restart 1000 -pc_type none. Pour les problèmes de point de selle simples, essayez -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_detect_saddle_point. Voir le manuel de l'utilisateur et la page de manuel PCFIELDSPLIT pour plus de détails. Pour les problèmes plus difficiles, lisez la littérature pour trouver des méthodes robustes et demandez ici (ou [email protected]ou [email protected]) si vous souhaitez des conseils sur la façon de les mettre en œuvre. Par exemple, voir cette question pour Helmholtz haute fréquence. Pour les tailles de problème modestes, voyez si vous pouvez vivre avec simplement en utilisant un solveur direct.
  • Si la méthode converge en résidu préconditionné, mais pas en résidu vrai, le préconditionneur est probablement singulier ou presque. Ceci est courant pour les problèmes de point de selle (par exemple, écoulement incompressible) ou les opérateurs fortement asymétriques (par exemple, les problèmes hyperboliques à faible Mach avec de grands pas de temps).
  • Le préconditionneur est trop faible ou instable. Voir si -pc_type asm -sub_pc_type luaméliore le taux de convergence. Si GMRES perd trop de progrès dans le redémarrage, voyez si un redémarrage plus long aide -ksp_gmres_restart 300. Si une transposition est disponible, essayez d' -ksp_type bcgsautres méthodes qui ne nécessitent pas de redémarrage. (Notez que la convergence avec ces méthodes est souvent erratique.)
  • La matrice de préconditionnement peut ne pas être proche de l'opérateur (éventuellement non assemblé). Essayez de résoudre avec un solveur direct, soit en série avec -pc_type luou en parallèle en utilisant un package tiers (par exemple -pc_type lu -pc_factor_mat_solver_package superlu_dist, ou mumps). La méthode doit converger en une seule itération si les matrices sont les mêmes, et en un "petit" nombre d'itérations sinon. Essayez -snes_type testde vérifier les matrices si vous résolvez un problème non linéaire.
  • Le préconditionneur est non linéaire (par exemple une résolution itérative imbriquée), essayez -ksp_type fgmres or -ksp_type gcr.
  • Vous utilisez une multigrille géométrique, mais certaines équations (souvent les conditions aux limites) ne sont pas mises à l'échelle de manière compatible entre les niveaux. Essayez -pc_mg_galerkinde construire algébriquement un opérateur grossier correctement mis à l'échelle ou assurez-vous que toutes les équations sont mises à l'échelle de la même manière si vous souhaitez utiliser des niveaux grossiers rediscrétisés.
  • La matrice est très mal conditionnée. Vérifiez le numéro de condition en utilisant les méthodes décrites ici . Essayez de l'améliorer en choisissant l'échelle relative des composants / conditions aux limites. Essayez -ksp_diagonal_scale -ksp_diagonal_scale_fix. Peut-être changer la formulation du problème pour produire des équations algébriques plus amicales. Si vous ne pouvez pas corriger l'échelle, vous devrez peut-être utiliser un solveur direct.
  • La matrice est non linéaire (par exemple évaluée en utilisant une différenciation finie d'une fonction non linéaire). Essayez différents paramètres de différenciation (par exemple -mat_mffd_type ds). Essayez d' utiliser une plus grande précision pour rendre la differentiation plus précise, ./configure --with-precision=__float128 --download-f2cblaslapack. Vérifiez s'il converge dans des régimes de paramètres "plus faciles".
  • Une méthode symétrique est utilisée pour un problème non symétrique.
  • Gram-Schmidt classique devient instable, essayez -ksp_gmres_modifiedgramschmidtou utilisez une méthode qui orthogonalise différemment, par exemple -ksp_type gcr.
Jed Brown
la source
16

Mon conseil aux étudiants est d'essayer un solveur direct dans ces cas. La raison en est qu'il existe deux classes de raisons pour lesquelles un solveur peut ne pas converger: (i) la matrice est incorrecte, ou (ii) il y a un problème avec le solveur / préconditionneur. Les solveurs directs produisent presque toujours quelque chose que vous pouvez comparer à la solution que vous attendez, donc si la réponse du solveur direct semble correcte, alors vous savez que le problème vient du solveur / précondition itératif. D'un autre côté, si la réponse semble incorrecte, le problème est lié à l'assemblage de la matrice et du côté droit.

J'utilise généralement simplement UMFPACK comme solveur direct. Je suis sûr qu'il est simple d'essayer quelque chose de similaire avec PETSC.

Wolfgang Bangerth
la source
5
-pc_type lu -pc_factor_mat_solver_type umfpackpour utiliser UMFPACK (ou -pc_type cholesky -pc_factor_mat_solver_package cholmodpour des problèmes SPD) via PETSc, mais notez que UMFPACK et CHOLMOD sont en série. Pour parallèle, l' utilisation -pc_factor_mat_solver_package superlu_distou mumps, pastix, spooles.
Jed Brown
2
Juste pour être clair, l'ensemble complet d'options pour l'utilisation (par exemple) superlu_distserait -ksp_type preonly -pc_type lu -pc_factor_mat_solver_package superlu_dist. Est-ce correct?
Leon Avery
Je ne sais pas. Que se passe-t-il si vous faites cela?
Wolfgang Bangerth