Actual source code: coarsen.c

  1: #include <petsc/private/matimpl.h>

  3: /* Logging support */
  4: PetscClassId MAT_COARSEN_CLASSID;

  6: PetscFunctionList MatCoarsenList              = NULL;
  7: PetscBool         MatCoarsenRegisterAllCalled = PETSC_FALSE;

  9: /*@C
 10:   MatCoarsenRegister - Adds a new sparse matrix coarsening algorithm to the matrix package.

 12:   Logically Collective

 14:   Input Parameters:
 15: + sname    - name of coarsen (for example `MATCOARSENMIS`)
 16: - function - function pointer that creates the coarsen type

 18:   Level: developer

 20:   Example Usage:
 21: .vb
 22:    MatCoarsenRegister("my_agg", MyAggCreate);
 23: .ve

 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`

 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: }

 37: /*@C
 38:   MatCoarsenGetType - Gets the Coarsen method type and name (as a string)
 39:   from the coarsen context.

 41:   Not Collective

 43:   Input Parameter:
 44: . coarsen - the coarsen context

 46:   Output Parameter:
 47: . type - coarsener type

 49:   Level: advanced

 51: .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenType`, `MatCoarsenSetType()`, `MatCoarsenRegister()`
 52: @*/
 53: PetscErrorCode MatCoarsenGetType(MatCoarsen coarsen, MatCoarsenType *type)
 54: {
 55:   PetscFunctionBegin;
 57:   PetscAssertPointer(type, 2);
 58:   *type = ((PetscObject)coarsen)->type_name;
 59:   PetscFunctionReturn(PETSC_SUCCESS);
 60: }

 62: /*@
 63:   MatCoarsenApply - Gets a coarsen for a matrix.

 65:   Collective

 67:   Input Parameter:
 68: . coarser - the coarsen

 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

 74:   Level: advanced

 76:   Notes:
 77:   Use `MatCoarsenGetData()` to access the results of the coarsening

 79:   The user can define additional coarsens; see `MatCoarsenRegister()`.

 81: .seealso: `MatCoarsen`, `MatCoarseSetFromOptions()`, `MatCoarsenSetType()`, `MatCoarsenRegister()`, `MatCoarsenCreate()`,
 82:           `MatCoarsenDestroy()`, `MatCoarsenSetAdjacency()`
 83:           `MatCoarsenGetData()`
 84: @*/
 85: PetscErrorCode MatCoarsenApply(MatCoarsen coarser)
 86: {
 87:   PetscFunctionBegin;
 89:   PetscAssertPointer(coarser, 1);
 90:   PetscCheck(coarser->graph->assembled, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
 91:   PetscCheck(!coarser->graph->factortype, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
 92:   PetscCall(PetscLogEventBegin(MAT_Coarsen, coarser, 0, 0, 0));
 93:   PetscUseTypeMethod(coarser, apply);
 94:   PetscCall(PetscLogEventEnd(MAT_Coarsen, coarser, 0, 0, 0));
 95:   PetscFunctionReturn(PETSC_SUCCESS);
 96: }

 98: /*@
 99:   MatCoarsenSetAdjacency - Sets the adjacency graph (matrix) of the thing to be coarsened.

101:   Collective

103:   Input Parameters:
104: + agg - the coarsen context
105: - adj - the adjacency matrix

107:   Level: advanced

109: .seealso: `MatCoarsen`, `MatCoarsenSetFromOptions()`, `Mat`, `MatCoarsenCreate()`, `MatCoarsenApply()`
110: @*/
111: PetscErrorCode MatCoarsenSetAdjacency(MatCoarsen agg, Mat adj)
112: {
113:   PetscFunctionBegin;
116:   agg->graph = adj;
117:   PetscFunctionReturn(PETSC_SUCCESS);
118: }

120: /*@
121:   MatCoarsenSetStrictAggs - Set whether to keep strict (non overlapping) aggregates in the linked list of aggregates for a coarsen context

123:   Logically Collective

125:   Input Parameters:
126: + agg - the coarsen context
127: - str - `PETSC_TRUE` keep strict aggregates, `PETSC_FALSE` allow overlap

129:   Level: advanced

131: .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenSetFromOptions()`
132: @*/
133: PetscErrorCode MatCoarsenSetStrictAggs(MatCoarsen agg, PetscBool str)
134: {
135:   PetscFunctionBegin;
137:   agg->strict_aggs = str;
138:   PetscFunctionReturn(PETSC_SUCCESS);
139: }

141: /*@
142:   MatCoarsenDestroy - Destroys the coarsen context.

144:   Collective

146:   Input Parameter:
147: . agg - the coarsen context

149:   Level: advanced

151: .seealso: `MatCoarsen`, `MatCoarsenCreate()`
152: @*/
153: PetscErrorCode MatCoarsenDestroy(MatCoarsen *agg)
154: {
155:   PetscFunctionBegin;
156:   if (!*agg) PetscFunctionReturn(PETSC_SUCCESS);
158:   if (--((PetscObject)*agg)->refct > 0) {
159:     *agg = NULL;
160:     PetscFunctionReturn(PETSC_SUCCESS);
161:   }

163:   PetscTryTypeMethod(*agg, destroy);
164:   if ((*agg)->agg_lists) PetscCall(PetscCDDestroy((*agg)->agg_lists));
165:   PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetMaximumIterations_C", NULL));
166:   PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetThreshold_C", NULL));
167:   PetscCall(PetscObjectComposeFunction((PetscObject)*agg, "MatCoarsenSetStrengthIndex_C", NULL));

169:   PetscCall(PetscHeaderDestroy(agg));
170:   PetscFunctionReturn(PETSC_SUCCESS);
171: }

173: /*@C
174:   MatCoarsenViewFromOptions - View the coarsener from the options database

176:   Collective

178:   Input Parameters:
179: + A    - the coarsen context
180: . obj  - Optional object that provides the prefix for the option name
181: - name - command line option (usually `-mat_coarsen_view`)

183:   Options Database Key:
184: . -mat_coarsen_view [viewertype]:... - the viewer and its options

186:   Note:
187: .vb
188:     If no value is provided ascii:stdout is used
189:        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
190:                                                   for example ascii::ascii_info prints just the information about the object not all details
191:                                                   unless :append is given filename opens in write mode, overwriting what was already there
192:        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
193:        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
194:        socket[:port]                             defaults to the standard output port
195:        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
196: .ve

198:   Level: intermediate

200: .seealso: `MatCoarsen`, `MatCoarsenView`, `PetscObjectViewFromOptions()`, `MatCoarsenCreate()`
201: @*/
202: PetscErrorCode MatCoarsenViewFromOptions(MatCoarsen A, PetscObject obj, const char name[])
203: {
204:   PetscFunctionBegin;
206:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
207:   PetscFunctionReturn(PETSC_SUCCESS);
208: }

210: /*@C
211:   MatCoarsenView - Prints the coarsen data structure.

213:   Collective

215:   Input Parameters:
216: + agg    - the coarsen context
217: - viewer - optional visualization context

219:    For viewing the options database see `MatCoarsenViewFromOptions()`

221:   Level: advanced

223: .seealso: `MatCoarsen`, `PetscViewer`, `PetscViewerASCIIOpen()`, `MatCoarsenViewFromOptions`
224: @*/
225: PetscErrorCode MatCoarsenView(MatCoarsen agg, PetscViewer viewer)
226: {
227:   PetscBool iascii;

229:   PetscFunctionBegin;
231:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)agg), &viewer));
233:   PetscCheckSameComm(agg, 1, viewer, 2);

235:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
236:   PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)agg, viewer));
237:   if (agg->ops->view) {
238:     PetscCall(PetscViewerASCIIPushTab(viewer));
239:     PetscUseTypeMethod(agg, view, viewer);
240:     PetscCall(PetscViewerASCIIPopTab(viewer));
241:   }
242:   if (agg->strength_index_size > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " Using scalar strength-of-connection index index[%d] = {%d, ..}\n", (int)agg->strength_index_size, (int)agg->strength_index[0]));
243:   PetscFunctionReturn(PETSC_SUCCESS);
244: }

246: /*@C
247:   MatCoarsenSetType - Sets the type of aggregator to use

249:   Collective

251:   Input Parameters:
252: + coarser - the coarsen context.
253: - type    - a known coarsening method

255:   Options Database Key:
256: . -mat_coarsen_type  <type> - maximal independent set based; distance k MIS; heavy edge matching

258:   Level: advanced

260: .seealso: `MatCoarsen`, `MatCoarsenCreate()`, `MatCoarsenApply()`, `MatCoarsenType`, `MatCoarsenGetType()`
261: @*/
262: PetscErrorCode MatCoarsenSetType(MatCoarsen coarser, MatCoarsenType type)
263: {
264:   PetscBool match;
265:   PetscErrorCode (*r)(MatCoarsen);

267:   PetscFunctionBegin;
269:   PetscAssertPointer(type, 2);

271:   PetscCall(PetscObjectTypeCompare((PetscObject)coarser, type, &match));
272:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

274:   PetscTryTypeMethod(coarser, destroy);
275:   coarser->ops->destroy = NULL;
276:   PetscCall(PetscMemzero(coarser->ops, sizeof(struct _MatCoarsenOps)));

278:   PetscCall(PetscFunctionListFind(MatCoarsenList, type, &r));
279:   PetscCheck(r, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown coarsen type %s", type);
280:   PetscCall((*r)(coarser));

282:   PetscCall(PetscFree(((PetscObject)coarser)->type_name));
283:   PetscCall(PetscStrallocpy(type, &((PetscObject)coarser)->type_name));
284:   PetscFunctionReturn(PETSC_SUCCESS);
285: }

287: /*@C
288:   MatCoarsenSetGreedyOrdering - Sets the ordering of the vertices to use with a greedy coarsening method

290:   Logically Collective

292:   Input Parameters:
293: + coarser - the coarsen context
294: - perm    - vertex ordering of (greedy) algorithm

296:   Level: advanced

298:   Note:
299:   The `IS` weights is freed by PETSc, the user should not destroy it or change it after this call

301: .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
302: @*/
303: PetscErrorCode MatCoarsenSetGreedyOrdering(MatCoarsen coarser, const IS perm)
304: {
305:   PetscFunctionBegin;
307:   coarser->perm = perm;
308:   PetscFunctionReturn(PETSC_SUCCESS);
309: }

311: /*@C
312:   MatCoarsenGetData - Gets the weights for vertices for a coarsener.

314:   Logically Collective

316:   Input Parameter:
317: . coarser - the coarsen context

319:   Output Parameter:
320: . llist - linked list of aggregates

322:   Level: advanced

324: .seealso: `MatCoarsen`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
325: @*/
326: PetscErrorCode MatCoarsenGetData(MatCoarsen coarser, PetscCoarsenData **llist)
327: {
328:   PetscFunctionBegin;
330:   PetscCheck(coarser->agg_lists, PetscObjectComm((PetscObject)coarser), PETSC_ERR_ARG_WRONGSTATE, "No linked list - generate it or call ApplyCoarsen");
331:   *llist             = coarser->agg_lists;
332:   coarser->agg_lists = NULL; /* giving up ownership */
333:   PetscFunctionReturn(PETSC_SUCCESS);
334: }

336: /*@
337:   MatCoarsenSetFromOptions - Sets various coarsen options from the options database.

339:   Collective

341:   Input Parameter:
342: . coarser - the coarsen context.

344:   Options Database Key:
345: . -mat_coarsen_type  <type> - mis: maximal independent set based; misk: distance k MIS; hem: heavy edge matching

347:   Level: advanced

349:   Note:
350:   Sets the `MatCoarsenType` to `MATCOARSENMISK` if has not been set previously

352: .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
353: @*/
354: PetscErrorCode MatCoarsenSetFromOptions(MatCoarsen coarser)
355: {
356:   PetscBool   flag;
357:   char        type[256];
358:   const char *def;

360:   PetscFunctionBegin;
361:   PetscObjectOptionsBegin((PetscObject)coarser);
362:   if (!((PetscObject)coarser)->type_name) {
363:     def = MATCOARSENMISK;
364:   } else {
365:     def = ((PetscObject)coarser)->type_name;
366:   }
367:   PetscCall(PetscOptionsFList("-mat_coarsen_type", "Type of aggregator", "MatCoarsenSetType", MatCoarsenList, def, type, 256, &flag));
368:   if (flag) PetscCall(MatCoarsenSetType(coarser, type));

370:   PetscCall(PetscOptionsInt("-mat_coarsen_max_it", "Number of iterations (for HEM)", "MatCoarsenSetMaximumIterations", coarser->max_it, &coarser->max_it, NULL));
371:   PetscCall(PetscOptionsInt("-mat_coarsen_threshold", "Threshold (for HEM)", "MatCoarsenSetThreshold", coarser->max_it, &coarser->max_it, NULL));
372:   coarser->strength_index_size = MAT_COARSEN_STRENGTH_INDEX_SIZE;
373:   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));
374:   /*
375:    Set the type if it was never set.
376:    */
377:   if (!((PetscObject)coarser)->type_name) PetscCall(MatCoarsenSetType(coarser, def));

