Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
DistributedAlinaLibraryUsage.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#include <iostream>
20#include <iomanip>
21#include <fstream>
22#include <vector>
23#include <numeric>
24
25#include <boost/scope_exit.hpp>
26
27#include "arccore/alina/MessagePassingUtils.h"
28#include "arccore/alina/AlinaLib.h"
29#include "AlinaSamplesCommon.h"
30#include "arccore/trace/ITraceMng.h"
31
32#include "DomainPartition.h"
33
34double constant_deflation(int, ptrdiff_t, void*)
35{
36 return 1;
37}
38
39using namespace Arcane;
40
41int main2(const Alina::SampleMainContext& ctx, int argc, char* argv[])
42{
43 ITraceMng* tm = ctx.traceMng();
44
45 Alina::mpi_communicator world(MPI_COMM_WORLD);
46
47 int rank = world.rank;
48 int size = world.size;
49 //MPI_Comm_rank(MPI_COMM_WORLD, &rank);
50 //MPI_Comm_size(MPI_COMM_WORLD, &size);
51
52 if (rank == 0)
53 tm->info() << "World size: " << size;
54
55 const ptrdiff_t n = argc > 1 ? atoi(argv[1]) : 1024;
56 const ptrdiff_t n2 = n * n;
57
58 // Partition
59 boost::array<ptrdiff_t, 2> lo = { { 0, 0 } };
60 boost::array<ptrdiff_t, 2> hi = { { n - 1, n - 1 } };
61
62 DomainPartition<2> part(lo, hi, size);
63 ptrdiff_t chunk = part.size(rank);
64
65 std::vector<ptrdiff_t> domain(size + 1);
66 ConstArrayView<ptrdiff_t> send_buf(1, &chunk);
67 ArrayView<ptrdiff_t> receive_buf(size, &domain[1]);
68 mpAllGather(world.m_message_passing_mng.get(), send_buf, receive_buf);
69 std::partial_sum(domain.begin(), domain.end(), domain.begin());
70
71 ptrdiff_t chunk_start = domain[rank];
72 ptrdiff_t chunk_end = domain[rank + 1];
73
74 std::vector<ptrdiff_t> renum(n2);
75 for (ptrdiff_t j = 0, idx = 0; j < n; ++j) {
76 for (ptrdiff_t i = 0; i < n; ++i, ++idx) {
77 boost::array<ptrdiff_t, 2> p = { { i, j } };
78 std::pair<int, ptrdiff_t> v = part.index(p);
79 renum[idx] = domain[v.first] + v.second;
80 }
81 }
82
83 // Assemble
84
85 // For 32 bit indexing
86 using ColumnType = Int32;
87 // For 64 bit indexing
88 // using ColumnType = Int64;
89
90 std::vector<ColumnType> ptr;
91 std::vector<ColumnType> col;
92 std::vector<double> val;
93 std::vector<double> rhs;
94
95 ptr.reserve(chunk + 1);
96 col.reserve(chunk * 5);
97 val.reserve(chunk * 5);
98 rhs.reserve(chunk);
99
100 ptr.push_back(0);
101
102 const double hinv = (n - 1);
103 const double h2i = (n - 1) * (n - 1);
104 for (ptrdiff_t j = 0, idx = 0; j < n; ++j) {
105 for (ptrdiff_t i = 0; i < n; ++i, ++idx) {
106 if (renum[idx] < chunk_start || renum[idx] >= chunk_end)
107 continue;
108
109 if (j > 0) {
110 col.push_back(renum[idx - n]);
111 val.push_back(-h2i);
112 }
113
114 if (i > 0) {
115 col.push_back(renum[idx - 1]);
116 val.push_back(-h2i - hinv);
117 }
118
119 col.push_back(renum[idx]);
120 val.push_back(4 * h2i + hinv);
121
122 if (i + 1 < n) {
123 col.push_back(renum[idx + 1]);
124 val.push_back(-h2i);
125 }
126
127 if (j + 1 < n) {
128 col.push_back(renum[idx + n]);
129 val.push_back(-h2i);
130 }
131
132 rhs.push_back(1);
133 ptr.push_back(col.size());
134 }
135 }
136
137 // Setup
138 AlinaParameters* prm = AlinaLib::params_create();
139
140 AlinaLib::params_set_string(prm, "local.coarsening.type", "smoothed_aggregation");
141 AlinaLib::params_set_string(prm, "local.relax.type", "spai0");
142 AlinaLib::params_set_string(prm, "isolver.type", "bicgstabl");
143 AlinaLib::params_set_string(prm, "dsolver.type", "skyline_lu");
144
145 AlinaDistributedSolver* solver = AlinaLib::solver_mpi_create(MPI_COMM_WORLD,
146 chunk, ptr.data(), col.data(), val.data(),
147 1, constant_deflation, NULL, prm);
148
149 // Solve
150 std::vector<double> x(chunk, 0);
151 AlinaConvergenceInfo cnv = AlinaLib::solver_mpi_solve(solver, rhs.data(), x.data());
152
153 std::cout << "Iterations: " << cnv.iterations << std::endl
154 << "Error: " << cnv.residual << std::endl;
155
156 // Clean up
157 AlinaLib::solver_mpi_destroy(solver);
158 AlinaLib::params_destroy(prm);
159
160 if (n <= 4096) {
161 if (rank == 0) {
162 std::vector<double> X(n2);
163 std::copy(x.begin(), x.end(), X.begin());
164
165 for (int i = 1; i < size; ++i)
166 MPI_Recv(&X[domain[i]], domain[i + 1] - domain[i], MPI_DOUBLE, i, 42, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
167
168 std::ofstream f("out.dat", std::ios::binary);
169 int m = n2;
170 f.write((char*)&m, sizeof(int));
171 for (ptrdiff_t i = 0; i < n2; ++i)
172 f.write((char*)&X[renum[i]], sizeof(double));
173 }
174 else {
175 MPI_Send(x.data(), chunk, MPI_DOUBLE, 0, 42, MPI_COMM_WORLD);
176 }
177 }
178 return 0;
179}
180
181int main(int argc, char* argv[])
182{
183 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
184}
Modifiable view of an array of type T.
Constant view of an array of type T.
virtual TraceMessage info()=0
Stream for an information message.
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
allGather() message for serialization
Definition Messages.cc:309
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Convenience wrapper around MPI_Comm.