Arcane  v3.16.7.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcanePostProcessingModule.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* ArcanePostProcessingModule.cc (C) 2000-2025 */
9/* */
10/* Module de post-traitement. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Ptr.h"
15#include "arcane/utils/List.h"
16
17#include "arcane/core/EntryPoint.h"
18#include "arcane/core/ISubDomain.h"
19#include "arcane/core/IVariableMng.h"
20#include "arcane/core/IParallelMng.h"
21#include "arcane/core/ItemGroup.h"
22#include "arcane/core/Directory.h"
23#include "arcane/core/ITimeHistoryMng.h"
24#include "arcane/core/ServiceUtils.h"
25#include "arcane/core/IPostProcessorWriter.h"
26#include "arcane/core/MeshAccessor.h"
27#include "arcane/core/IMesh.h"
28#include "arcane/core/VariableTypes.h"
29#include "arcane/core/CommonVariables.h"
31#include "arcane/core/ITimeLoopMng.h"
33#include "arcane/core/ModuleFactory.h"
34#include "arcane/core/Timer.h"
35#include "arcane/core/VariableCollection.h"
36#include "arcane/core/OutputChecker.h"
37#include "arcane/core/IExternalPlugin.h"
38
39#include "arcane/std/ArcanePostProcessing_axl.h"
40
41#include <set>
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46namespace Arcane
47{
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
59class ArcanePostProcessingModule
60: public ArcaneArcanePostProcessingObject
61{
62 public:
63
64 explicit ArcanePostProcessingModule(const ModuleBuildInfo& mbi);
65 ~ArcanePostProcessingModule() override;
66
67 public:
68
69 VersionInfo versionInfo() const override { return VersionInfo(0, 1, 2); }
70
71 public:
72
73 void exportData() override;
74 void exportDataStart() override;
75
76 void postProcessingStartInit() override;
77 void postProcessingInit() override;
78 void postProcessingExit() override;
79
80 private:
81
82 OutputChecker m_output_checker;
83 OutputChecker m_history_output_checker;
85 bool m_is_output_active = true;
89 bool m_output_dir_created = false;
90 VariableList m_variables;
93 bool m_is_plugin_initialized = false;
94
95 private:
96
97 void _readConfig();
98 void _saveAtTime(Real);
99
100 void _checkCreateOutputDir();
103 void _checkExternalPlugin();
104};
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109ARCANE_REGISTER_MODULE_ARCANEPOSTPROCESSING(ArcanePostProcessingModule);
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114ArcanePostProcessingModule::
115ArcanePostProcessingModule(const ModuleBuildInfo& mbi)
117, m_output_checker(mbi.subDomain(),"PostProcessing")
118, m_history_output_checker(mbi.subDomain(),"PostProcessingHistory")
119, m_times(VariableBuilder(this,"ExportTimes"))
120{
121 m_output_checker.assignIteration(&m_next_iteration,&options()->outputPeriod);
122 m_output_checker.assignGlobalTime(&m_next_global_time,&options()->outputFrequency);
123
124 m_history_output_checker.assignIteration(&m_history_next_iteration,&options()->outputHistoryPeriod);
125 m_post_processor_timer = new Timer(mbi.subDomain(),"PostProcessorTimer",Timer::TimerReal);
126}
127
128/*---------------------------------------------------------------------------*/
129/*---------------------------------------------------------------------------*/
130
131ArcanePostProcessingModule::
132~ArcanePostProcessingModule()
133{
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
142{
143 Integer nb_var = options()->output().variable.size();
144 Integer nb_group = options()->output().group.size();
145
146 IVariableMng* var_mng = subDomain()->variableMng();
148
149 if (nb_var!=0){
150 std::set<String> used_variables; // Liste des variables déjà indiquées
151 m_variables.clear();
152 info() << " ";
153 info() << "-- List of output variables (" << nb_var << " variables):";
154 for( Integer i=0; i<nb_var; ++i ){
155 String varname(options()->output().variable[i]);
156 IVariable* var = var_mng->findMeshVariable(defaultMesh(),varname);
157 if (!var)
158 ARCANE_FATAL("PostTreatment: no variable with name '{0}' exists",varname);
159 eItemKind ik = var->itemKind();
160 if (ik!=IK_Node && ik!=IK_Edge && ik!=IK_Face && ik!=IK_Cell)
161 ARCANE_FATAL("PostTreatment: variable ({0}) must"
162 " be a mesh variable (node, edge, face or cell)",varname);
163
164 if (used_variables.find(varname)==used_variables.end()){
165 info() << "Variable <" << varname << ">";
166 m_variables.add(var);
167 used_variables.insert(varname);
169 }
170 else{
171 warning() << "Variable <" << varname << "> required twice during post-processing analysis";
172 }
173 }
174 }
175 else
176 m_is_output_active = false;
177
178 if (nb_group!=0){
179 std::set<String> used_groups; // Liste des groupes déjà indiquées
180 //m_group_list.resize(nb_group);
181 info() << " ";
182 info() << "-- List of output groups (" << nb_group << " groups):";
183 for( Integer i=0; i<nb_group; ++i ){
184 ItemGroup group = options()->output().group[i];
185 if (group.null())
186 continue;
187 String groupname = group.name();
188 if (used_groups.find(groupname)==used_groups.end()){
189 info() << "Group <" << groupname << ">";
190 used_groups.insert(groupname);
191 m_groups.add(group);
192 }
193 else
194 warning() << "Group <" << groupname << "> required twice during post-processing analysis";
195 }
196 //m_group_list.resize(index);
197 }
198 else{
199 // Si aucun groupe spécifié, sauve uniquement l'ensemble des mailles.
200 //m_groups.resize(1);
201
203 if (mesh->isAmrActivated())
204 m_groups.add(mesh->allActiveCells());
205 else
206 m_groups.add(mesh->allCells());
207 }
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213void ArcanePostProcessingModule::
214_checkCreateOutputDir()
215{
217 return;
218 m_output_directory = Directory(subDomain()->exportDirectory(),"depouillement");
221}
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
225
226void ArcanePostProcessingModule::
227postProcessingInit()
228{
229 info() << " -------------------------------------------";
230 info() << "| POST PROCESSING |";
231 info() << " -------------------------------------------";
232 info() << " ";
233
234 bool is_continue = subDomain()->isContinue();
235
236 info() << "Variables output:";
237 m_output_checker.initialize(is_continue);
238
239 info() << "History output:";
240 m_history_output_checker.initialize(is_continue);
241
242 _readConfig();
243
244 // Positionnement de l'option 'shrink' du timeHistoryMng depuis l'axl
245 if (options()->outputHistoryShrink)
246 subDomain()->timeHistoryMng()->setShrinkActive(options()->outputHistoryShrink);
247
248 // initialize parameter with a dry call to checker
250 const Real old_time = vc.globalOldTime();
251 const Real current_time = vc.globalTime();
252 m_output_checker.check(old_time, current_time, vc.globalIteration(), 0);
253 m_history_output_checker.check(old_time, current_time, vc.globalIteration(), 0);
254
255 if (options()->saveInit())
256 _saveAtTime(current_time);
257}
258
259/*---------------------------------------------------------------------------*/
260/*---------------------------------------------------------------------------*/
261
262void ArcanePostProcessingModule::
263postProcessingStartInit()
264{
265 m_next_global_time = 0.0;
267 m_curves_next_global_time = 0.0;
268 m_curves_next_iteration = 0;
269 m_history_next_iteration = 0;
270}
271
272/*---------------------------------------------------------------------------*/
273/*---------------------------------------------------------------------------*/
284{
285 const Real current_time = subDomain()->commonVariables().globalTime();
286 bool save_at_exit = false;
287 if (subDomain()->timeLoopMng()->finalTimeReached())
288 save_at_exit = options()->saveFinalTime();
289 if (!save_at_exit)
290 save_at_exit = options()->endExecutionOutput();
291 if (save_at_exit){
292 _saveAtTime(current_time);
293 }
294
295 // Affiche les statistiques d'exécutions
296 Real total_time = m_post_processor_timer->totalTime();
297 info() << "Total time for post-processing analysis output (second): " << total_time;
298 Integer nb_time = m_post_processor_timer->nbActivated();
299 if (nb_time!=0)
300 info() << "Average time per output (second): " << total_time / nb_time
301 << " (for " << nb_time << " outputs";
302 IPostProcessorWriter* post_processor = options()->format();
303 if (post_processor)
304 post_processor->close();
305}
306
307/*---------------------------------------------------------------------------*/
308/*---------------------------------------------------------------------------*/
314{
316 const Real current_time = subDomain()->commonVariables().globalTime();
317 _saveAtTime(current_time);
318 }
319}
320
321/*---------------------------------------------------------------------------*/
322/*---------------------------------------------------------------------------*/
328{
329 ISubDomain* sd = subDomain();
330 const CommonVariables& vc = sd->commonVariables();
331
332 const Int32 global_iteration = vc.globalIteration();
333 // Écrit les valeurs du dépouillement pour l'initialisation.
334 if (global_iteration == 0)
335 _saveAtTime(0.0);
336
338
339 // Regarde s'il faut activer les historiques pour cette itération
340 const Real old_time = vc.globalOldTime();
341 const Real current_time = vc.globalTime();
342 bool do_history_output = m_history_output_checker.check(old_time, current_time, global_iteration, 0);
343 sd->timeHistoryMng()->setActive(do_history_output);
344
345 // Regarde si des sorties de post-traitement sont prévues pour cette itération
346 if (m_is_output_active) {
347 bool do_at_current_iteration = m_output_checker.check(old_time, current_time, global_iteration, 0);
348 if (do_at_current_iteration)
350 }
351}
352
353/*---------------------------------------------------------------------------*/
354/*---------------------------------------------------------------------------*/
355
356void ArcanePostProcessingModule::
357_saveAtTime(Real saved_time)
358{
360
361 const Int32 size = m_times.size();
362
364
365 // Ne sauvegarde pas si le temps actuel est le même que le précédent
366 // (Sinon ca fait planter Ensight...)
367 if (size!=0 && math::isEqual(m_times[size-1],saved_time))
368 return;
369
370 m_times.resize(size+1);
371 m_times[size] = saved_time;
372
373 _checkCreateOutputDir();
374
375 if (m_is_output_active) {
376 IPostProcessorWriter* post_processor = options()->format();
378 post_processor->setTimes(m_times);
379 post_processor->setVariables(m_variables);
380 post_processor->setGroups(m_groups);
381 info() << " ";
382 info() << "**** Output in progress at time " << saved_time <<" ******";
383
384 {
386 _checkExternalPlugin();
387 vm->writePostProcessing(post_processor);
388 }
389 }
390}
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
399{
401 for (VariableList::Enumerator v_iter(m_variables); ++v_iter;) {
402 IVariable* v = *v_iter;
404 }
405}
406
407/*---------------------------------------------------------------------------*/
408/*---------------------------------------------------------------------------*/
414{
416 for (VariableList::Enumerator v_iter(m_variables); ++v_iter;) {
417 IVariable* v = *v_iter;
419 }
420}
421
422/*---------------------------------------------------------------------------*/
423/*---------------------------------------------------------------------------*/
424
425void ArcanePostProcessingModule::
426_checkExternalPlugin()
427{
428 // Mode expérimental pour utiliser une fonction python.
429 // Il faut que wrapper C# soit actif et que le module 'pythonnet' soit installé.
430 auto& plugin_option = options()->experimentalPythonPlugin;
431 if (!plugin_option.isPresent())
432 return;
433 IExternalPlugin* p = plugin_option.externalPlugin();
434 String function = plugin_option.functionName();
435 info() << "Executing Python function '" << function << "'";
436 if (!m_is_plugin_initialized){
437 info() << "Initializing Python environment";
438 p->loadFile(String{});
439 m_is_plugin_initialized = true;
440 }
441 p->executeContextFunction(function);
442}
443
444/*---------------------------------------------------------------------------*/
445/*---------------------------------------------------------------------------*/
446
447} // End namespace Arcane
448
449/*---------------------------------------------------------------------------*/
450/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
Fonctions mathématiques diverses.
Generation de la classe de base du Module.
CaseOptionsArcanePostProcessing * options() const
Options du jeu de données du module.
Arcane::VariableScalarInteger m_next_iteration
Variables du module.
ISubDomain * subDomain() const override
Sous-domaine associé au module.
IMesh * defaultMesh() const override
Maillage par défaut pour ce module.
Module de sortie pour le dépouillement.
Timer * m_post_processor_timer
Timer pour le temps passé à écrire.
bool m_output_dir_created
true si répertoire créé.
VariableArrayReal m_times
Instants de temps des sauvegardes.
void _markCurrentIterationPostProcessing()
Marque les variables comme étant post-processées lors de cette itération.
VariableList m_variables
Liste des variables a exporter.
bool m_is_output_at_current_iteration
Indique si on réalise des sorties lors de cette itération.
void _resetCurrentIterationPostProcessing()
Supprime les tags des variables post-processées lors de cette itération.
void exportData() override
Vérifie et écrit les valeurs pour le dépouillement.
void postProcessingExit() override
Informations de dépouillement en sortie de la boucle de calcul.
ItemGroupList m_groups
Liste des groupes à exporter.
void exportDataStart() override
Point d'entrée en début d'itération.
VersionInfo versionInfo() const override
Version du module.
Directory m_output_directory
Répertoire de sortie.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
Variables communes d'un cas.
Real globalTime() const
Temps courant.
Int32 globalIteration() const
Numéro de l'itération courante.
CommonVariables(IModule *c)
Construit les références des variables communes pour le module c.
Real globalOldTime() const
Temps courant précédent.
Classe gérant un répertoire.
Definition Directory.h:35
bool createDirectory() const override
Créé le répertoire.
Definition Directory.cc:102
String path() const override
Retourne le chemin du répertoire.
Definition Directory.cc:111
Interface du service de chargement de services externes.
virtual void executeContextFunction(const String &function_name)=0
Exécute la fonction function_name avec un contexte.
virtual void loadFile(const String &filename)=0
Charge et exécute un fichier contenant un script externe.
Interface d'un écrivain pour les informations de post-traitement.
virtual void setVariables(VariableCollection variables)=0
Positionne la liste des variables à sortir.
virtual void setTimes(RealConstArrayView times)=0
Positionne la liste des temps.
virtual void close()=0
Ferme l'écrivain. Après fermeture, il ne peut plus être utilisé
virtual void setGroups(ItemGroupCollection groups)=0
Positionne la liste des groupes à sortir.
virtual void setBaseDirectoryName(const String &dirname)=0
Positionne le nom du répertoire de sortie des fichiers. Ce répertoire doit exister.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual const CommonVariables & commonVariables() const =0
Informations sur les variables standards.
virtual IMesh * defaultMesh()=0
Maillage par défaut.
virtual bool isContinue() const =0
Vrai si on effectue une reprise, faux sinon.
virtual ITimeHistoryMng * timeHistoryMng()=0
Retourne le gestionnaire d'historique.
virtual IVariableMng * variableMng()=0
Retourne le gestionnaire de variables.
virtual void setShrinkActive(bool is_active)=0
Positionne le booléen indiquant si l'historique est compressé
virtual void setActive(bool is_active)=0
Positionne l'état d'activation.
Interface du gestionnaire de variables.
virtual IVariable * findMeshVariable(IMesh *mesh, const String &name)=0
Retourne la variable du maillage de nom name ou 0 si aucune de se nom existe.
virtual void writePostProcessing(IPostProcessorWriter *writer)=0
Ecrit les variables pour un post-traitement.
Interface d'une variable.
Definition IVariable.h:39
virtual void addTag(const String &tagname, const String &tagvalue)=0
Ajoute le tag tagname avev la valeur tagvalue.
virtual eItemKind itemKind() const =0
Genre des entités du maillage sur lequel repose la variable.
static const char * TAG_POST_PROCESSING
Tag utilisé pour indiquer si une variable sera post-traitée.
Definition IVariable.h:150
virtual void removeTag(const String &tagname)=0
Supprime le tag tagname.
static const char * TAG_POST_PROCESSING_AT_THIS_ITERATION
Tag utilisé pour indiquer si une variable sera post-traitée à cette itération.
Definition IVariable.h:153
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
Informations pour construire un module.
ISubDomain * subDomain() const
Accès au sous-domaine associé
Gère les sorties basées sur un temps physique, temps CPU ou un nombre d'itération.
bool check(Real old_time, Real current_time, Integer current_iteration, Integer current_cpu_time, const String &from_function=String())
Vérifie s'il faut effectuer une sortie.
Chaîne de caractères unicode.
Sentinelle pour le timer. La sentinelle associée à un timer permet de déclancher celui-ci au moment d...
Definition Timer.h:89
Gestion d'un timer.
Definition Timer.h:62
@ TimerReal
Timer utilisant le temps réel.
Definition Timer.h:76
TraceMessage info() const
Flot pour un message d'information.
TraceMessage warning() const
Flot pour un message d'avertissement.
virtual void resize(Integer new_size)
Redimensionne le tableau pour contenir new_size éléments.
Informations sur une version.
Definition VersionInfo.h:46
constexpr Integer size() const noexcept
Retourne la taille du tableau.
VariableRefArrayT< Real > VariableArrayReal
Variable tableau de type réels.
constexpr __host__ __device__ bool isEqual(const _Type &a, const _Type &b)
Teste l'égalité bit à bit entre deux valeurs.
Definition Numeric.h:253
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Int32 Integer
Type représentant un entier.
List< ItemGroup > ItemGroupList
Tableau de groupes d'éléments du maillage.
eItemKind
Genre d'entité de maillage.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
double Real
Type représentant un réel.
std::int32_t Int32
Type entier signé sur 32 bits.