Epetra Package Browser (Single Doxygen Collection) Development
Loading...
Searching...
No Matches
test/BlockMap_LL/cxx_main.cpp
Go to the documentation of this file.
1//@HEADER
2// ************************************************************************
3//
4// Epetra: Linear Algebra Services Package
5// Copyright 2011 Sandia Corporation
6//
7// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8// the U.S. Government retains certain rights in this software.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ************************************************************************
40//@HEADER
41
42
43// Epetra_BlockMap Test routine
44
45#include "Epetra_Time.h"
46#include "Epetra_BlockMap.h"
47#ifdef EPETRA_MPI
48#include "Epetra_MpiComm.h"
49#include <mpi.h>
50#endif
51#include "Epetra_SerialComm.h"
52#include "checkmap.h"
53#include "../epetra_test_err.h"
54#include "Epetra_Version.h"
55
56int main(int argc, char *argv[]) {
57 bool verbose = false;
58 // Check if we should print results to standard out
59 if (argc > 1)
60 if ((argv[1][0] == '-') && (argv[1][1] == 'v'))
61 verbose = true;
62
63 int i;
64 int ierr = 0;
65 int returnierr = 0;
66
67#ifdef EPETRA_MPI
68
69 // Initialize MPI
70 MPI_Init(&argc,&argv);
71 Epetra_MpiComm Comm(MPI_COMM_WORLD);
72#else
74#endif
75
76 if (!verbose) {
77 Comm.SetTracebackMode(0); // This should shut down any error traceback reporting
78 }
79 int MyPID = Comm.MyPID();
80 int NumProc = Comm.NumProc();
81
82 int verbose_int = verbose ? 1 : 0;
83 Comm.Broadcast(&verbose_int, 1, 0);
84 verbose = verbose_int==1 ? true : false;
85
86 if (verbose && MyPID==0)
87 cout << Epetra_Version() << endl << endl;
88
89 if (verbose) cout << Comm << endl << flush;
90 Comm.Barrier();
91 bool verbose1 = verbose;
92 if (verbose) verbose = (MyPID==0);
93
94 int NumMyElements = 10000;
95 long long NumGlobalElements = NumMyElements*NumProc+EPETRA_MIN(NumProc,3);
96 if (MyPID < 3) NumMyElements++;
97 long long IndexBase = 0;
98 int ElementSize = 7;
99 bool DistributedGlobal = (NumGlobalElements>NumMyElements);
100 bool IsOneToOne = true;
101 Epetra_BlockMap * Map;
102
103 // Test exceptions
104
105 if (verbose)
106 cout << "*******************************************************************************************" << endl
107 << " Testing Exceptions (Expect error messages if EPETRA_NO_ERROR_REPORTS is not defined" << endl
108 << "*******************************************************************************************" << endl
109 << endl << endl;
110
111 try {
112 if (verbose) cout << "Checking Epetra_BlockMap(-2, ElementSize, IndexBase, Comm)" << endl;
113 Epetra_BlockMap TestMap(-2LL, ElementSize, IndexBase, Comm);
114 }
115 catch (int Error) {
116 if (Error != -1) {
117 if (Error != 0) {
118 EPETRA_TEST_ERR(Error,returnierr);
119 if (verbose) cout << "Error code should be -1" << endl;
120 }
121 else { // Error == 0
122 cout << "Error code = " << Error << "Should be -1" << endl;
123 returnierr += 1;
124 }
125 }
126 else if (verbose) cout << "Checked OK\n\n" << endl;
127 }
128
129 try {
130 if (verbose) cout << "Checking Epetra_BlockMap(2, 3, ElementSize, IndexBase, Comm)" << endl;
131 Epetra_BlockMap TestMap(2LL, 3, ElementSize, IndexBase, Comm);
132 }
133 catch (int Error) {
134 if (Error != -4) {
135 if (Error != 0) {
136 EPETRA_TEST_ERR(Error,returnierr);
137 if (verbose) cout << "Error code should be -4" << endl;
138 }
139 else { // Error == 0
140 cout << "Error code = " << Error << "Should be -4" << endl;
141 returnierr += 1;
142 }
143 }
144 else if (verbose) cout << "Checked OK\n\n" << endl;
145 }
146
147 if (verbose) cerr << flush;
148 if (verbose) cout << flush;
149 Comm.Barrier();
150 if (verbose)
151 cout << endl << endl
152 << "*******************************************************************************************" << endl
153 << " Testing valid constructor now......................................................" << endl
154 << "*******************************************************************************************" << endl
155 << endl << endl;
156 // Test Epetra-defined uniform linear distribution constructor
157 Map = new Epetra_BlockMap(NumGlobalElements, ElementSize, IndexBase, Comm);
158 if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, ElementSize, IndexBase, Comm)" << endl;
159 ierr = checkmap(*Map, NumGlobalElements, NumMyElements, 0, ElementSize, 0,
160 NumGlobalElements*ElementSize, NumMyElements*ElementSize,
161 IndexBase, Comm, DistributedGlobal,IsOneToOne);
162
163 EPETRA_TEST_ERR(ierr,returnierr);
164 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
165
166 delete Map;
167
168 // Test User-defined linear distribution constructor
169 Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm);
170
171 if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm)" << endl;
172 ierr = checkmap(*Map, NumGlobalElements, NumMyElements, 0, ElementSize, 0,
173 NumGlobalElements*ElementSize, NumMyElements*ElementSize,
174 IndexBase, Comm, DistributedGlobal,IsOneToOne);
175
176 EPETRA_TEST_ERR(ierr,returnierr);
177 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
178
179 delete Map;
180
181 // Test User-defined arbitrary distribution constructor and fill MyGlobalElements
182 // such that the map is not one-to-one.
183 int NumMyElems = 5;
184 long long NumGlobalElems = (Comm.NumProc()+1)*NumMyElems;
185 long long myFirstElem = Comm.MyPID()*NumMyElems;
186 if (Comm.MyPID() == 0) NumMyElems *= 2;
187
188 long long* myElems = new long long[NumMyElems];
189 for(int ii=0; ii<NumMyElems; ++ii) {
190 myElems[ii] = myFirstElem + ii;
191 }
192
193 Map = new Epetra_BlockMap(NumGlobalElems, NumMyElems, myElems, 1, 0, Comm);
194
195 if (verbose) cout << "Checking non-oneToOne Epetra_BlockMap(...)"<<endl;
196 ierr = Map->IsOneToOne() == false ? 0 : -1;
197
198 //this Map is 1-to-1 if we're running on 1 processor, otherwise it
199 //should not be 1-to-1.
200 if (Comm.NumProc() > 1) {
201 EPETRA_TEST_ERR(ierr,returnierr);
202 }
203 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
204
205 delete [] myElems;
206 delete Map;
207
208 // Test User-defined arbitrary distribution constructor
209 // Generate Global Element List. Do in reverse for fun!
210
211 long long * MyGlobalElements = new long long[NumMyElements];
212 long long MaxMyGID = (Comm.MyPID()+1)*NumMyElements-1+IndexBase;
213 if (Comm.MyPID()>2)
214 MaxMyGID+=3;
215 for (i = 0; i<NumMyElements; i++)
216 MyGlobalElements[i] = MaxMyGID-i;
217
218 Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize,
219 IndexBase, Comm);
220
221 if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, IndexBase, Comm)" << endl;
222 ierr = checkmap(*Map, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, 0,
223 NumGlobalElements*ElementSize, NumMyElements*ElementSize,
224 IndexBase, Comm, DistributedGlobal,IsOneToOne);
225
226 EPETRA_TEST_ERR(ierr,returnierr);
227 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
228
229 Epetra_BlockMap * Map3 = new Epetra_BlockMap(*Map);// A map to test the SameAs method later
230
231 delete Map;
232
233 int * ElementSizeList = new int[NumMyElements];
234 int NumMyEquations = 0;
235 int NumGlobalEquations = 0;
236 for (i = 0; i<NumMyElements; i++) {
237 ElementSizeList[i] = i%6 + 2; // elementsizes go from 2 to 7
238 NumMyEquations += ElementSizeList[i];
239 }
240 ElementSize = 7; // Set to maximum for use in checkmap
241 NumGlobalEquations = Comm.NumProc()*NumMyEquations;
242
243 // Adjust NumGlobalEquations based on processor ID
244 if (Comm.NumProc() > 3) {
245 if (Comm.MyPID()>2)
246 NumGlobalEquations += 3*((NumMyElements)%6+2);
247 else
248 NumGlobalEquations -= (Comm.NumProc()-3)*((NumMyElements-1)%6+2);
249 }
250 Map = new Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSizeList,
251 IndexBase, Comm);
252 if (verbose) cout << "Checking Epetra_BlockMap(NumGlobalElements, NumMyElements, MyGlobalElements, ElementSizeList, IndexBase, Comm)" << endl;
253 ierr = checkmap(*Map, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, ElementSizeList,
254 NumGlobalEquations, NumMyEquations,
255 IndexBase, Comm, DistributedGlobal,IsOneToOne);
256
257 EPETRA_TEST_ERR(ierr,returnierr);
258 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
259
260 // Test Copy constructor
261 Epetra_BlockMap * Map1 = new Epetra_BlockMap(*Map);
262
263 // Test SameAs() method
264 bool same = Map1->SameAs(*Map);
265 EPETRA_TEST_ERR(!(same==true),returnierr);// should return true since Map1 is a copy of Map
266
267 Epetra_BlockMap * Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList,IndexBase,Comm);
268 same = Map2->SameAs(*Map);
269 EPETRA_TEST_ERR(!(same==true),returnierr); // Map and Map2 were created with the same sets of parameters
270 delete Map2;
271
272 // now test SameAs() on some maps that are different
273
274 Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList,IndexBase-1,Comm);
275 same = Map2->SameAs(*Map);
276 EPETRA_TEST_ERR(!(same==false),returnierr); // IndexBases are different
277 delete Map2;
278
279 int *ElementSizeList1 = new int[NumMyElements];
280 for (i=0; i<NumMyElements; i++)
281 ElementSizeList1[i] = i%5 + 2; // element sizes go from 2 to 6
282 Map2 = new Epetra_BlockMap(NumGlobalElements,NumMyElements,MyGlobalElements,ElementSizeList1,IndexBase,Comm);
283 same = Map2->SameAs(*Map);
284 EPETRA_TEST_ERR(!(same==false),returnierr); // ElementSizes are different
285 delete [] ElementSizeList1;
286 delete Map2;
287
288 same = Map3->SameAs(*Map);
289 EPETRA_TEST_ERR(!(same==false),returnierr); // Map3 saved from an earlier test
290 delete Map3;
291
292 // Back to testing copy constructor
293 if (verbose) cout << "Checking Epetra_BlockMap(*Map)" << endl;
294 ierr = checkmap(*Map1, NumGlobalElements, NumMyElements, MyGlobalElements, ElementSize, ElementSizeList,
295 NumGlobalEquations, NumMyEquations,
296 IndexBase, Comm, DistributedGlobal,IsOneToOne);
297
298 EPETRA_TEST_ERR(ierr,returnierr);
299 if (verbose && ierr==0) cout << "Checked OK\n\n" <<endl;
300
301 if (verbose1) {
302 if (verbose) cout << "Test ostream << operator" << endl << flush;
303 }
304 // Build a small map for test cout. Use 10 elements from current map
305 long long * MyEls = Map->MyGlobalElements64();
306 int * MySz = Map->ElementSizeList();
307 long long IndBase = Map->IndexBase64();
308 int MyLen = EPETRA_MIN(10+Comm.MyPID(),Map->NumMyElements());
309 Epetra_BlockMap * SmallMap = new Epetra_BlockMap((long long)-1, MyLen, MyEls, MySz, IndBase, Comm);
310 if (verbose1) {
311 cout << *SmallMap;
312 }
313 delete SmallMap;
314
315 delete Map;
316 delete Map1;
317
318
319 //create a map where proc 1 has no local elements, then check to make sure that
320 //if NumMyElements == 0, then MaxMyGID < MinMyGID.
321
322 if (MyPID == 1) {
323 Map1 = new Epetra_BlockMap(-1, 0, (long long*)0, (int*)0, IndexBase, Comm);
324 }
325 else {
326 Map1 = new Epetra_BlockMap(-1, NumMyElements, MyGlobalElements, ElementSizeList, IndexBase, Comm);
327 }
328
329 int numMyElems = Map1->NumMyElements();
330 if (MyPID == 1) {
331 EPETRA_TEST_ERR(!(numMyElems == 0), returnierr);
332 long long maxgid = Map1->MaxMyGID64();
333 long long mingid = Map1->MinMyGID64();
334 EPETRA_TEST_ERR( !(maxgid<mingid), returnierr);
335 }
336
337 delete[] ElementSizeList;
338 delete[] MyGlobalElements;
339 delete Map1;
340
341 // test reference counting
342 ierr = 0;
343
344 if (verbose)
345 cout << endl << endl
346 << "*******************************************************************************************" << endl
347 << " Testing reference counting now....................................................." << endl
348 << "*******************************************************************************************" << endl << endl;
349
350 Epetra_BlockMap b1(NumGlobalElements, NumMyElements, ElementSize, IndexBase, Comm);
351 int b1count = b1.ReferenceCount();
352 const Epetra_BlockMapData* b1addr = b1.DataPtr();
353 EPETRA_TEST_ERR(!(b1count==1),ierr); // count should be 1
354 if(verbose) cout << "Default constructor. \nb1= " << b1count << " " << b1addr << endl;
355
356 Epetra_BlockMap* b2 = new Epetra_BlockMap(b1);
357 int b2count = b2->ReferenceCount();
358 const Epetra_BlockMapData* b2addr = b2->DataPtr();
359 int b1countold = b1count;
360 b1count = b1.ReferenceCount();
361 EPETRA_TEST_ERR(!(b2count==b1count && b1count==(b1countold+1)),ierr); // both counts should be 2
362 EPETRA_TEST_ERR(!(b1addr==b2addr),ierr); // addresses should be same
363 if(verbose) cout << "Copy constructor. \nb1= " << b1count << " " << b1addr << "\nb2= " << b2count << " " << b2addr << endl;
364
365 delete b2;
366 b1countold = b1count;
367 b1count = b1.ReferenceCount();
368 EPETRA_TEST_ERR(!(b1count==b1countold-1), ierr); // count should have decremented (to 1)
369 EPETRA_TEST_ERR(!(b1addr==b1.DataPtr()), ierr); // b1addr should be unchanged
370 if(verbose) cout << "b2 destroyed. \nb1= " << b1count << " " << b1addr << endl;
371
372 { // inside of braces to test stack deallocation.
373 if(verbose) cout << "Assignment operator, post construction" << endl;
374 Epetra_BlockMap b3(NumGlobalElements, NumMyElements, ElementSize, IndexBase-1, Comm);
375 int b3count = b3.ReferenceCount();
376 const Epetra_BlockMapData* b3addr = b3.DataPtr();
377 EPETRA_TEST_ERR(!(b3count==1),ierr); // b3count should be 1 initially
378 EPETRA_TEST_ERR(!(b1addr!=b3addr),ierr); // b1 and b3 should have different ptr addresses
379 if(verbose) cout << "Prior to assignment: \nb1= " << b1count << " " << b1addr << "\nb3= " << b3count << " " << b3addr << endl;
380 b3 = b1;
381 b3count = b3.ReferenceCount();
382 b3addr = b3.DataPtr();
383 b1countold = b1count;
384 b1count = b1.ReferenceCount();
385 EPETRA_TEST_ERR(!(b3count==b1count && b1count==b1countold+1),ierr); // both counts should be 2
386 EPETRA_TEST_ERR(!(b1addr==b3addr),ierr); // addresses should be same
387 if(verbose) cout << "After assignment: \nb1= " << b1count << " " << b1addr << "\nb3= " << b3count << " " << b3addr << endl;
388 }
389 b1countold = b1count;
390 b1count = b1.ReferenceCount();
391 EPETRA_TEST_ERR(!(b1count==b1countold-1), ierr); // count should have decremented (to 1)
392 EPETRA_TEST_ERR(!(b1addr==b1.DataPtr()), ierr); // b1addr should be unchanged
393 if (verbose) cout << "b3 destroyed. \nb1= " << b1count << " " << b1addr << endl;
394
395 EPETRA_TEST_ERR(ierr,returnierr);
396 if (verbose && (ierr == 0)) cout << "Checked OK\n\n" <<endl;
397 // done with reference counting testing
398
399
400 // test subcommunicators
401 ierr=0;
402 if (verbose)
403 cout << endl << endl
404 << "*******************************************************************************************" << endl
405 << " Testing subcommunicators now......................................................." << endl
406 << "*******************************************************************************************" << endl << endl;
407
408 // Create a map where everything is on proc 0
409 if (MyPID != 0) {
410 Map1 = new Epetra_BlockMap((long long)-1, 0, 1, IndexBase, Comm);
411 }
412 else {
413 Map1 = new Epetra_BlockMap((long long)-1, NumMyElements, 1, IndexBase, Comm);
414 }
415
416 // Remove empty processes ...
417 Map2=0; Map2 = Map1->RemoveEmptyProcesses();
418 if(MyPID==0) {EPETRA_TEST_ERR(Map2 == 0,ierr);}
419 else {EPETRA_TEST_ERR(Map2 != 0,ierr);}
420
421 // Replace comm
422 const Epetra_Comm * TempComm = Map2 ? &Map2->Comm() : 0;
423 Map3=0; Map3 = Map1->ReplaceCommWithSubset(TempComm);
424 if(MyPID==0) {EPETRA_TEST_ERR(Map3 == 0,ierr);}
425 else {EPETRA_TEST_ERR(Map3 != 0,ierr);}
426
427 delete Map1; delete Map2; delete Map3;
428
429
430#ifdef EPETRA_MPI
431 MPI_Finalize();
432#endif
433
434 return returnierr;
435}
int checkmap(Epetra_BlockMap &Map, int NumGlobalElements, int NumMyElements, int *MyGlobalElements, int ElementSize, int *ElementSizeList, int NumGlobalPoints, int NumMyPoints, int IndexBase, Epetra_Comm &Comm, bool DistributedGlobal, bool IsOneToOne)
#define EPETRA_MIN(x, y)
std::string Epetra_Version()
Epetra_BlockMapData: The Epetra BlockMap Data Class.
Epetra_BlockMap: A class for partitioning block element vectors and matrices.
long long IndexBase64() const
long long * MyGlobalElements64() const
long long MaxMyGID64() const
int * ElementSizeList() const
List of the element sizes corresponding to the array MyGlobalElements().
int ReferenceCount() const
Returns the reference count of BlockMapData.
bool SameAs(const Epetra_BlockMap &Map) const
Returns true if this and Map are identical maps.
Epetra_BlockMap * ReplaceCommWithSubset(const Epetra_Comm *Comm) const
Replace this BlockMap's communicator with a subset communicator.
const Epetra_Comm & Comm() const
Access function for Epetra_Comm communicator.
const Epetra_BlockMapData * DataPtr() const
Returns a pointer to the BlockMapData instance this BlockMap uses.
long long MinMyGID64() const
int NumMyElements() const
Number of elements on the calling processor.
bool IsOneToOne() const
Epetra_BlockMap * RemoveEmptyProcesses() const
Return a new BlockMap with processes with zero elements removed.
Epetra_Comm: The Epetra Communication Abstract Base Class.
Definition Epetra_Comm.h:73
Epetra_MpiComm: The Epetra MPI Communication Class.
void Barrier() const
Epetra_MpiComm Barrier function.
int Broadcast(double *MyVals, int Count, int Root) const
Epetra_MpiComm Broadcast function.
int NumProc() const
Returns total number of processes.
int MyPID() const
Return my process ID.
static void SetTracebackMode(int TracebackModeValue)
Set the value of the Epetra_Object error traceback report mode.
Epetra_SerialComm: The Epetra Serial Communication Class.
#define EPETRA_TEST_ERR(a, b)
int main(int argc, char *argv[])