Skip to content

Instantly share code, notes, and snippets.

@julesghub
Last active April 8, 2019 06:13
Show Gist options
  • Save julesghub/0c73c4109328cf435df9eef8e7b64529 to your computer and use it in GitHub Desktop.
Save julesghub/0c73c4109328cf435df9eef8e7b64529 to your computer and use it in GitHub Desktop.
Jules attempt at having a reflective condition on the top wall. SNES fails to converge under significant rotations (alpha). Also py3 petsc_gen_xdmf.py attached
static char help[] = "Poiseuille Flow in 2d and 3d channels with finite elements.\n\
We solve the Poiseuille flow problem in a rectangular\n\
domain, using a parallel unstructured mesh (DMPLEX) to discretize it.\n\n\n";
/*F
A Poiseuille flow is a steady-state isoviscous Stokes flow in a pipe of constant cross-section. We discretize using the
finite element method on an unstructured mesh. The weak form equations are
\begin{align*}
< \nabla v, \nu (\nabla u + {\nabla u}^T) > - < \nabla\cdot v, p > + < v, \Delta \hat n >_{\Gamma_o} = 0
< q, \nabla\cdot u > = 0
\end{align*}
where $\nu$ is the kinematic viscosity, $\Delta$ is the pressure drop per unit length, assuming that pressure is 0 on
the left edge, and $\Gamma_o$ is the outlet boundary at the right edge of the pipe. The normal velocity will be zero at
the wall, but we will allow a fixed tangential velocity $u_0$.
In order to test our global to local basis transformation, we will allow the pipe to be at an angle $\alpha$ to the
coordinate axes.
For visualization, use
-dm_view hdf5:$PWD/sol.h5 -sol_vec_view hdf5:$PWD/sol.h5::append -exact_vec_view hdf5:$PWD/sol.h5::append
F*/
#include <petscdmplex.h>
#include <petscsnes.h>
#include <petscds.h>
#include <petscbag.h>
typedef struct {
PetscReal Delta; /* Pressure drop per unit length */
PetscReal nu; /* Kinematic viscosity */
PetscReal u_0; /* Tangential velocity at the wall */
PetscReal alpha; /* Angle of pipe wall to x-axis */
} Parameter;
typedef struct {
/* Domain and mesh definition */
PetscInt dim; /* The topological mesh dimension */
PetscBool simplex; /* Use simplices or tensor product cells */
PetscInt cells[3]; /* The initial domain division */
/* Problem definition */
PetscBag bag; /* Holds problem parameters */
PetscErrorCode (**exactFuncs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx);
} AppCtx;
/*
In 2D, plane Poiseuille flow has exact solution:
u = \Delta/(2 \nu) y (1 - y) + u_0
v = 0
p = -\Delta x
f = 0
so that
-\nu \Delta u + \nabla p + f = <\Delta, 0> + <-\Delta, 0> + <0, 0> = 0
\nabla \cdot u = 0 + 0 = 0
In 3D we use exact solution:
u = \Delta/(4 \nu) (y (1 - y) + z (1 - z)) + u_0
v = 0
w = 0
p = -\Delta x
f = 0
so that
-\nu \Delta u + \nabla p + f = <Delta, 0, 0> + <-Delta, 0, 0> + <0, 0, 0> = 0
\nabla \cdot u = 0 + 0 + 0 = 0
Note that these functions use coordinates X in the global (rotated) frame
*/
PetscErrorCode quadratic_u(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
{
Parameter *param = (Parameter *) ctx;
PetscReal Delta = param->Delta;
PetscReal nu = param->nu;
PetscReal u_0 = param->u_0;
PetscReal fac = (PetscReal) (dim - 1);
PetscInt d;
u[0] = u_0;
for (d = 1; d < dim; ++d) u[0] += Delta/(fac * 2.0*nu) * X[d] * (1.0 - X[d]);
for (d = 1; d < dim; ++d) u[d] = 0.0;
return 0;
}
PetscErrorCode linear_p(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *p, void *ctx)
{
Parameter *param = (Parameter *) ctx;
PetscReal Delta = param->Delta;
p[0] = -Delta * X[0];
return 0;
}
PetscErrorCode static_wall(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
{
Parameter *param = (Parameter *) ctx;
PetscInt d;
for (d = 0; d < dim; ++d) u[d] = 0.0;
return 0;
}
PetscErrorCode top_wall_velocity(PetscInt dim, PetscReal time, const PetscReal X[], PetscInt Nf, PetscScalar *u, void *ctx)
{
Parameter *param = (Parameter *) ctx;
PetscReal u_0 = param->u_0;
PetscInt d;
//u[0] = u_0;
for (d = 1; d < dim; ++d) u[d] = 0.0;
return 0;
}
/* gradU[comp*dim+d] = {u_x, u_y, v_x, v_y} or {u_x, u_y, u_z, v_x, v_y, v_z, w_x, w_y, w_z}
u[Ncomp] = {p} */
void f1_u(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])
{
const PetscReal nu = PetscRealPart(constants[1]);
const PetscInt Nc = dim;
PetscInt c, d;
for (c = 0; c < Nc; ++c) {
for (d = 0; d < dim; ++d) {
/* f1[c*dim+d] = 0.5*nu*(u_x[c*dim+d] + u_x[d*dim+c]); */
f1[c*dim+d] = nu*u_x[c*dim+d];
}
f1[c*dim+c] -= u[uOff[1]];
}
}
/* gradU[comp*dim+d] = {u_x, u_y, v_x, v_y} or {u_x, u_y, u_z, v_x, v_y, v_z, w_x, w_y, w_z} */
void f0_p(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
{
PetscInt d;
for (d = 0, f0[0] = 0.0; d < dim; ++d) f0[0] += u_x[d*dim+d];
}
/* Residual functions are in reference coordinates */
static void f0_bd_u(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
{
const PetscReal Delta = PetscRealPart(constants[0]);
PetscReal alpha = PetscRealPart(constants[3]);
PetscReal X = PetscCosReal(alpha)*x[0] + PetscSinReal(alpha)*x[1];
PetscInt d;
for (d = 0; d < dim; ++d) {
f0[d] = -Delta * X * n[d];
}
}
/* < q, \nabla\cdot u >
NcompI = 1, NcompJ = dim */
void g1_pu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[])
{
PetscInt d;
for (d = 0; d < dim; ++d) g1[d*dim+d] = 1.0; /* \frac{\partial\phi^{u_d}}{\partial x_d} */
}
/* -< \nabla\cdot v, p >
NcompI = dim, NcompJ = 1 */
void g2_up(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[])
{
PetscInt d;
for (d = 0; d < dim; ++d) g2[d*dim+d] = -1.0; /* \frac{\partial\psi^{u_d}}{\partial x_d} */
}
/* < \nabla v, \nabla u + {\nabla u}^T >
This just gives \nabla u, give the perdiagonal for the transpose */
void g3_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux,
const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])
{
const PetscReal nu = PetscRealPart(constants[1]);
const PetscInt Nc = dim;
PetscInt c, d;
for (c = 0; c < Nc; ++c) {
for (d = 0; d < dim; ++d) {
g3[((c*Nc+c)*dim+d)*dim+d] = nu;
}
}
}
PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
{
PetscInt n = 3;
PetscErrorCode ierr;
PetscFunctionBeginUser;
options->dim = 2;
options->simplex = PETSC_TRUE;
options->cells[0] = 3;
options->cells[1] = 3;
options->cells[2] = 3;
ierr = PetscOptionsBegin(comm, "", "Poiseuille Flow Options", "DMPLEX");CHKERRQ(ierr);
ierr = PetscOptionsInt("-dim", "The topological mesh dimension", "ex62.c", options->dim, &options->dim, NULL);CHKERRQ(ierr);
ierr = PetscOptionsBool("-simplex", "Use simplices or tensor product cells", "ex62.c", options->simplex, &options->simplex, NULL);CHKERRQ(ierr);
ierr = PetscOptionsIntArray("-cells", "The initial mesh division", "ex62.c", options->cells, &n, NULL);CHKERRQ(ierr);
ierr = PetscOptionsEnd();
PetscFunctionReturn(0);
}
static PetscErrorCode SetupParameters(AppCtx *user)
{
PetscBag bag;
Parameter *p;
PetscErrorCode ierr;
PetscFunctionBeginUser;
/* setup PETSc parameter bag */
ierr = PetscBagGetData(user->bag, (void **) &p);CHKERRQ(ierr);
ierr = PetscBagSetName(user->bag, "par", "Poiseuille flow parameters");CHKERRQ(ierr);
bag = user->bag;
ierr = PetscBagRegisterReal(bag, &p->Delta, 1.0, "Delta", "Pressure drop per unit length");CHKERRQ(ierr);
ierr = PetscBagRegisterReal(bag, &p->nu, 1.0, "nu", "Kinematic viscosity");CHKERRQ(ierr);
ierr = PetscBagRegisterReal(bag, &p->u_0, 0.0, "u_0", "Tangential velocity at the wall");CHKERRQ(ierr);
ierr = PetscBagRegisterReal(bag, &p->alpha, 0.0, "alpha", "Angle of pipe wall to x-axis");CHKERRQ(ierr);
PetscFunctionReturn(0);
}
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm)
{
PetscInt dim = user->dim;
PetscErrorCode ierr;
PetscFunctionBeginUser;
ierr = DMPlexCreateBoxMesh(comm, dim, user->simplex, user->cells, NULL, NULL, NULL, PETSC_TRUE, dm);CHKERRQ(ierr);
{
Parameter *param;
Vec coordinates;
PetscScalar *coords;
PetscReal alpha;
PetscInt cdim, N, bs, i;
ierr = DMGetCoordinateDim(*dm, &cdim);CHKERRQ(ierr);
ierr = DMGetCoordinates(*dm, &coordinates);CHKERRQ(ierr);
ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr);
ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr);
if (bs != cdim) SETERRQ2(comm, PETSC_ERR_ARG_WRONG, "Invalid coordinate blocksize %D != embedding dimension %D", bs, cdim);
ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
ierr = PetscBagGetData(user->bag, (void **) &param);CHKERRQ(ierr);
alpha = param->alpha;
for (i = 0; i < N; i += cdim) {
PetscScalar x = coords[i+0];
PetscScalar y = coords[i+1];
coords[i+0] = PetscCosReal(alpha)*x - PetscSinReal(alpha)*y;
coords[i+1] = PetscSinReal(alpha)*x + PetscCosReal(alpha)*y;
#if 0
if ((PetscAbsReal(x - 0.333333333) < 1.0e-7) && (PetscAbsReal(y - 0.333333333) < 1.0e-7)) {
coords[i+0] += PetscCosReal(alpha)*0.05;
coords[i+1] += PetscSinReal(alpha)*0.05;
}
#endif
}
ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
ierr = DMSetCoordinates(*dm, coordinates);CHKERRQ(ierr);
}
{
DM pdm = NULL;
PetscPartitioner part;
ierr = DMPlexGetPartitioner(*dm, &part);CHKERRQ(ierr);
ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr);
ierr = DMPlexDistribute(*dm, 0, NULL, &pdm);CHKERRQ(ierr);
if (pdm) {
ierr = DMDestroy(dm);CHKERRQ(ierr);
*dm = pdm;
}
}
ierr = DMSetFromOptions(*dm);CHKERRQ(ierr);
ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr);
PetscFunctionReturn(0);
}
PetscErrorCode SetupProblem(DM dm, AppCtx *user)
{
PetscDS prob;
Parameter *ctx;
PetscInt id;
PetscErrorCode ierr;
PetscFunctionBeginUser;
ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
ierr = PetscDSSetResidual(prob, 0, NULL, f1_u);CHKERRQ(ierr);
ierr = PetscDSSetResidual(prob, 1, f0_p, NULL);CHKERRQ(ierr);
ierr = PetscDSSetBdResidual(prob, 0, f0_bd_u, NULL);CHKERRQ(ierr);
ierr = PetscDSSetJacobian(prob, 0, 0, NULL, NULL, NULL, g3_uu);CHKERRQ(ierr);
ierr = PetscDSSetJacobian(prob, 0, 1, NULL, NULL, g2_up, NULL);CHKERRQ(ierr);
ierr = PetscDSSetJacobian(prob, 1, 0, NULL, g1_pu, NULL, NULL);CHKERRQ(ierr);
/* Setup constants */
{
Parameter *param;
PetscScalar constants[4];
ierr = PetscBagGetData(user->bag, (void **) &param);CHKERRQ(ierr);
constants[0] = param->Delta;
constants[1] = param->nu;
constants[2] = param->u_0;
constants[3] = param->alpha;
ierr = PetscDSSetConstants(prob, 4, constants);CHKERRQ(ierr);
}
/* Setup Boundary Conditions */
ierr = PetscBagGetData(user->bag, (void **) &ctx);CHKERRQ(ierr);
PetscInt dofs[2] = {0,1};
/* Top wall conditions */
id = 3;
ierr = PetscDSAddBoundary(prob, DM_BC_ESSENTIAL, "top wall_vy", "marker", 0, 1, &dofs[1], (void (*)(void)) top_wall_velocity, 1, &id, ctx);CHKERRQ(ierr);
//ierr = PetscDSAddBoundary(prob, DM_BC_NATURAL, "top wall_vx", "marker", 0, 1, &dofs[0], (void (*)(void)) top_wall_vx, 1, &id, ctx);CHKERRQ(ierr);
id = 1;
ierr = PetscDSAddBoundary(prob, DM_BC_ESSENTIAL, "bottom wall", "marker", 0, 0, NULL, (void (*)(void)) static_wall, 1, &id, ctx);CHKERRQ(ierr);
id = 2;
ierr = PetscDSAddBoundary(prob, DM_BC_NATURAL, "right wall", "marker", 0, 0, NULL, (void (*)(void)) NULL, 1, &id, ctx);CHKERRQ(ierr);
/* Setup exact solution */
user->exactFuncs[0] = quadratic_u;
user->exactFuncs[1] = linear_p;
ierr = PetscDSSetExactSolution(prob, 0, user->exactFuncs[0], ctx);CHKERRQ(ierr);
ierr = PetscDSSetExactSolution(prob, 1, user->exactFuncs[1], ctx);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
PetscErrorCode SetupDiscretization(DM dm, AppCtx *user)
{
DM cdm = dm;
const PetscInt dim = user->dim;
PetscFE fe[2];
PetscQuadrature q;
Parameter *param;
MPI_Comm comm;
PetscErrorCode ierr;
PetscFunctionBeginUser;
/* Create finite element */
ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
ierr = PetscFECreateDefault(comm, dim, dim, user->simplex, "vel_", PETSC_DEFAULT, &fe[0]);CHKERRQ(ierr);
ierr = PetscObjectSetName((PetscObject) fe[0], "velocity");CHKERRQ(ierr);
ierr = PetscFEGetQuadrature(fe[0], &q);CHKERRQ(ierr);
ierr = PetscFECreateDefault(comm, dim, 1, user->simplex, "pres_", PETSC_DEFAULT, &fe[1]);CHKERRQ(ierr);
ierr = PetscFESetQuadrature(fe[1], q);CHKERRQ(ierr);
ierr = PetscObjectSetName((PetscObject) fe[1], "pressure");CHKERRQ(ierr);
/* Set discretization and boundary conditions for each mesh */
ierr = DMSetField(dm, 0, NULL, (PetscObject) fe[0]);CHKERRQ(ierr);
ierr = DMSetField(dm, 1, NULL, (PetscObject) fe[1]);CHKERRQ(ierr);
ierr = DMCreateDS(dm);CHKERRQ(ierr);
ierr = SetupProblem(dm, user);CHKERRQ(ierr);
ierr = PetscBagGetData(user->bag, (void **) &param);CHKERRQ(ierr);
while (cdm) {
ierr = DMCopyDisc(dm, cdm);CHKERRQ(ierr);
ierr = DMPlexCreateBasisRotation(cdm, param->alpha, 0.0, 0.0);CHKERRQ(ierr);
ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr);
}
ierr = PetscFEDestroy(&fe[0]);CHKERRQ(ierr);
ierr = PetscFEDestroy(&fe[1]);CHKERRQ(ierr);
PetscFunctionReturn(0);
}
int main(int argc, char **argv)
{
SNES snes; /* nonlinear solver */
DM dm; /* problem definition */
Vec u, r; /* solution and residual */
AppCtx user; /* user-defined work context */
PetscErrorCode ierr;
ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr;
ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr);
ierr = PetscBagCreate(PETSC_COMM_WORLD, sizeof(Parameter), &user.bag);CHKERRQ(ierr);
ierr = SetupParameters(&user);CHKERRQ(ierr);
ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr);
ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr);
ierr = SNESSetDM(snes, dm);CHKERRQ(ierr);
ierr = DMSetApplicationContext(dm, &user);CHKERRQ(ierr);
/* Setup problem */
ierr = PetscMalloc(2 * sizeof(void (*)(const PetscReal[], PetscScalar *, void *)), &user.exactFuncs);CHKERRQ(ierr);
ierr = SetupDiscretization(dm, &user);CHKERRQ(ierr);
ierr = DMPlexCreateClosureIndex(dm, NULL);CHKERRQ(ierr);
ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr);
ierr = VecDuplicate(u, &r);CHKERRQ(ierr);
ierr = DMPlexSetSNESLocalFEM(dm,&user,&user,&user);CHKERRQ(ierr);
ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);
{
Parameter *param;
void *ctxs[2];
ierr = PetscBagGetData(user.bag, (void **) &param);CHKERRQ(ierr);
ctxs[0] = ctxs[1] = param;
ierr = DMProjectFunction(dm, 0.0, user.exactFuncs, ctxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr);
ierr = PetscObjectSetName((PetscObject) u, "Exact Solution");CHKERRQ(ierr);
ierr = VecViewFromOptions(u, NULL, "-exact_vec_view");CHKERRQ(ierr);
}
ierr = DMSNESCheckFromOptions(snes, u, NULL, NULL);CHKERRQ(ierr);
ierr = VecSet(u, 0.0);CHKERRQ(ierr);
ierr = PetscObjectSetName((PetscObject) u, "Solution");CHKERRQ(ierr);
ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr);
ierr = VecViewFromOptions(u, NULL, "-sol_vec_view");CHKERRQ(ierr);
ierr = VecDestroy(&u);CHKERRQ(ierr);
ierr = VecDestroy(&r);CHKERRQ(ierr);
ierr = PetscFree(user.exactFuncs);CHKERRQ(ierr);
ierr = DMDestroy(&dm);CHKERRQ(ierr);
ierr = SNESDestroy(&snes);CHKERRQ(ierr);
ierr = PetscBagDestroy(&user.bag);CHKERRQ(ierr);
ierr = PetscFinalize();
return ierr;
}
/*TEST
# Convergence
test:
suffix: 2d_quad_q1_p0_conv
requires: !single
args: -simplex 0 -dm_plex_separate_marker -dm_refine 1 \
-vel_petscspace_degree 1 -pres_petscspace_degree 0 \
-snes_convergence_estimate -convest_num_refine 2 -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type lu \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_quad_q1_p0_conv_u0
requires: !single
args: -simplex 0 -dm_plex_separate_marker -dm_refine 1 -u_0 0.125 \
-vel_petscspace_degree 1 -pres_petscspace_degree 0 \
-snes_convergence_estimate -convest_num_refine 2 -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type lu \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_quad_q1_p0_conv_u0_alpha
requires: !single
args: -simplex 0 -dm_plex_separate_marker -dm_refine 1 -u_0 0.125 -alpha 0.3927 \
-vel_petscspace_degree 1 -pres_petscspace_degree 0 \
-snes_convergence_estimate -convest_num_refine 2 -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type lu \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_quad_q1_p0_conv_gmg_vanka
requires: !single
args: -simplex 0 -dm_plex_separate_marker -cells 2,2 -dm_refine_hierarchy 1 \
-vel_petscspace_degree 1 -pres_petscspace_degree 0 \
-snes_convergence_estimate -convest_num_refine 1 -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type mg \
-fieldsplit_velocity_mg_levels_pc_type patch -fieldsplit_velocity_mg_levels_pc_patch_partition_of_unity 0 \
-fieldsplit_velocity_mg_levels_pc_patch_construct_codim 0 -fieldsplit_velocity_mg_levels_pc_patch_construct_type vanka \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_tri_p2_p1_conv
requires: triangle !single
args: -dm_plex_separate_marker -dm_refine 1 \
-vel_petscspace_degree 2 -pres_petscspace_degree 1 \
-dmsnes_check -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type lu \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_tri_p2_p1_conv_u0_alpha
requires: triangle !single
args: -dm_plex_separate_marker -dm_refine 0 -u_0 0.125 -alpha 0.3927 \
-vel_petscspace_degree 2 -pres_petscspace_degree 1 \
-dmsnes_check -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type lu \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
test:
suffix: 2d_tri_p2_p1_conv_gmg_vcycle
requires: triangle !single
args: -dm_plex_separate_marker -cells 2,2 -dm_refine_hierarchy 1 \
-vel_petscspace_degree 2 -pres_petscspace_degree 1 \
-dmsnes_check -snes_error_if_not_converged \
-ksp_type fgmres -ksp_gmres_restart 10 -ksp_rtol 1.0e-9 -ksp_error_if_not_converged \
-pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_factorization_type full \
-fieldsplit_velocity_pc_type mg \
-fieldsplit_pressure_ksp_rtol 1e-10 -fieldsplit_pressure_pc_type jacobi
TEST*/
#!/usr/bin/env python
import h5py
import numpy as np
import os, sys
class Xdmf:
def __init__(self, filename):
self.filename = filename
self.cellMap = {1 : {1 : 'Polyvertex', 2 : 'Polyline'}, 2 : {3 : 'Triangle', 4 : 'Quadrilateral'}, 3 : {4 : 'Tetrahedron', 6: 'Wedge', 8 : 'Hexahedron'}}
self.typeMap = {b'scalar' : 'Scalar', b'vector' : 'Vector', b'tensor' :
'Tensor6', b'matrix' : 'Matrix'}
self.typeExt = {2 : {b'vector' : ['x', 'y'], b'tensor' : ['xx', 'yy',
'xy']}, 3 : {b'vector' : ['x', 'y', 'z'], b'tensor' : ['xx', 'yy', 'zz', 'xy', 'yz', 'xz']}}
return
def writeHeader(self, fp, hdfFilename):
fp.write('''\
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" [
<!ENTITY HeavyData "%s">
]>
''' % os.path.basename(hdfFilename))
fp.write('\n<Xdmf>\n <Domain Name="domain">\n')
return
def writeCells(self, fp, topologyPath, numCells, numCorners):
fp.write('''\
<DataItem Name="cells"
ItemType="Uniform"
Format="HDF"
NumberType="Float" Precision="8"
Dimensions="%d %d">
&HeavyData;:/%s/cells
</DataItem>
''' % (numCells, numCorners, topologyPath))
return
def writeVertices(self, fp, geometryPath, numVertices, spaceDim):
fp.write('''\
<DataItem Name="vertices"
Format="HDF"
Dimensions="%d %d">
&HeavyData;:/%s/vertices
</DataItem>
<!-- ============================================================ -->
''' % (numVertices, spaceDim, geometryPath))
return
def writeLocations(self, fp, numParticles, spaceDim):
fp.write('''\
<DataItem Name="xcoord"
Format="HDF"
Dimensions="%d">
&HeavyData;:/particles/xcoord
</DataItem>
''' % (numParticles))
if spaceDim == 1: return
fp.write('''\
<DataItem Name="ycoord"
Format="HDF"
Dimensions="%d">
&HeavyData;:/particles/ycoord
</DataItem>
''' % (numParticles))
if spaceDim == 2: return
fp.write('''\
<DataItem Name="zcoord"
Format="HDF"
Dimensions="%d">
&HeavyData;:/particles/zcoord
</DataItem>
''' % (numParticles))
return
def writeTimeGridHeader(self, fp, time):
fp.write('''\
<Grid Name="TimeSeries" GridType="Collection" CollectionType="Temporal">
<Time TimeType="List">
<DataItem Format="XML" NumberType="Float" Dimensions="%d">
''' % (len(time)))
fp.write(' '.join([str(float(t)) for t in time]))
fp.write('''
</DataItem>
</Time>
''')
return
def writeSpaceGridHeader(self, fp, numCells, numCorners, cellDim, spaceDim):
fp.write('''\
<Grid Name="domain" GridType="Uniform">
<Topology
TopologyType="%s"
NumberOfElements="%d">
<DataItem Reference="XML">
/Xdmf/Domain/DataItem[@Name="cells"]
</DataItem>
</Topology>
<Geometry GeometryType="%s">
<DataItem Reference="XML">
/Xdmf/Domain/DataItem[@Name="vertices"]
</DataItem>
</Geometry>
''' % (self.cellMap[cellDim][numCorners], numCells, "XYZ" if spaceDim > 2 else "XY"))
return
def writeFieldSingle(self, fp, numSteps, timestep, spaceDim, name, f, domain):
if len(f[1].shape) > 2:
dof = f[1].shape[1]
bs = f[1].shape[2]
elif len(f[1].shape) > 1:
if numSteps > 1:
dof = f[1].shape[1]
bs = 1
else:
dof = f[1].shape[0]
bs = f[1].shape[1]
else:
dof = f[1].shape[0]
bs = 1
fp.write('''\
<Attribute
Name="%s"
Type="%s"
Center="%s">
<DataItem ItemType="HyperSlab"
Dimensions="1 %d %d"
Type="HyperSlab">
<DataItem
Dimensions="3 3"
Format="XML">
%d 0 0
1 1 1
1 %d %d
</DataItem>
<DataItem
DataType="Float" Precision="8"
Dimensions="%d %d %d"
Format="HDF">
&HeavyData;:%s
</DataItem>
</DataItem>
</Attribute>
''' % (f[0], self.typeMap[f[1].attrs['vector_field_type']], domain, dof, bs, timestep, dof, bs, numSteps, dof, bs, name))
return
def writeFieldComponents(self, fp, numSteps, timestep, spaceDim, name, f, domain):
vtype = f[1].attrs['vector_field_type']
if len(f[1].shape) > 2:
dof = f[1].shape[1]
bs = f[1].shape[2]
cdims = '1 %d 1' % dof
dims = '%d %d %d' % (numSteps, dof, bs)
stride = '1 1 1'
size = '1 %d 1' % dof
else:
dof = f[1].shape[0]
bs = f[1].shape[1]
cdims = '%d 1' % dof
dims = '%d %d' % (dof, bs)
stride = '1 1'
size = '%d 1' % dof
for c in range(bs):
ext = self.typeExt[spaceDim][vtype][c]
if len(f[1].shape) > 2: start = '%d 0 %d' % (timestep, c)
else: start = '0 %d' % c
fp.write('''\
<Attribute
Name="%s"
Type="Scalar"
Center="%s">
<DataItem ItemType="HyperSlab"
Dimensions="%s"
Type="HyperSlab">
<DataItem
Dimensions="3 %d"
Format="XML">
%s
%s
%s
</DataItem>
<DataItem
DataType="Float" Precision="8"
Dimensions="%s"
Format="HDF">
&HeavyData;:%s
</DataItem>
</DataItem>
</Attribute>
''' % (f[0]+'_'+ext, domain, cdims, len(f[1].shape), start, stride, size, dims, name))
return
def writeField(self, fp, numSteps, timestep, cellDim, spaceDim, name, f, domain):
ctypes = [b'tensor', b'matrix']
if spaceDim == 2 or cellDim != spaceDim: ctypes.append(b'vector')
if f[1].attrs['vector_field_type'] in ctypes:
self.writeFieldComponents(fp, numSteps, timestep, spaceDim, name, f, domain)
else:
self.writeFieldSingle(fp, numSteps, timestep, spaceDim, name, f, domain)
return
def writeSpaceGridFooter(self, fp):
fp.write(' </Grid>\n')
return
def writeParticleGridHeader(self, fp, numParticles, spaceDim):
fp.write('''\
<Grid Name="particle_domain" GridType="Uniform">
<Topology TopologyType="Polyvertex" NodesPerElement="%d" />
<Geometry GeometryType="%s">
<DataItem Reference="XML">/Xdmf/Domain/DataItem[@Name="xcoord"]</DataItem>
<DataItem Reference="XML">/Xdmf/Domain/DataItem[@Name="ycoord"]</DataItem>
%s
</Geometry>
''' % (numParticles, "X_Y_Z" if spaceDim > 2 else "X_Y", "<DataItem Reference=\"XML\">/Xdmf/Domain/DataItem[@Name=\"zcoord\"]</DataItem>" if spaceDim > 2 else ""))
return
def writeParticleField(self, fp, numParticles, spaceDim):
fp.write('''\
<Attribute Name="particles/icoord">
<DataItem Name="icoord"
Format="HDF"
Dimensions="%d">
&HeavyData;:/particles/icoord
</DataItem>
</Attribute>''' % (numParticles))
return
def writeTimeGridFooter(self, fp):
fp.write(' </Grid>\n')
return
def writeFooter(self, fp):
fp.write(' </Domain>\n</Xdmf>\n')
return
def write(self, hdfFilename, topologyPath, numCells, numCorners, cellDim, geometryPath, numVertices, spaceDim, time, vfields, cfields, numParticles):
useTime = not (len(time) < 2 and time[0] == -1)
with open(self.filename, 'w') as fp:
self.writeHeader(fp, hdfFilename)
# Field information
self.writeCells(fp, topologyPath, numCells, numCorners)
self.writeVertices(fp, geometryPath, numVertices, spaceDim)
if useTime: self.writeTimeGridHeader(fp, time)
for t in range(len(time)):
self.writeSpaceGridHeader(fp, numCells, numCorners, cellDim, spaceDim)
for vf in vfields: self.writeField(fp, len(time), t, cellDim, spaceDim, '/vertex_fields/'+vf[0], vf, 'Node')
for cf in cfields: self.writeField(fp, len(time), t, cellDim, spaceDim, '/cell_fields/'+cf[0], cf, 'Cell')
self.writeSpaceGridFooter(fp)
if useTime: self.writeTimeGridFooter(fp)
if numParticles:
self.writeLocations(fp, numParticles, spaceDim)
if useTime: self.writeTimeGridHeader(fp, time)
for t in range(len(time)):
self.writeParticleGridHeader(fp, numParticles, spaceDim)
self.writeSpaceGridFooter(fp)
if useTime: self.writeTimeGridFooter(fp)
self.writeFooter(fp)
return
def generateXdmf(hdfFilename, xdmfFilename = None):
if xdmfFilename is None:
xdmfFilename = os.path.splitext(hdfFilename)[0] + '.xmf'
# Read mesh
h5 = h5py.File(hdfFilename, 'r')
if 'viz' in h5 and 'geometry' in h5['viz']:
geomPath = 'viz/geometry'
geom = h5['viz']['geometry']
else:
geomPath = 'geometry'
geom = h5['geometry']
if 'viz' in h5 and 'topology' in h5['viz']:
topoPath = 'viz/topology'
topo = h5['viz']['topology']
else:
topoPath = 'topology'
topo = h5['topology']
vertices = geom['vertices']
numVertices = vertices.shape[0]
spaceDim = vertices.shape[1]
cells = topo['cells']
numCells = cells.shape[0]
numCorners = cells.shape[1]
cellDim = topo['cells'].attrs['cell_dim']
if 'time' in h5:
time = np.array(h5['time']).flatten()
else:
time = [-1]
vfields = []
cfields = []
if 'vertex_fields' in h5: vfields = h5['vertex_fields'].items()
if 'cell_fields' in h5: cfields = h5['cell_fields'].items()
numParticles = 0
if 'particles' in h5: numParticles = h5['particles']['xcoord'].shape[0]
'''
if 'vertex_fields' in h5: vfields = list(h5['vertex_fields'].items())
if 'cell_fields' in h5: cfields = list(h5['cell_fields'].items())
numParticles = 0
if 'particles' in h5: numParticles = list(h5['particles']['xcoord'].shape[0])
'''
# Write Xdmf
Xdmf(xdmfFilename).write(hdfFilename, topoPath, numCells, numCorners, cellDim, geomPath, numVertices, spaceDim, time, vfields, cfields, numParticles)
h5.close()
return
if __name__ == '__main__':
for f in sys.argv[1:]:
generateXdmf(f)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment