Arcane  4.1.11.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DistributedCheckDirect.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/*---------------------------------------------------------------------------*/
9/*
10 * This file is based on the work on AMGCL library (version march 2026)
11 * which can be found at https://github.com/ddemidov/amgcl.
12 *
13 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
14 * SPDX-License-Identifier: MIT
15 */
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19#if defined(ARCCORE_ALINA_HAVE_EIGEN)
20// To remove warnings about deprecated Eigen usage.
21#pragma GCC diagnostic ignored "-Wdeprecated-copy"
22#pragma GCC diagnostic ignored "-Wint-in-bool-context"
23#include "arccore/alina/DistributedEigenSparseLUDirectSolver.h"
24#include "arccore/alina/EigenBackend.h"
25#endif
26
27#include "arccore/trace/ITraceMng.h"
28
29#include "arccore/alina/DistributedDirectSolverRuntime.h"
30#include "arccore/alina/Profiler.h"
31
32#include "AlinaSamplesCommon.h"
33
34#include <boost/program_options.hpp>
35
36using namespace Arcane;
37
38int main2(const Alina::SampleMainContext& ctx, int argc, char* argv[])
39{
40 ITraceMng* tm = ctx.traceMng();
41
42 auto& prof = Alina::Profiler::globalProfiler();
43
44 Alina::mpi_communicator comm(MPI_COMM_WORLD);
45
46 tm->info() << "World size: " << comm.size;
47
48 namespace po = boost::program_options;
49 po::options_description desc("Options");
50
51 desc.add_options()("help,h", "show help")("size,n",
52 po::value<int>()->default_value(128),
53 "domain size");
54 desc.add_options()("prm-file,P",
55 po::value<std::string>(),
56 "Parameter file in json format. ");
57 desc.add_options()("prm,p",
58 po::value<std::vector<std::string>>()->multitoken(),
59 "Parameters specified as name=value pairs. "
60 "May be provided multiple times. Examples:\n"
61 " -p solver.tol=1e-3\n"
62 " -p precond.coarse_enough=300");
63
64 po::variables_map vm;
65 po::store(po::parse_command_line(argc, argv, desc), vm);
66 po::notify(vm);
67
68 if (vm.count("help")) {
69 if (comm.rank == 0)
70 std::cout << desc << std::endl;
71 return 0;
72 }
73
75 if (vm.count("prm-file")) {
76 prm.read_json(vm["prm-file"].as<std::string>());
77 }
78
79 if (vm.count("prm")) {
80 for (const std::string& v : vm["prm"].as<std::vector<std::string>>()) {
81 prm.putKeyValue(v);
82 }
83 }
84
85 const int n = vm["size"].as<int>();
86 const int n2 = n * n;
87
88 int chunk = (n2 + comm.size - 1) / comm.size;
89 int chunk_start = comm.rank * chunk;
90 int chunk_end = std::min(chunk_start + chunk, n2);
91
92 chunk = chunk_end - chunk_start;
93
94 std::vector<int> domain(comm.size + 1);
95 MPI_Allgather(&chunk, 1, MPI_INT, &domain[1], 1, MPI_INT, comm);
96 std::partial_sum(domain.begin(), domain.end(), domain.begin());
97
98 prof.tic("assemble");
100 A.set_size(chunk, domain.back(), true);
101 A.set_nonzeros(chunk * 5);
102 std::vector<double> rhs(chunk, 1);
103
104 const double h2i = (n - 1) * (n - 1);
105 for (int idx = chunk_start, row = 0, head = 0; idx < chunk_end; ++idx, ++row) {
106 int j = idx / n;
107 int i = idx % n;
108
109 if (j > 0) {
110 A.col[head] = idx - n;
111 A.val[head] = -h2i;
112 ++head;
113 }
114
115 if (i > 0) {
116 A.col[head] = idx - 1;
117 A.val[head] = -h2i;
118 ++head;
119 }
120
121 A.col[head] = idx;
122 A.val[head] = 4 * h2i;
123 ++head;
124
125 if (i + 1 < n) {
126 A.col[head] = idx + 1;
127 A.val[head] = -h2i;
128 ++head;
129 }
130
131 if (j + 1 < n) {
132 A.col[head] = idx + n;
133 A.val[head] = -h2i;
134 ++head;
135 }
136
137 A.ptr[row + 1] = head;
138 }
139 A.setNbNonZero(A.ptr[chunk]);
140 prof.toc("assemble");
141
142 std::vector<double> x(chunk);
143
144 {
145 auto t = prof.scoped_tic("skyline");
146
147 prof.tic("setup");
148 using Backend = Alina::BuiltinBackend<double>;
150 tm->info() << "Solver is = " << solve.type();
151 prof.toc("setup");
152
153 prof.tic("solve1");
154 solve(rhs, x);
155 prof.toc("solve1");
156 }
157
158#if defined(ARCCORE_ALINA_HAVE_EIGEN)
159 {
160 auto t = prof.scoped_tic("eigen");
161
162 prof.tic("setup");
165 prof.toc("setup");
166
167 prof.tic("solve");
168 std::vector<double> x2(chunk);
169 solve(rhs, x2);
170 prof.toc("solve");
171 // Compare values between skyline and eigen
172 Int32 nb_error = 0;
173 for (Int32 i = 0; i < chunk; ++i) {
174 Real x_ref = x[i];
175 Real x_eigen = x2[i];
176 Real abs_sum = std::abs(x_ref);
177
178 Real diff = std::abs(x_eigen - x_ref);
179 if (abs_sum != 0.0)
180 diff /= abs_sum;
181
182 if (diff > 1.0e-12) {
183 tm->info() << "I=" << i << " compare skyline=" << x[i] << " eigen=" << x2[i] << " diff=" << diff;
184 ++nb_error;
185 }
186 }
187 if (nb_error != 0)
188 ARCCORE_FATAL("Error when comparing Eigen and SkylineLU nb_error={0}", nb_error);
189 }
190#endif
191
192 tm->info() << prof;
193 return 0;
194}
195
196int main(int argc, char* argv[])
197{
198 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
199}
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Runtime wrapper for distributed direct solvers.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
Sparse matrix stored in CSR (Compressed Sparse Row) format.
Definition CSRMatrix.h:98
Convenience wrapper around MPI_Comm.