Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
PreciseOutputChecker.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* Outputs based on time (physical or CPU) or a number of iterations. */
11/*---------------------------------------------------------------------------*/
12
13#include "arcane/core/PreciseOutputChecker.h"
14
15/*---------------------------------------------------------------------------*/
16/*---------------------------------------------------------------------------*/
17
18namespace Arcane
19{
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
26{
27 m_output_period_physical_time = output_period;
28}
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
32
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 // Update of the output period in the case of a marching table
66 if (m_table_values_physical_time != nullptr) {
67 m_table_values_physical_time->value(current_time, m_output_period_physical_time);
68 }
69 // Check on exact time
70 if (!output_requested) {
71 output_requested = _checkTime(old_time, current_time, m_output_period_physical_time);
72 }
73 // Check on time interval
74 if (!output_requested) {
75 output_requested = _checkTimeInterval(old_time, current_time, m_output_period_physical_time);
76 }
77
78 // Check on iterations
79 if (!output_requested) {
80 // Update of the output frequency for marching tables
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 // Exact check
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 // We must check that due to truncation errors, we do not end up in a
107 // case where the output was already performed at an exact output in
108 // the previous iteration.
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 // Then we reconstruct the output time:
129 Real prev_output_time_round = current_number_of_outputs * output_period;
130 // And we check if the previous time step leads to an output
131 bool old_time_output_requested = _compareTime(old_time, prev_output_time_round);
132 // If yes, we cancel the output
133 if (old_time_output_requested) {
134 output_requested = false;
135 }
136 }
137
138 // We check the upper bound for overlaps
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 // Then we reconstruct the output time:
143 Real prev_output_time_ceil = prev_number_of_outputs_ceil * output_period;
144 // And we check if the previous time step leads to an output
145 bool old_time_output_requested = _compareTime(old_time, prev_output_time_ceil);
146 // If yes, we cancel the 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 of the time interval in which the code is located.
165 // To know the number of outputs already performed in a fixed period,
166 // we take the floor and ceiling conversion.
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 // Then we reconstruct the output time:
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 // The following two blocks constitute a FIX:
176 // we must check that the previous time does not lead to an output time
177 // to cancel the output request if so.
178 // Otherwise, rounding errors in the exact comparison
179 // can lead to considering several times
180 // as part of the requested output time (e.g., if t=1e-7 and dt=1e-15,
181 // then the relative comparison of comparTime will give several valid times,
182 // leading to...). The comparison is made on the upper and
183 // lower bounds to remove uncertainty in the case where dt=output time.
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 // If the relative difference between the times is < 1e-7 (i.e., the precision
209 // related to the division), then we consider
210 // that the requested time corresponds to the output time.
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/*---------------------------------------------------------------------------*/
bool checkIfOutput(double old_time, double current_time, Integer current_iteration)
Indicates whether or not an output should be made.
void initializeOutputPhysicalTime(double output_period)
__host__ __device__ double floor(double v)
Round v down to the immediately lower integer.
Definition Math.h:100
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.