379:   PetscTryTypeMethod(coarser, setfromoptions, PetscOptionsObject);
380:   PetscOptionsEnd();
381:   PetscFunctionReturn(PETSC_SUCCESS);
382: }

384: /*@
385:   MatCoarsenSetMaximumIterations - Max HEM iterations

387:   Logically Collective

389:   Input Parameters:
390: + coarse - the coarsen context
391: - n      - number of HEM iterations

393:   Options Database Key:
394: . -mat_coarsen_max_it <default=4> - Max HEM iterations

396:   Level: intermediate

398: .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
399: @*/
400: PetscErrorCode MatCoarsenSetMaximumIterations(MatCoarsen coarse, PetscInt n)
401: {
402:   PetscFunctionBegin;
405:   PetscTryMethod(coarse, "MatCoarsenSetMaximumIterations_C", (MatCoarsen, PetscInt), (coarse, n));
406:   PetscFunctionReturn(PETSC_SUCCESS);
407: }

409: static PetscErrorCode MatCoarsenSetMaximumIterations_MATCOARSEN(MatCoarsen coarse, PetscInt b)
410: {
411:   PetscFunctionBegin;
412:   coarse->max_it = b;
413:   PetscFunctionReturn(PETSC_SUCCESS);
414: }

416: /*@
417:   MatCoarsenSetStrengthIndex -  Index array to use for index to use for strength of connection

419:   Logically Collective

421:   Input Parameters:
422: + coarse - the coarsen context
423: . n      - number of indices
424: - idx    - array of indices

426:   Options Database Key:
427: . -mat_coarsen_strength_index - array of subset of variables per vertex to use for strength norm, -1 for using all (default)

429:   Level: intermediate

431: .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
432: @*/
433: PetscErrorCode MatCoarsenSetStrengthIndex(MatCoarsen coarse, PetscInt n, PetscInt idx[])
434: {
435:   PetscFunctionBegin;
438:   PetscTryMethod(coarse, "MatCoarsenSetStrengthIndex_C", (MatCoarsen, PetscInt, PetscInt[]), (coarse, n, idx));
439:   PetscFunctionReturn(PETSC_SUCCESS);
440: }

