This file contains the code compiled for both the 2D and 3D demo. This is accomplished with only minimal redefinitions. We write the code only once and use it twice. The 3D source userdata/userdata_run3.c is a formal wrapper. In this sense, the code is mostly dimension independent.
This file contains the detailed code of the demo. Its entry point is called from userdata/userdata2.c, which is a good example of setting up a main program and defining and parsing command line options.
#include "userdata_global.h"
#ifndef P4_TO_P8
#else
#endif
typedef struct userdata_quadrant_internal
{
double value;
}
userdata_quadrant_internal_t;
static double
userdata_analytic (p4est_userdata_global_t *g, const double coords[3])
{
return
.5 * sin (M_PI * coords[0]) +
.25 * exp (-.5 * pow ((coords[1] - .5) / 2.5, 2.)) +
.25 * cos (4. * M_PI * coords[2]);
}
static double
userdata_value (p4est_userdata_global_t *g,
{
double coords_out[3];
coords_in, coords_out);
return userdata_analytic (g, coords_out);
}
static void
userdata_iterate_volume (p4est_userdata_global_t *g,
{
P4EST_ASSERT (g->qcount == 0);
#ifdef P4_TO_P8
NULL,
#endif
NULL);
P4EST_ASSERT (g->qcount == g->p4est->local_num_quadrants);
g->qcount = 0;
}
static int
userdata_vtk_general (p4est_userdata_global_t *g, const char *filename)
{
const char *fnames[1] = { "value" };
sc_array_t *fvalues[1] = { NULL };
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est != NULL);
P4EST_ASSERT (!g->novtk);
P4EST_ASSERT (g->qarray != NULL);
P4EST_ASSERT (g->qarray->elem_size == sizeof (double));
P4EST_ASSERT (g->qarray->elem_count ==
(size_t) g->p4est->local_num_quadrants);
fvalues[0] = g->qarray;
P4EST_ASSERT (g->p4est != NULL);
P4EST_GLOBAL_LERRORF ("ERROR: write VTK header for %s\n", filename);
return -1;
}
P4EST_ASSERT (rvtk == vtk);
fnames, fvalues)) == NULL) {
P4EST_GLOBAL_LERRORF ("ERROR: write VTK data for %s\n", filename);
return -1;
}
P4EST_ASSERT (rvtk == vtk);
P4EST_GLOBAL_LERRORF ("ERROR: write VTK footer for %s\n", filename);
return -1;
}
return 0;
}
static void
{
p4est_userdata_global_t *g =
userdata_quadrant_internal_t *qdat =
(userdata_quadrant_internal_t *) quadrant->
p.
user_data;
qdat->value = userdata_value (g, which_tree, quadrant);
g->qcount++;
}
static void
{
p4est_userdata_global_t *g = (p4est_userdata_global_t *) user_data;
userdata_quadrant_internal_t *qdat;
P4EST_ASSERT (v != NULL);
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (v->
p4est == g->p4est);
P4EST_ASSERT (g->qarray != NULL);
P4EST_ASSERT (qdat != NULL);
*(double *) sc_array_index (g->qarray, g->qcount) = qdat->value;
++g->qcount;
}
static int
userdata_vtk_internal (p4est_userdata_global_t *g, const char *filename)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est != NULL);
P4EST_ASSERT (g->qarray == NULL);
P4EST_ASSERT (g->in_internal);
if (g->novtk) {
return 0;
}
g->qarray = sc_array_new_count (sizeof (double), (size_t)
g->p4est->local_num_quadrants);
userdata_iterate_volume (g, userdata_vtk_internal_volume);
if (userdata_vtk_general (g, filename)) {
P4EST_GLOBAL_LERRORF ("ERROR: write VTK file %s\n", filename);
sc_array_destroy_null (&g->qarray);
return -1;
}
sc_array_destroy_null (&g->qarray);
return 0;
}
static int
{
int refine;
p4est_userdata_global_t *g =
userdata_quadrant_internal_t *qdat =
(userdata_quadrant_internal_t *) quadrant->
p.
user_data;
P4EST_ASSERT (qdat != NULL);
refine = ((which_tree % 3) == 0) || (fabs (qdat->value) > .8);
if (!refine || quadrant->
level >= g->maxlevel) {
g->qcount++;
return 0;
}
else {
return 1;
}
}
static int
{
int coarsen;
p4est_userdata_global_t *g =
if (quadrant[1] == NULL) {
++g->qcount;
return 0;
}
coarsen = ((which_tree % 3) == 1);
if (!coarsen) {
++g->qcount;
return 0;
}
else {
return 1;
}
}
static void
{
int i;
double sum;
p4est_userdata_global_t *g =
P4EST_ASSERT (g->in_balance || g->bcount == 0);
if (num_incoming > 1) {
P4EST_ASSERT (num_outgoing == 1);
userdata_quadrant_internal_t *qold =
(userdata_quadrant_internal_t *) outgoing[0]->p.user_data;
P4EST_ASSERT (qold != NULL);
if (!g->in_balance) {
}
else {
}
userdata_quadrant_internal_t *qnew =
(userdata_quadrant_internal_t *) incoming[i]->p.user_data;
P4EST_ASSERT (qnew != NULL);
qnew->value = qold->value;
}
}
else {
P4EST_ASSERT (!g->in_balance);
P4EST_ASSERT (num_incoming == 1);
userdata_quadrant_internal_t *qnew =
(userdata_quadrant_internal_t *) incoming[0]->p.user_data;
P4EST_ASSERT (qnew != NULL);
g->qcount++;
sum = 0.;
userdata_quadrant_internal_t *qold =
(userdata_quadrant_internal_t *) outgoing[i]->p.user_data;
P4EST_ASSERT (qold != NULL);
sum += qold->value;
}
}
}
static int
userdata_run_internal_return (int retval, p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
if (g->p4est != NULL) {
g->p4est = NULL;
}
return retval;
}
static int
userdata_run_internal (p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est == NULL);
P4EST_ASSERT (g->in_internal);
"_userdata: application data INTERNAL\n");
P4EST_ASSERT (g->qcount == 0);
(g->mpicomm, g->conn, 0, SC_MAX (g->maxlevel - 1, 0), 1,
sizeof (userdata_quadrant_internal_t), userdata_init_internal, g);
P4EST_ASSERT (g->qcount == g->p4est->local_num_quadrants);
g->qcount = 0;
if (userdata_vtk_internal (g,
P4EST_STRING "_userdata_internal_new")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after forest_new\n");
return userdata_run_internal_return (-1, g);
}
P4EST_ASSERT (g->qcount == 0);
NULL, userdata_replace_internal);
P4EST_ASSERT (g->qcount == g->p4est->local_num_quadrants);
g->qcount = 0;
P4EST_ASSERT (g->qcount == 0);
NULL, userdata_replace_internal);
P4EST_ASSERT (g->qcount == g->p4est->local_num_quadrants);
g->qcount = 0;
P4EST_ASSERT (g->qcount == 0);
P4EST_ASSERT (g->bcount == 0);
P4EST_ASSERT (!g->in_balance);
g->in_balance = 1;
NULL, userdata_replace_internal);
g->bcount = 0;
g->in_balance = 0;
if (userdata_vtk_internal (g,
P4EST_STRING "_userdata_internal_adapt")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after adaptation\n");
return userdata_run_internal_return (-1, g);
}
if (userdata_vtk_internal (g,
P4EST_STRING "_userdata_internal_partition")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after adaptation\n");
return userdata_run_internal_return (-1, g);
}
return userdata_run_internal_return (0, g);
}
typedef struct userdata_quadrant_external
{
int8_t refine;
int8_t coarsen;
}
userdata_quadrant_external_t;
static void
{
p4est_userdata_global_t *g =
userdata_quadrant_external_t *qdat =
(userdata_quadrant_external_t *) quadrant->
p.
user_data;
memset (qdat, 0, sizeof (*qdat));
++g->qcount;
}
static void
{
p4est_userdata_global_t *g = (p4est_userdata_global_t *) user_data;
P4EST_ASSERT (v != NULL);
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (v->p4est == g->p4est);
P4EST_ASSERT (g->qarray != NULL);
*(double *) sc_array_index (g->qarray, g->qcount++) =
}
static int
userdata_vtk_external (p4est_userdata_global_t *g, const char *filename)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est != NULL);
P4EST_ASSERT (g->qarray != NULL);
P4EST_ASSERT (g->in_external);
if (g->novtk) {
return 0;
}
if (userdata_vtk_general (g, filename)) {
P4EST_GLOBAL_LERRORF ("ERROR: write VTK file %s\n", filename);
return -1;
}
return 0;
}
static void
void *user_data)
{
p4est_userdata_global_t *g = (p4est_userdata_global_t *) user_data;
P4EST_ASSERT (v != NULL);
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (v->p4est == g->p4est);
userdata_quadrant_external_t *qdat =
qdat->refine = ((v->
treeid % 3) == 0);
qdat->coarsen = ((v->
treeid % 3) == 1);
P4EST_ASSERT (g->qarray != NULL);
if (fabs (*(double *) sc_array_index (g->qarray, g->qcount++)) > .8) {
qdat->refine = 1;
}
}
static int
{
p4est_userdata_global_t *g =
userdata_quadrant_external_t *qdat =
(userdata_quadrant_external_t *) quadrant->
p.
user_data;
P4EST_ASSERT (qdat != NULL);
if (!qdat->refine || quadrant->
level >= g->maxlevel) {
return 0;
}
return 1;
}
static int
{
int i;
P4EST_ASSERT (quadrant[1] != NULL);
userdata_quadrant_external_t *qdat =
(userdata_quadrant_external_t *) quadrant[i]->p.user_data;
P4EST_ASSERT (qdat != NULL);
if (!qdat->coarsen || qdat->refine) {
return 0;
}
}
return 1;
}
static void
userdata_project_external (p4est_userdata_global_t *g)
{
int i;
double value;
size_t pdindex, ndindex;
size_t pdbound;
#ifdef P4EST_ENABLE_DEBUG
size_t ndbound;
#endif
sc_array_t *parray, *narray;
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est != NULL);
P4EST_ASSERT (g->n4est != NULL);
P4EST_ASSERT (g->qarray != NULL);
P4EST_ASSERT (g->in_external);
pdindex = ndindex = 0;
parray = g->qarray;
P4EST_ASSERT (parray->elem_count == (size_t) g->p4est->local_num_quadrants);
narray = sc_array_new_count (sizeof (double),
(size_t) g->n4est->local_num_quadrants);
P4EST_ASSERT (g->p4est->first_local_tree == g->n4est->first_local_tree);
P4EST_ASSERT (g->p4est->last_local_tree == g->n4est->last_local_tree);
for (tt = g->n4est->first_local_tree; tt <= g->n4est->last_local_tree; ++tt) {
ptree = p4est_tree_array_index (g->p4est->trees, tt);
pquad = p4est_quadrant_array_index (&ptree->
quadrants, 0);
ntree = p4est_tree_array_index (g->n4est->trees, tt);
nquad = p4est_quadrant_array_index (&ntree->
quadrants, 0);
#ifdef P4EST_ENABLE_DEBUG
#endif
for (;;) {
P4EST_ASSERT (abs (pquad->
level - nquad->
level) <= 1);
*(double *) sc_array_index (narray, ndindex++) =
*(double *) sc_array_index (parray, pdindex++);
pquad++;
nquad++;
}
value = *(double *) sc_array_index (parray, pdindex++);
*(double *) sc_array_index (narray, ndindex++) = value;
++nquad;
}
++pquad;
}
value = 0.;
value += *(double *) sc_array_index (parray, pdindex++);
++pquad;
}
*(double *) sc_array_index (narray, ndindex++) =
++nquad;
}
else {
SC_ABORT_NOT_REACHED ();
}
if (pdindex == pdbound) {
P4EST_ASSERT (ndindex == ndbound);
break;
}
P4EST_ASSERT (ndindex < ndbound);
}
P4EST_ASSERT (pquad - p4est_quadrant_array_index (&ptree->
quadrants, 0) ==
P4EST_ASSERT (nquad - p4est_quadrant_array_index (&ntree->
quadrants, 0) ==
}
P4EST_ASSERT (pdindex == (size_t) g->p4est->local_num_quadrants);
P4EST_ASSERT (ndindex == (size_t) g->n4est->local_num_quadrants);
sc_array_destroy (g->qarray);
g->qarray = narray;
}
static void
userdata_adapt_external (p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->in_external);
P4EST_ASSERT (g->n4est == NULL);
userdata_refine_external, userdata_init_external);
userdata_coarsen_external, userdata_init_external);
userdata_project_external (g);
g->p4est = g->n4est;
g->n4est = NULL;
}
static void
userdata_partition_external (p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->qarray != NULL);
P4EST_ASSERT (g->n4est == NULL);
P4EST_ASSERT (g->in_external);
P4EST_ASSERT (g->p4est->local_num_quadrants ==
g->n4est->local_num_quadrants);
}
else {
sc_array_t *parray, *narray;
parray = g->qarray;
P4EST_ASSERT (parray->elem_count ==
(size_t) g->p4est->local_num_quadrants);
narray = sc_array_new_count (sizeof (double),
(size_t) g->n4est->local_num_quadrants);
g->p4est->global_first_quadrant,
g->p4est->mpicomm, P4EST_COMM_TAG_LAST + 0,
sc_array_index_null (narray, 0),
sc_array_index_null (parray, 0), parray->elem_size);
sc_array_destroy (g->qarray);
g->qarray = narray;
g->p4est = g->n4est;
}
g->n4est = NULL;
}
static int
userdata_run_external_return (int retval, p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
if (g->qarray != NULL) {
sc_array_destroy_null (&g->qarray);
}
if (g->n4est != NULL) {
g->n4est = NULL;
}
if (g->p4est != NULL) {
g->p4est = NULL;
}
return retval;
}
static int
userdata_run_external (p4est_userdata_global_t *g)
{
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->p4est == NULL);
P4EST_ASSERT (g->qarray == NULL);
P4EST_ASSERT (g->in_external);
"_userdata: application data EXTERNAL\n");
P4EST_ASSERT (g->qcount == 0);
(g->mpicomm, g->conn, 0, SC_MAX (g->maxlevel - 1, 0), 1,
sizeof (userdata_quadrant_external_t), userdata_init_external, g);
P4EST_ASSERT (g->qcount == g->p4est->local_num_quadrants);
g->qcount = 0;
P4EST_ASSERT (g->qarray == NULL);
g->qarray = sc_array_new_count (sizeof (double),
(size_t) g->p4est->local_num_quadrants);
userdata_iterate_volume (g, userdata_init_external_volume);
g->qcount = 0;
if (userdata_vtk_external (g,
P4EST_STRING "_userdata_external_new")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after forest_new\n");
return userdata_run_external_return (-1, g);
}
userdata_iterate_volume (g, userdata_criterion_external_volume);
userdata_adapt_external (g);
if (userdata_vtk_external (g,
P4EST_STRING "_userdata_external_adapt")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after forest_adapt\n");
return userdata_run_external_return (-1, g);
}
userdata_partition_external (g);
if (userdata_vtk_external (g,
P4EST_STRING "_userdata_external_partition")) {
P4EST_GLOBAL_LERROR ("ERROR: write VTK output after forest_partition\n");
return userdata_run_external_return (-1, g);
}
return userdata_run_external_return (0, g);
}
int
p4est_userdata_run (p4est_userdata_global_t *g)
{
int erres;
P4EST_ASSERT (g != NULL);
P4EST_ASSERT (g->options != NULL);
P4EST_ASSERT (g->conn != NULL);
P4EST_ASSERT (!g->in_internal);
P4EST_ASSERT (!g->in_external);
erres = 0;
g->in_internal = 1;
if (!erres && !g->noint && (erres = userdata_run_internal (g))) {
P4EST_GLOBAL_LERROR ("ERROR: run with internal data\n");
}
g->in_internal = 0;
g->in_external = 1;
if (!erres && !g->noext && (erres = userdata_run_external (g))) {
P4EST_GLOBAL_LERROR ("ERROR: run with external data\n");
}
g->in_external = 0;
P4EST_ASSERT (!g->in_internal);
P4EST_ASSERT (!g->in_external);
return erres;
}
void p4est_refine(p4est_t *p4est, int refine_recursive, p4est_refine_t refine_fn, p4est_init_t init_fn)
Refine a forest.
void p4est_destroy(p4est_t *p4est)
Destroy a p4est.
void p4est_partition(p4est_t *p4est, int allow_for_coarsening, p4est_weight_t weight_fn)
Equally partition the forest.
void p4est_balance(p4est_t *p4est, p4est_connect_type_t btype, p4est_init_t init_fn)
2:1 balance the size differences of neighboring elements in a forest.
p4est_t * p4est_copy(p4est_t *input, int copy_data)
Make a deep copy of a p4est.
void p4est_coarsen(p4est_t *p4est, int coarsen_recursive, p4est_coarsen_t coarsen_fn, p4est_init_t init_fn)
Coarsen a forest.
int32_t p4est_qcoord_t
Typedef for quadrant coordinates.
Definition: p4est_base.h:81
int32_t p4est_topidx_t
Typedef for counting topological entities (trees, tree vertices).
Definition: p4est_base.h:93
Routines for manipulating quadrants (neighbors, parents, children, etc.)
void p4est_quadrant_volume_coordinates(const p4est_quadrant_t *q, p4est_qcoord_t coords[])
Compute the coordinates of a quadrant's midpoint.
int p4est_quadrant_child_id(const p4est_quadrant_t *q)
Compute the position of this child within its siblings.
Parallel messaging and support code.
void p4est_transfer_fixed(const p4est_gloidx_t *dest_gfq, const p4est_gloidx_t *src_gfq, sc_MPI_Comm mpicomm, int tag, void *dest_data, const void *src_data, size_t data_size)
Transfer data associated with one forest partition to another.
#define P4EST_DIM
The spatial dimension.
Definition: p4est_connectivity.h:71
int p4est_connectivity_is_valid(p4est_connectivity_t *connectivity)
Examine a connectivity structure.
#define P4EST_STRING
p4est identification string
Definition: p4est_connectivity.h:94
#define P4EST_CHILDREN
The number of children of a quadrant, also the number of corners.
Definition: p4est_connectivity.h:75
@ P4EST_CONNECT_FULL
= CORNER.
Definition: p4est_connectivity.h:119
Interface routines with extended capabilities.
void p4est_coarsen_ext(p4est_t *p4est, int coarsen_recursive, int callback_orphans, p4est_coarsen_t coarsen_fn, p4est_init_t init_fn, p4est_replace_t replace_fn)
Coarsen a forest.
p4est_gloidx_t p4est_partition_ext(p4est_t *p4est, int partition_for_coarsening, p4est_weight_t weight_fn)
Repartition the forest.
void p4est_balance_ext(p4est_t *p4est, p4est_connect_type_t btype, p4est_init_t init_fn, p4est_replace_t replace_fn)
2:1 balance the size differences of neighboring elements in a forest.
void p4est_refine_ext(p4est_t *p4est, int refine_recursive, int maxlevel, p4est_refine_t refine_fn, p4est_init_t init_fn, p4est_replace_t replace_fn)
Refine a forest with a bounded refinement level and a replace option.
p4est_t * p4est_new_ext(sc_MPI_Comm mpicomm, p4est_connectivity_t *connectivity, p4est_locidx_t min_quadrants, int min_level, int fill_uniform, size_t data_size, p4est_init_t init_fn, void *user_pointer)
Create a new forest.
void p4est_geometry_transform_coordinates(p4est_geometry_t *geom, p4est_topidx_t which_tree, p4est_qcoord_t coords_in[2], double coords_out[3])
Transform a quadrant reference coordinate into the geometry.
void p4est_iterate(p4est_t *p4est, p4est_ghost_t *ghost_layer, void *user_data, p4est_iter_volume_t iter_volume, p4est_iter_face_t iter_face, p4est_iter_corner_t iter_corner)
Execute user supplied callbacks at every volume, face, and corner in the local forest.
void(* p4est_iter_volume_t)(p4est_iter_volume_info_t *info, void *user_data)
The prototype for a function that p4est_iterate will execute at every quadrant local to the current p...
Definition: p4est_iterate.h:62
Routines for printing a forest and associated fields to VTK format.
p4est_vtk_context_t * p4est_vtk_write_header(p4est_vtk_context_t *cont)
Write the VTK header.
int p4est_vtk_write_footer(p4est_vtk_context_t *cont)
Write the VTU footer and clean up.
p4est_vtk_context_t * p4est_vtk_context_new(p4est_t *p4est, const char *filename)
The first call to write a VTK file using individual functions.
p4est_vtk_context_t * p4est_vtk_write_cell_data(p4est_vtk_context_t *cont, int write_tree, int write_level, int write_rank, int wrap_rank, int num_cell_scalars, int num_cell_vectors, const char *fieldnames[], sc_array_t *values[])
Write VTK cell data.
void p4est_vtk_context_set_geom(p4est_vtk_context_t *cont, p4est_geometry_t *geom)
Modify the geometry transformation registered in the context.
struct p4est_vtk_context p4est_vtk_context_t
Opaque context type for writing VTK output with multiple function calls.
Definition: p4est_vtk.h:42
Routines for manipulating quadrants (neighbors, parents, children, etc.)
Parallel messaging and support code.
Interface routines with extended capabilities.
Routines for printing a forest and associated fields to VTK format.
The information that is available to the user-defined p4est_iter_volume_t callback function.
Definition: p4est_iterate.h:47
p4est_quadrant_t * quad
the quadrant of the callback
Definition: p4est_iterate.h:50
p4est_topidx_t treeid
the tree containing quad
Definition: p4est_iterate.h:53
The 2D quadrant datatype.
Definition: p4est.h:76
int8_t level
level of refinement
Definition: p4est.h:80
union p4est_quadrant::p4est_quadrant_data p
a union of additional data attached to a quadrant
The p4est tree datatype.
Definition: p4est.h:129
sc_array_t quadrants
locally stored quadrants
Definition: p4est.h:130
p4est_locidx_t quadrants_offset
cumulative sum over earlier trees on this processor (locals only)
Definition: p4est.h:133
The p4est forest datatype.
Definition: p4est.h:150
void * user_pointer
convenience pointer for users, never touched by p4est
Definition: p4est.h:157
void * user_data
never changed by p4est
Definition: p4est.h:94