Arcane  4.2.1.0
Developer documentation
Loading...
Searching...
No Matches
DistributedSPMMScaling.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 <vector>
21
22#include <boost/scope_exit.hpp>
23
24#include "arccore/alina/BuiltinBackend.h"
25#include "arccore/alina/Adapters.h"
26#include "arccore/alina/DistributedMatrix.h"
27#include "arccore/alina/Profiler.h"
28
29#include "arccore/common/internal/ProgramOptions.h"
30
31#include "DomainPartition.h"
32
33using namespace Arcane;
34
35struct renumbering
36{
37 const DomainPartition<3>& part;
38 const std::vector<ptrdiff_t>& dom;
39
40 renumbering(const DomainPartition<3>& p,
41 const std::vector<ptrdiff_t>& d)
42 : part(p)
43 , dom(d)
44 {}
45
46 ptrdiff_t operator()(ptrdiff_t i, ptrdiff_t j, ptrdiff_t k) const
47 {
48 boost::array<ptrdiff_t, 3> p = { { i, j, k } };
49 std::pair<int, ptrdiff_t> v = part.index(p);
50 return dom[v.first] + v.second;
51 }
52};
53
54int main(int argc, char* argv[])
55{
56 auto& prof = Alina::Profiler::globalProfiler();
57 MPI_Init(&argc, &argv);
58 BOOST_SCOPE_EXIT(void)
59 {
60 MPI_Finalize();
61 }
62 BOOST_SCOPE_EXIT_END
63
64 Alina::mpi_communicator world(MPI_COMM_WORLD);
65
66 if (world.rank == 0)
67 std::cout << "World size: " << world.size << std::endl;
68
69 // Read configuration from command line
70 ptrdiff_t n = 128;
71
72 namespace po = Arcane::ProgramOptions;
73 po::options_description desc("Options");
74
75 desc.add_options()("help,h", "show help")(
76 "size,n",
77 po::value<ptrdiff_t>(&n)->default_value(n),
78 "domain size");
79
81 po::store(po::parse_command_line(argc, argv, desc), vm);
82 po::notify(vm);
83
84 if (vm.count("help")) {
85 std::cout << desc << std::endl;
86 return 0;
87 }
88
89 boost::array<ptrdiff_t, 3> lo = { { 0, 0, 0 } };
90 boost::array<ptrdiff_t, 3> hi = { { n - 1, n - 1, n - 1 } };
91
92 prof.tic("partition");
93 DomainPartition<3> part(lo, hi, world.size);
94 ptrdiff_t chunk = part.size(world.rank);
95
96 std::vector<ptrdiff_t> domain = world.exclusive_sum(chunk);
97
98 lo = part.domain(world.rank).min_corner();
99 hi = part.domain(world.rank).max_corner();
100
101 renumbering renum(part, domain);
102 prof.toc("partition");
103
104 prof.tic("assemble");
105 std::vector<ptrdiff_t> ptr;
106 std::vector<ptrdiff_t> col;
107 std::vector<double> val;
108 std::vector<double> rhs;
109
110 ptr.reserve(chunk + 1);
111 col.reserve(chunk * 7);
112 val.reserve(chunk * 7);
113
114 ptr.push_back(0);
115
116 const double h2i = (n - 1) * (n - 1);
117
118 for (ptrdiff_t k = lo[2]; k <= hi[2]; ++k) {
119 for (ptrdiff_t j = lo[1]; j <= hi[1]; ++j) {
120 for (ptrdiff_t i = lo[0]; i <= hi[0]; ++i) {
121 if (k > 0) {
122 col.push_back(renum(i, j, k - 1));
123 val.push_back(-h2i);
124 }
125
126 if (j > 0) {
127 col.push_back(renum(i, j - 1, k));
128 val.push_back(-h2i);
129 }
130
131 if (i > 0) {
132 col.push_back(renum(i - 1, j, k));
133 val.push_back(-h2i);
134 }
135
136 col.push_back(renum(i, j, k));
137 val.push_back(6 * h2i);
138
139 if (i + 1 < n) {
140 col.push_back(renum(i + 1, j, k));
141 val.push_back(-h2i);
142 }
143
144 if (j + 1 < n) {
145 col.push_back(renum(i, j + 1, k));
146 val.push_back(-h2i);
147 }
148
149 if (k + 1 < n) {
150 col.push_back(renum(i, j, k + 1));
151 val.push_back(-h2i);
152 }
153
154 ptr.push_back(col.size());
155 }
156 }
157 }
158 prof.toc("assemble");
159
160 typedef Alina::BuiltinBackend<double> Backend;
162
163 prof.tic("create distributed version");
164 Matrix A(world, std::tie(chunk, ptr, col, val), chunk);
165 prof.toc("create distributed version");
166
167 prof.tic("distributed product");
168 auto B = product(A, A);
169 prof.toc("distributed product");
170
171 if (world.rank == 0) {
172 if (world.size == 1) {
173 typedef Alina::CSRMatrix<double> matrix;
174 matrix A(std::tie(chunk, ptr, col, val));
175 prof.tic("openmp product");
176 auto B = product(A, A);
177 prof.toc("openmp product");
178 }
179
180 std::cout << prof << std::endl;
181 }
182}
Distributed Matrix using message passing.
Matrix class, to be used by user.
Describes a set of command-line options.
Stores parsed option values.
-- 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.