Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
AlephMultiTest.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/* AlephMultiTest.cc (C) 2000-2015 */
9/* */
10/* Aleph+Multi service test. */
11/*---------------------------------------------------------------------------*/
12#include "arcane/aleph/tests/AlephTest.h"
13#include "arcane/aleph/tests/AlephMultiTest_axl.h"
14#include "arcane/aleph/tests/AlephMultiTest.h"
15
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19namespace ArcaneTest
20{
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25using namespace Arcane;
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30// ****************************************************************************
31// * 'solver' class which will mimic what is done at a higher level
32// ****************************************************************************
33class AlephSolver
34: public TraceAccessor
35, public MeshAccessor
36{
37 public:
38
39 AlephSolver(ITraceMng* traceMng,
40 ISubDomain* subDomain,
41 Integer numberOfResolutionsPerSolvers,
42 Integer underlyingSolver,
43 Integer numberOfCores,
44 Real deltaT)
46 , MeshAccessor(subDomain->defaultMesh())
47 , m_sub_domain(subDomain)
48 , m_aleph_number_of_resolutions_per_solvers(numberOfResolutionsPerSolvers)
49 , m_delta_t(deltaT)
50 , m_aleph_params(new AlephParams())
51 ,
52 // We instantiate a minimalist kernel that will handle the initialization for us
53 m_aleph_kernel(new AlephKernel(subDomain, underlyingSolver, numberOfCores))
54 , m_aleph_mat(0)
55 , m_aleph_rhs(0)
56 , m_aleph_sol(0)
57 , m_vector_zeroes(0)
58 , m_get_solution_idx(0)
59 {
60 info() << Trace::Color::cyan() << "[AlephSolver] New solver "
61 << "with " << numberOfResolutionsPerSolvers << " resolutions, "
62 << "underlying solver is '" << underlyingSolver << "', "
63 << "and numberOfCores is " << numberOfCores;
64 m_aleph_mat.resize(numberOfResolutionsPerSolvers);
65 m_aleph_rhs.resize(numberOfResolutionsPerSolvers);
66 m_aleph_sol.resize(numberOfResolutionsPerSolvers);
67 ENUMERATE_CELL (cell, ownCells())
68 m_vector_zeroes.add(0.0);
69 }
70
71 ~AlephSolver()
72 {
73 info() << Trace::Color::cyan() << "[AlephSolver] Delete solver";
74 delete m_aleph_kernel;
75 delete m_aleph_params;
76 }
77
78 // ****************************************************************************
79 // * launchResolutions
80 // ****************************************************************************
81 void launchResolutions(VariableCellReal& cell_temperature,
82 VariableFaceReal& face_temperature)
83 {
86 Integer nb_iteration;
87 Real residual_norm[4];
88
89 indexs.resize(m_aleph_number_of_resolutions_per_solvers);
90 values.resize(m_aleph_number_of_resolutions_per_solvers);
91
92 for (int i = 0;
93 i < m_aleph_number_of_resolutions_per_solvers;
94 i += 1)
95 postSingleResolution(cell_temperature,
96 face_temperature,
97 i, m_delta_t, values[i], indexs[i]);
98
99 // And should be able to get the solutions after the last resolution was fired
100 for (int i = m_aleph_number_of_resolutions_per_solvers - 1; i >= 0; i -= 1) {
101 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Getting solution #" << i;
102 AlephVector* solution = m_aleph_kernel->syncSolver(i, nb_iteration, &residual_norm[0]);
103 if (i != m_get_solution_idx)
104 continue;
105 info() << Trace::Color::cyan() << "Solved in \33[7m" << nb_iteration << "\33[m iterations,"
106 << "residuals=[\33[1m" << residual_norm[0] << "\33[m," << residual_norm[3] << "]";
107 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Applying solution #" << m_get_solution_idx;
108 solution->getLocalComponents(values[i]);
109 m_get_solution_idx += 1;
110 }
111 m_get_solution_idx %= m_aleph_number_of_resolutions_per_solvers;
112 // Otherwise, we copy the results
113 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] Now get our results";
114 ENUMERATE_CELL (cell, ownCells())
115 cell_temperature[cell] =
116 values[m_get_solution_idx][m_aleph_kernel->indexing()->get(cell_temperature, *cell)];
117 debug() << Trace::Color::cyan() << "[AlephSolver::launchResolutions] done";
118 }
119
120 // ****************************************************************************
121 // * postSingleResolution
122 // ****************************************************************************
123 void postSingleResolution(VariableCellReal& cell_temperature,
124 VariableFaceReal& face_temperature,
125 const Integer i,
126 Real optionDeltaT,
127 Array<Real>& values,
128 Array<Integer>& indexs)
129 {
130 // We force the deltaTs to be different to have calculation times that can be scheduled
131 Real deltaT = (1.0 + (Real)i) * optionDeltaT;
132 Integer fake_nb_iteration = 0;
133 Real fake_residual_norm[4];
134
135 // Filling the right-hand side: boundary conditions + right-hand side
136 debug() << Trace::Color::cyan()
137 << "[AlephSolver::postSingleResolution] Resize (" << m_vector_zeroes.size()
138 << ") + filling the right-hand side";
139 values.resize(m_vector_zeroes.size());
140 indexs.resize(m_vector_zeroes.size());
141 ENUMERATE_CELL (cell, ownCells()) {
142 Integer row = m_aleph_kernel->indexing()->get(cell_temperature, cell);
143 //info()<<Trace::Color::yellow()<<"[AlephSolver::postSingleResolution] row="<<row;
144 indexs[row] = row;
145 values[row] = cell_temperature[cell];
146 }
147
148 debug() << Trace::Color::cyan() << "[AlephSolver::postSingleResolution] ENUMERATE_FACE";
149 ENUMERATE_FACE (iFace, allCells().outerFaceGroup()) {
150 if (!iFace->cell(0).isOwn())
151 continue;
152 values[m_aleph_kernel->indexing()->get(cell_temperature, iFace->cell(0))] +=
153 deltaT * (face_temperature[iFace]) / geoFaceSurface(*iFace, nodesCoordinates());
154 }
155
156 // Creation of the MatVec matrix and Aleph requirements
157 m_aleph_mat.setAt(i, m_aleph_kernel->createSolverMatrix());
158 m_aleph_rhs.setAt(i, m_aleph_kernel->createSolverVector()); // First vector returned IS the rhs
159 m_aleph_sol.setAt(i, m_aleph_kernel->createSolverVector()); // Next one IS the solution
160
161 m_aleph_mat.at(i)->create();
162 m_aleph_rhs.at(i)->create();
163 m_aleph_sol.at(i)->create();
164 m_aleph_mat.at(i)->reset();
165
166 // Filling the matrix and assembly
167 setValues(cell_temperature, face_temperature, deltaT, m_aleph_mat.at(i));
168 m_aleph_mat.at(i)->assemble();
169
170 debug() << Trace::Color::cyan() << "[AlephSolver::postSingleResolution] setLocalComponents";
171 //m_aleph_rhs.at(i)->setLocalComponents(indexs.size(), indexs.view(), values.view());
172 m_aleph_rhs.at(i)->setLocalComponents(values.view());
173 m_aleph_rhs.at(i)->assemble();
174
175 //m_aleph_sol.at(i)->setLocalComponents(indexs.size(), indexs.view(), m_vector_zeroes.view());
176 m_aleph_sol.at(i)->setLocalComponents(m_vector_zeroes.view());
177 m_aleph_sol.at(i)->assemble();
178
179 debug() << Trace::Color::cyan() << "\33[37m[AlephSolver::postSingleResolution] Now solve with Aleph";
180 m_aleph_mat.at(i)->solve(m_aleph_sol.at(i),
181 m_aleph_rhs.at(i),
182 fake_nb_iteration,
183 &fake_residual_norm[0],
184 m_aleph_params,
185 true); // We wish to post asynchronously
186 }
187
188 // ****************************************************************************
189 // * setValues for a matrix
190 // ****************************************************************************
191 void setValues(VariableCellReal& cell_temperature,
192 [[maybe_unused]] VariableFaceReal& face_temperature,
193 const Real deltaT, AlephMatrix* aleph_mat)
194 {
195 VariableCellReal coefs(VariableBuildInfo(m_sub_domain->defaultMesh(), "cellCoefs"));
196 // We flush the coefficients
197 ENUMERATE_CELL (cell, ownCells())
198 coefs[cell] = 0.;
199 // Faces 'inner'
200 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] inner-faces";
201 ENUMERATE_FACE (iFace, allCells().innerFaceGroup()) {
202 if (iFace->backCell().isOwn()) {
203 const Real surface = geoFaceSurface(*iFace, nodesCoordinates());
204 aleph_mat->setValue(cell_temperature, iFace->backCell(),
205 cell_temperature, iFace->frontCell(),
206 -deltaT / surface);
207 coefs[iFace->backCell()] += 1.0 / surface;
208 }
209 if (iFace->frontCell().isOwn()) {
210 const Real surface = geoFaceSurface(*iFace, nodesCoordinates());
211 aleph_mat->setValue(cell_temperature, iFace->frontCell(),
212 cell_temperature, iFace->backCell(),
213 -deltaT / surface);
214 coefs[iFace->frontCell()] += 1.0 / surface;
215 }
216 }
217 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] outer-faces";
218 ENUMERATE_FACE (iFace, allCells().outerFaceGroup()) {
219 if (!iFace->cell(0).isOwn())
220 continue;
221 coefs[iFace->cell(0)] += 1.0 / geoFaceSurface(*iFace, nodesCoordinates());
222 }
223 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] diagonal";
224 ENUMERATE_CELL (cell, ownCells()) {
225 aleph_mat->setValue(cell_temperature, cell,
226 cell_temperature, cell,
227 1.0 + deltaT * coefs[cell]);
228 }
229 debug() << Trace::Color::cyan() << "[AlephSolver::setValues] done";
230 }
231
232 private:
233
234 // ****************************************************************************
235 // * geoFaceSurface
236 // ****************************************************************************
237 Real geoFaceSurface(Face face, VariableItemReal3& nodes_coords)
238 {
239 if (face.nbNode() == 4) {
240 const Real3 xyz0 = nodes_coords[face.node(0)];
241 const Real3 xyz1 = nodes_coords[face.node(1)];
242 const Real3 xyz3 = nodes_coords[face.node(3)];
243 return (xyz0 - xyz1).normL2() * (xyz0 - xyz3).normL2();
244 }
245 if (face.nbNode() == 2) {
246 const Real3 xyz0 = nodes_coords[face.node(0)];
247 const Real3 xyz1 = nodes_coords[face.node(1)];
248 return (xyz0 - xyz1).normL2();
249 }
250 throw FatalErrorException("geoFace", "Nb nodes != 4 !=2");
251 }
252
253 private:
254
255 ISubDomain* m_sub_domain;
256 Integer m_aleph_number_of_resolutions_per_solvers;
257 Real m_delta_t;
258 AlephParams* m_aleph_params;
259 AlephKernel* m_aleph_kernel;
260 UniqueArray<AlephMatrix*> m_aleph_mat;
261 UniqueArray<AlephVector*> m_aleph_rhs;
262 UniqueArray<AlephVector*> m_aleph_sol;
263 UniqueArray<Real> m_vector_zeroes;
264 Integer m_get_solution_idx;
265};
266
267// ****************************************************************************
268// * AlephMultiTest class + deletes
269// ****************************************************************************
270AlephMultiTest::
271AlephMultiTest(const ModuleBuildInfo& mbi)
273{
274}
275
276AlephMultiTest::
277~AlephMultiTest(void)
278{
279 // NOTE: the elements of m_posted_solvers must not be destroyed
280 delete m_aleph_factory;
281 debug() << Trace::Color::cyan() << "[AlephMultiTest::AlephMultiTest] Delete";
282 for (Integer i = 0, n = m_global_aleph_solver.size(); i < n; ++i)
283 delete m_global_aleph_solver[i];
284}
285
286// ****************************************************************************
287// * Initialization entry point
288// ****************************************************************************
290init(void)
291{
292 ISubDomain* sd = subDomain();
293 m_aleph_factory = new AlephFactory(sd->application(), sd->traceMng());
294
295 // Time step initialization
296 m_global_deltat = options()->deltaT;
297 // Initialization of cell and outer face temperatures
298 m_cell_temperature.fill(options()->iniTemperature());
299
300 ENUMERATE_FACE (iFace, outerFaces()) {
301 m_face_temperature[iFace] = options()->hotTemperature();
302 }
303 mesh()->checkValidMeshFull();
304
305 // Initialization of global solvers
306 for (Integer i = 0; i < options()->alephNumberOfSuccessiveSolvers(); ++i) {
307 SolverBuildInfo sbi;
308 Integer underlying_solver = (options()->alephUnderlyingSolver >> (4ul * i)) & 0xFul;
309 if (!m_aleph_factory->hasSolverImplementation(underlying_solver)) {
310 info() << "Skipping solver index " << underlying_solver
311 << " because implementation is not available";
312 continue;
313 }
314
315 sbi.m_number_of_resolution_per_solvers = (options()->alephNumberOfResolutionsPerSolvers >> (4ul * i)) & 0xFul;
316 sbi.m_underliying_solver = underlying_solver;
317 sbi.m_number_of_core = (options()->alephNumberOfCores >> (4ul * i)) & 0xFul;
318 m_solvers_build_info.add(sbi);
319 }
320
321 // Initialization of global solvers
322 for (Integer i = 0, n = m_solvers_build_info.size(); i < n; ++i) {
323 const SolverBuildInfo& sbi = m_solvers_build_info[i];
324 m_global_aleph_solver.add(new AlephSolver(traceMng(), subDomain(),
325 sbi.m_number_of_resolution_per_solvers,
326 sbi.m_underliying_solver,
327 sbi.m_number_of_core,
328 options()->deltaT));
329 }
330}
331
332// ****************************************************************************
333// * Computation loop entry point
334// ****************************************************************************
335void AlephMultiTest::
336compute(void)
337{
338 // For each solver, we launch the resolutions
339 for (Integer i = 0, n = m_solvers_build_info.size(); i < n; ++i) {
340 const SolverBuildInfo& sbi = m_solvers_build_info[i];
341 // Creation and launch of local solvers with shifted options
342 // This is in order to test the deletes
344 sbi.m_number_of_resolution_per_solvers,
345 sbi.m_underliying_solver,
346 sbi.m_number_of_core,
347 options()->deltaT);
348 m_posted_solvers.add(s);
349 s->launchResolutions(m_cell_temperature, m_face_temperature);
350 // Launching global solvers
351 m_global_aleph_solver.at(i)->launchResolutions(m_cell_temperature, m_face_temperature);
352 }
353
354 // If we have reached our maximum iterations, we exit
355 if (subDomain()->commonVariables().globalIteration() >= options()->iterations)
357}
358
359/*---------------------------------------------------------------------------*/
360/*---------------------------------------------------------------------------*/
361
362// ****************************************************************************
363// * REGISTER + NAMESPACE
364// ****************************************************************************
365ARCANE_DEFINE_STANDARD_MODULE(AlephMultiTest, AlephMultiTest);
366
367/*---------------------------------------------------------------------------*/
368/*---------------------------------------------------------------------------*/
369
370} // namespace ArcaneTest
371
372/*---------------------------------------------------------------------------*/
373/*---------------------------------------------------------------------------*/
#define ENUMERATE_FACE(name, group)
Generic enumerator for a face group.
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
void init(void)
points d'entrée
Generation de la classe de base du Module.
CaseOptionsAlephMultiTest * options() const
Options du jeu de données du module.
Arcane::VariableCellReal m_cell_temperature
Variables du module.
ITraceMng * traceMng() const override
Trace manager.
ISubDomain * subDomain() const override
Sub-domain associated with the module.
Matrix of a linear system.
Definition AlephMatrix.h:33
void setValue(const VariableRef &, const Item &, const VariableRef &, const Item &, const Real)
setValue from arguments in IVariables, Items, and Real
Parameters of a linear system.
Definition AlephParams.h:32
Vector of a linear system.
Definition AlephVector.h:33
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
ArrayView< T > view() const
Mutable view of this array.
Int32 globalIteration() const
Current iteration number.
VariableScalarReal m_global_deltat
Global Delta T.
Face of a cell.
Definition Item.h:1032
virtual ITraceMng * traceMng() const =0
Trace manager.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual IMesh * defaultMesh()=0
Default mesh.
virtual IApplication * application()=0
Application.
virtual ITimeLoopMng * timeLoopMng()=0
Returns the time loop manager.
virtual void stopComputeLoop(bool is_final_time, bool has_error=false)=0
Indicates that the compute loop must stop.
Node node(Int32 i) const
i-th node of the entity
Definition Item.h:840
Int32 nbNode() const
Number of nodes of the entity.
Definition Item.h:837
CellGroup allCells() const
Returns the group containing all cells.
CellGroup ownCells() const
Returns the group containing all cells specific to this domain.
FaceGroup outerFaces() const
Returns the group containing all boundary faces.
VariableNodeReal3 & nodesCoordinates() const
Returns the coordinates of the mesh nodes.
Information for building a module.
Class managing a 3-dimensional real vector.
Definition Real3.h:132
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
MeshVariableScalarRefT< Face, Real > VariableFaceReal
Real type quantity at face.
MeshVariableScalarRefT< Cell, Real > VariableCellReal
Real type quantity at cell center.
ItemVariableScalarRefT< Real3 > VariableItemReal3
3D coordinate type quantity
Int32 Integer
Type representing an integer.
double Real
Type representing a real number.