Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
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 int rank, size;
46 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
47 MPI_Comm_size(MPI_COMM_WORLD, &size);
48
49 if (rank == 0)
50 tm->info() << "World size: " << size;
51
52 const ptrdiff_t n = argc > 1 ? atoi(argv[1]) : 1024;
53 const ptrdiff_t n2 = n * n;
54
55 // Partition
56 boost::array<ptrdiff_t, 2> lo = { { 0, 0 } };
57 boost::array<ptrdiff_t, 2> hi = { { n - 1, n - 1 } };
58
59 DomainPartition<2> part(lo, hi, size);
60 ptrdiff_t chunk = part.size(rank);
61
62 std::vector<ptrdiff_t> domain(size + 1);
63 MPI_Allgather(&chunk, 1, Alina::mpi_datatype<ptrdiff_t>(), &domain[1], 1, Alina::mpi_datatype<ptrdiff_t>(), MPI_COMM_WORLD);
64 std::partial_sum(domain.begin(), domain.end(), domain.begin());
65
66 ptrdiff_t chunk_start = domain[rank];
67 ptrdiff_t chunk_end = domain[rank + 1];
68
69 std::vector<ptrdiff_t> renum(n2);
70 for (ptrdiff_t j = 0, idx = 0; j < n; ++j) {
71 for (ptrdiff_t i = 0; i < n; ++i, ++idx) {
72 boost::array<ptrdiff_t, 2> p = { { i, j } };
73 std::pair<int, ptrdiff_t> v = part.index(p);
74 renum[idx] = domain[v.first] + v.second;
75 }
76 }
77
78 // Assemble
79 std::vector<ptrdiff_t> ptr;
80 std::vector<ptrdiff_t> col;
81 std::vector<double> val;
82 std::vector<double> rhs;
83
84 ptr.reserve(chunk + 1);
85 col.reserve(chunk * 5);
86 val.reserve(chunk * 5);
87 rhs.reserve(chunk);
88
89 ptr.push_back(0);
90
91 const double hinv = (n - 1);
92 const double h2i = (n - 1) * (n - 1);
93 for (ptrdiff_t j = 0, idx = 0; j < n; ++j) {
94 for (ptrdiff_t i = 0; i < n; ++i, ++idx) {
95 if (renum[idx] < chunk_start || renum[idx] >= chunk_end)
96 continue;
97
98 if (j > 0) {
99 col.push_back(renum[idx - n]);
100 val.push_back(-h2i);
101 }
102
103 if (i > 0) {
104 col.push_back(renum[idx - 1]);
105 val.push_back(-h2i - hinv);
106 }
107
108 col.push_back(renum[idx]);
109 val.push_back(4 * h2i + hinv);
110
111 if (i + 1 < n) {
112 col.push_back(renum[idx + 1]);
113 val.push_back(-h2i);
114 }
115
116 if (j + 1 < n) {
117 col.push_back(renum[idx + n]);
118 val.push_back(-h2i);
119 }
120
121 rhs.push_back(1);
122 ptr.push_back(col.size());
123 }
124 }
125
126 // Setup
127 AlinaParameters* prm = AlinaLib::params_create();
128
129 AlinaLib::params_set_string(prm, "local.coarsening.type", "smoothed_aggregation");
130 AlinaLib::params_set_string(prm, "local.relax.type", "spai0");
131 AlinaLib::params_set_string(prm, "isolver.type", "bicgstabl");
132 AlinaLib::params_set_string(prm, "dsolver.type", "skyline_lu");
133
134 AlinaDistributedSolver* solver = AlinaLib::solver_mpi_create(MPI_COMM_WORLD,
135 chunk, ptr.data(), col.data(), val.data(),
136 1, constant_deflation, NULL, prm);
137
138 // Solve
139 std::vector<double> x(chunk, 0);
140 AlinaConvergenceInfo cnv = AlinaLib::solver_mpi_solve(solver, rhs.data(), x.data());
141
142 std::cout << "Iterations: " << cnv.iterations << std::endl
143 << "Error: " << cnv.residual << std::endl;
144
145 // Clean up
146 AlinaLib::solver_mpi_destroy(solver);
147 AlinaLib::params_destroy(prm);
148
149 if (n <= 4096) {
150 if (rank == 0) {
151 std::vector<double> X(n2);
152 std::copy(x.begin(), x.end(), X.begin());
153
154 for (int i = 1; i < size; ++i)
155 MPI_Recv(&X[domain[i]], domain[i + 1] - domain[i], MPI_DOUBLE, i, 42, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
156
157 std::ofstream f("out.dat", std::ios::binary);
158 int m = n2;
159 f.write((char*)&m, sizeof(int));
160 for (ptrdiff_t i = 0; i < n2; ++i)
161 f.write((char*)&X[renum[i]], sizeof(double));
162 }
163 else {
164 MPI_Send(x.data(), chunk, MPI_DOUBLE, 0, 42, MPI_COMM_WORLD);
165 }
166 }
167 return 0;
168}
169
170int main(int argc, char* argv[])
171{
172 return Arcane::Alina::SampleMainContext::execMain(main2, argc, argv);
173}
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 -*-