Actual source code: pf.c

  1: /*
  2:     The PF mathematical functions interface routines, callable by users.
  3: */
  4: #include <../src/vec/pf/pfimpl.h>

  6: PetscClassId      PF_CLASSID          = 0;
  7: PetscFunctionList PFList              = NULL; /* list of all registered PD functions */
  8: PetscBool         PFRegisterAllCalled = PETSC_FALSE;

 10: /*@
 11:   PFSet - Sets the C/C++/Fortran functions to be used by the PF function

 13:   Collective

 15:   Input Parameters:
 16: + pf       - the function context
 17: . apply    - function to apply to an array
 18: . applyvec - function to apply to a Vec
 19: . view     - function that prints information about the `PF`
 20: . destroy  - function to free the private function context
 21: - ctx      - private function context

 23:   Level: beginner

 25: .seealso: `PF`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFApply()`, `PFApplyVec()`
 26: @*/
 27: PetscErrorCode PFSet(PF pf, PetscErrorCode (*apply)(PetscCtx, PetscInt, const PetscScalar *, PetscScalar *), PetscErrorCode (*applyvec)(PetscCtx, Vec, Vec), PetscErrorCode (*view)(PetscCtx, PetscViewer), PetscErrorCode (*destroy)(PetscCtxRt), PetscCtx ctx)
 28: {
 29:   PetscFunctionBegin;
 31:   pf->data          = ctx;
 32:   pf->ops->destroy  = destroy;
 33:   pf->ops->apply    = apply;
 34:   pf->ops->applyvec = applyvec;
 35:   pf->ops->view     = view;
 36:   PetscFunctionReturn(PETSC_SUCCESS);
 37: }

 39: /*@
 40:   PFDestroy - Destroys `PF` context that was created with `PFCreate()`.

 42:   Collective

 44:   Input Parameter:
 45: . pf - the function context

 47:   Level: beginner

 49: .seealso: `PF`, `PFCreate()`, `PFSet()`, `PFSetType()`
 50: @*/
 51: PetscErrorCode PFDestroy(PF *pf)
 52: {
 53:   PetscFunctionBegin;
 54:   if (!*pf) PetscFunctionReturn(PETSC_SUCCESS);
 56:   if (--((PetscObject)*pf)->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);

 58:   PetscCall(PFViewFromOptions(*pf, NULL, "-pf_view"));
 59:   /* if memory was published with SAWs then destroy it */
 60:   PetscCall(PetscObjectSAWsViewOff((PetscObject)*pf));

 62:   if ((*pf)->ops->destroy) PetscCall((*(*pf)->ops->destroy)((*pf)->data));
 63:   PetscCall(PetscHeaderDestroy(pf));
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

 67: /*@
 68:   PFCreate - Creates a mathematical function context.

 70:   Collective

 72:   Input Parameters:
 73: + comm   - MPI communicator
 74: . dimin  - dimension of the space you are mapping from
 75: - dimout - dimension of the space you are mapping to

 77:   Output Parameter:
 78: . pf - the function context

 80:   Level: developer

 82: .seealso: `PF`, `PFSet()`, `PFApply()`, `PFDestroy()`, `PFApplyVec()`
 83: @*/
 84: PetscErrorCode PFCreate(MPI_Comm comm, PetscInt dimin, PetscInt dimout, PF *pf)
 85: {
 86:   PF newpf;

 88:   PetscFunctionBegin;
 89:   PetscAssertPointer(pf, 4);
 90:   *pf = NULL;
 91:   PetscCall(PFInitializePackage());

 93:   PetscCall(PetscHeaderCreate(newpf, PF_CLASSID, "PF", "Mathematical functions", "Vec", comm, PFDestroy, PFView));
 94:   newpf->data          = NULL;
 95:   newpf->ops->destroy  = NULL;
 96:   newpf->ops->apply    = NULL;
 97:   newpf->ops->applyvec = NULL;
 98:   newpf->ops->view     = NULL;
 99:   newpf->dimin         = dimin;
100:   newpf->dimout        = dimout;

102:   *pf = newpf;
103:   PetscFunctionReturn(PETSC_SUCCESS);
104: }

106: /*@
107:   PFApplyVec - Applies the mathematical function to a vector

109:   Collective

111:   Input Parameters:
112: + pf - the function context
113: - x  - input vector (or `NULL` for the vector (0,1, .... N-1)

115:   Output Parameter:
116: . y - output vector

118:   Level: beginner

120: .seealso: `PF`, `PFApply()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
121: @*/
122: PetscErrorCode PFApplyVec(PF pf, Vec x, Vec y)
123: {
124:   PetscInt  i, rstart, rend, n, p;
125:   PetscBool nox = PETSC_FALSE;

127:   PetscFunctionBegin;
130:   if (x) {
132:     PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different vectors");
133:   } else {
134:     PetscScalar *xx;
135:     PetscInt     lsize;

137:     PetscCall(VecGetLocalSize(y, &lsize));
138:     lsize = pf->dimin * lsize / pf->dimout;
139:     PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)y), lsize, PETSC_DETERMINE, &x));
140:     nox = PETSC_TRUE;
141:     PetscCall(VecGetOwnershipRange(x, &rstart, &rend));
142:     PetscCall(VecGetArray(x, &xx));
143:     for (i = rstart; i < rend; i++) xx[i - rstart] = (PetscScalar)i;
144:     PetscCall(VecRestoreArray(x, &xx));
145:   }