442: static PetscErrorCode MatCoarsenSetStrengthIndex_MATCOARSEN(MatCoarsen coarse, PetscInt n, PetscInt idx[])
443: {
444:   PetscFunctionBegin;
445:   coarse->strength_index_size = n;
446:   for (int iii = 0; iii < n; iii++) coarse->strength_index[iii] = idx[iii];
447:   PetscFunctionReturn(PETSC_SUCCESS);
448: }

450: /*@
451:   MatCoarsenSetThreshold - Max HEM iterations

453:   Logically Collective

455:   Input Parameters:
456: + coarse - the coarsen context
457: - b      - threshold value

459:   Options Database Key:
460: . -mat_coarsen_threshold <-1> - Max HEM iterations

462:   Level: intermediate

464: .seealso: `MatCoarsen`, `MatCoarsenType`, `MatCoarsenApply()`, `MatCoarsenCreate()`, `MatCoarsenSetType()`
465: @*/
466: PetscErrorCode MatCoarsenSetThreshold(MatCoarsen coarse, PetscReal b)
467: {
468:   PetscFunctionBegin;
471:   PetscTryMethod(coarse, "MatCoarsenSetThreshold_C", (MatCoarsen, PetscReal), (coarse, b));
472:   PetscFunctionReturn(PETSC_SUCCESS);
473: }

475: static PetscErrorCode MatCoarsenSetThreshold_MATCOARSEN(MatCoarsen coarse, PetscReal b)
476: {
477:   PetscFunctionBegin;
478:   coarse->threshold = b;
479:   PetscFunctionReturn(PETSC_SUCCESS);
480: }

482: /*@
483:   MatCoarsenCreate - Creates a coarsen context.

485:   Collective

487:   Input Parameter:
488: . comm - MPI communicator

490:   Output Parameter:
491: . newcrs - location to put the context

493:   Level: advanced

495: .seealso: `MatCoarsen`, `MatCoarsenSetType()`, `MatCoarsenApply()`, `MatCoarsenDestroy()`,
496:           `MatCoarsenSetAdjacency()`, `MatCoarsenGetData()`

498: @*/
499: PetscErrorCode MatCoarsenCreate(MPI_Comm comm, MatCoarsen *newcrs)
500: {
501:   MatCoarsen agg;

503:   PetscFunctionBegin;
504:   *newcrs = NULL;

506:   PetscCall(MatInitializePackage());
507:   PetscCall(PetscHeaderCreate(agg, MAT_COARSEN_CLASSID, "MatCoarsen", "Matrix/graph coarsen", "MatCoarsen", comm, MatCoarsenDestroy, MatCoarsenView));
508:   PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetMaximumIterations_C", MatCoarsenSetMaximumIterations_MATCOARSEN));
509:   PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetThreshold_C", MatCoarsenSetThreshold_MATCOARSEN));
510:   PetscCall(PetscObjectComposeFunction((PetscObject)agg, "MatCoarsenSetStrengthIndex_C", MatCoarsenSetStrengthIndex_MATCOARSEN));

512:   agg->strength_index_size = 0;

514:   *newcrs = agg;
515:   PetscFunctionReturn(PETSC_SUCCESS);
516: }