1 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 2 3 /* Logging support */ 4 PetscClassId MAT_COARSEN_CLASSID; 5 6 PetscFunctionList MatCoarsenList = NULL; 7 PetscBool MatCoarsenRegisterAllCalled = PETSC_FALSE; 8 9 /*@C 10 MatCoarsenRegister - Adds a new sparse matrix coarsening algorithm to the matrix package. 11 12 Logically Collective, No Fortran Support 13 14 Input Parameters: 15 + sname - name of coarsen (for example `MATCOARSENMIS`) 16 - function - function pointer that creates the coarsen type 17 18 Level: developer 19 20 Example Usage: 21 .vb 22 MatCoarsenRegister("my_agg", MyAggCreate); 23 .ve 24 25 Then, your aggregator can be chosen with the procedural interface via `MatCoarsenSetType(agg, "my_agg")` or at runtime via the option `-mat_coarsen_type my_agg` 26 27 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenSetType()`, `MatCoarsenCreate()`, `MatCoarsenRegisterDestroy()`, `MatCoarsenRegisterAll()` 28 @*/ 29 PetscErrorCode MatCoarsenRegister(const char sname[], PetscErrorCode (*function)(MatCoarsen)) 30 { 31 PetscFunctionBegin; 32 PetscCall(MatInitializePackage()); 33 PetscCall(PetscFunctionListAdd(&MatCoarsenList, sname, function)); 34 PetscFunctionReturn(PETSC_SUCCESS); 35 } 36 37 /*@ 38 MatCoarsenGetType - Gets the Coarsen method type and name (as a string) 39 from the coarsen context. 40 41 Not Collective 42 43 Input Parameter: 44 . coarsen - the coarsen context 45 46 Output Parameter: 47 . type - coarsener type 48 49 Level: advanced 50 51 .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenType`, `MatCoarsenSetType()`, `MatCoarsenRegister()` 52 @*/ 53 PetscErrorCode MatCoarsenGetType(MatCoarsen coarsen, MatCoarsenType *type) 54 { 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(coarsen, MAT_COARSEN_CLASSID, 1); 57 PetscAssertPointer(type, 2); 58 *type = ((PetscObject)coarsen)->type_name; 59 PetscFunctionReturn(PETSC_SUCCESS); 60 } 61 62 /*@ 63 MatCoarsenApply - Gets a coarsen for a matrix. 64 65 Collective 66 67 Input Parameter: 68 . coarser - the coarsen 69 70 Options Database Keys: 71 + -mat_coarsen_type mis|hem|misk - mis: maximal independent set based; misk: distance k MIS; hem: heavy edge matching 72 - -mat_coarsen_view - view the coarsening object 73 74 Level: advanced 75 76 Notes: 77 When the coarsening is used inside `PCGAMG` then the options database keys are prefixed with `-pc_gamg_` 78 79 Use `MatCoarsenGetData()` to access the results of the coarsening 80 81 The user can define additional coarsens; see `MatCoarsenRegister()`. 82 83 .seealso: `MatCoarsen`, `MatCoarsenSetFromOptions()`, `MatCoarsenSetType()`, `MatCoarsenRegister()`, `MatCoarsenCreate()`, 84 `MatCoarsenDestroy()`, `MatCoarsenSetAdjacency()` 85 `MatCoarsenGetData()` 86 @*/ 87 PetscErrorCode MatCoarsenApply(MatCoarsen coarser) 88 { 89 PetscFunctionBegin; 90 PetscValidHeaderSpecific(coarser, MAT_COARSEN_CLASSID, 1); 91 PetscAssertPointer(coarser, 1); 92 PetscCheck(coarser->graph->assembled, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 93 PetscCheck(!coarser->graph->factortype, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 94 PetscCall(PetscLogEventBegin(MAT_Coarsen, coarser, 0, 0, 0)); 95 PetscUseTypeMethod(coarser, apply); 96 PetscCall(PetscLogEventEnd(MAT_Coarsen, coarser, 0, 0, 0)); 97 PetscFunctionReturn(PETSC_SUCCESS); 98 } 99 100 /*@ 101 MatCoarsenSetAdjacency - Sets the adjacency graph (matrix) of the thing to be coarsened. 102 103 Collective 104 105 Input Parameters: 106 + agg - the coarsen context 107 - adj - the adjacency matrix 108 109 Level: advanced 110 111 .seealso: `MatCoarsen`, `MatCoarsenSetFromOptions()`, `Mat`, `MatCoarsenCreate()`, `MatCoarsenApply()` 112 @*/ 113 PetscErrorCode MatCoarsenSetAdjacency(MatCoarsen agg, Mat adj) 114 { 115 PetscFunctionBegin; 116 PetscValidHeaderSpecific(agg, MAT_COARSEN_CLASSID, 1); 117 PetscValidHeaderSpecific(adj, MAT_CLASSID, 2); 118 agg->graph = adj; 119 PetscFunctionReturn(PETSC_SUCCESS); 120 } 121 122 /*@ 123 MatCoarsenSetStrictAggs - Set whether to keep strict (non overlapping) aggregates in the linked list of aggregates for a coarsen context 124 125 Logically Collective 126 127 Input Parameters: 128 + agg - the coarsen context 129 - str - `PETSC_TRUE` keep strict aggregates, `PETSC_FALSE` allow overlap 130 131 Level: advanced 132 133 .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenSetFromOptions()` 134 @*/ 135 PetscErrorCode MatCoarsenSetStrictAggs(MatCoarsen agg, PetscBool str) 136 { 137 PetscFunctionBegin; 138 PetscValidHeaderSpecific(agg, MAT_COARSEN_CLASSID, 1); 139 agg->strict_aggs = str; 140 PetscFunctionReturn(PETSC_SUCCESS); 141 } 142 143 /*@ 144 MatCoarsenDestroy - Destroys the coarsen context. 145 146 Collective 147 148 Input Parameter: 149 . agg - the coarsen context 150 151 Level: advanced 152 153 .seealso: `MatCoarsen`, `MatCoarsenCreate()` 154 @*/ 155 PetscErrorCode MatCoarsenDestroy(MatCoarsen *agg) 156 { 157 PetscFunctionBegin; 158 if (!*agg) PetscFunctionReturn(PETSC_SUCCESS); 159 PetscValidHeaderSpecific(*agg, MAT_COARSEN_CLASSID, 1); 160 if (--((PetscObject)*agg)->refct > 0) { 161 *agg = NULL; 162 PetscFunctionReturn(PETSC_SUCCESS); 163 } 164 165 PetscTryTypeMethod(*agg, destroy); 166 if ((*agg)->agg_lists) PetscCall(PetscCDDestroy((*agg)->agg_lists)); 167 PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetMaximumIterations_C", NULL)); 168 PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetThreshold_C", NULL)); 169 PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetStrengthIndex_C", NULL)); 170 171 PetscCall(PetscHeaderDestroy(agg)); 172 PetscFunctionReturn(PETSC_SUCCESS); 173 } 174 175 /*@ 176 MatCoarsenViewFromOptions - View the coarsener from the options database 177 178 Collective 179 180 Input Parameters: 181 + A - the coarsen context 182 . obj - Optional object that provides the prefix for the option name 183 - name - command line option (usually `-mat_coarsen_view`) 184 185 Options Database Key: 186 . -mat_coarsen_view [viewertype]:... - the viewer and its options 187 188 Note: 189 .vb 190 If no value is provided ascii:stdout is used 191 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 192 for example ascii::ascii_info prints just the information about the object not all details 193 unless :append is given filename opens in write mode, overwriting what was already there 194 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 195 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 196 socket[:port] defaults to the standard output port 197 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 198 .ve 199 200 Level: intermediate 201 202 .seealso: `MatCoarsen`, `MatCoarsenView`, `PetscObjectViewFromOptions()`, `MatCoarsenCreate()` 203 @*/ 204 PetscErrorCode MatCoarsenViewFromOptions(MatCoarsen A, PetscObject obj, const char name[]) 205 { 206 PetscFunctionBegin; 207 PetscValidHeaderSpecific(A, MAT_COARSEN_CLASSID, 1); 208 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 209 PetscFunctionReturn(PETSC_SUCCESS); 210 } 211 212 /*@ 213 MatCoarsenView - Prints the coarsen data structure. 214 215 Collective 216 217 Input Parameters: 218 + agg - the coarsen context 219 - viewer - optional visualization context 220 221 For viewing the options database see `MatCoarsenViewFromOptions()` 222 223 Level: advanced 224 225 .seealso: `MatCoarsen`, `PetscViewer`, `PetscViewerASCIIOpen()`, `MatCoarsenViewFromOptions` 226 @*/ 227 PetscErrorCode MatCoarsenView(MatCoarsen agg, PetscViewer viewer) 228 { 229 PetscBool isascii; 230 231 PetscFunctionBegin; 232 PetscValidHeaderSpecific(agg, MAT_COARSEN_CLASSID, 1); 233 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)agg), &viewer)); 234 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 235 PetscCheckSameComm(agg, 1, viewer, 2); 236 237 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 238 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)agg, viewer)); 239 if (agg->ops->view) { 240 PetscCall(PetscViewerASCIIPushTab(viewer)); 241 PetscUseTypeMethod(agg, view, viewer); 242 PetscCall(PetscViewerASCIIPopTab(viewer)); 243 } 244 if (agg->strength_index_size > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " Using scalar strength-of-connection index[%" PetscInt_FMT "] = {%" PetscInt_FMT ", ..}\n", agg->strength_index_size, agg->strength_index[0])); 245 PetscFunctionReturn(PETSC_SUCCESS); 246 } 247 248 /*@ 249 MatCoarsenSetType - Sets the type of aggregator to use 250 251 Collective 252 253 Input Parameters: 254 + coarser - the coarsen context. 255 - type - a known coarsening method 256 257 Options Database Key: 258 . -mat_coarsen_type <type> - maximal independent set based; distance k MIS; heavy edge matching 259 260 Level: advanced 261 262 .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenApply()`, `MatCoarsenType`, `MatCoarsenGetType()` 263 @*/ 264 PetscErrorCode MatCoarsenSetType(MatCoarsen coarser, MatCoarsenType type) 265 { 266 PetscBool match; 267 PetscErrorCode (*r)(MatCoarsen); 268 269 PetscFunctionBegin; 270 PetscValidHeaderSpecific(coarser, MAT_COARSEN_CLASSID, 1); 271 PetscAssertPointer(type, 2); 272 273 PetscCall(PetscObjectTypeCompare((PetscObject)coarser, type, &match)); 274 if (match) PetscFunctionReturn(PETSC_SUCCESS); 275 276 PetscTryTypeMethod(coarser, destroy); 277 coarser->ops->destroy = NULL; 278 PetscCall(PetscMemzero(coarser->ops, sizeof(struct _MatCoarsenOps))); 279 280 PetscCall(PetscFunctionListFind(MatCoarsenList, type, &r)); 281 PetscCheck(r, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown coarsen type %s", type); 282 PetscCall((*r)(coarser)); 283 284 PetscCall(PetscFree(((PetscObject)coarser)->type_name)); 285 PetscCall(PetscStrallocpy(type, &((PetscObject)coarser)->type_name)); 286 PetscFunctionReturn(PETSC_SUCCESS); 287 } 288 289 /*@ 290 MatCoarsenSetGreedyOrdering - Sets the ordering of the vertices to use with a greedy coarsening method 291 292 Logically Collective 293 294 Input Parameters: 295 + coarser - the coarsen context 296 - perm - vertex ordering of (greedy) algorithm 297 298 Level: advanced 299 300 Note: 301 The `IS` weights is freed by PETSc, the user should not destroy it or change it after this call 302 303 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenCreate()`, `MatCoarsenSetType()` 304 @*/ 305 PetscErrorCode MatCoarsenSetGreedyOrdering(MatCoarsen coarser, const IS perm) 306 { 307 PetscFunctionBegin; 308 PetscValidHeaderSpecific(coarser, MAT_COARSEN_CLASSID, 1); 309 coarser->perm = perm; 310 PetscFunctionReturn(PETSC_SUCCESS); 311 } 312 313 /*@C 314 MatCoarsenGetData - Gets the weights for vertices for a coarsener. 315 316 Logically Collective, No Fortran Support 317 318 Input Parameter: 319 . coarser - the coarsen context 320 321 Output Parameter: 322 . llist - linked list of aggregates 323 324 Level: advanced 325 326 Note: 327 This passes ownership to the caller and nullifies the value of weights (`PetscCoarsenData`) within the `MatCoarsen` 328 329 .seealso: `MatCoarsen`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`, `PetscCoarsenData` 330 @*/ 331 PetscErrorCode MatCoarsenGetData(MatCoarsen coarser, PetscCoarsenData **llist) 332 { 333 PetscFunctionBegin; 334 PetscValidHeaderSpecific(coarser, MAT_COARSEN_CLASSID, 1); 335 PetscCheck(coarser->agg_lists, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "No linked list - generate it or call ApplyCoarsen"); 336 *llist = coarser->agg_lists; 337 coarser->agg_lists = NULL; /* giving up ownership */ 338 PetscFunctionReturn(PETSC_SUCCESS); 339 } 340 341 /*@ 342 MatCoarsenSetFromOptions - Sets various coarsen options from the options database. 343 344 Collective 345 346 Input Parameter: 347 . coarser - the coarsen context. 348 349 Options Database Key: 350 + -mat_coarsen_type <type> - mis: maximal independent set based; misk: distance k MIS; hem: heavy edge matching 351 - -mat_coarsen_max_it <its> number of iterations to use in the coarsening process - see `MatCoarsenSetMaximumIterations()` 352 353 Level: advanced 354 355 Notes: 356 When the coarsening is used inside `PCGAMG` then the options database keys are prefixed with `-pc_gamg_` 357 358 Sets the `MatCoarsenType` to `MATCOARSENMISK` if has not been set previously 359 360 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`, 361 `MatCoarsenSetMaximumIterations()` 362 @*/ 363 PetscErrorCode MatCoarsenSetFromOptions(MatCoarsen coarser) 364 { 365 PetscBool flag; 366 char type[256]; 367 const char *def; 368 369 PetscFunctionBegin; 370 PetscObjectOptionsBegin((PetscObject)coarser); 371 if (!((PetscObject)coarser)->type_name) { 372 def = MATCOARSENMISK; 373 } else { 374 def = ((PetscObject)coarser)->type_name; 375 } 376 PetscCall(PetscOptionsFList("-mat_coarsen_type", "Type of aggregator", "MatCoarsenSetType", MatCoarsenList, def, type, 256, &flag)); 377 if (flag) PetscCall(MatCoarsenSetType(coarser, type)); 378 379 PetscCall(PetscOptionsInt("-mat_coarsen_max_it", "Number of iterations (for HEM)", "MatCoarsenSetMaximumIterations", coarser->max_it, &coarser->max_it, NULL)); 380 PetscCall(PetscOptionsInt("-mat_coarsen_threshold", "Threshold (for HEM)", "MatCoarsenSetThreshold", coarser->max_it, &coarser->max_it, NULL)); 381 coarser->strength_index_size = MAT_COARSEN_STRENGTH_INDEX_SIZE; 382 PetscCall(PetscOptionsIntArray("-mat_coarsen_strength_index", "Array of indices to use strength of connection measure (default is all indices)", "MatCoarsenSetStrengthIndex", coarser->strength_index, &coarser->strength_index_size, NULL)); 383 /* 384 Set the type if it was never set. 385 */ 386 if (!((PetscObject)coarser)->type_name) PetscCall(MatCoarsenSetType(coarser, def)); 387 388 PetscTryTypeMethod(coarser, setfromoptions, PetscOptionsObject); 389 PetscOptionsEnd(); 390 PetscFunctionReturn(PETSC_SUCCESS); 391 } 392 393 /*@ 394 MatCoarsenSetMaximumIterations - Maximum `MATCOARSENHEM` iterations to use 395 396 Logically Collective 397 398 Input Parameters: 399 + coarse - the coarsen context 400 - n - number of HEM iterations 401 402 Options Database Key: 403 . -mat_coarsen_max_it <default=4> - Maximum `MATCOARSENHEM` iterations to use 404 405 Level: intermediate 406 407 Note: 408 When the coarsening is used inside `PCGAMG` then the options database keys are prefixed with `-pc_gamg_` 409 410 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()` 411 @*/ 412 PetscErrorCode MatCoarsenSetMaximumIterations(MatCoarsen coarse, PetscInt n) 413 { 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(coarse, MAT_COARSEN_CLASSID, 1); 416 PetscValidLogicalCollectiveInt(coarse, n, 2); 417 PetscTryMethod(coarse, "MatCoarsenSetMaximumIterations_C", (MatCoarsen, PetscInt), (coarse, n)); 418 PetscFunctionReturn(PETSC_SUCCESS); 419 } 420 421 static PetscErrorCode MatCoarsenSetMaximumIterations_MATCOARSEN(MatCoarsen coarse, PetscInt b) 422 { 423 PetscFunctionBegin; 424 coarse->max_it = b; 425 PetscFunctionReturn(PETSC_SUCCESS); 426 } 427 428 /*@ 429 MatCoarsenSetStrengthIndex - Index array to use for index to use for strength of connection 430 431 Logically Collective 432 433 Input Parameters: 434 + coarse - the coarsen context 435 . n - number of indices 436 - idx - array of indices 437 438 Options Database Key: 439 . -mat_coarsen_strength_index - array of subset of variables per vertex to use for strength norm, -1 for using all (default) 440 441 Level: intermediate 442 443 Note: 444 When the coarsening is used inside `PCGAMG` then the options database keys are prefixed with `-pc_gamg_` 445 446 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()` 447 @*/ 448 PetscErrorCode MatCoarsenSetStrengthIndex(MatCoarsen coarse, PetscInt n, PetscInt idx[]) 449 { 450 PetscFunctionBegin; 451 PetscValidHeaderSpecific(coarse, MAT_COARSEN_CLASSID, 1); 452 PetscValidLogicalCollectiveInt(coarse, n, 2); 453 PetscTryMethod(coarse, "MatCoarsenSetStrengthIndex_C", (MatCoarsen, PetscInt, PetscInt[]), (coarse, n, idx)); 454 PetscFunctionReturn(PETSC_SUCCESS); 455 } 456 457 static PetscErrorCode MatCoarsenSetStrengthIndex_MATCOARSEN(MatCoarsen coarse, PetscInt n, PetscInt idx[]) 458 { 459 PetscFunctionBegin; 460 coarse->strength_index_size = n; 461 for (int iii = 0; iii < n; iii++) coarse->strength_index[iii] = idx[iii]; 462 PetscFunctionReturn(PETSC_SUCCESS); 463 } 464 465 /*@ 466 MatCoarsenSetThreshold - Set the threshold for HEM 467 468 Logically Collective 469 470 Input Parameters: 471 + coarse - the coarsen context 472 - b - threshold value 473 474 Options Database Key: 475 . -mat_coarsen_threshold <-1> - threshold 476 477 Level: intermediate 478 479 Note: 480 When the coarsening is used inside `PCGAMG` then the options database keys are prefixed with `-pc_gamg_` 481 482 Developer Note: 483 It is not documented how this threshold is used 484 485 .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()` 486 @*/ 487 PetscErrorCode MatCoarsenSetThreshold(MatCoarsen coarse, PetscReal b) 488 { 489 PetscFunctionBegin; 490 PetscValidHeaderSpecific(coarse, MAT_COARSEN_CLASSID, 1); 491 PetscValidLogicalCollectiveReal(coarse, b, 2); 492 PetscTryMethod(coarse, "MatCoarsenSetThreshold_C", (MatCoarsen, PetscReal), (coarse, b)); 493 PetscFunctionReturn(PETSC_SUCCESS); 494 } 495 496 static PetscErrorCode MatCoarsenSetThreshold_MATCOARSEN(MatCoarsen coarse, PetscReal b) 497 { 498 PetscFunctionBegin; 499 coarse->threshold = b; 500 PetscFunctionReturn(PETSC_SUCCESS); 501 } 502 503 /*@ 504 MatCoarsenCreate - Creates a coarsen context. 505 506 Collective 507 508 Input Parameter: 509 . comm - MPI communicator 510 511 Output Parameter: 512 . newcrs - location to put the context 513 514 Level: advanced 515 516 .seealso: `MatCoarsen`, `MatCoarsenSetType()`, `MatCoarsenApply()`, `MatCoarsenDestroy()`, 517 `MatCoarsenSetAdjacency()`, `MatCoarsenGetData()` 518 @*/ 519 PetscErrorCode MatCoarsenCreate(MPI_Comm comm, MatCoarsen *newcrs) 520 { 521 MatCoarsen agg; 522 523 PetscFunctionBegin; 524 PetscAssertPointer(newcrs, 2); 525 PetscCall(MatInitializePackage()); 526 527 PetscCall(PetscHeaderCreate(agg, MAT_COARSEN_CLASSID, "MatCoarsen", "Matrix/graph coarsen", "MatCoarsen", comm, MatCoarsenDestroy, MatCoarsenView)); 528 PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetMaximumIterations_C", MatCoarsenSetMaximumIterations_MATCOARSEN)); 529 PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetThreshold_C", MatCoarsenSetThreshold_MATCOARSEN)); 530 PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetStrengthIndex_C", MatCoarsenSetStrengthIndex_MATCOARSEN)); 531 agg->strength_index_size = 0; 532 *newcrs = agg; 533 PetscFunctionReturn(PETSC_SUCCESS); 534 } 535