#include /*I "petscdm.h" I*/ /*@ DMGetLocalVector - Gets a PETSc vector that may be used with the `DM` local routines. This vector has spaces for the ghost values. Not Collective Input Parameter: . dm - the `DM` Output Parameter: . g - the local vector Level: beginner Note: The vector values are NOT initialized and may have garbage in them, so you may need to zero them. The output parameter, `g`, is a regular PETSc vector that should be returned with `DMRestoreLocalVector()` DO NOT call `VecDestroy()` on it. This is intended to be used for vectors you need for a short time, like within a single function call. For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your code you should use `DMCreateLocalVector()`. VecStride*() operations can be useful when using `DM` with dof > 1 .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()`, `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearLocalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()` @*/ PetscErrorCode DMGetLocalVector(DM dm, Vec *g) { PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(g, 2); for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (dm->localin[i]) { DM vdm; *g = dm->localin[i]; dm->localin[i] = NULL; PetscCall(VecGetDM(*g, &vdm)); PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); PetscCall(VecSetDM(*g, dm)); goto alldone; } } PetscCall(DMCreateLocalVector(dm, g)); alldone: for (PetscInt i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (!dm->localout[i]) { dm->localout[i] = *g; break; } } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMRestoreLocalVector - Returns a PETSc vector that was obtained from `DMGetLocalVector()`. Do not use with vector obtained via `DMCreateLocalVector()`. Not Collective Input Parameters: + dm - the `DM` - g - the local vector Level: beginner .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMGetLocalVector()`, `DMClearLocalVectors()` @*/ PetscErrorCode DMRestoreLocalVector(DM dm, Vec *g) { PetscInt i, j; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(g, 2); for (j = 0; j < DM_MAX_WORK_VECTORS; j++) { if (*g == dm->localout[j]) { DM vdm; PetscCall(VecGetDM(*g, &vdm)); PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); PetscCall(VecSetDM(*g, NULL)); dm->localout[j] = NULL; for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (!dm->localin[i]) { dm->localin[i] = *g; goto alldone; } } } } PetscCall(VecDestroy(g)); alldone: *g = NULL; PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMGetGlobalVector - Gets a PETSc vector that may be used with the `DM` global routines. Collective Input Parameter: . dm - the `DM` Output Parameter: . g - the global vector Level: beginner Note: The vector values are NOT initialized and may have garbage in them, so you may need to zero them. The output parameter, `g`, is a regular PETSc vector that should be returned with `DMRestoreGlobalVector()` DO NOT call `VecDestroy()` on it. This is intended to be used for vectors you need for a short time, like within a single function call. For vectors that you intend to keep around (for example in a C struct) or pass around large parts of your code you should use `DMCreateGlobalVector()`. VecStride*() operations can be useful when using `DM` with dof > 1 .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearGlobalVectors()`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()` @*/ PetscErrorCode DMGetGlobalVector(DM dm, Vec *g) { PetscInt i; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(g, 2); for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (dm->globalin[i]) { DM vdm; *g = dm->globalin[i]; dm->globalin[i] = NULL; PetscCall(VecGetDM(*g, &vdm)); PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); PetscCall(VecSetDM(*g, dm)); goto alldone; } } PetscCall(DMCreateGlobalVector(dm, g)); alldone: for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (!dm->globalout[i]) { dm->globalout[i] = *g; break; } } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMClearGlobalVectors - Destroys all the global vectors that have been created for `DMGetGlobalVector()` calls in this `DM` Collective Input Parameter: . dm - the `DM` Level: developer .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToLocalBegin()`, `DMGlobalToLocalEnd()`, `DMLocalToGlobalBegin()`, `DMCreateLocalVector()`, `DMRestoreLocalVector()` `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearLocalVectors()` @*/ PetscErrorCode DMClearGlobalVectors(DM dm) { PetscInt i; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { Vec g; PetscCheck(!dm->globalout[i], PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of global vectors that has a global vector obtained with DMGetGlobalVector()"); g = dm->globalin[i]; dm->globalin[i] = NULL; if (g) { DM vdm; PetscCall(VecGetDM(g, &vdm)); PetscCheck(!vdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Clearing global vector that has a DM attached"); } PetscCall(VecDestroy(&g)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMClearLocalVectors - Destroys all the local vectors that have been created for `DMGetLocalVector()` calls in this `DM` Collective Input Parameter: . dm - the `DM` Level: developer .seealso: `DM`, `DMCreateLocalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMLocalToLocalBegin()`, `DMLocalToLocalEnd()`, `DMRestoreLocalVector()` `VecStrideMax()`, `VecStrideMin()`, `VecStrideNorm()`, `DMClearGlobalVectors()` @*/ PetscErrorCode DMClearLocalVectors(DM dm) { PetscInt i; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { Vec g; PetscCheck(!dm->localout[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing DM of local vectors that has a local vector obtained with DMGetLocalVector()"); g = dm->localin[i]; dm->localin[i] = NULL; if (g) { DM vdm; PetscCall(VecGetDM(g, &vdm)); PetscCheck(!vdm, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Clearing local vector that has a DM attached"); } PetscCall(VecDestroy(&g)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMRestoreGlobalVector - Returns a PETSc vector that obtained from `DMGetGlobalVector()`. Do not use with vector obtained via `DMCreateGlobalVector()`. Not Collective Input Parameters: + dm - the `DM` - g - the global vector Level: beginner .seealso: `DM`, `DMCreateGlobalVector()`, `VecDuplicate()`, `VecDuplicateVecs()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMGlobalToGlobalBegin()`, `DMGlobalToGlobalEnd()`, `DMGlobalToGlobal()`, `DMCreateLocalVector()`, `DMGetGlobalVector()`, `DMClearGlobalVectors()` @*/ PetscErrorCode DMRestoreGlobalVector(DM dm, Vec *g) { PetscInt i, j; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(g, 2); PetscCall(VecSetErrorIfLocked(*g, 2)); for (j = 0; j < DM_MAX_WORK_VECTORS; j++) { if (*g == dm->globalout[j]) { DM vdm; PetscCall(VecGetDM(*g, &vdm)); PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); PetscCall(VecSetDM(*g, NULL)); dm->globalout[j] = NULL; for (i = 0; i < DM_MAX_WORK_VECTORS; i++) { if (!dm->globalin[i]) { dm->globalin[i] = *g; goto alldone; } } } } PetscCall(VecDestroy(g)); alldone: *g = NULL; PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMClearNamedGlobalVectors - Destroys all the named global vectors that have been created with `DMGetNamedGlobalVector()` in this `DM` Collective Input Parameter: . dm - the `DM` Level: developer .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()` @*/ PetscErrorCode DMClearNamedGlobalVectors(DM dm) { DMNamedVecLink nnext; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); nnext = dm->namedglobal; dm->namedglobal = NULL; for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */ nnext = nlink->next; PetscCheck(nlink->status == DMVEC_STATUS_IN, ((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "DM still has global Vec named '%s' checked out", nlink->name); PetscCall(PetscFree(nlink->name)); PetscCall(VecDestroy(&nlink->X)); PetscCall(PetscFree(nlink)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMClearNamedLocalVectors - Destroys all the named local vectors that have been created with `DMGetNamedLocalVector()` in this `DM` Collective Input Parameter: . dm - the `DM` Level: developer .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedGlobalVectors()` @*/ PetscErrorCode DMClearNamedLocalVectors(DM dm) { DMNamedVecLink nnext; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); nnext = dm->namedlocal; dm->namedlocal = NULL; for (DMNamedVecLink nlink = nnext; nlink; nlink = nnext) { /* Destroy the named vectors */ nnext = nlink->next; PetscCheck(nlink->status == DMVEC_STATUS_IN, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM still has local Vec named '%s' checked out", nlink->name); PetscCall(PetscFree(nlink->name)); PetscCall(VecDestroy(&nlink->X)); PetscCall(PetscFree(nlink)); } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMHasNamedGlobalVector - check for a named, persistent global vector created with `DMGetNamedGlobalVector()` Not Collective Input Parameters: + dm - `DM` to hold named vectors - name - unique name for `Vec` Output Parameter: . exists - true if the vector was previously created Level: developer .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedGlobalVectors()` @*/ PetscErrorCode DMHasNamedGlobalVector(DM dm, const char *name, PetscBool *exists) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(exists, 3); *exists = PETSC_FALSE; for (link = dm->namedglobal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { *exists = PETSC_TRUE; break; } } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMGetNamedGlobalVector - get access to a named, persistent global vector Collective Input Parameters: + dm - `DM` to hold named vectors - name - unique name for `X` Output Parameter: . X - named `Vec` Level: developer Note: If a `Vec` with the given name does not exist, it is created. .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMHasNamedGlobalVector()`, `DMClearNamedGlobalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()` @*/ PetscErrorCode DMGetNamedGlobalVector(DM dm, const char *name, Vec *X) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(X, 3); for (link = dm->namedglobal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { DM vdm; PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); PetscCall(VecGetDM(link->X, &vdm)); PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); PetscCall(VecSetDM(link->X, dm)); goto found; } } /* Create the Vec */ PetscCall(PetscNew(&link)); PetscCall(PetscStrallocpy(name, &link->name)); PetscCall(DMCreateGlobalVector(dm, &link->X)); link->next = dm->namedglobal; dm->namedglobal = link; found: *X = link->X; link->status = DMVEC_STATUS_OUT; PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMRestoreNamedGlobalVector - restore access to a named, persistent global vector Collective Input Parameters: + dm - `DM` on which `X` was gotten . name - name under which `X` was gotten - X - `Vec` to restore Level: developer .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMClearNamedGlobalVectors()` @*/ PetscErrorCode DMRestoreNamedGlobalVector(DM dm, const char *name, Vec *X) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(X, 3); PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); for (link = dm->namedglobal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { DM vdm; PetscCall(VecGetDM(*X, &vdm)); PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name); PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); link->status = DMVEC_STATUS_IN; PetscCall(VecSetDM(link->X, NULL)); *X = NULL; PetscFunctionReturn(PETSC_SUCCESS); } } SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); } /*@ DMHasNamedLocalVector - check for a named, persistent local vector created with `DMGetNamedLocalVector()` Not Collective Input Parameters: + dm - `DM` to hold named vectors - name - unique name for `Vec` Output Parameter: . exists - true if the vector was previously created Level: developer Note: If a `Vec` with the given name does not exist, it is created. .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMClearNamedLocalVectors()` @*/ PetscErrorCode DMHasNamedLocalVector(DM dm, const char *name, PetscBool *exists) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(exists, 3); *exists = PETSC_FALSE; for (link = dm->namedlocal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { *exists = PETSC_TRUE; break; } } PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMGetNamedLocalVector - get access to a named, persistent local vector Not Collective Input Parameters: + dm - `DM` to hold named vectors - name - unique name for `X` Output Parameter: . X - named `Vec` Level: developer Note: If a `Vec` with the given name does not exist, it is created. .seealso: `DM`, `DMGetNamedGlobalVector()`, `DMRestoreNamedLocalVector()`, `DMHasNamedLocalVector()`, `DMClearNamedLocalVectors()`, `DMGetGlobalVector()`, `DMGetLocalVector()` @*/ PetscErrorCode DMGetNamedLocalVector(DM dm, const char *name, Vec *X) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(X, 3); for (link = dm->namedlocal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { DM vdm; PetscCheck(link->status == DMVEC_STATUS_IN, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' already checked out", name); PetscCall(VecGetDM(link->X, &vdm)); PetscCheck(!vdm, PetscObjectComm((PetscObject)vdm), PETSC_ERR_LIB, "Invalid vector"); PetscCall(VecSetDM(link->X, dm)); goto found; } } /* Create the Vec */ PetscCall(PetscNew(&link)); PetscCall(PetscStrallocpy(name, &link->name)); PetscCall(DMCreateLocalVector(dm, &link->X)); link->next = dm->namedlocal; dm->namedlocal = link; found: *X = link->X; link->status = DMVEC_STATUS_OUT; PetscFunctionReturn(PETSC_SUCCESS); } /*@ DMRestoreNamedLocalVector - restore access to a named, persistent local vector obtained with `DMGetNamedLocalVector()` Not Collective Input Parameters: + dm - `DM` on which `X` was gotten . name - name under which `X` was gotten - X - `Vec` to restore Level: developer .seealso: `DM`, `DMRestoreNamedGlobalVector()`, `DMGetNamedLocalVector()`, `DMClearNamedLocalVectors()` @*/ PetscErrorCode DMRestoreNamedLocalVector(DM dm, const char *name, Vec *X) { DMNamedVecLink link; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscAssertPointer(name, 2); PetscAssertPointer(X, 3); PetscValidHeaderSpecific(*X, VEC_CLASSID, 3); for (link = dm->namedlocal; link; link = link->next) { PetscBool match; PetscCall(PetscStrcmp(name, link->name, &match)); if (match) { DM vdm; PetscCall(VecGetDM(*X, &vdm)); PetscCheck(link->status == DMVEC_STATUS_OUT, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Vec name '%s' was not checked out", name); PetscCheck(link->X == *X, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Attempt to restore Vec name '%s', but Vec does not match the cache", name); PetscCheck(vdm == dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Invalid vector"); link->status = DMVEC_STATUS_IN; PetscCall(VecSetDM(link->X, NULL)); *X = NULL; PetscFunctionReturn(PETSC_SUCCESS); } } SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Could not find Vec name '%s' to restore", name); }