PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
anonymous_namespace{testParallelCompLib.cpp} Namespace Reference

Functions

void printMsg (std::string msg, int mpiRank, int printMpiRank)
 
double f1 (const double &x)
 
double f2 (const double &x)
 
void setupOwnerAndGhost (size_t mpiSize, size_t mpiRank, const std::vector< size_t > &nodePartition, const std::vector< std::vector< size_t > > &nodeNeighs, std::vector< size_t > &ownedNodes, std::vector< size_t > &ownedInternalNodes, std::vector< size_t > &ownedBdryNodes, std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > &ghostData)
 
void exchangeDispData (size_t mpiSize, size_t mpiRank, const std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > &ghostData, std::vector< std::pair< std::vector< util::Point >, std::vector< util::Point > > > &dispGhostData, std::vector< util::Point > &dispNodes)
 

Function Documentation

◆ exchangeDispData()

void anonymous_namespace{testParallelCompLib.cpp}::exchangeDispData ( size_t  mpiSize,
size_t  mpiRank,
const std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > &  ghostData,
std::vector< std::pair< std::vector< util::Point >, std::vector< util::Point > > > &  dispGhostData,
std::vector< util::Point > &  dispNodes 
)

Definition at line 163 of file testParallelCompLib.cpp.

167 {
168 // resize dispGhostData if not done
169 dispGhostData.resize(mpiSize);
170 for (size_t j_proc = 0; j_proc < mpiSize; j_proc++) {
171 auto j_data_size = ghostData[j_proc].first.size(); // same size for second
172 dispGhostData[j_proc].first.resize(j_data_size);
173 dispGhostData[j_proc].second.resize(j_data_size);
174 }
175
176 // exchange data
177 util::io::print("\n\nBegin exchange data\n\n");
178 util::io::print(std::format("\n\nThis processor's rank = {}\n\n", mpiRank), util::io::print_default_tab, -1);
179 MPI_Request mpiRequests[2*(mpiSize-1)];
180 size_t requestCounter = 0;
181 for (size_t j_proc=0; j_proc<mpiSize; j_proc++) {
182 auto & sendIds = ghostData[j_proc].second;
183 auto & recvIds = ghostData[j_proc].first;
184
185 if (j_proc != mpiRank and recvIds.size() != 0) {
186
187 util::io::print(std::format("\n\n Processing j_proc = {}\n\n", j_proc), util::io::print_default_tab, -1);
188
189 // fill in ghost displacement data that we are sending from nodal displacement data
190 for (size_t k = 0; k<sendIds.size(); k++)
191 dispGhostData[j_proc].second[k] = dispNodes[sendIds[k]];
192
193 // send data from this process to j_proc
194 MPI_Isend(dispGhostData[j_proc].second.data(), 3*sendIds.size(),
195 MPI_DOUBLE, j_proc, 0, MPI_COMM_WORLD,
196 &mpiRequests[requestCounter++]);
197
198 // receive data from j_proc
199 MPI_Irecv(dispGhostData[j_proc].first.data(), 3*recvIds.size(),
200 MPI_DOUBLE, j_proc, 0, MPI_COMM_WORLD,
201 &mpiRequests[requestCounter++]);
202 }
203 } // loop over j_proc
204
205 util::io::print("\n\nCalling MPI_Waitall\n\n");
206 MPI_Waitall(requestCounter, mpiRequests, MPI_STATUSES_IGNORE);
207
208 util::io::print("\n\nUpdate dispNodes data\n\n");
209
210 for (size_t j_proc=0; j_proc<mpiSize; j_proc++) {
211 auto & recvIds = ghostData[j_proc].first;
212 if (j_proc != mpiRank and recvIds.size() != 0) {
213 for (size_t k = 0; k<recvIds.size(); k++)
214 dispNodes[recvIds[k]] = dispGhostData[j_proc].first[k];
215 }
216 } // loop over j_proc
217 } // exchangeDispData()
const int print_default_tab
Default value of tab used in outputting formatted information.
Definition constants.h:18
void print(const T &msg, int nt=print_default_tab, int printMpiRank=print_default_mpi_rank)
Prints formatted information.
Definition io.h:171
int mpiSize()
Get size (number) of processors.

References util::io::print(), and util::io::print_default_tab.

Referenced by test::testMPI().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ f1()

double anonymous_namespace{testParallelCompLib.cpp}::f1 ( const double &  x)

Definition at line 44 of file testParallelCompLib.cpp.

44 {
45 return x*x*x + std::exp(x) - std::sin(x);
46 }

Referenced by test::testTaskflow().

Here is the caller graph for this function:

◆ f2()

double anonymous_namespace{testParallelCompLib.cpp}::f2 ( const double &  x)

Definition at line 48 of file testParallelCompLib.cpp.

48 {
49 return 2*(x-0.5)*(x-0.5)*(x-0.5) + std::exp(x-0.5) - std::cos(x-0.5);
50 }

Referenced by test::testTaskflow().

Here is the caller graph for this function:

◆ printMsg()

void anonymous_namespace{testParallelCompLib.cpp}::printMsg ( std::string  msg,
int  mpiRank,
int  printMpiRank 
)

