/* Plots vectors obtained with DMDACreate1d() */ #include /*I "petscdmda.h" I*/ /*@ DMDASetUniformCoordinates - Sets a `DMDA` coordinates to be a uniform grid Collective Input Parameters: + da - the `DMDA` object . xmin - min extreme in the x direction . xmax - max extreme in the x direction . ymin - min extreme in the y direction (value ignored for 1 dimensional problems) . ymax - max extreme in the y direction (value ignored for 1 dimensional problems) . zmin - min extreme in the z direction (value ignored for 1 or 2 dimensional problems) - zmax - max extreme in the z direction (value ignored for 1 or 2 dimensional problems) Level: beginner .seealso: [](sec_struct), `DM`, `DMDA`, `DMSetCoordinates()`, `DMGetCoordinates()`, `DMDACreate1d()`, `DMDACreate2d()`, `DMDACreate3d()`, `DMStagSetUniformCoordinates()` @*/ PetscErrorCode DMDASetUniformCoordinates(DM da, PetscReal xmin, PetscReal xmax, PetscReal ymin, PetscReal ymax, PetscReal zmin, PetscReal zmax) { MPI_Comm comm; DM cda; DM_DA *dd = (DM_DA *)da->data; DMBoundaryType bx, by, bz; Vec xcoor; PetscScalar *coors; PetscReal hx = 0., hy = 0., hz_ = 0.; PetscInt i, j, k, M, N, P, istart, isize, jstart, jsize, kstart, ksize, dim, cnt; PetscFunctionBegin; PetscValidHeaderSpecificType(da, DM_CLASSID, 1, DMDA); PetscCheck(dd->gtol, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_WRONGSTATE, "Cannot set coordinates until after DMDA has been setup"); PetscCall(DMDAGetInfo(da, &dim, &M, &N, &P, NULL, NULL, NULL, NULL, NULL, &bx, &by, &bz, NULL)); PetscCheck(xmax >= xmin, PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_INCOMP, "xmax must be larger than xmin %g %g", (double)xmin, (double)xmax); PetscCheck(!(dim > 1) || !(ymax < ymin), PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_INCOMP, "ymax must be larger than ymin %g %g", (double)ymin, (double)ymax); PetscCheck(!(dim > 2) || !(zmax < zmin), PetscObjectComm((PetscObject)da), PETSC_ERR_ARG_INCOMP, "zmax must be larger than zmin %g %g", (double)zmin, (double)zmax); PetscCall(PetscObjectGetComm((PetscObject)da, &comm)); PetscCall(DMDAGetCorners(da, &istart, &jstart, &kstart, &isize, &jsize, &ksize)); PetscCall(DMGetCoordinateDM(da, &cda)); PetscCall(DMCreateGlobalVector(cda, &xcoor)); if (dim == 1) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax - xmin) / M; else hx = (xmax - xmin) / (M - 1); PetscCall(VecGetArray(xcoor, &coors)); for (i = 0; i < isize; i++) coors[i] = xmin + hx * (i + istart); PetscCall(VecRestoreArray(xcoor, &coors)); } else if (dim == 2) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax - xmin) / (M); else hx = (xmax - xmin) / (M - 1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax - ymin) / (N); else hy = (ymax - ymin) / (N - 1); PetscCall(VecGetArray(xcoor, &coors)); cnt = 0; for (j = 0; j < jsize; j++) { for (i = 0; i < isize; i++) { coors[cnt++] = xmin + hx * (i + istart); coors[cnt++] = ymin + hy * (j + jstart); } } PetscCall(VecRestoreArray(xcoor, &coors)); } else if (dim == 3) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax - xmin) / (M); else hx = (xmax - xmin) / (M - 1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax - ymin) / (N); else hy = (ymax - ymin) / (N - 1); if (bz == DM_BOUNDARY_PERIODIC) hz_ = (zmax - zmin) / (P); else hz_ = (zmax - zmin) / (P - 1); PetscCall(VecGetArray(xcoor, &coors)); cnt = 0; for (k = 0; k < ksize; k++) { for (j = 0; j < jsize; j++) { for (i = 0; i < isize; i++) { coors[cnt++] = xmin + hx * (i + istart); coors[cnt++] = ymin + hy * (j + jstart); coors[cnt++] = zmin + hz_ * (k + kstart); } } } PetscCall(VecRestoreArray(xcoor, &coors)); } else SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_SUP, "Cannot create uniform coordinates for this dimension %" PetscInt_FMT, dim); PetscCall(DMSetCoordinates(da, xcoor)); PetscCall(VecDestroy(&xcoor)); // Handle periodicity if (bx == DM_BOUNDARY_PERIODIC || by == DM_BOUNDARY_PERIODIC || bz == DM_BOUNDARY_PERIODIC) { PetscReal maxCell[3] = {hx, hy, hz_}; PetscReal Lstart[3] = {xmin, ymin, zmin}; PetscReal L[3] = {xmax - xmin, ymax - ymin, zmax - zmin}; PetscCall(DMSetPeriodicity(da, maxCell, Lstart, L)); } PetscFunctionReturn(PETSC_SUCCESS); } /* Allows a user to select a subset of the fields to be drawn by VecView() when the vector comes from a DMDA */ PetscErrorCode DMDASelectFields(DM da, PetscInt *outfields, PetscInt **fields) { PetscInt step, ndisplayfields, *displayfields, k, j; PetscBool flg; PetscFunctionBegin; PetscCall(DMDAGetInfo(da, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &step, NULL, NULL, NULL, NULL, NULL)); PetscCall(PetscMalloc1(step, &displayfields)); for (k = 0; k < step; k++) displayfields[k] = k; ndisplayfields = step; PetscCall(PetscOptionsGetIntArray(NULL, NULL, "-draw_fields", displayfields, &ndisplayfields, &flg)); if (!ndisplayfields) ndisplayfields = step; if (!flg) { char **fields; const char *fieldname; PetscInt nfields = step; PetscCall(PetscMalloc1(step, &fields)); PetscCall(PetscOptionsGetStringArray(NULL, NULL, "-draw_fields_by_name", fields, &nfields, &flg)); if (flg) { ndisplayfields = 0; for (k = 0; k < nfields; k++) { for (j = 0; j < step; j++) { PetscCall(DMDAGetFieldName(da, j, &fieldname)); PetscCall(PetscStrcmp(fieldname, fields[k], &flg)); if (flg) goto found; } SETERRQ(PetscObjectComm((PetscObject)da), PETSC_ERR_USER, "Unknown fieldname %s", fields[k]); found: displayfields[ndisplayfields++] = j; } } for (k = 0; k < nfields; k++) PetscCall(PetscFree(fields[k])); PetscCall(PetscFree(fields)); } *fields = displayfields; *outfields = ndisplayfields; PetscFunctionReturn(PETSC_SUCCESS); } #include PetscErrorCode VecView_MPI_Draw_DA1d(Vec xin, PetscViewer v) { DM da; PetscMPIInt rank, size, tag; PetscInt i, n, N, dof, istart, isize, j, nbounds; MPI_Status status; PetscReal min, max, xmin = 0.0, xmax = 0.0, tmp = 0.0, xgtmp = 0.0; const PetscScalar *array, *xg; PetscDraw draw; PetscBool isnull, useports = PETSC_FALSE, showmarkers = PETSC_FALSE; MPI_Comm comm; PetscDrawAxis axis; Vec xcoor; DMBoundaryType bx; const char *tlabel = NULL, *xlabel = NULL; const PetscReal *bounds; PetscInt *displayfields; PetscInt k, ndisplayfields; PetscBool hold; PetscDrawViewPorts *ports = NULL; PetscViewerFormat format; PetscFunctionBegin; PetscCall(PetscViewerDrawGetDraw(v, 0, &draw)); PetscCall(PetscDrawIsNull(draw, &isnull)); if (isnull) PetscFunctionReturn(PETSC_SUCCESS); PetscCall(PetscViewerDrawGetBounds(v, &nbounds, &bounds)); PetscCall(VecGetDM(xin, &da)); PetscCheck(da, PetscObjectComm((PetscObject)xin), PETSC_ERR_ARG_WRONG, "Vector not generated from a DMDA"); PetscCall(PetscObjectGetComm((PetscObject)xin, &comm)); PetscCallMPI(MPI_Comm_size(comm, &size)); PetscCallMPI(MPI_Comm_rank(comm, &rank)); PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_vec_use_markers", &showmarkers, NULL)); PetscCall(DMDAGetInfo(da, NULL, &N, NULL, NULL, NULL, NULL, NULL, &dof, NULL, &bx, NULL, NULL, NULL)); PetscCall(DMDAGetCorners(da, &istart, NULL, NULL, &isize, NULL, NULL)); PetscCall(VecGetArrayRead(xin, &array)); PetscCall(VecGetLocalSize(xin, &n)); n = n / dof; /* Get coordinates of nodes */ PetscCall(DMGetCoordinates(da, &xcoor)); if (!xcoor) { PetscCall(DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0)); PetscCall(DMGetCoordinates(da, &xcoor)); } PetscCall(VecGetArrayRead(xcoor, &xg)); PetscCall(DMDAGetCoordinateName(da, 0, &xlabel)); /* Determine the min and max coordinate in plot */ if (rank == 0) xmin = PetscRealPart(xg[0]); if (rank == size - 1) xmax = PetscRealPart(xg[n - 1]); PetscCallMPI(MPI_Bcast(&xmin, 1, MPIU_REAL, 0, comm)); PetscCallMPI(MPI_Bcast(&xmax, 1, MPIU_REAL, size - 1, comm)); PetscCall(DMDASelectFields(da, &ndisplayfields, &displayfields)); PetscCall(PetscViewerGetFormat(v, &format)); PetscCall(PetscOptionsGetBool(NULL, NULL, "-draw_ports", &useports, NULL)); if (format == PETSC_VIEWER_DRAW_PORTS) useports = PETSC_TRUE; if (useports) { PetscCall(PetscViewerDrawGetDraw(v, 0, &draw)); PetscCall(PetscViewerDrawGetDrawAxis(v, 0, &axis)); PetscCall(PetscDrawCheckResizedWindow(draw)); PetscCall(PetscDrawClear(draw)); PetscCall(PetscDrawViewPortsCreate(draw, ndisplayfields, &ports)); } /* Loop over each field; drawing each in a different window */ for (k = 0; k < ndisplayfields; k++) { j = displayfields[k]; /* determine the min and max value in plot */ PetscCall(VecStrideMin(xin, j, NULL, &min)); PetscCall(VecStrideMax(xin, j, NULL, &max)); if (j < nbounds) { min = PetscMin(min, bounds[2 * j]); max = PetscMax(max, bounds[2 * j + 1]); } if (min == max) { min -= 1.e-5; max += 1.e-5; } if (useports) { PetscCall(PetscDrawViewPortsSet(ports, k)); PetscCall(DMDAGetFieldName(da, j, &tlabel)); } else { const char *title; PetscCall(PetscViewerDrawGetHold(v, &hold)); PetscCall(PetscViewerDrawGetDraw(v, k, &draw)); PetscCall(PetscViewerDrawGetDrawAxis(v, k, &axis)); PetscCall(DMDAGetFieldName(da, j, &title)); if (title) PetscCall(PetscDrawSetTitle(draw, title)); PetscCall(PetscDrawCheckResizedWindow(draw)); if (!hold) PetscCall(PetscDrawClear(draw)); } PetscCall(PetscDrawAxisSetLabels(axis, tlabel, xlabel, NULL)); PetscCall(PetscDrawAxisSetLimits(axis, xmin, xmax, min, max)); PetscCall(PetscDrawAxisDraw(axis)); /* draw local part of vector */ PetscCall(PetscObjectGetNewTag((PetscObject)xin, &tag)); if (rank < size - 1) { /*send value to right */ PetscCallMPI(MPI_Send((void *)&xg[n - 1], 1, MPIU_REAL, rank + 1, tag, comm)); PetscCallMPI(MPI_Send((void *)&array[j + (n - 1) * dof], 1, MPIU_REAL, rank + 1, tag, comm)); } if (rank) { /* receive value from left */ PetscCallMPI(MPI_Recv(&xgtmp, 1, MPIU_REAL, rank - 1, tag, comm, &status)); PetscCallMPI(MPI_Recv(&tmp, 1, MPIU_REAL, rank - 1, tag, comm, &status)); } PetscDrawCollectiveBegin(draw); if (rank) { PetscCall(PetscDrawLine(draw, xgtmp, tmp, PetscRealPart(xg[0]), PetscRealPart(array[j]), PETSC_DRAW_RED)); if (showmarkers) PetscCall(PetscDrawPoint(draw, xgtmp, tmp, PETSC_DRAW_BLACK)); } for (i = 1; i < n; i++) { PetscCall(PetscDrawLine(draw, PetscRealPart(xg[i - 1]), PetscRealPart(array[j + dof * (i - 1)]), PetscRealPart(xg[i]), PetscRealPart(array[j + dof * i]), PETSC_DRAW_RED)); if (showmarkers) PetscCall(PetscDrawMarker(draw, PetscRealPart(xg[i - 1]), PetscRealPart(array[j + dof * (i - 1)]), PETSC_DRAW_BLACK)); } if (rank == size - 1) { if (showmarkers) PetscCall(PetscDrawMarker(draw, PetscRealPart(xg[n - 1]), PetscRealPart(array[j + dof * (n - 1)]), PETSC_DRAW_BLACK)); } PetscDrawCollectiveEnd(draw); PetscCall(PetscDrawFlush(draw)); PetscCall(PetscDrawPause(draw)); if (!useports) PetscCall(PetscDrawSave(draw)); } if (useports) { PetscCall(PetscViewerDrawGetDraw(v, 0, &draw)); PetscCall(PetscDrawSave(draw)); } PetscCall(PetscDrawViewPortsDestroy(ports)); PetscCall(PetscFree(displayfields)); PetscCall(VecRestoreArrayRead(xcoor, &xg)); PetscCall(VecRestoreArrayRead(xin, &array)); PetscFunctionReturn(PETSC_SUCCESS); }