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: /*@C
 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: `PFCreate()`, `PFDestroy()`, `PFSetType()`, `PFApply()`, `PFApplyVec()`
 26: @*/
 27: PetscErrorCode PFSet(PF pf, PetscErrorCode (*apply)(void *, PetscInt, const PetscScalar *, PetscScalar *), PetscErrorCode (*applyvec)(void *, Vec, Vec), PetscErrorCode (*view)(void *, PetscViewer), PetscErrorCode (*destroy)(void *), void *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: /*@C
 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: `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: /*@C
 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: `PFSet()`, `PFApply()`, `PFDestroy()`, `PFApplyVec()`
 83: @*/
 84: PetscErrorCode PFCreate(MPI_Comm comm, PetscInt dimin, PetscInt dimout, PF *pf)
 85: {
 86:   PF newpf;

 88:   PetscFunctionBegin;
 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: /* -------------------------------------------------------------------------------*/

108: /*@
109:    PFApplyVec - Applies the mathematical function to a vector

111:    Collective

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

117:    Output Parameter:
118: .  y - output vector

120:    Level: beginner

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

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

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

149:   PetscCall(VecGetLocalSize(x, &n));
150:   PetscCall(VecGetLocalSize(y, &p));
151:   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);
152:   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);
153:   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);

155:   if (pf->ops->applyvec) PetscCall((*pf->ops->applyvec)(pf->data, x, y));
156:   else {
157:     PetscScalar *xx, *yy;

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

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

174:    Collective

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

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

186:    Level: beginner

188:    Notes:

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

200:   PetscCall((*pf->ops->apply)(pf->data, n, x, y));
201:   PetscFunctionReturn(PETSC_SUCCESS);
202: }

204: /*@C
205:    PFViewFromOptions - View from Options

207:    Collective

209:    Input Parameters:
210: +  A - the PF context
211: .  obj - Optional object
212: -  name - command line option

214:    Level: intermediate
215: .seealso: `PF`, `PFView`, `PetscObjectViewFromOptions()`, `PFCreate()`
216: @*/
217: PetscErrorCode PFViewFromOptions(PF A, PetscObject obj, const char name[])
218: {
219:   PetscFunctionBegin;
221:   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
222:   PetscFunctionReturn(PETSC_SUCCESS);
223: }

225: /*@
226:    PFView - Prints information about a mathematical function

228:    Collective on PF unless PetscViewer is PETSC_VIEWER_STDOUT_SELF

230:    Input Parameters:
231: +  PF - the PF context
232: -  viewer - optional visualization context

234:    Note:
235:    The available visualization contexts include
236: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
237: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
238:          output where only the first processor opens
239:          the file.  All other processors send their
240:          data to the first processor to print.

242:    The user can open an alternative visualization contexts with
243:    PetscViewerASCIIOpen() (output to a specified file).

245:    Level: developer

247: .seealso: `PetscViewerCreate()`, `PetscViewerASCIIOpen()`
248: @*/
249: PetscErrorCode PFView(PF pf, PetscViewer viewer)
250: {
251:   PetscBool         iascii;
252:   PetscViewerFormat format;

254:   PetscFunctionBegin;
256:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pf), &viewer));
258:   PetscCheckSameComm(pf, 1, viewer, 2);

260:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
261:   if (iascii) {
262:     PetscCall(PetscViewerGetFormat(viewer, &format));
263:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pf, viewer));
264:     if (pf->ops->view) {
265:       PetscCall(PetscViewerASCIIPushTab(viewer));
266:       PetscCall((*pf->ops->view)(pf->data, viewer));
267:       PetscCall(PetscViewerASCIIPopTab(viewer));
268:     }
269:   }
270:   PetscFunctionReturn(PETSC_SUCCESS);
271: }

273: /*@C
274:    PFRegister - Adds a method to the mathematical function package.

276:    Not collective

278:    Input Parameters:
279: +  name_solver - name of a new user-defined solver
280: -  routine_create - routine to create method context

282:    Notes:
283:    PFRegister() may be called multiple times to add several user-defined functions

285:    Sample usage:
286: .vb
287:    PFRegister("my_function",MyFunctionSetCreate);
288: .ve

290:    Then, your solver can be chosen with the procedural interface via
291: $     PFSetType(pf,"my_function")
292:    or at runtime via the option
293: $     -pf_type my_function

295:    Level: advanced

297: .seealso: `PFRegisterAll()`, `PFRegisterDestroy()`, `PFRegister()`
298: @*/
299: PetscErrorCode PFRegister(const char sname[], PetscErrorCode (*function)(PF, void *))
300: {
301:   PetscFunctionBegin;
302:   PetscCall(PFInitializePackage());
303:   PetscCall(PetscFunctionListAdd(&PFList, sname, function));
304:   PetscFunctionReturn(PETSC_SUCCESS);
305: }

