xref: /petsc/src/mat/tests/ex231.cxx (revision 589a23caa660d2a5f330cc8d1ed213e9cfaf51a7)
1c4762a1bSJed Brown static char help[] = "A test for MatAssembly that heavily relies on PetscSortIntWithArrayPair\n";
2c4762a1bSJed Brown 
3c4762a1bSJed Brown /*
4c4762a1bSJed Brown    The characteristic of the array (about 4M in length) to sort in this test is that it has
5c4762a1bSJed Brown    many duplicated values that already clustered together (around 95 duplicates per unique integer).
6c4762a1bSJed Brown 
7c4762a1bSJed Brown    It was gotten from a petsc performance bug report from the Moose project. One can use
8c4762a1bSJed Brown    it for future performance study.
9c4762a1bSJed Brown 
10c4762a1bSJed Brown    Contributed-by: Fande Kong <fdkong.jd@gmail.com>, John Peterson <jwpeterson@gmail.com>
11c4762a1bSJed Brown  */
12c4762a1bSJed Brown #define PETSC_SKIP_CXX_COMPLEX_FIX
13c4762a1bSJed Brown 
14c4762a1bSJed Brown // PETSc includes
15c4762a1bSJed Brown #include <petscmat.h>
16c4762a1bSJed Brown 
17c4762a1bSJed Brown // C++ includes
18c4762a1bSJed Brown #include <iostream>
19c4762a1bSJed Brown #include <fstream>
20c4762a1bSJed Brown #include <sstream>
21c4762a1bSJed Brown #include <algorithm>
22c4762a1bSJed Brown #include <vector>
23c4762a1bSJed Brown #include <string>
24c4762a1bSJed Brown #include <set>
25c4762a1bSJed Brown 
26c4762a1bSJed Brown int main (int argc, char** argv)
27c4762a1bSJed Brown {
28c4762a1bSJed Brown   PetscErrorCode ierr;
29c4762a1bSJed Brown   PetscMPIInt    size, rank;
30c4762a1bSJed Brown   char           file[2][PETSC_MAX_PATH_LEN];
31c4762a1bSJed Brown   PetscBool      flg;
32c4762a1bSJed Brown   const unsigned int n_dofs = 26559;
33c4762a1bSJed Brown   unsigned int   first_local_index;
34c4762a1bSJed Brown   unsigned int   last_local_index;
35c4762a1bSJed Brown 
36c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr;
37c4762a1bSJed Brown   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
38c4762a1bSJed Brown   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
39c4762a1bSJed Brown   if (size > 2) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This example is for <=2 procs");
40c4762a1bSJed Brown 
41*589a23caSBarry Smith   ierr = PetscOptionsGetString(NULL,NULL,"-f0",file[0],sizeof(file[0]),&flg);CHKERRQ(ierr);
42c4762a1bSJed Brown   if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate dof indices file for rank 0 with -f0 option");
43c4762a1bSJed Brown   if (size == 2) {
44*589a23caSBarry Smith     ierr = PetscOptionsGetString(NULL,NULL,"-f1",file[1],sizeof(file[1]),&flg);CHKERRQ(ierr);
45c4762a1bSJed Brown     if (!flg) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_USER,"Must indicate dof indices file for rank 1 with -f1 option");
46c4762a1bSJed Brown   }
47c4762a1bSJed Brown 
48c4762a1bSJed Brown   if (size == 1) {
49c4762a1bSJed Brown     first_local_index = 0;
50c4762a1bSJed Brown     last_local_index  = 26559;
51c4762a1bSJed Brown   } else {
52c4762a1bSJed Brown     if (rank == 0) {
53c4762a1bSJed Brown       first_local_index = 0;
54c4762a1bSJed Brown       last_local_index  = 13911;
55c4762a1bSJed Brown     } else {
56c4762a1bSJed Brown       first_local_index = 13911;
57c4762a1bSJed Brown       last_local_index  = 26559;
58c4762a1bSJed Brown     }
59c4762a1bSJed Brown   }
60c4762a1bSJed Brown 
61c4762a1bSJed Brown   // Read element dof indices from files
62c4762a1bSJed Brown   std::vector<std::vector<std::vector<PetscInt> > > elem_dof_indices(size);
63c4762a1bSJed Brown   for (PetscInt proc_id = 0; proc_id < size; ++proc_id) {
64c4762a1bSJed Brown     std::string line;
65c4762a1bSJed Brown     std::ifstream dof_file(file[proc_id]);
66c4762a1bSJed Brown     if (dof_file.good()) {
67c4762a1bSJed Brown       while (std::getline (dof_file,line)) {
68c4762a1bSJed Brown         std::vector<PetscInt> dof_indices;
69c4762a1bSJed Brown         std::stringstream sstream(line);
70c4762a1bSJed Brown         std::string token;
71c4762a1bSJed Brown         while (std::getline(sstream, token, ' ')) {dof_indices.push_back(std::atoi(token.c_str()));}
72c4762a1bSJed Brown         elem_dof_indices[proc_id].push_back(dof_indices);
73c4762a1bSJed Brown       }
74c4762a1bSJed Brown     } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Could not open file %s",file[proc_id]);
75c4762a1bSJed Brown   }
76c4762a1bSJed Brown 
77c4762a1bSJed Brown   // Debugging: Verify we read in elem_dof_indices correctly
78c4762a1bSJed Brown   // for (unsigned int i=0; i<elem_dof_indices.size(); ++i)
79c4762a1bSJed Brown   //   {
80c4762a1bSJed Brown   //     for (unsigned int j=0; j<elem_dof_indices[i].size(); ++j)
81c4762a1bSJed Brown   //       {
82c4762a1bSJed Brown   //         for (unsigned int k=0; k<elem_dof_indices[i][j].size(); ++k)
83c4762a1bSJed Brown   //           std::cout << elem_dof_indices[i][j][k] << " ";
84c4762a1bSJed Brown   //         std::cout << std::endl;
85c4762a1bSJed Brown   //       }
86c4762a1bSJed Brown   //     std::cout << std::endl;
87c4762a1bSJed Brown   //   }
88c4762a1bSJed Brown 
89c4762a1bSJed Brown   // Set up the (global) sparsity pattern
90c4762a1bSJed Brown   std::vector< std::set< unsigned int > > sparsity(n_dofs);
91c4762a1bSJed Brown   for (PetscInt proc_id = 0; proc_id < size; ++proc_id)
92c4762a1bSJed Brown     for (unsigned int k = 0; k < elem_dof_indices[proc_id].size(); k++) {
93c4762a1bSJed Brown       std::vector<PetscInt>& dof_indices = elem_dof_indices[proc_id][k];
94c4762a1bSJed Brown       for (unsigned int i = 0; i < dof_indices.size(); ++i)
95c4762a1bSJed Brown         for (unsigned int j = 0; j < dof_indices.size(); ++j)
96c4762a1bSJed Brown           sparsity[dof_indices[i]].insert(dof_indices[j]);
97c4762a1bSJed Brown     }
98c4762a1bSJed Brown 
99c4762a1bSJed Brown   // Determine the local nonzeros on this processor
100c4762a1bSJed Brown   const unsigned int n_local_dofs = last_local_index - first_local_index;
101c4762a1bSJed Brown   std::vector<PetscInt> n_nz(n_local_dofs);
102c4762a1bSJed Brown   std::vector<PetscInt> n_oz(n_local_dofs);
103c4762a1bSJed Brown 
104c4762a1bSJed Brown   for (unsigned int i = 0; i < n_local_dofs; ++i) {
105c4762a1bSJed Brown     for (std::set<unsigned int>::iterator iter = sparsity[i+first_local_index].begin(); iter != sparsity[i+first_local_index].end(); iter++) {
106c4762a1bSJed Brown       unsigned int dof = *iter;
107c4762a1bSJed Brown       if ((dof >= first_local_index) && (dof < last_local_index)) n_nz[i]++;
108c4762a1bSJed Brown       else n_oz[i]++;
109c4762a1bSJed Brown     }
110c4762a1bSJed Brown   }
111c4762a1bSJed Brown 
112c4762a1bSJed Brown   // Debugging: print number of on/off diagonal nonzeros
113c4762a1bSJed Brown   // for (unsigned int i=0; i<n_nz.size(); ++i)
114c4762a1bSJed Brown   //   std::cout << n_nz[i] << " ";
115c4762a1bSJed Brown   // std::cout << std::endl;
116c4762a1bSJed Brown 
117c4762a1bSJed Brown   // for (unsigned int i=0; i<n_oz.size(); ++i)
118c4762a1bSJed Brown   //   std::cout << n_oz[i] << " ";
119c4762a1bSJed Brown   // std::cout << std::endl;
120c4762a1bSJed Brown 
121c4762a1bSJed Brown   // Compute and print max number of on- and off-diagonal nonzeros.
122c4762a1bSJed Brown   PetscInt n_nz_max = *std::max_element(n_nz.begin(), n_nz.end());
123c4762a1bSJed Brown   PetscInt n_oz_max = *std::max_element(n_oz.begin(), n_oz.end());
124c4762a1bSJed Brown 
125c4762a1bSJed Brown   ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "Max on-diagonal non-zeros: = %d\n", n_nz_max);CHKERRQ(ierr);
126c4762a1bSJed Brown   ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "Max off-diagonal non-zeros: = %d\n", n_oz_max);CHKERRQ(ierr);
127c4762a1bSJed Brown   ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,PETSC_STDOUT);CHKERRQ(ierr);
128c4762a1bSJed Brown 
129c4762a1bSJed Brown   // Initialize the matrix similar to what we do in the PetscMatrix
130c4762a1bSJed Brown   // ctor and init() routines.
131c4762a1bSJed Brown   Mat mat;
132c4762a1bSJed Brown   ierr = MatCreate(PETSC_COMM_WORLD, &mat);CHKERRQ(ierr);
133c4762a1bSJed Brown   ierr = MatSetSizes(mat, n_local_dofs, n_local_dofs, n_dofs, n_dofs);CHKERRQ(ierr);
134c4762a1bSJed Brown   ierr = MatSetBlockSize(mat, 1);CHKERRQ(ierr);
135c4762a1bSJed Brown   ierr = MatSetType(mat, MATAIJ);CHKERRQ(ierr); // Automatically chooses seqaij or mpiaij
136c4762a1bSJed Brown   ierr = MatSeqAIJSetPreallocation(mat, 0, &n_nz[0]);CHKERRQ(ierr);
137c4762a1bSJed Brown   ierr = MatMPIAIJSetPreallocation(mat, 0, &n_nz[0], 0, &n_oz[0]); CHKERRQ(ierr);
138c4762a1bSJed Brown   ierr = MatSetOption(mat, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
139c4762a1bSJed Brown 
140c4762a1bSJed Brown   // Local "element" loop
141c4762a1bSJed Brown   for (unsigned int k = 0; k < elem_dof_indices[rank].size(); k++) {
142c4762a1bSJed Brown     std::vector<PetscInt>& dof_indices = elem_dof_indices[rank][k];
143c4762a1bSJed Brown     // DenseMatrix< Number >  zero_mat( dof_indices.size(), dof_indices.size() );
144c4762a1bSJed Brown     // B.add_matrix( zero_mat, dof_indices );
145c4762a1bSJed Brown     std::vector<PetscScalar> ones(dof_indices.size() * dof_indices.size(), 1.);
146c4762a1bSJed Brown     ierr = MatSetValues(mat, dof_indices.size(), &dof_indices[0], dof_indices.size(), &dof_indices[0], &ones[0], ADD_VALUES);CHKERRQ(ierr);
147c4762a1bSJed Brown   }
148c4762a1bSJed Brown 
149c4762a1bSJed Brown   // Matrix assembly
150c4762a1bSJed Brown   ierr = MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
151c4762a1bSJed Brown   ierr = MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
152c4762a1bSJed Brown 
153c4762a1bSJed Brown   // Clean up
154c4762a1bSJed Brown   ierr = MatDestroy(&mat);CHKERRQ(ierr);
155c4762a1bSJed Brown   ierr = PetscFinalize();
156c4762a1bSJed Brown   return ierr;
157c4762a1bSJed Brown }
158c4762a1bSJed Brown /*TEST
159c4762a1bSJed Brown    build:
160c4762a1bSJed Brown       requires: !define(PETSC_HAVE_SUN_CXX)
161c4762a1bSJed Brown 
162c4762a1bSJed Brown    test:
163c4762a1bSJed Brown       nsize: 2
164c4762a1bSJed Brown       args: -f0 ${DATAFILESPATH}/meshes/moose_dof_indices_np_2_proc_0.txt -f1 ${DATAFILESPATH}/meshes/moose_dof_indices_np_2_proc_1.txt
165c4762a1bSJed Brown       # Skip the test for Sun C++ compiler because of its warnings/errors in petscmat.h
166c4762a1bSJed Brown       requires: datafilespath
167c4762a1bSJed Brown 
168c4762a1bSJed Brown TEST*/
169