Il est fastidieux pour l'utilisateur de spécifier chaque aspect d'un algorithme. Si l'algorithme autorise les composants imbriqués, aucun nombre fini d'options ne serait suffisant. Par conséquent, il est essentiel que les options ne remontent pas nécessairement au niveau supérieur, comme dans le cas d'arguments explicites ou de paramètres de modèle. C'est ce qu'on appelle parfois le «problème de configuration» en génie logiciel. Je crois que PETSc dispose d'un système unique et puissant pour la gestion de la configuration. Il est similaire au modèle Service Locator dans l'essai de Martin Fowler sur l'inversion de contrôle .
Le système de configuration de PETSc fonctionne grâce à une combinaison de configurations spécifiées par l'utilisateur gérées par les objets du solveur (avec des requêtes get et set) et la base de données d'options. Tout composant de la simulation peut déclarer une option de configuration, une valeur par défaut et un emplacement pour placer le résultat. Les objets imbriqués ont des préfixes qui peuvent être composés, de sorte que chaque objet nécessitant une configuration peut être adressé indépendamment. Les options elles-mêmes peuvent être lues à partir de la ligne de commande, de l'environnement, des fichiers de configuration ou du code. Lorsqu'une option est déclarée, une chaîne d'aide et une page de manuel sont spécifiées, afin que l' -help
option soit compréhensible et pour qu'une interface graphique correctement liée puisse être écrite.
L'utilisateur appelle une SetFromOptions
méthode pour configurer un objet lui-même en fonction des options de ligne de commande. L'appel de cette fonction est facultatif et peut ne pas être appelé si l'utilisateur (personne qui écrit du code qui appelle PETSc) expose les options via une autre interface. Nous recommandons fortement à l'utilisateur d'exposer la base de données d'options car cela donne à l'utilisateur final (personne exécutant l'application) beaucoup de pouvoir, mais ce n'est pas nécessaire.
Une configuration typique, appelée via
PetscObjectOptionsBegin(object); /* object has prefix and descriptive string */
PetscOptionsReal("-ts_atol", /* options database key */
"Absolute tolerance for local truncation error", /* long description */
"TSSetTolerances", /* function and man page on topic */
ts->atol, /* current/default value *?
&ts->atol, /* place to store value */
&option_set); /* TRUE if the option was set */
PetscOptionsList("-ts_type","Time stepping method","TSSetType",TSList,
defaultType,typeName,sizeof typeName,&option_set);
TSAdaptSetFromOptions(ts->adapt); /* configures adaptive controller method */
/* ... many others */
/* ... the following is only called from implicit implementations */
SNESSetFromOptions(ts->snes); /* configure nonlinear solver. */
PetscOptionsEnd();
Remarques:
PetscOptionsList()
présente à l'utilisateur un choix dans une liste dynamique. Il existe une architecture de plugin que les nouvelles implémentations peuvent utiliser pour s'exposer en tant que première classe aux appelants. (Ces implémentations peuvent être placées dans des bibliothèques partagées et utilisées comme première classe sans recompiler les programmes.)
SNESSetFromOptions()
configure récursivement les solveurs linéaires, les préconditionneurs et tous les autres composants qui nécessitent une configuration.