147:   PetscCall(VecGetLocalSize(x, &n));
148:   PetscCall(VecGetLocalSize(y, &p));
149:   PetscCheck((pf->dimin * (n / pf->dimin)) == n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local input vector length %" PetscInt_FMT " not divisible by dimin %" PetscInt_FMT " of function", n, pf->dimin);
150:   PetscCheck((pf->dimout * (p / pf->dimout)) == p, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local output vector length %" PetscInt_FMT " not divisible by dimout %" PetscInt_FMT " of function", p, pf->dimout);
151:   PetscCheck((n / pf->dimin) == (p / pf->dimout), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Local vector lengths %" PetscInt_FMT " %" PetscInt_FMT " are wrong for dimin and dimout %" PetscInt_FMT " %" PetscInt_FMT " of function", n, p, pf->dimin, pf->dimout);

153:   if (pf->ops->applyvec) PetscCallBack("PF callback apply to vector", (*pf->ops->applyvec)(pf->data, x, y));
154:   else {
155:     const PetscScalar *xx;
156:     PetscScalar       *yy;

158:     PetscCall(VecGetLocalSize(x, &n));
159:     n = n / pf->dimin;
160:     PetscCall(VecGetArrayRead(x, &xx));
161:     PetscCall(VecGetArray(y, &yy));
162:     PetscCallBack("PF callback apply to array", (*pf->ops->apply)(pf->data, n, xx, yy));
163:     PetscCall(VecRestoreArrayRead(x, &xx));
164:     PetscCall(VecRestoreArray(y, &yy));
165:   }
166:   if (nox) PetscCall(VecDestroy(&x));
167:   PetscFunctionReturn(PETSC_SUCCESS);
168: }

170: /*@
171:   PFApply - Applies the mathematical function to an array of values.

173:   Collective

175:   Input Parameters:
176: + pf - the function context
177: . n  - number of pointwise function evaluations to perform, each pointwise function evaluation
178:        is a function of dimin variables and computes dimout variables where dimin and dimout are defined
179:        in the call to `PFCreate()`
180: - x  - input array

182:   Output Parameter:
183: . y - output array

185:   Level: beginner

187: .seealso: `PF`, `PFApplyVec()`, `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFSet()`
188: @*/
189: PetscErrorCode PFApply(PF pf, PetscInt n, const PetscScalar *x, PetscScalar *y)
190: {
191:   PetscFunctionBegin;
193:   PetscAssertPointer(x, 3);
194:   PetscAssertPointer(y, 4);
195:   PetscCheck(x != y, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "x and y must be different arrays");

197:   PetscCallBack("PF callback apply", (*pf->ops->apply)(pf->data, n, x, y));
198:   PetscFunctionReturn(PETSC_SUCCESS);
199: }

201: /*@
202:   PFViewFromOptions - View a `PF` based on options set in the options database

204:   Collective

206:   Input Parameters:
207: + A    - the `PF` context
208: . obj  - optional object that provides the prefix used to search the options database, pass `NULL` to use the options prefix of `A`
209: - name - command line option

211:   Options Database Key:
212: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

214:   Level: intermediate

216:   Note:
217:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
218:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

220: .seealso: `PF`, `PFView()`, `PetscObjectViewFromOptions()`, `PFCreate()`, `PetscOptionsCreateViewer()`
221: @*/
222: PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[])
223: {
224:   PetscFunctionBegin;
226:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
227:   PetscFunctionReturn(PETSC_SUCCESS);
228: }

230: /*@
231:   PFView - Prints information about a mathematical function

233:   Collective unless `viewer` is `PETSC_VIEWER_STDOUT_SELF`

235:   Input Parameters:
236: + pf     - the `PF` context
237: - viewer - optional visualization context

239:   Level: developer

241:   Note:
242:   The available visualization contexts include
243: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
244: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
245:   output where only the first processor opens
246:   the file.  All other processors send their
247:   data to the first processor to print.

249:   The user can open an alternative visualization contexts with
250:   `PetscViewerASCIIOpen()` (output to a specified file).

252: .seealso: `PF`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`
253: @*/
254: PetscErrorCode PFView(PF pf, PetscViewer viewer)
255: {
256:   PetscBool         isascii;
257:   PetscViewerFormat format;

259:   PetscFunctionBegin;
261:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer));
263:   PetscCheckSameComm(pf, 1, viewer, 2);

265:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
266:   if (isascii) {
267:     PetscCall(PetscViewerGetFormat(viewer, &format));
268:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer));
269:     if (pf->ops->view) {
270:       PetscCall(PetscViewerASCIIPushTab(viewer));
271:       PetscCallBack("PF callback view", (*pf->ops->view)(pf->data, viewer));
272:       PetscCall(PetscViewerASCIIPopTab(viewer));
273:     }
274:   }
275:   PetscFunctionReturn(PETSC_SUCCESS);
276: }

278: /*@
279:   PFRegister - Adds a method to the mathematical function package.

281:   Not Collective

283:   Input Parameters:
284: + sname    - name of a new user-defined solver
285: - function - routine to create method context

287:   Example Usage:
288: .vb
289:    PFRegister("my_function", MyFunctionSetCreate);
290: .ve

292:   Then, your solver can be chosen with the procedural interface via
293: .vb
294:   PFSetType(pf, "my_function")
295: .ve
296:   or at runtime via the option
297: .vb
298:   -pf_type my_function
299: .ve

301:   Level: advanced

303:   Note:
304:   `PFRegister()` may be called multiple times to add several user-defined functions

306: .seealso: `PF`, `PFRegisterAll()`, `PFRegisterDestroy()`
307: @*/
308: PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, PetscCtx))
309: {
310:   PetscFunctionBegin;
311:   PetscCall(PFInitializePackage());
312:   PetscCall(PetscFunctionListAdd(&PFList, sname, function));
313:   PetscFunctionReturn(PETSC_SUCCESS);
314: }

316: /*@
317:   PFGetType - Gets the `PFType` name (as a string) from the `PF`
318:   context.

320:   Not Collective

322:   Input Parameter:
323: . pf - the function context

325:   Output Parameter:
326: . type - name of function

328:   Level: intermediate

330:   Note:
331:   `type` should not be retained for later use as it will be an invalid pointer if the `PFType` of `pf` is changed.

333: .seealso: `PF`, `PFSetType()`, `PFType`, `PetscObjectTypeCompare()`, `PetscObjectTypeCompareAny()`
334: @*/
335: PetscErrorCode PFGetType(PF pf, PFType *type)
336: {
337:   PetscFunctionBegin;
339:   PetscAssertPointer(type, 2);
340:   *type = ((PetscObject)pf)->type_name;
341:   PetscFunctionReturn(PETSC_SUCCESS);
342: }

344: /*@
345:   PFSetType - Builds `PF` for a particular function

347:   Collective

349:   Input Parameters:
350: + pf   - the function context.
351: . type - a known type, see `PFType` for available methods (for instance, `PFCONSTANT`)
352: - ctx  - optional type dependent context

354:   Options Database Key:
355: . -pf_type (constant|mat|string|quick|identity|matlab) - Set the `PFType`

357:   Level: intermediate

359: .seealso: `PF`, `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()`, `PFType`, `PFGetType()`
360: @*/
361: PetscErrorCode PFSetType(PF pf, PFType type, PetscCtx ctx)
362: {
363:   PetscBool match;
364:   PetscErrorCode (*r)(PF, PetscCtx);

366:   PetscFunctionBegin;
368:   PetscAssertPointer(type, 2);

370:   PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match));
371:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

373:   PetscTryTypeMethod(pf, destroy);
374:   pf->data = NULL;

376:   /* Determine the PFCreateXXX routine for a particular function */
377:   PetscCall(PetscFunctionListFind(PFList, type, &r));
378:   PetscCheck(r, PetscObjectComm((PetscObject)pf), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type);
379:   pf->ops->destroy  = NULL;
380:   pf->ops->view     = NULL;
381:   pf->ops->apply    = NULL;
382:   pf->ops->applyvec = NULL;

384:   /* Call the PFCreateXXX routine for this particular function */
385:   PetscCall((*r)(pf, ctx));

387:   PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type));
388:   PetscFunctionReturn(PETSC_SUCCESS);
389: }

391: /*@
392:   PFSetFromOptions - Sets `PF` options from the options database.

394:   Collective

396:   Input Parameters:
397: . pf - the mathematical function context

399:   Level: intermediate

401:   Notes:
402:   To see all options, run your program with the -help option
403:   or consult the users manual.

405: .seealso: `PF`
406: @*/
407: PetscErrorCode PFSetFromOptions(PF pf)
408: {
409:   char      type[256];
410:   PetscBool flg;

412:   PetscFunctionBegin;

415:   PetscObjectOptionsBegin((PetscObject)pf);
416:   PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, sizeof(type), &flg));
417:   if (flg) PetscCall(PFSetType(pf, type, NULL));
418:   PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject);

420:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
421:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject));
422:   PetscOptionsEnd();
423:   PetscFunctionReturn(PETSC_SUCCESS);
424: }

426: static PetscBool PFPackageInitialized = PETSC_FALSE;

428: /*@
429:   PFFinalizePackage - This function destroys everything in the PETSc `PF` package. It is
430:   called from `PetscFinalize()`.

432:   Level: developer

434: .seealso: `PF`, `PetscFinalize()`
435: @*/
436: PetscErrorCode PFFinalizePackage(void)
437: {
438:   PetscFunctionBegin;
439:   PetscCall(PetscFunctionListDestroy(&PFList));
440:   PFPackageInitialized = PETSC_FALSE;
441:   PFRegisterAllCalled  = PETSC_FALSE;
442:   PetscFunctionReturn(PETSC_SUCCESS);
443: }

445: /*@
446:   PFInitializePackage - This function initializes everything in the `PF` package. It is called
447:   from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to `PFCreate()`
448:   when using shared or static libraries.

450:   Level: developer

452: .seealso: `PF`, `PetscInitialize()`
453: @*/
454: PetscErrorCode PFInitializePackage(void)
455: {
456:   char      logList[256];
457:   PetscBool opt, pkg;

459:   PetscFunctionBegin;
460:   if (PFPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
461:   PFPackageInitialized = PETSC_TRUE;
462:   /* Register Classes */
463:   PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID));
464:   /* Register Constructors */
465:   PetscCall(PFRegisterAll());
466:   /* Process Info */
467:   {
468:     PetscClassId classids[1];

470:     classids[0] = PF_CLASSID;
471:     PetscCall(PetscInfoProcessClass("pf", 1, classids));
472:   }
473:   /* Process summary exclusions */
474:   PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
475:   if (opt) {
476:     PetscCall(PetscStrInList("pf", logList, ',', &pkg));
477:     if (pkg) PetscCall(PetscLogEventExcludeClass(PF_CLASSID));
478:   }
479:   /* Register package finalizer */
480:   PetscCall(PetscRegisterFinalize(PFFinalizePackage));
481:   PetscFunctionReturn(PETSC_SUCCESS);
482: }

484: /*@
485:   PFSetOptionsPrefix - Sets the prefix used for searching for all
486:   `PF` options in the database.

488:   Logically Collective

490:   Input Parameters:
491: + pf     - the `PF` context
492: - prefix - the prefix string to prepend to all `PF` option requests

494:   Level: advanced

496:   Note:
497:   A hyphen (-) must NOT be given at the beginning of the prefix name.
498:   The first character of all runtime options is AUTOMATICALLY the
499:   hyphen.

501: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFAppendOptionsPrefix()`, `PFGetOptionsPrefix()`
502: @*/
503: PetscErrorCode PFSetOptionsPrefix(PF pf, const char prefix[])
504: {
505:   PetscFunctionBegin;
507:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pf, prefix));
508:   PetscFunctionReturn(PETSC_SUCCESS);
509: }

511: /*@
512:   PFAppendOptionsPrefix - Appends to the prefix used for searching for all
513:   `PF` options in the database.

515:   Logically Collective

517:   Input Parameters:
518: + pf     - the `PF`
519: - prefix - the prefix string to prepend to all `PF` option requests

521:   Level: advanced

523:   Note:
524:   A hyphen (-) must NOT be given at the beginning of the prefix name.
525:   The first character of all runtime options is AUTOMATICALLY the
526:   hyphen.

528: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFSetOptionsPrefix()`, `PFGetOptionsPrefix()`
529: @*/
530: PetscErrorCode PFAppendOptionsPrefix(PF pf, const char prefix[])
531: {
532:   PetscFunctionBegin;
534:   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)pf, prefix));
535:   PetscFunctionReturn(PETSC_SUCCESS);
536: }

538: /*@
539:   PFGetOptionsPrefix - Gets the prefix used for searching for all
540:   `PF` options in the database.

542:   Not Collective

544:   Input Parameter:
545: . pf - the `PF`

547:   Output Parameter:
548: . prefix - pointer to the prefix string used, is returned

550:   Level: advanced

552: .seealso: [](ch_ksp), `PF`, `PFSetFromOptions()`, `PFSetOptionsPrefix()`, `PFAppendOptionsPrefix()`
553: @*/
554: PetscErrorCode PFGetOptionsPrefix(PF pf, const char *prefix[])
555: {
556:   PetscFunctionBegin;
558:   PetscAssertPointer(prefix, 2);
559:   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pf, prefix));
560:   PetscFunctionReturn(PETSC_SUCCESS);
561: }