Definition at line 35 of file testParallelCompLib.cpp.

35 {
36 if (printMpiRank < 0) {
37 std::cout << msg;
38 } else {
39 if (mpiRank == printMpiRank)
40 std::cout << msg;
41 }
42 }

Referenced by test::testMPI().

Here is the caller graph for this function:

◆ setupOwnerAndGhost()

void anonymous_namespace{testParallelCompLib.cpp}::setupOwnerAndGhost ( size_t  mpiSize,
size_t  mpiRank,
const std::vector< size_t > &  nodePartition,
const std::vector< std::vector< size_t > > &  nodeNeighs,
std::vector< size_t > &  ownedNodes,
std::vector< size_t > &  ownedInternalNodes,
std::vector< size_t > &  ownedBdryNodes,
std::vector< std::pair< std::vector< size_t >, std::vector< size_t > > > &  ghostData 
)

Definition at line 52 of file testParallelCompLib.cpp.

59 {
60
61 auto numNodes = nodePartition.size();
62
63 // clear data
64 ownedNodes.clear();
65 ownedInternalNodes.clear();
66 ownedBdryNodes.clear();
67 ghostData.resize(mpiSize);
68 for (size_t i_proc=0; i_proc<mpiSize; i_proc++) {
69 ghostData[i_proc].first.clear();
70 ghostData[i_proc].second.clear();
71 }
72
73 // setup
74 for (size_t i=0; i<numNodes; i++) {
75 if (nodePartition[i] == mpiRank) {
76 // this processor owns this node
77 ownedNodes.push_back(i);
78
79 // ascertain if this node has neighboring nodes owned by other processors
80 bool ghostExist = false;
81 for (auto j : nodeNeighs[i]) {
82 auto j_proc = nodePartition[j];
83 if (j_proc != mpiRank) {
84 ghostExist = true;
85
86 // add j to ghost node list (to receive from j_proc)
87 ghostData[j_proc].first.push_back(j);
88
89 // add i to ghost node list (to send to j_proc)
90 ghostData[j_proc].second.push_back(i);
91 }
92 }
93
94 if (ghostExist)
95 ownedBdryNodes.push_back(i);
96 else
97 ownedInternalNodes.push_back(i);
98 } // loop over neighboring nodes
99 } // loop over nodes
100
102 bool debugGhostData = false;
103 if (debugGhostData and mpiRank == 0) {
104 std::vector<std::vector<std::pair<std::vector<size_t>, std::vector<size_t>>>> ghostDataAllProc(
105 mpiSize);
106 std::vector<std::vector<size_t>> numGhostDataAllProc(mpiSize);
107 for (size_t i_proc = 0; i_proc < mpiSize; i_proc++) {
108 numGhostDataAllProc[i_proc].resize(mpiSize);
109 ghostDataAllProc[i_proc].resize(mpiSize);
110 }
111
112 for (size_t i_proc = 0; i_proc < mpiSize; i_proc++) {
113 // assume we are i_proc and then create ghostData for i_proc
114 for (size_t i = 0; i < numNodes; i++) {
115 if (nodePartition[i] == i_proc) {
116 // i_proc processor owns this node
117 for (auto j: nodeNeighs[i]) {
118 auto j_proc = nodePartition[j];
119 if (j_proc != i_proc) {
120 // add to ghost node list
121 ghostDataAllProc[i_proc][j_proc].first.push_back(j);
122 }
123 }
124 } // loop over neighboring nodes
125 } // loop over nodes
126
127 // total number of ghost nodes from neighboring processors
128 for (size_t j_proc = 0; j_proc < mpiSize; j_proc++)
129 numGhostDataAllProc[i_proc][j_proc] = ghostDataAllProc[i_proc][j_proc].first.size();
130 } // loop over i_proc
131
132 // print the information
133 std::cout << "\n\nGhost data debug output\n\n";
134 bool found_asym = false;
135 for (size_t i_proc = 0; i_proc < mpiSize; i_proc++) {
136 for (size_t j_proc = 0; j_proc < mpiSize; j_proc++) {
137 std::cout << std::format("(i,j) = ({}, {}), num data = {}\n",
138 i_proc, j_proc,
139 numGhostDataAllProc[i_proc][j_proc]);
140
141 if (j_proc > i_proc) {
142 if (numGhostDataAllProc[i_proc][j_proc] == numGhostDataAllProc[j_proc][i_proc])
143 std::cout << std::format(" symmetric: data ({}, {}) = data ({}, {})\n",
144 i_proc, j_proc, j_proc, i_proc);
145 else {
146 found_asym = true;
147 std::cout << std::format(
148 " asymmetric: data ({}, {}) != data ({}, {})\n",
149 i_proc, j_proc, j_proc, i_proc);
150 }
151 }
152 }
153 }
154 if (found_asym)
155 std::cout << "Found asymetric ghost data\n";
156 else
157 std::cout << "No asymetric ghost data\n";
158
159 }
161 } // setupOwnerAndGhost()

Referenced by test::testMPI().

Here is the caller graph for this function: