Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
PreciseOutputChecker.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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/* PreciseOutputChecker.cc (C) 2000-2020 */
9/* */
10/* Sorties basées sur un temps (physique ou CPU) ou un nombre d'itération. */
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/PreciseOutputChecker.h"
14
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18namespace Arcane
19{
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
25initializeOutputPhysicalTime(Real output_period)
26{
27 m_output_period_physical_time = output_period;
28}
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
34initializeOutputPhysicalTime(ICaseFunction* output_table)
35{
36 m_table_values_physical_time = output_table;
37}
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42void PreciseOutputChecker::
43initializeOutputIteration(Integer output_period)
44{
45 m_output_period_iteration = output_period;
46}
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51void PreciseOutputChecker::
52initializeOutputIteration(ICaseFunction* output_table)
53{
54 m_table_values_iteration = output_table;
55}
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
61checkIfOutput(Real old_time, Real current_time, Integer current_iteration)
62{
63 bool output_requested = false;
64
65 //Mise à jour de la période de sortie dans le cas d'une table de marche
66 if (m_table_values_physical_time != nullptr) {
67 m_table_values_physical_time->value(current_time, m_output_period_physical_time);
68 }
69 //Contrôle sur le temps exact
70 if (!output_requested) {
71 output_requested = _checkTime(old_time, current_time, m_output_period_physical_time);
72 }
73 //Contrôle sur l'encadrement du temps
74 if (!output_requested) {
75 output_requested = _checkTimeInterval(old_time, current_time, m_output_period_physical_time);
76 }
77
78 //Contrôle sur les itérations
79 if (!output_requested) {
80 //Mise a jour de la fréquence de sortie pour les tables de marche
81 if (m_table_values_iteration != nullptr) {
82 m_table_values_iteration->value(current_iteration, m_output_period_iteration);
83 }
84 if (m_output_period_iteration > 0) {
85 //Contrôle exact
86 if (current_iteration % m_output_period_iteration == 0) {
87 output_requested = true;
88 }
89 }
90 }
91 return output_requested;
92}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97bool PreciseOutputChecker::
98_checkTimeInterval(Real old_time, Real current_time, Real output_period)
99{
100 bool output_requested = false;
101 if (output_period > 0) {
102 Integer number_of_previous_outputs = (int)floor(old_time / output_period);
103 Integer number_of_current_outputs = (int)floor(current_time / output_period);
104
105 if (number_of_previous_outputs != number_of_current_outputs) {
106 // Il faut vérifier qu'à cause des erreurs de troncature, on ne se
107 // retrouve pas sur un cas où la sortie aurrait déjà été réalisée sur
108 // une sortie exacte à l'itération précédente.
109 Integer number_of_previous_outputs_ceil = (int)ceil(old_time / output_period);
110 Real old_time_reconstruct = number_of_previous_outputs_ceil * output_period;
111 if ((old_time_reconstruct - old_time) > 1e-7 * old_time) {
112 output_requested = true;
113 }
114 }
115 }
116 return output_requested;
117}
118
119/*---------------------------------------------------------------------------*/
120/*---------------------------------------------------------------------------*/
121
122bool PreciseOutputChecker::
123_checkOldTime(Real old_time, Real output_period, Integer current_number_of_outputs)
124{
125 bool output_requested = true;
126 Integer prev_number_of_outputs_round = (int)floor(old_time / output_period);
127 if (prev_number_of_outputs_round == current_number_of_outputs) {
128 // Puis on reconstruit le temps de sortie :
129 Real prev_output_time_round = current_number_of_outputs * output_period;
130 // Et on contrôle si le pas de temps précédent conduit à un output
131 bool old_time_output_requested = _compareTime(old_time, prev_output_time_round);
132 // Si oui, on annule l'output
133 if (old_time_output_requested) {
134 output_requested = false;
135 }
136 }
137
138 // On vérifie la borne sup pour les recouvrements
139 if (output_requested) {
140 Integer prev_number_of_outputs_ceil = (int)ceil(old_time / output_period);
141 if (prev_number_of_outputs_ceil == current_number_of_outputs) {
142 // Puis on reconstruit le temps de sortie :
143 Real prev_output_time_ceil = prev_number_of_outputs_ceil * output_period;
144 // Et on contrôle si le pas de temps précédent conduit à un output
145 bool old_time_output_requested = _compareTime(old_time, prev_output_time_ceil);
146 // Si oui, on annule l'output
147 if (old_time_output_requested) {
148 output_requested = false;
149 }
150 }
151 }
152 return output_requested;
153}
154
155/*---------------------------------------------------------------------------*/
156/*---------------------------------------------------------------------------*/
157
158bool PreciseOutputChecker::
159_checkTime(Real old_time, Real current_time, Real output_period)
160{
161 bool output_requested = false;
162
163 if (output_period > 0) {
164 // Reconstruction de l'intervalle de temps dans lequel se trouve le code.
165 // Pour connaitre le nombre d'output déjà effectués en période fixe,
166 // on prend la conversion entière inf et sup.
167 Integer number_of_outputs_round = (int)floor(current_time / output_period);
168 Integer number_of_outputs_ceil = (int)ceil(current_time / output_period);
169 // Puis on reconstruit le temps de sortie:
170 Real next_output_time_round = number_of_outputs_round * output_period;
171 Real next_output_time_ceil = number_of_outputs_ceil * output_period;
172
173 output_requested = _compareTime(current_time, next_output_time_round);
174
175 // Les deux blocs suivants constituent un FIX :
176 // il faut vérifier que le temps précédent ne conduit pas à un temps de sortie
177 // pour annuler la demande de sortie si tel est le cas.
178 // Dans le cas contraire, les erreurs d'arrondis sur la comparaison exacte
179 // peuvent conduire à considérer plusieurs temps
180 // comme faisant parti du temps de sortie demandé (ex : si t=1e-7 et dt=1e-15,
181 // alors la comparaison relative de comparTime donnera plusieurs temps
182 // valides, conduisant à ...). La comparaison est faite sur les bornes sup et
183 // inf pour lever l'incertitude dans le cas ou dt=temps de sortie.
184 if (output_requested) {
185 output_requested = _checkOldTime(old_time, output_period, number_of_outputs_round);
186 }
187
188 if (!output_requested) {
189 output_requested = _compareTime(current_time, next_output_time_ceil);
190
191 if (output_requested) {
192 output_requested = _checkOldTime(old_time, output_period, number_of_outputs_ceil);
193 }
194 }
195 }
196
197 return output_requested;
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203bool PreciseOutputChecker::
204_compareTime(Real current_time, Real compar_time)
205{
206 bool output_requested = false;
207 if (compar_time > 0.0) {
208 // Si l'écart relatif entre les temps est < à 1e-7 (soit la précision
209 // liée à la division), alors on considère
210 // que le temps demandé correspond à celui de l'output.
211 if (((math::abs(current_time - compar_time))) < 1.0e-7 * compar_time) {
212 output_requested = true;
213 }
214 }
215 return output_requested;
216}
217
218/*---------------------------------------------------------------------------*/
219/*---------------------------------------------------------------------------*/
220
221} // namespace Arcane
222
223/*---------------------------------------------------------------------------*/
224/*---------------------------------------------------------------------------*/
virtual void value(Real param, Real &v) const =0
Valeur v de l'option pour le paramètre param.
bool checkIfOutput(double old_time, double current_time, Integer current_iteration)
Indique s'il faut ou non faire une sortie.
void initializeOutputPhysicalTime(double output_period)
__host__ __device__ double floor(double v)
Arondir v à l'entier immédiatement inférieur.
Definition Math.h:96
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
double Real
Type représentant un réel.
Int32 Integer
Type représentant un entier.