Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
Comment ça fonctionne

L'utilisation du TimeHistory est extrêmement simple.

À chaque itération, une valeur sera enregistrée pour chaque historique de valeurs. S'il n'y a pas d'enregistrement de valeur explicite lors d'une itération, un 0 sera enregistré. S'il y a deux valeurs enregistrées pendant une même itération pour un historique de valeurs, c'est la dernière valeur qui sera réellement enregistrée.

Historiquement, les historiques de valeurs étaient gérés uniquement par le processus 0. Aujourd'hui, ce n'est plus le cas. Chaque processus peut avoir son historique, avec une même clef. De plus, on peut lier un historique à un maillage. Ainsi, on peut avoir un historique par maillage, toujours avec la même clef.

Avertissement
Pour activer l'enregistrement en multi-processus, il est nécessaire de définir la variable d'environnement ARCANE_ENABLE_NON_IO_MASTER_CURVES=1.

GlobalTimeHistoryAdder

La première structure permettant de gérer des historiques de valeurs est le GlobalTimeHistoryAdder. Il permet d'ajouter des valeurs à un historique. Le "Global" signifie que les variables internes utilisées pour gérer cet historique sont globales, liées aux sous-domaines.

Admettons que l'on ai un maillage partagé dans quatre sous-domaines (SD0, SD1, SD2, SD3). Chaque maille possède une pression. On veut avoir, pour chaque itération, la pression moyenne de chaque sous-domaine. Et en plus, on veut avoir la pression moyenne de tout le domaines.

Utilisons comme clef : avg_pressure :

Chaque sous-domaine possède une pression moyenne et il y a une pression moyenne globale. L'image présente une seule itération : l'itération 0.

Pour obtenir un historique comme celui-ci, on peut faire comme ceci :

// Calcul de la moyenne des pressions du sous-domaine.
Real avg_pressure_subdomain = 0;
ENUMERATE_ (Cell, icell, mesh()->ownCells()) {
avg_pressure_subdomain += m_pressure[icell];
}
if (!mesh()->ownCells().empty()) {
avg_pressure_subdomain /= mesh()->ownCells().size();
}
ISubDomain* sd = subDomain();
IParallelMng* pm = parallelMng();
Integer my_rank = pm->commRank();
Integer nb_proc = pm->commSize();
// Calcul de la pression moyenne globale.
Real avg_pressure_global = pm->reduce(IParallelMng::eReduceType::ReduceSum, avg_pressure_subdomain);
avg_pressure_global /= nb_proc;
// Création de l'objet permettant d'ajouter des valeurs dans un historique des valeurs.
GlobalTimeHistoryAdder global_adder(sd->timeHistoryMng());
// Ajout de la valeur avg_pressure_subdomain dans l'historique "avg_pressure". Un historique par sous-domaine.
global_adder.addValue(TimeHistoryAddValueArg("avg_pressure", true, my_rank), avg_pressure_subdomain);
// Ajout de la valeur avg_pressure_global dans l'historique "avg_pressure". Historique global.
global_adder.addValue(TimeHistoryAddValueArg("avg_pressure"), avg_pressure_global);
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
Remarques
En interne, GlobalTimeHistoryAdder utilise la partie interne du ITimeHistoryMng passé en paramètre. L'objet GlobalTimeHistoryAdder peut donc être détruit sans problème.
Note
Pour utiliser GlobalTimeHistoryAdder, ne pas oublier d'importer les headers nécessaires :
#include <arcane/core/ITimeHistoryMng.h>
#include <arcane/core/GlobalTimeHistoryAdder.h>

Ce bout de code, s'il est appelé à toutes les itérations, permet d'obtenir les moyennes à chaque itération.

MeshTimeHistoryAdder

La seconde structure permettant de gérer des historiques de valeurs est le MeshTimeHistoryAdder. Comme la première structure, il permet d'ajouter des valeurs à un historique. Le "Mesh" signifie que les variables internes utilisées pour gérer cet historique sont liées au maillage souhaité. Donc, chaque maillage peut avoir une variable différente de même nom.

