Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
VerifierService.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/* VerifierService.cc (C) 2000-2025 */
9/* */
10/* Base class for the data verification service. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/core/VerifierService.h"
15
16#include "arcane/utils/List.h"
17#include "arcane/utils/ITraceMng.h"
18#include "arcane/utils/OStringStream.h"
19
20#include "arcane/core/ServiceBuildInfo.h"
21#include "arcane/core/ISubDomain.h"
22#include "arcane/core/IVariable.h"
23#include "arcane/core/IParallelMng.h"
24#include "arcane/core/IVariableMng.h"
25#include "arcane/core/ArcaneException.h"
26#include "arcane/core/CommonVariables.h"
27#include "arcane/core/SerializeBuffer.h"
28#include "arcane/core/VariableCollection.h"
29#include "arcane/core/IMesh.h"
30#include "arcane/core/VariableComparer.h"
31
32#include <map>
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43VerifierService::
44VerifierService(const ServiceBuildInfo& sbi)
45: AbstractService(sbi)
46, m_sub_domain(sbi.subDomain())
47, m_service_info(sbi.serviceInfo())
48, m_file_name()
49{
50}
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
55IBase* VerifierService::
56serviceParent() const
57{
58 return m_sub_domain;
59}
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64void VerifierService::
65_getVariables(VariableCollection variables, bool parallel_sequential)
66{
67 ISubDomain* sd = subDomain();
68 IParallelMng* pm_sd = sd->parallelMng();
69 IVariableMng* vm = sd->variableMng();
70 VariableCollection used_vars = vm->usedVariables();
71
72 for (VariableCollection::Enumerator i(used_vars); ++i;) {
73 IVariable* variable = *i;
74 if (parallel_sequential) {
75 if (variable->property() & IVariable::PSubDomainDepend)
76 continue;
77 // Do not compare array variables during parallel/sequential comparisons
78 // because generally these variables are dependent on the decomposition.
79 if (variable->itemKind() == IK_Unknown)
80 continue;
81 // Do not compare variables whose mesh does not use the same
82 // parallelMng() as the subdomain. Indeed, in this case, it is not possible
83 // to make a sequential view of the mesh.
84 MeshHandle mesh_handle = variable->meshHandle();
85 if (mesh_handle.hasMesh()) {
86 IMesh* mesh = mesh_handle.mesh();
87 if (mesh->parallelMng() != pm_sd)
88 continue;
89 }
90 }
91 if (variable->property() & IVariable::PExecutionDepend)
92 continue;
93 variables.add(variable);
94 }
95}
96
97/*---------------------------------------------------------------------------*/
98/*---------------------------------------------------------------------------*/
99
100template <typename ReaderType> void VerifierService::
101_doVerif2(ReaderType reader, const VariableList& variables, bool compare_ghost)
102{
103 ISubDomain* sd = subDomain();
104 IParallelMng* pm = sd->parallelMng();
105 ITraceMng* trace = sd->traceMng();
106
107 OStringStream not_compared_str;
108 Integer nb_not_compared = 0;
109 Integer nb_compared = 0;
110
111 typedef std::map<String, DiffInfo> MapDiffInfos;
112 typedef std::map<String, DiffInfo>::value_type MapDiffInfosValues;
113 MapDiffInfos diff_infos;
114 VariableComparer variable_comparer;
115 VariableComparerArgs compare_args = variable_comparer.buildForCheckIfSame(reader);
116 compare_args.setMaxPrint(10);
117 compare_args.setComputeDifferenceMethod(m_compute_diff_method);
118 compare_args.setCompareGhost(compare_ghost);
119 {
120 for (VariableList::Enumerator i(variables); ++i;) {
121 IVariable* variable = *i;
122 Integer nb_diff = 0;
123 String var_name(variable->name());
124 try {
125 VariableComparerResults r = variable_comparer.apply(variable, compare_args);
126 nb_diff = r.nbDifference();
127 ++nb_compared;
128 }
129 catch (const ReaderWriterException& rw) {
130 OStringStream ostr;
131 rw.explain(ostr());
132 trace->pinfo() << "Impossible to compare the variable '" << var_name << "'\n"
133 << "(Exception: " << ostr.str() << ")";
134 not_compared_str() << ' ' << var_name;
135 ++nb_not_compared;
136 }
137 diff_infos.insert(MapDiffInfosValues(var_name, DiffInfo(var_name, nb_diff)));
138 }
139 }
140 if (nb_not_compared != 0) {
141 trace->warning() << "Impossible to compare " << nb_not_compared << " variable(s): "
142 << not_compared_str.str();
143 }
144 if (nb_compared == 0) {
145 trace->pfatal() << "No variable has been compared";
146 }
147 Int32 sid = pm->commRank();
148 Int32 nb_sub_domain = pm->commSize();
149 bool is_master = sid == 0;
150
151 if (is_master) {
152
153 for (Integer i = 0; i < nb_sub_domain; ++i) {
154 if (i == sid)
155 continue;
156 SerializeBuffer sbuf;
157 pm->recvSerializer(&sbuf, i);
158 sbuf.setMode(ISerializer::ModeGet);
159
160 {
161 Int64 n = sbuf.getInt64();
162 String var_name;
163 for (Integer z = 0; z < n; ++z) {
164 Int64 nb_var_diff = sbuf.getInt64();
165 sbuf.get(var_name);
166 String uvar_name(var_name);
167 trace->debug() << "RECEIVE: "
168 << " varname=" << var_name
169 << " nbdiff=" << nb_var_diff;
170 auto i_map = diff_infos.find(uvar_name);
171 if (i_map == diff_infos.end()) {
172 diff_infos.insert(MapDiffInfosValues(uvar_name, DiffInfo(uvar_name, nb_var_diff)));
173 }
174 else
175 i_map->second.m_nb_diff += nb_var_diff;
176 }
177 }
178 }
179 }
180 else {
181 SerializeBuffer sbuf;
182 Int64 nb_diff = diff_infos.size();
183 sbuf.setMode(ISerializer::ModeReserve);
184 sbuf.reserve(DT_Int64, 1); // for the size
185 for (auto& i_map : diff_infos) {
186 const DiffInfo& diff_info = i_map.second;
187 sbuf.reserve(DT_Int64, 1);
188 sbuf.reserve(diff_info.m_variable_name);
189 }
190 sbuf.allocateBuffer();
191 sbuf.setMode(ISerializer::ModePut);
192 sbuf.putInt64(nb_diff);
193 for (auto& i_map : diff_infos) {
194 const DiffInfo& diff_info = i_map.second;
195 Int64 n = diff_info.m_nb_diff;
196 sbuf.putInt64(n);
197 sbuf.put(diff_info.m_variable_name);
198 }
199 pm->sendSerializer(&sbuf, 0);
200 }
201
202 pm->barrier();
203
204 if (is_master) {
205 Int64 total_nb_diff = 0;
206 for (auto& diff_info : diff_infos)
207 total_nb_diff += diff_info.second.m_nb_diff;
208
209 if (!m_result_file_name.empty()) {
210 const CommonVariables& vc = subDomain()->commonVariables();
211 std::ofstream result_file(m_result_file_name.localstr());
212 result_file << "<?xml version='1.0'?>\n";
213 result_file << "<compare-results"
214 << " version='1.0'"
215 << " total-nb-diff='" << total_nb_diff << "'"
216 << " global-iteration='" << vc.globalIteration() << "'"
217 << " global-time='" << vc.globalTime() << "'"
218 << ">\n";
219 for (auto& i_map : diff_infos) {
220 const DiffInfo& diff_info = i_map.second;
221 result_file << " <variable>\n"
222 << " <name>" << diff_info.m_variable_name << "</name>\n"
223 << " <nb-diff>" << diff_info.m_nb_diff << "</nb-diff>\n"
224 << " </variable>\n";
225 }
226 result_file << "</compare-results>\n";
227 }
228 if (total_nb_diff != 0) {
229 trace->error() << "Some differences exist (N=" << total_nb_diff << ") with the reference file";
230 }
231 else {
232 trace->info() << "No difference with the reference !";
233 }
234 }
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240void VerifierService::
241_doVerif(IDataReader* reader, const VariableList& variables, bool compare_ghost)
242{
243 _doVerif2(reader, variables, compare_ghost);
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249} // End namespace Arcane
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
Base class of a service.
Interface of the base class for main arcane objects.
Definition IBase.h:32
virtual ITraceMng * traceMng() const =0
Trace manager.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void barrier()=0
Performs a barrier.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual IParallelMng * parallelMng()=0
Returns the parallelism manager.
virtual IVariableMng * variableMng()=0
Returns the variable manager.
virtual TraceMessage warning()=0
Stream for a warning message.
virtual TraceMessage pfatal()=0
Stream for a parallel fatal error message.
virtual TraceMessage pinfo()=0
Stream for a parallel information message.
virtual TraceMessage error()=0
Stream for an error message.
virtual TraceMessage info()=0
Stream for an information message.
virtual TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium)=0
Stream for a debug message.
Variable manager interface.
virtual VariableCollection usedVariables()=0
List of used variables.
Interface of a variable.
Definition IVariable.h:40
@ PSubDomainDepend
Indicates that the variable value is dependent on the subdomain.
Definition IVariable.h:81
@ PExecutionDepend
Indicates that the variable value is dependent on the execution.
Definition IVariable.h:96
virtual int property() const =0
Returns the properties of the variable.
virtual eItemKind itemKind() const =0
Kind of mesh entities on which the variable is based.
virtual MeshHandle meshHandle() const =0
Mesh associated with the variable.
virtual String name() const =0
Variable name.
Handle on a mesh.
Definition MeshHandle.h:48
bool hasMesh() const
Indicates if the associated mesh has already been created (i.e.: mesh() is valid).
IMesh * mesh() const
Associated mesh.
Output stream linked to a String.
Structure containing the information to create a service.
Arguments for VariableComparer methods.
void setMaxPrint(Int32 v)
Sets the number of errors to display in the listing.
void setCompareGhost(bool v)
Indicates on which entities the comparison is performed.
Results of a comparison operation.
Class to perform comparisons between variables.
VariableComparerResults apply(IVariable *var, const VariableComparerArgs &compare_args)
Applies the comparison compare_args to the variable var.
VariableComparerArgs buildForCheckIfSame(IDataReader *data_reader)
Creates a comparison to verify that a variable is identical to a reference value.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
@ IK_Unknown
Unknown or uninitialized mesh entity.