openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
test_petsc_numbering_empty_rank.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) NumeriCor GmbH
2 // SPDX-License-Identifier: Apache-2.0
3 
19 #include "SF_base.h"
20 #include "basics.h"
21 
22 #include <mpi.h>
23 
24 #include <iostream>
25 #include <string>
26 #include <vector>
27 
28 namespace {
29 
30 using SF::vector;
32 
35 constexpr int NX = 4;
36 constexpr int NY = 4;
37 constexpr int NUM_PTS = NX * NY;
38 
39 int failures = 0;
40 
41 void check(bool ok, const std::string& what, int rank)
42 {
43  if (!ok) {
44  std::cerr << "FAILED [rank " << rank << "]: " << what << '\n';
45  failures++;
46  }
47 }
48 
52 void global_indices(int rank, vector<SF_int>& gidx)
53 {
54  gidx.resize(rank == 0 ? NUM_PTS : 0);
55  for (size_t i = 0; i < gidx.size(); i++) gidx[i] = SF_int(i);
56 }
57 
60 void build_mesh(int rank, MPI_Comm comm, mesh_t& mesh)
61 {
62  mesh.comm = comm;
63  mesh.g_numpts = NUM_PTS;
64 
65  vector<SF_int> cnt;
66  if (rank == 0) {
67  for (int y = 0; y + 1 < NY; y++) {
68  for (int x = 0; x + 1 < NX; x++) {
69  const SF_int n = SF_int(y * NX + x);
70  mesh.con.push_back(n);
71  mesh.con.push_back(n + 1);
72  mesh.con.push_back(n + NX + 1);
73  mesh.con.push_back(n + NX);
74  cnt.push_back(4);
75  }
76  }
77  }
78 
79  mesh.l_numelem = cnt.size();
80  SF::dsp_from_cnt(cnt, mesh.dsp);
81 
82  vector<SF_int> gidx;
83  global_indices(rank, gidx);
84  mesh.pl.assign(gidx, comm);
85  mesh.l_numpts = mesh.pl.num_local_idx();
86 }
87 
89 void run_case(bool use_rcm, MPI_Comm comm, int rank)
90 {
91  const std::string what = use_rcm ? "renumbered" : "ascending";
92 
93  mesh_t mesh;
94  build_mesh(rank, comm, mesh);
95 
96  const vector<SF_int>& alg_nod = mesh.pl.algebraic_nodes();
97  if (rank == 0)
98  check(alg_nod.size() == NUM_PTS, what + ": rank 0 owns the whole grid", rank);
99  else
100  check(alg_nod.size() == 0, what + ": rank owns no algebraic node", rank);
101 
102  SF::petsc_numbering<SF_int, SF_real> numbering(mesh.pl, use_rcm);
103  numbering(mesh);
104 
105  const vector<SF_int>& petsc_idx = mesh.get_numbering(SF::NBR_PETSC);
106  const vector<SF_int>& alg_dsp = mesh.pl.algebraic_layout();
107  const SF_int alg_start = alg_dsp[rank];
108 
109  // The invariant that makes a renumbering invisible to everything reading the local
110  // PETSc arrays by algebraic position.
111  bool positional = true;
112  for (size_t i = 0; i < alg_nod.size(); i++)
113  if (petsc_idx[alg_nod[i]] != alg_start + SF_int(i)) positional = false;
114  check(positional, what + ": algebraic position matches the PETSc slot", rank);
115 
116  // Renumbering permutes the algebraic node set, it must not change which nodes are in it.
117  std::vector<bool> seen(mesh.pl.num_local_idx(), false);
118  bool set_intact = true;
119  for (size_t i = 0; i < alg_nod.size(); i++) {
120  const SF_int n = alg_nod[i];
121  if (n < 0 || size_t(n) >= seen.size() || seen[n]) set_intact = false;
122  else seen[n] = true;
123  }
124  check(set_intact, what + ": algebraic node set is free of gaps and duplicates", rank);
125 }
126 
127 } // namespace
128 
129 int main(int argc, char** argv)
130 {
131  MPI_Init(&argc, &argv);
132 
133  MPI_Comm comm = MPI_COMM_WORLD;
134  int size, rank;
135  MPI_Comm_size(comm, &size);
136  MPI_Comm_rank(comm, &rank);
137 
138  if (size < 2) {
139  if (!rank) std::cerr << "FAILED: this test needs at least 2 ranks to leave one empty\n";
140  MPI_Finalize();
141  return 1;
142  }
143 
144  run_case(false, comm, rank);
145  run_case(true, comm, rank);
146 
147  int total = 0;
148  MPI_Allreduce(&failures, &total, 1, MPI_INT, MPI_SUM, comm);
149 
150  MPI_Finalize();
151  return total ? 1 : 0;
152 }
The base header file.
opencarp::global_index_t SF_int
Global algebraic index type.
Definition: SF_globals.h:17
Basic utility structs and functions, mostly IO related.
The mesh storage class. It contains both element and vertex data.
Definition: SF_container.h:381
Functor class generating a numbering optimized for PETSc.
Definition: SF_numbering.h:238
A vector storing arbitrary data.
Definition: SF_vector.h:28
void dsp_from_cnt(const vector< T > &cnt, vector< T > &dsp)
Compute displacements from counts.
Definition: SF_vector.h:295
@ NBR_PETSC
PETSc numbering of nodes.
Definition: SF_container.h:188
mesh_t
The enum identifying the different meshes we might want to load.
Definition: sf_interface.h:44
int main(int argc, char **argv)