307: /*@C
308:    PFGetType - Gets the PF method type and name (as a string) from the PF
309:    context.

311:    Not Collective

313:    Input Parameter:
314: .  pf - the function context

316:    Output Parameter:
317: .  type - name of function

319:    Level: intermediate

321: .seealso: `PFSetType()`

323: @*/
324: PetscErrorCode PFGetType(PF pf, PFType *type)
325: {
326:   PetscFunctionBegin;
329:   *type = ((PetscObject)pf)->type_name;
330:   PetscFunctionReturn(PETSC_SUCCESS);
331: }

333: /*@C
334:    PFSetType - Builds PF for a particular function

336:    Collective

338:    Input Parameters:
339: +  pf - the function context.
340: .  type - a known method
341: -  ctx - optional type dependent context

343:    Options Database Key:
344: .  -pf_type <type> - Sets PF type

346:   Notes:
347:   See "petsc/include/petscpf.h" for available methods (for instance,
348:   PFCONSTANT)

350:   Level: intermediate

352: .seealso: `PFSet()`, `PFRegister()`, `PFCreate()`, `DMDACreatePF()`

354: @*/
355: PetscErrorCode PFSetType(PF pf, PFType type, void *ctx)
356: {
357:   PetscBool match;
358:   PetscErrorCode (*r)(PF, void *);

360:   PetscFunctionBegin;

364:   PetscCall(PetscObjectTypeCompare((PetscObject)pf, type, &match));
365:   if (match) PetscFunctionReturn(PETSC_SUCCESS);

367:   PetscTryTypeMethod(pf, destroy);
368:   pf->data = NULL;

370:   /* Determine the PFCreateXXX routine for a particular function */
371:   PetscCall(PetscFunctionListFind(PFList, type, &r));
372:   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unable to find requested PF type %s", type);
373:   pf->ops->destroy  = NULL;
374:   pf->ops->view     = NULL;
375:   pf->ops->apply    = NULL;
376:   pf->ops->applyvec = NULL;

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

381:   PetscCall(PetscObjectChangeTypeName((PetscObject)pf, type));
382:   PetscFunctionReturn(PETSC_SUCCESS);
383: }

385: /*@
386:    PFSetFromOptions - Sets PF options from the options database.

388:    Collective

390:    Input Parameters:
391: .  pf - the mathematical function context

393:    Options Database Keys:

395:    Notes:
396:    To see all options, run your program with the -help option
397:    or consult the users manual.

399:    Level: intermediate

401: .seealso:
402: @*/
403: PetscErrorCode PFSetFromOptions(PF pf)
404: {
405:   char      type[256];
406:   PetscBool flg;

408:   PetscFunctionBegin;

411:   PetscObjectOptionsBegin((PetscObject)pf);
412:   PetscCall(PetscOptionsFList("-pf_type", "Type of function", "PFSetType", PFList, NULL, type, 256, &flg));
413:   if (flg) PetscCall(PFSetType(pf, type, NULL));
414:   PetscTryTypeMethod(pf, setfromoptions, PetscOptionsObject);

416:   /* process any options handlers added with PetscObjectAddOptionsHandler() */
417:   PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)pf, PetscOptionsObject));
418:   PetscOptionsEnd();
419:   PetscFunctionReturn(PETSC_SUCCESS);
420: }

422: static PetscBool PFPackageInitialized = PETSC_FALSE;
423: /*@C
424:   PFFinalizePackage - This function destroys everything in the Petsc interface to Mathematica. It is
425:   called from PetscFinalize().

427:   Level: developer

429: .seealso: `PetscFinalize()`
430: @*/
431: PetscErrorCode PFFinalizePackage(void)
432: {
433:   PetscFunctionBegin;
434:   PetscCall(PetscFunctionListDestroy(&PFList));
435:   PFPackageInitialized = PETSC_FALSE;
436:   PFRegisterAllCalled  = PETSC_FALSE;
437:   PetscFunctionReturn(PETSC_SUCCESS);
438: }

440: /*@C
441:   PFInitializePackage - This function initializes everything in the PF package. It is called
442:   from PetscDLLibraryRegister_petscvec() when using dynamic libraries, and on the first call to PFCreate()
443:   when using shared or static libraries.

445:   Level: developer

447: .seealso: `PetscInitialize()`
448: @*/
449: PetscErrorCode PFInitializePackage(void)
450: {
451:   char      logList[256];
452:   PetscBool opt, pkg;

454:   PetscFunctionBegin;
455:   if (PFPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
456:   PFPackageInitialized = PETSC_TRUE;
457:   /* Register Classes */
458:   PetscCall(PetscClassIdRegister("PointFunction", &PF_CLASSID));
459:   /* Register Constructors */
460:   PetscCall(PFRegisterAll());
461:   /* Process Info */
462:   {
463:     PetscClassId classids[1];

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