Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
DomainPartition.h
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#ifndef EXAMPLES_MPI_DOMAIN_PARTITION_HPP
20#define EXAMPLES_MPI_DOMAIN_PARTITION_HPP
21
22#include <vector>
23#include <utility>
24
25#include <boost/geometry.hpp>
26#include <boost/geometry/geometries/adapted/boost_array.hpp>
27#include <boost/geometry/geometries/box.hpp>
28#include <boost/geometry/index/rtree.hpp>
29
30BOOST_GEOMETRY_REGISTER_BOOST_ARRAY_CS(cs::cartesian)
31
32template <int NDIM>
33class DomainPartition
34{
35 public:
36
37 typedef boost::array<ptrdiff_t, NDIM> point;
38 typedef boost::geometry::model::box<point> box;
39 typedef std::pair<box, int> process;
40
41 DomainPartition(point lo, point hi, int num_processes)
42 {
43 split(box(lo, hi), num_processes);
44
45 for (int i = 0; i < num_processes; ++i)
46 rtree.insert(std::make_pair(subdomains[i], i));
47 }
48
49 std::pair<int, ptrdiff_t> index(point p) const
50 {
51 namespace bgi = boost::geometry::index;
52
53 for (const process& v : rtree | bgi::adaptors::queried(bgi::intersects(p))) {
54 return std::make_pair(v.second, local_index(v.first, p));
55 }
56
57 // Unreachable:
58 return std::make_pair(0, 0l);
59 }
60
61 size_t size(size_t process) const
62 {
63 if (process >= subdomains.size())
64 return 0;
65
66 point lo = subdomains[process].min_corner();
67 point hi = subdomains[process].max_corner();
68
69 size_t v = 1;
70
71 for (int i = 0; i < NDIM; ++i)
72 v *= hi[i] - lo[i] + 1;
73
74 return v;
75 }
76
77 box domain(size_t process) const
78 {
79 if (process < subdomains.size())
80 return subdomains[process];
81 else {
82 point lo;
83 point hi;
84 for (int i = 0; i < NDIM; ++i) {
85 lo[i] = 0;
86 hi[i] = -1;
87 }
88 return box(lo, hi);
89 }
90 }
91
92 private:
93
94 std::vector<box> subdomains;
95
96 boost::geometry::index::rtree<
97 process,
98 boost::geometry::index::quadratic<16>>
99 rtree;
100
101 static ptrdiff_t local_index(box domain, point p)
102 {
103 point lo = domain.min_corner();
104 point hi = domain.max_corner();
105
106 ptrdiff_t stride = 1, idx = 0;
107 for (int i = 0; i < NDIM; ++i) {
108 idx += (p[i] - lo[i]) * stride;
109 stride *= hi[i] - lo[i] + 1;
110 }
111
112 return idx;
113 }
114
115 void split(box domain, int np)
116 {
117 if (np == 1) {
118 subdomains.push_back(domain);
119 return;
120 }
121
122 point lo = domain.min_corner();
123 point hi = domain.max_corner();
124
125 // Get longest dimension of the domain
126 int wd = 0;
127 for (int i = 1; i < NDIM; ++i)
128 if (hi[i] - lo[i] > hi[wd] - lo[wd])
129 wd = i;
130
131 ptrdiff_t mid = lo[wd] + (hi[wd] - lo[wd]) * (np / 2) / np;
132
133 box sd1 = domain;
134 box sd2 = domain;
135
136 sd1.max_corner()[wd] = mid;
137 sd2.min_corner()[wd] = mid + 1;
138
139 split(sd1, np / 2);
140 split(sd2, np - np / 2);
141 }
142};
143
144#endif