Reprenons l'exemple au-dessus mais avec deux maillages. Ces deux maillages sont réparties sur quatre sous-domaines. On veut avoir, pour chaque sous-domaine, la moyenne des pressions des mailles de chaque maillage. Mais on veut toujours, comme au-dessus, la pression moyenne de chaque sous-domaine.

Utilisons la même clef : avg_pressure :

On peut voir qu'en plus des avg_pressure de chaque sous-domaine et du globale, il y a des avg_pressure pour les deux maillages.

Voici un exemple de code pour réaliser ce calcul :

ISubDomain* sd = subDomain();
IParallelMng* pm = parallelMng();
Integer my_rank = pm->commRank();
Integer nb_proc = pm->commSize();
Integer nb_mesh = sd->meshes().size();
// Contiendra la moyenne des pressions du sous-domaine ("(2)" sur l'image).
Real avg_pressure_subdomain = 0;
// Contiendra la moyenne des pressions de tout le domaine ("(4)" sur l'image)
Real avg_pressure_global = 0;
// Pour chaque maillage.
for (auto mesh : sd->meshes()) {
// Contiendra la moyenne des pressions du sous-domaines et du maillage "mesh" ("(1)" sur l'image).
Real avg_pressure_subdomain_mesh = 0;
ENUMERATE_ (Cell, icell, mesh->ownCells()) {
avg_pressure_subdomain_mesh += m_pressure[icell];
}
if (!mesh->ownCells().empty()) {
avg_pressure_subdomain_mesh /= mesh->ownCells().size();
}
// Contiendra la moyenne des pressions de tout le domaine et du maillage "mesh" ("(3)" sur l'image).
Real avg_pressure_global_mesh = pm->reduce(IParallelMng::eReduceType::ReduceSum, avg_pressure_subdomain_mesh);
avg_pressure_global_mesh /= nb_proc;
// Création de l'objet permettant d'ajouter des valeurs dans un historique des valeurs lié au maillage "mesh".
MeshTimeHistoryAdder mesh_adder(sd->timeHistoryMng(), mesh->handle());
// Ajout de la valeur avg_pressure_subdomain_mesh dans l'historique "avg_pressure" lié au maillage "mesh".
// Un historique par sous-domaine.
mesh_adder.addValue(TimeHistoryAddValueArg("avg_pressure", true, my_rank), avg_pressure_subdomain_mesh);
// Ajout de la valeur avg_pressure_global dans l'historique "avg_pressure" lié au maillage "mesh".
// Historique global.
mesh_adder.addValue(TimeHistoryAddValueArg("avg_pressure"), avg_pressure_global_mesh);
avg_pressure_subdomain += avg_pressure_subdomain_mesh;
avg_pressure_global += avg_pressure_global_mesh;
}
if (nb_mesh != 0) {
avg_pressure_subdomain /= nb_mesh;
avg_pressure_global /= nb_mesh;
}
// Création de l'objet permettant d'ajouter des valeurs dans un historique des valeurs.
GlobalTimeHistoryAdder global_adder(sd->timeHistoryMng());
// Ajout de la valeur avg_pressure_subdomain dans l'historique "avg_pressure". Un historique par sous-domaine.
global_adder.addValue(TimeHistoryAddValueArg("avg_pressure", true, my_rank), avg_pressure_subdomain);
// Ajout de la valeur avg_pressure_global dans l'historique "avg_pressure". Historique global.
global_adder.addValue(TimeHistoryAddValueArg("avg_pressure"), avg_pressure_global);

La différence ici, c'est qu'on itère sur les maillages. Pour créer le MeshTimeHistoryAdder, on doit donner, en plus d'un ITimeHistoryMng*, un handle de maillage. Ça permet de lier l'historique au maillage.

Remarques
En interne, MeshTimeHistoryAdder utilise la partie interne du ITimeHistoryMng passé en paramètre. L'objet MeshTimeHistoryAdder peut donc être détruit sans problème.
Note
Pour utiliser MeshTimeHistoryAdder, ne pas oublier d'importer les headers nécessaires :
#include <arcane/core/ITimeHistoryMng.h>
#include <arcane/core/MeshTimeHistoryAdder.h>
Le TimeHistoryMng gère les checkpoints, l'utilisateur n'a donc pas à s'en occuper.