00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "PetscMatTools.hpp"
00037 #include <algorithm>
00038 #include <cassert>
00039
00040
00042
00044
00045 void PetscMatTools::SetElement(Mat matrix, PetscInt row, PetscInt col, double value)
00046 {
00047 PetscInt lo, hi;
00048 GetOwnershipRange(matrix, lo, hi);
00049
00050 if (row >= lo && row < hi)
00051 {
00052 MatSetValue(matrix, row, col, value, INSERT_VALUES);
00053 }
00054 }
00055
00056 void PetscMatTools::AddToElement(Mat matrix, PetscInt row, PetscInt col, double value)
00057 {
00058 PetscInt lo, hi;
00059 GetOwnershipRange(matrix, lo, hi);
00060
00061 if (row >= lo && row < hi)
00062 {
00063 MatSetValue(matrix, row, col, value, ADD_VALUES);
00064 }
00065 }
00066
00067 void PetscMatTools::Finalise(Mat matrix)
00068 {
00069 MatAssemblyBegin(matrix, MAT_FINAL_ASSEMBLY);
00070 MatAssemblyEnd(matrix, MAT_FINAL_ASSEMBLY);
00071 }
00072
00073 void PetscMatTools::SwitchWriteMode(Mat matrix)
00074 {
00075 MatAssemblyBegin(matrix, MAT_FLUSH_ASSEMBLY);
00076 MatAssemblyEnd(matrix, MAT_FLUSH_ASSEMBLY);
00077 }
00078
00079 void PetscMatTools::Display(Mat matrix)
00080 {
00081
00082 PetscViewerSetFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_MATLAB);
00083 MatView(matrix,PETSC_VIEWER_STDOUT_WORLD);
00084 }
00085
00086 void PetscMatTools::SetRow(Mat matrix, PetscInt row, double value)
00087 {
00088 PetscInt lo, hi;
00089 GetOwnershipRange(matrix, lo, hi);
00090
00091 if (row >= lo && row < hi)
00092 {
00093 PetscInt rows, cols;
00094 MatGetSize(matrix, &rows, &cols);
00095 for (PetscInt i=0; i<cols; i++)
00096 {
00097 SetElement(matrix, row, i, value);
00098 }
00099 }
00100 }
00101
00102 void PetscMatTools::ZeroRowsWithValueOnDiagonal(Mat matrix, std::vector<unsigned>& rRows, double diagonalValue)
00103 {
00104 Finalise(matrix);
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 1) //PETSc 3.1 or later
00116 MatSetOption(matrix, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE);
00117 #elif (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR == 0) //PETSc 3.0
00118 MatSetOption(matrix, MAT_KEEP_ZEROED_ROWS, PETSC_TRUE);
00119 #else //PETSc 2.x.x
00120 MatSetOption(matrix, MAT_KEEP_ZEROED_ROWS);
00121 #endif
00122
00123 PetscInt* rows = new PetscInt[rRows.size()];
00124 for (unsigned i=0; i<rRows.size(); i++)
00125 {
00126 rows[i] = rRows[i];
00127 }
00128 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00129 IS is;
00130 ISCreateGeneral(PETSC_COMM_WORLD, rRows.size(), rows, &is);
00131 MatZeroRows(matrix, is, &diagonalValue);
00132 ISDestroy(PETSC_DESTROY_PARAM(is));
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #elif (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 2) //PETSc 3.2 or later
00176 MatZeroRows(matrix, rRows.size(), rows, diagonalValue , NULL, NULL);
00177 #else
00178 MatZeroRows(matrix, rRows.size(), rows, diagonalValue);
00179 #endif
00180 delete [] rows;
00181 }
00182
00183
00184 void PetscMatTools::ZeroRowsAndColumnsWithValueOnDiagonal(Mat matrix, std::vector<unsigned> rowColIndices, double diagonalValue)
00185 {
00186 Finalise(matrix);
00187
00188
00189 std::sort(rowColIndices.begin(), rowColIndices.end());
00190
00191 PetscInt lo, hi;
00192 GetOwnershipRange(matrix, lo, hi);
00193 unsigned size = hi-lo;
00194
00195 std::vector<unsigned>* cols_to_zero_per_row = new std::vector<unsigned>[size];
00196
00197
00198
00199 for (PetscInt row = lo; row < hi; row++)
00200 {
00201
00202 PetscInt num_cols;
00203 const PetscInt* cols;
00204 MatGetRow(matrix, row, &num_cols, &cols, PETSC_NULL);
00205
00206
00207 for(PetscInt i=0; i<num_cols; i++)
00208 {
00209 if(std::binary_search(rowColIndices.begin(), rowColIndices.end(), cols[i]))
00210 {
00211 cols_to_zero_per_row[row-lo].push_back(cols[i]);
00212 }
00213 }
00214
00215
00216 MatRestoreRow(matrix, row, &num_cols, &cols, PETSC_NULL);
00217 }
00218
00219
00220 for (PetscInt row = lo; row < hi; row++)
00221 {
00222 unsigned num_cols_to_zero_this_row = cols_to_zero_per_row[row-lo].size();
00223
00224 if(num_cols_to_zero_this_row>0)
00225 {
00226 PetscInt* cols_to_zero = new PetscInt[num_cols_to_zero_this_row];
00227 double* zeros = new double[num_cols_to_zero_this_row];
00228 for(unsigned i=0; i<num_cols_to_zero_this_row; i++)
00229 {
00230 cols_to_zero[i] = cols_to_zero_per_row[row-lo][i];
00231 zeros[i] = 0.0;
00232 }
00233
00234 PetscInt rows[1];
00235 rows[0] = row;
00236 MatSetValues(matrix, 1, rows, num_cols_to_zero_this_row, cols_to_zero, zeros, INSERT_VALUES);
00237 delete [] cols_to_zero;
00238 delete [] zeros;
00239 }
00240 }
00241
00242 delete [] cols_to_zero_per_row;
00243
00244
00245 ZeroRowsWithValueOnDiagonal(matrix, rowColIndices, diagonalValue);
00246 }
00247
00248 void PetscMatTools::ZeroColumn(Mat matrix, PetscInt col)
00249 {
00250 Finalise(matrix);
00251
00252 PetscInt lo, hi;
00253 GetOwnershipRange(matrix, lo, hi);
00254
00255
00256 std::vector<unsigned> nonzero_rows;
00257 for (PetscInt row = lo; row < hi; row++)
00258 {
00259 if (GetElement(matrix, row, col) != 0.0)
00260 {
00261 nonzero_rows.push_back(row);
00262 }
00263 }
00264
00265
00266 unsigned size = nonzero_rows.size();
00267 PetscInt* rows = new PetscInt[size];
00268 PetscInt cols[1];
00269 double* zeros = new double[size];
00270
00271 cols[0] = col;
00272
00273 for (unsigned i=0; i<size; i++)
00274 {
00275 rows[i] = nonzero_rows[i];
00276 zeros[i] = 0.0;
00277 }
00278
00279 MatSetValues(matrix, size, rows, 1, cols, zeros, INSERT_VALUES);
00280 delete [] rows;
00281 delete [] zeros;
00282 }
00283
00284 void PetscMatTools::Zero(Mat matrix)
00285 {
00286 MatZeroEntries(matrix);
00287 }
00288
00289 unsigned PetscMatTools::GetSize(Mat matrix)
00290 {
00291 PetscInt rows, cols;
00292
00293 MatGetSize(matrix, &rows, &cols);
00294 assert(rows == cols);
00295 return (unsigned) rows;
00296 }
00297
00298 void PetscMatTools::GetOwnershipRange(Mat matrix, PetscInt& lo, PetscInt& hi)
00299 {
00300 MatGetOwnershipRange(matrix, &lo, &hi);
00301 }
00302
00303 double PetscMatTools::GetElement(Mat matrix, PetscInt row, PetscInt col)
00304 {
00305 PetscInt lo, hi;
00306 GetOwnershipRange(matrix, lo, hi);
00307
00308 assert(lo <= row && row < hi);
00309 PetscInt row_as_array[1];
00310 row_as_array[0] = row;
00311 PetscInt col_as_array[1];
00312 col_as_array[0] = col;
00313
00314 double ret_array[1];
00315
00316 MatGetValues(matrix, 1, row_as_array, 1, col_as_array, ret_array);
00317
00318 return ret_array[0];
00319 }
00320
00321 void PetscMatTools::SetOption(Mat matrix, MatOption option)
00322 {
00323 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00324 MatSetOption(matrix, option, PETSC_TRUE);
00325 #else
00326 MatSetOption(matrix, option);
00327 #endif
00328 }
00329
00330 Vec PetscMatTools::GetMatrixRowDistributed(Mat matrix, unsigned rowIndex)
00331 {
00332
00333
00334
00335
00336
00337 PetscInt lo, hi;
00338 PetscMatTools::GetOwnershipRange(matrix, lo, hi);
00339 unsigned size = PetscMatTools::GetSize(matrix);
00340
00341 Vec mat_ith_row = PetscTools::CreateVec(size, hi-lo, false);
00342
00343 PetscInt num_entries;
00344 const PetscInt* column_indices;
00345 const PetscScalar* values;
00346
00347 bool am_row_owner = (PetscInt)rowIndex >= lo && (PetscInt)rowIndex < hi;
00348
00349
00350
00351
00352
00353 if (am_row_owner)
00354 {
00355 MatGetRow(matrix, rowIndex, &num_entries, &column_indices, &values);
00356 VecSetValues(mat_ith_row, num_entries, column_indices, values, INSERT_VALUES);
00357 }
00358
00359 VecAssemblyBegin(mat_ith_row);
00360 VecAssemblyEnd(mat_ith_row);
00361
00362 if (am_row_owner)
00363 {
00364 MatRestoreRow(matrix, rowIndex, &num_entries, &column_indices, &values);
00365 }
00366
00367 return mat_ith_row;
00368 }
00369
00370
00371 bool PetscMatTools::CheckEquality(const Mat mat1, const Mat mat2, double tol)
00372 {
00373 Mat y;
00374 MatDuplicate(mat2, MAT_COPY_VALUES, &y);
00375
00376 double minus_one = -1.0;
00377 #if (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 2) //PETSc 2.2
00378
00379 MatAYPX(&minus_one, mat1, y);
00380 #elif (PETSC_VERSION_MAJOR == 2 && PETSC_VERSION_MINOR == 3 && PETSC_VERSION_SUBMINOR == 1) //PETSc 2.3.1
00381
00382 MatAYPX(y, minus_one, mat1);
00383 #else
00384
00385 MatAYPX(y, minus_one, mat1, DIFFERENT_NONZERO_PATTERN);
00386 #endif
00387 PetscReal norm;
00388 MatNorm(y, NORM_INFINITY, &norm);
00389 PetscTools::Destroy(y);
00390
00391 return (norm < tol);
00392 }
00393
00394 bool PetscMatTools::CheckSymmetry(const Mat matrix, double tol)
00395 {
00396 Mat trans;
00397 #if (PETSC_VERSION_MAJOR == 3) //PETSc 3.x.x
00398 MatTranspose(matrix, MAT_INITIAL_MATRIX, &trans);
00399 #else
00400 MatTranspose(matrix, &trans);
00401 #endif
00402 bool is_symmetric = PetscMatTools::CheckEquality(matrix, trans, tol);
00403 PetscTools::Destroy(trans);
00404 return is_symmetric;
00405 }
00406
00407 void PetscMatTools::TurnOffVariableAllocationError(Mat matrix)
00408 {
00409 #if (PETSC_VERSION_MAJOR == 3 && PETSC_VERSION_MINOR >= 3) //PETSc 3.3 or later
00410 MatSetOption(matrix, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
00411 #endif
00412 }
00413