/** Compute the timestep. * * Find the smallest quadrant and scale the timestep based on that length and * the advection velocity. * * \param [in] p4est the forest * \return the timestep. */ static double step3_get_timestep (p4est_t * p4est) { step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; p4est_topidx_t t, flt, llt; p4est_tree_t *tree; int max_level, global_max_level; int mpiret, i; double min_h, vnorm; double dt; /* compute the timestep by finding the smallest quadrant */ flt = p4est->first_local_tree; llt = p4est->last_local_tree; max_level = 0; for (t = flt; t <= llt; t++) { tree = p4est_tree_array_index (p4est->trees, t); max_level = SC_MAX (max_level, tree->maxlevel); } mpiret = sc_MPI_Allreduce (&max_level, &global_max_level, 1, sc_MPI_INT, sc_MPI_MAX, p4est->mpicomm); SC_CHECK_MPI (mpiret); min_h = (double) P4EST_QUADRANT_LEN (global_max_level) / (double) P4EST_ROOT_LEN; vnorm = 0; for (i = 0; i < P4EST_DIM; i++) { vnorm += ctx->v[i] * ctx->v[i]; } vnorm = sqrt (vnorm); dt = min_h / 2. / vnorm; return dt; }
int main (int argc, char **argv) { sc_MPI_Comm mpicomm; int mpiret; int found_total; p4est_locidx_t jt, Al, Bl; p4est_locidx_t local_count; p4est_connectivity_t *conn; p4est_quadrant_t *A, *B; p4est_geometry_t *geom; p4est_t *p4est; sc_array_t *points; test_point_t *p; const char *vtkname; /* Initialize MPI */ mpiret = sc_MPI_Init (&argc, &argv); SC_CHECK_MPI (mpiret); mpicomm = sc_MPI_COMM_WORLD; /* Initialize packages */ sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT); p4est_init (NULL, SC_LP_DEFAULT); /* Create forest */ #ifndef P4_TO_P8 conn = p4est_connectivity_new_star (); geom = NULL; vtkname = "test_search2"; #else conn = p8est_connectivity_new_sphere (); geom = p8est_geometry_new_sphere (conn, 1., 0.191728, 0.039856); vtkname = "test_search3"; #endif p4est = p4est_new_ext (mpicomm, conn, 0, 0, 0, 0, NULL, &local_count); p4est_refine (p4est, 1, refine_fn, NULL); p4est_partition (p4est, 0, NULL); p4est_vtk_write_file (p4est, geom, vtkname); /* The following code should really be in a separate function. */ /* Prepare a point search -- fix size so the memory is not relocated */ points = sc_array_new_size (sizeof (test_point_t), 2); /* A */ p = (test_point_t *) sc_array_index (points, 0); p->name = "A"; A = &p->quad; P4EST_QUADRANT_INIT (A); p4est_quadrant_set_morton (A, 3, 23); A->p.piggy3.which_tree = 0; A->p.piggy3.local_num = -1; Al = -1; /* B */ p = (test_point_t *) sc_array_index (points, 1); p->name = "B"; B = &p->quad; P4EST_QUADRANT_INIT (B); p4est_quadrant_set_morton (B, 2, 13); B->p.piggy3.which_tree = conn->num_trees / 2; B->p.piggy3.local_num = -1; Bl = -1; /* Find quadrant numbers if existing */ for (jt = p4est->first_local_tree; jt <= p4est->last_local_tree; ++jt) { size_t zz; p4est_tree_t *tree = p4est_tree_array_index (p4est->trees, jt); p4est_quadrant_t *quad; sc_array_t *tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { quad = p4est_quadrant_array_index (tquadrants, zz); if (A->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, A)) { Al = tree->quadrants_offset + (p4est_locidx_t) zz; P4EST_VERBOSEF ("Searching for A at %lld\n", (long long) Al); } if (B->p.piggy3.which_tree == jt && !p4est_quadrant_compare (quad, B)) { Bl = tree->quadrants_offset + (p4est_locidx_t) zz; P4EST_VERBOSEF ("Searching for B at %lld\n", (long long) Bl); } } } /* Go */ found_count = 0; p4est_search_local (p4est, 0, NULL, search_callback, points); mpiret = sc_MPI_Allreduce (&found_count, &found_total, 1, sc_MPI_INT, sc_MPI_SUM, mpicomm); SC_CHECK_MPI (mpiret); SC_CHECK_ABORT (found_total == (int) points->elem_count, "Point search"); SC_CHECK_ABORT (A->p.piggy3.local_num == Al, "Search A"); SC_CHECK_ABORT (B->p.piggy3.local_num == Bl, "Search B"); /* Use another search to count local quadrants */ local_count = 0; p4est_search_local (p4est, 0, count_callback, NULL, NULL); SC_CHECK_ABORT (local_count == p4est->local_num_quadrants, "Count search"); /* Clear memory */ sc_array_destroy (points); p4est_destroy (p4est); if (geom != NULL) { p4est_geometry_destroy (geom); } p4est_connectivity_destroy (conn); /* Test the build_local function and friends */ test_build_local (mpicomm); /* Finalize */ sc_finalize (); mpiret = sc_MPI_Finalize (); SC_CHECK_MPI (mpiret); return 0; }
static void mesh_run (mpi_context_t * mpi, p4est_connectivity_t * connectivity, int uniform, int compute_tree_index, int compute_level_lists, p4est_connect_type_t mesh_btype) { int mpiret; unsigned crc; long local_used[4], global_used[4]; p4est_t *p4est; p4est_ghost_t *ghost; p4est_mesh_t *mesh; user_data_t *ghost_data; p4est = p4est_new (mpi->mpicomm, connectivity, sizeof (user_data_t), init_fn, NULL); if (!uniform) p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_new"); /* refinement */ if (uniform) { p4est_refine (p4est, 1, refine_uniform, init_fn); } else { p4est_refine (p4est, 1, refine_normal, init_fn); p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_refined"); } /* balance */ p4est_balance (p4est, P4EST_CONNECT_FULL, init_fn); if (!uniform) p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_balanced"); /* partition */ p4est_partition (p4est, 0, NULL); if (!uniform) { p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_partition"); } crc = p4est_checksum (p4est); /* print and verify forest checksum */ P4EST_GLOBAL_STATISTICSF ("Tree %s checksum 0x%08x\n", uniform ? "uniform" : "adapted", crc); /* create ghost layer and mesh */ ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL); ghost_data = P4EST_ALLOC (user_data_t, ghost->ghosts.elem_count); p4est_ghost_exchange_data (p4est, ghost, ghost_data); mesh = p4est_mesh_new_ext (p4est, ghost, compute_tree_index, compute_level_lists, mesh_btype); test_mesh (p4est, ghost, mesh, compute_tree_index, compute_level_lists, mesh_btype, ghost_data, uniform); /* compute memory used */ local_used[0] = (long) p4est_connectivity_memory_used (p4est->connectivity); local_used[1] = (long) p4est_memory_used (p4est); local_used[2] = (long) p4est_ghost_memory_used (ghost); local_used[3] = (long) p4est_mesh_memory_used (mesh); mpiret = sc_MPI_Allreduce (local_used, global_used, 4, sc_MPI_LONG, sc_MPI_SUM, mpi->mpicomm); SC_CHECK_MPI (mpiret); P4EST_GLOBAL_PRODUCTIONF ("Total %s memory used %ld %ld %ld %ld\n", uniform ? "uniform" : "adapted", global_used[0], global_used[1], global_used[2], global_used[3]); /* destroy ghost layer and mesh */ P4EST_FREE (ghost_data); p4est_mesh_destroy (mesh); p4est_ghost_destroy (ghost); /* destroy the p4est structure */ p4est_destroy (p4est); }
int p6est_profile_sync (p6est_profile_t * profile) { p4est_lnodes_t *lnodes = profile->lnodes; p4est_locidx_t nln = lnodes->num_local_nodes; sc_array_t lrview; p4est_lnodes_buffer_t *countbuf; sc_array_t *sharers; size_t zz, nsharers; int nleft; int8_t *recv, *send; int *array_of_indices; p4est_locidx_t recv_total; p4est_locidx_t *recv_offsets, recv_offset; p4est_locidx_t send_total; p4est_locidx_t *send_offsets, send_offset; p4est_locidx_t (*lr)[2]; sc_array_t *lc = profile->lnode_columns; sc_MPI_Request *recv_request, *send_request; sc_array_t *work; int any_change = 0; int any_global_change; int mpiret, mpirank; int evenodd = profile->evenodd; lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; sharers = lnodes->sharers; nsharers = sharers->elem_count; mpiret = sc_MPI_Comm_rank (lnodes->mpicomm, &mpirank); SC_CHECK_MPI (mpiret); sc_array_init_data (&lrview, lr, 2 * sizeof (p4est_locidx_t), nln); countbuf = p4est_lnodes_share_all_begin (&lrview, lnodes); send_offsets = P4EST_ALLOC (p4est_locidx_t, nsharers + 1); send_offset = 0; for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *sharer; sc_array_t *send_buf; size_t zy, nnodes; send_offsets[zz] = send_offset; sharer = p4est_lnodes_rank_array_index (sharers, zz); if (sharer->rank == mpirank) { continue; } send_buf = (sc_array_t *) sc_array_index (countbuf->send_buffers, zz); nnodes = sharer->shared_nodes.elem_count; P4EST_ASSERT (nnodes == send_buf->elem_count); P4EST_ASSERT (send_buf->elem_size == 2 * sizeof (p4est_locidx_t)); for (zy = 0; zy < nnodes; zy++) { p4est_locidx_t *lp = (p4est_locidx_t *) sc_array_index (send_buf, zy); P4EST_ASSERT (lp[0] >= 0); P4EST_ASSERT (lp[1] >= 0); send_offset += lp[1]; } } send_total = send_offsets[nsharers] = send_offset; p4est_lnodes_share_all_end (countbuf); recv_offsets = P4EST_ALLOC (p4est_locidx_t, nsharers + 1); recv_offset = 0; for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *sharer; sc_array_t *recv_buf; size_t zy, nnodes; recv_offsets[zz] = recv_offset; sharer = p4est_lnodes_rank_array_index (sharers, zz); if (sharer->rank == mpirank) { continue; } recv_buf = (sc_array_t *) sc_array_index (countbuf->recv_buffers, zz); nnodes = sharer->shared_nodes.elem_count; P4EST_ASSERT (nnodes == recv_buf->elem_count); P4EST_ASSERT (recv_buf->elem_size == 2 * sizeof (p4est_locidx_t)); for (zy = 0; zy < nnodes; zy++) { p4est_locidx_t *lp = (p4est_locidx_t *) sc_array_index (recv_buf, zy); P4EST_ASSERT (lp[0] >= 0); P4EST_ASSERT (lp[1] >= 0); recv_offset += lp[1]; } } recv_total = recv_offsets[nsharers] = recv_offset; recv = P4EST_ALLOC (int8_t, recv_total); recv_request = P4EST_ALLOC (sc_MPI_Request, nsharers); send = P4EST_ALLOC (int8_t, send_total); send_request = P4EST_ALLOC (sc_MPI_Request, nsharers); /* post receives */ nleft = 0; for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *sharer; int icount = recv_offsets[zz + 1] - recv_offsets[zz]; sharer = p4est_lnodes_rank_array_index (sharers, zz); if (sharer->rank == mpirank) { recv_request[zz] = sc_MPI_REQUEST_NULL; continue; } if (icount) { mpiret = sc_MPI_Irecv (recv + recv_offsets[zz], icount * sizeof (int8_t), sc_MPI_BYTE, sharer->rank, P6EST_COMM_BALANCE, lnodes->mpicomm, recv_request + zz); SC_CHECK_MPI (mpiret); nleft++; } else { recv_request[zz] = sc_MPI_REQUEST_NULL; } } /* post sends */ for (zz = 0; zz < nsharers; zz++) { p4est_lnodes_rank_t *sharer; size_t zy, nnodes; int icount; sc_array_t *shared_nodes; sharer = p4est_lnodes_rank_array_index (sharers, zz); if (sharer->rank == mpirank) { send_request[zz] = sc_MPI_REQUEST_NULL; continue; } shared_nodes = &sharer->shared_nodes; nnodes = shared_nodes->elem_count; icount = 0; for (zy = 0; zy < nnodes; zy++) { p4est_locidx_t nidx; int8_t *c; nidx = *((p4est_locidx_t *) sc_array_index (shared_nodes, zy)); if (lr[nidx][1]) { c = (int8_t *) sc_array_index (lc, lr[nidx][0]); memcpy (send + send_offsets[zz] + icount, c, lr[nidx][1] * sizeof (int8_t)); icount += lr[nidx][1]; } else { P4EST_ASSERT (!lr[nidx][0]); } } P4EST_ASSERT (icount == send_offsets[zz + 1] - send_offsets[zz]); if (icount) { mpiret = sc_MPI_Isend (send + send_offsets[zz], icount * sizeof (int8_t), sc_MPI_BYTE, sharer->rank, P6EST_COMM_BALANCE, lnodes->mpicomm, send_request + zz); SC_CHECK_MPI (mpiret); } else { send_request[zz] = sc_MPI_REQUEST_NULL; } } work = sc_array_new (sizeof (int8_t)); array_of_indices = P4EST_ALLOC (int, nsharers); while (nleft) { int outcount; int i; mpiret = sc_MPI_Waitsome (nsharers, recv_request, &outcount, array_of_indices, sc_MPI_STATUSES_IGNORE); SC_CHECK_MPI (mpiret); for (i = 0; i < outcount; i++) { p4est_lnodes_rank_t *sharer; size_t zy, nnode; sc_array_t *shared_nodes; sc_array_t *recv_buf; zz = array_of_indices[i]; sharer = p4est_lnodes_rank_array_index (sharers, zz); shared_nodes = &sharer->shared_nodes; recv_buf = (sc_array_t *) sc_array_index (countbuf->recv_buffers, zz); nnode = shared_nodes->elem_count; P4EST_ASSERT (nnode == recv_buf->elem_count); recv_offset = recv_offsets[zz]; for (zy = 0; zy < nnode; zy++) { p4est_locidx_t *lp; p4est_locidx_t nidx; sc_array_t oldview, newview; nidx = *((p4est_locidx_t *) sc_array_index (shared_nodes, zy)); lp = (p4est_locidx_t *) sc_array_index (recv_buf, zy); sc_array_init_view (&oldview, lc, lr[nidx][0], lr[nidx][1]); sc_array_init_data (&newview, recv + recv_offset, sizeof (int8_t), lp[1]); if (profile->ptype == P6EST_PROFILE_UNION) { p6est_profile_union (&oldview, &newview, work); if (work->elem_count > oldview.elem_count) { int8_t *c; any_change = 1; lr[nidx][0] = lc->elem_count; lr[nidx][1] = work->elem_count; profile->lnode_changed[evenodd][nidx] = 1; c = (int8_t *) sc_array_push_count (lc, work->elem_count); memcpy (c, work->array, work->elem_count * work->elem_size); } } else { p6est_profile_intersection (&oldview, &newview, work); P4EST_ASSERT (work->elem_count <= oldview.elem_count); if (work->elem_count < oldview.elem_count) { lr[nidx][1] = work->elem_count; memcpy (oldview.array, work->array, work->elem_count * work->elem_size); } } recv_offset += lp[1]; } P4EST_ASSERT (recv_offset == recv_offsets[zz + 1]); } nleft -= outcount; P4EST_ASSERT (nleft >= 0); } P4EST_FREE (array_of_indices); sc_array_destroy (work); p6est_profile_compress (profile); p4est_lnodes_buffer_destroy (countbuf); P4EST_FREE (recv_request); P4EST_FREE (recv_offsets); P4EST_FREE (recv); { mpiret = sc_MPI_Waitall (nsharers, send_request, sc_MPI_STATUSES_IGNORE); SC_CHECK_MPI (mpiret); P4EST_FREE (send_request); P4EST_FREE (send_offsets); P4EST_FREE (send); any_global_change = any_change; mpiret = sc_MPI_Allreduce (&any_change, &any_global_change, 1, sc_MPI_INT, sc_MPI_LOR, lnodes->mpicomm); SC_CHECK_MPI (mpiret); } return any_global_change; }
trilinear_mesh_t * p8est_trilinear_mesh_new_from_nodes (p4est_t * p4est, p4est_nodes_t * nodes) { const int num_procs = p4est->mpisize; const int rank = p4est->mpirank; int mpiret; int k, owner; #ifdef P4EST_DEBUG int prev_owner = 0; int64_t prev_fvnid = -1; #endif int *sharers; size_t current, zz, num_sharers; int32_t e, n, local_owned_end; int64_t global_borrowed, global_shared; int64_t local_counts[5], global_counts[5]; int32link_t *lynk, **tail; p4est_topidx_t which_tree; p4est_locidx_t *local_node, *shared_offsets; p4est_tree_t *tree; p4est_quadrant_t *q; p4est_indep_t *in; p8est_hang4_t *fh; p8est_hang2_t *eh; trilinear_elem_t *elem; trilinear_anode_t *anode; trilinear_dnode_t *dnode; trilinear_mesh_t *mesh; trilinear_mesh_pid_t *elem_pids; trilinear_mesh_pid_t *node_pids; sc_recycle_array_t *rarr; P4EST_GLOBAL_PRODUCTIONF ("Into trilinear_mesh_extract with %lld total elements\n", (long long) p4est->global_num_quadrants); p4est_log_indent_push (); /* Allocate output data structure. */ mesh = P4EST_ALLOC_ZERO (trilinear_mesh_t, 1); memset (mesh, -1, sizeof (*mesh)); shared_offsets = nodes->shared_offsets; /* Assign local counts. */ P4EST_ASSERT (nodes->num_local_quadrants == p4est->local_num_quadrants); mesh->local_elem_num = p4est->local_num_quadrants; mesh->local_anode_num = nodes->indep_nodes.elem_count; mesh->local_dnode_num = nodes->face_hangings.elem_count + nodes->edge_hangings.elem_count; mesh->local_onode_num = nodes->num_owned_indeps; mesh->local_owned_offset = nodes->offset_owned_indeps; mesh->local_node_num = mesh->local_anode_num + mesh->local_dnode_num; local_owned_end = mesh->local_owned_offset + mesh->local_onode_num; /* Communicate global counts. */ local_counts[0] = mesh->local_elem_num; local_counts[1] = mesh->local_anode_num; local_counts[2] = mesh->local_onode_num; local_counts[3] = mesh->local_dnode_num; local_counts[4] = nodes->num_owned_shared; mpiret = sc_MPI_Allreduce (local_counts, global_counts, 5, sc_MPI_LONG_LONG_INT, sc_MPI_SUM, p4est->mpicomm); SC_CHECK_MPI (mpiret); P4EST_ASSERT (global_counts[0] == p4est->global_num_quadrants); mesh->total_elem_num = global_counts[0]; global_borrowed = global_counts[1] - global_counts[2]; mesh->total_anode_num = global_counts[2]; mesh->total_dnode_num = global_counts[3]; global_shared = global_counts[4]; mesh->total_node_num = mesh->total_anode_num + mesh->total_dnode_num; /* Allocate the mesh memory. */ mesh->elem_table = P4EST_ALLOC (trilinear_elem_t, mesh->local_elem_num); mesh->node_table = P4EST_ALLOC (trilinear_node_t, mesh->local_node_num); mesh->fvnid_count_table = P4EST_ALLOC (int64_t, num_procs + 1); mesh->fvnid_interval_table = P4EST_ALLOC (int64_t, num_procs + 1); mesh->all_fvnid_start = mesh->fvnid_interval_table; mesh->sharer_pool = sc_mempool_new (sizeof (int32link_t)); mesh->elem_pids = P4EST_ALLOC (trilinear_mesh_pid_t, mesh->local_node_num); mesh->node_pids = P4EST_ALLOC (trilinear_mesh_pid_t, mesh->local_node_num); /* Assign global free variable information. */ mesh->fvnid_interval_table[0] = 0; for (k = 0; k < num_procs; ++k) { mesh->fvnid_interval_table[k + 1] = mesh->fvnid_interval_table[k] + (mesh->fvnid_count_table[k] = nodes->global_owned_indeps[k]); } mesh->fvnid_count_table[num_procs] = -1; mesh->global_fvnid_num = mesh->fvnid_interval_table[num_procs]; mesh->global_fvnid_start = 0; mesh->global_fvnid_end = mesh->global_fvnid_num - 1; P4EST_ASSERT (mesh->global_fvnid_num == mesh->total_anode_num); /* Assign element information. */ local_node = nodes->local_nodes; which_tree = p4est->first_local_tree; elem_pids = mesh->elem_pids; if (which_tree >= 0) { tree = p4est_tree_array_index (p4est->trees, which_tree); current = 0; for (e = 0; e < mesh->local_elem_num; ++e) { if (current == tree->quadrants.elem_count) { ++which_tree; tree = p4est_tree_array_index (p4est->trees, which_tree); current = 0; } q = p4est_quadrant_array_index (&tree->quadrants, current); elem = mesh->elem_table + e; for (k = 0; k < P4EST_CHILDREN; ++k) { elem->local_node_id[k] = *local_node++; } elem->lx = (tick_t) q->x; elem->ly = (tick_t) q->y; elem->lz = (tick_t) q->z; elem->size = P4EST_QUADRANT_LEN (q->level); elem->data = q->p.user_data; elem_pids[e] = (trilinear_mesh_pid_t) which_tree; ++current; } P4EST_ASSERT (which_tree == p4est->last_local_tree); P4EST_ASSERT (current == tree->quadrants.elem_count); } /* Assign anchored node information. */ mesh->anode_table = mesh->node_table; mesh->onode_table = mesh->node_table + mesh->local_owned_offset; mesh->dnode_table = mesh->node_table + mesh->local_anode_num; node_pids = mesh->node_pids; for (n = 0; n < mesh->local_anode_num; ++n) { anode = &mesh->node_table[n].anchored; in = (p4est_indep_t *) sc_array_index (&nodes->indep_nodes, (size_t) n); anode->point.x = in->x; anode->point.y = in->y; anode->point.z = in->z; node_pids[n] = (trilinear_mesh_pid_t) in->p.piggy3.which_tree; if (n < mesh->local_owned_offset) { owner = nodes->nonlocal_ranks[n]; P4EST_ASSERT (owner < rank && owner >= prev_owner); } else if (n >= local_owned_end) { owner = nodes->nonlocal_ranks[n - mesh->local_onode_num]; P4EST_ASSERT (owner > rank && owner >= prev_owner); } else { owner = rank; } anode->fvnid = mesh->all_fvnid_start[owner] + in->p.piggy3.local_num; P4EST_ASSERT (anode->fvnid > prev_fvnid); if (in->pad8 == 0) { P4EST_ASSERT (in->pad16 == -1); P4EST_ASSERT (shared_offsets == NULL || shared_offsets[n] == -1); anode->share = NULL; } else { P4EST_ASSERT (in->pad8 > 0); num_sharers = (size_t) in->pad8; rarr = (sc_recycle_array_t *) sc_array_index (&nodes->shared_indeps, num_sharers - 1); if (nodes->shared_offsets == NULL) { P4EST_ASSERT (in->pad16 >= 0); zz = (size_t) in->pad16; } else { P4EST_ASSERT (in->pad16 == -1); zz = (size_t) shared_offsets[n]; } sharers = (int *) sc_array_index (&rarr->a, zz); tail = &anode->share; for (zz = 0; zz < num_sharers; ++zz) { *tail = lynk = (int32link_t *) sc_mempool_alloc (mesh->sharer_pool); lynk->id = (int32_t) sharers[zz]; tail = &lynk->next; } *tail = NULL; } #ifdef P4EST_DEBUG prev_owner = owner; prev_fvnid = anode->fvnid; #endif } /* Assign face hanging node information. */ for (zz = 0; zz < nodes->face_hangings.elem_count; ++n, ++zz) { dnode = &mesh->node_table[n].dangling; fh = (p8est_hang4_t *) sc_array_index (&nodes->face_hangings, zz); dnode->point.x = fh->x; dnode->point.y = fh->y; dnode->point.z = fh->z; dnode->type = 0; /* Not used in Rhea. */ dnode->local_anode_id[0] = fh->p.piggy.depends[0]; dnode->local_anode_id[1] = fh->p.piggy.depends[1]; dnode->local_anode_id[2] = fh->p.piggy.depends[2]; dnode->local_anode_id[3] = fh->p.piggy.depends[3]; node_pids[n] = (trilinear_mesh_pid_t) fh->p.piggy.which_tree; } /* Assign edge hanging node information. */ for (zz = 0; zz < nodes->edge_hangings.elem_count; ++n, ++zz) { dnode = &mesh->node_table[n].dangling; eh = (p8est_hang2_t *) sc_array_index (&nodes->edge_hangings, zz); dnode->point.x = eh->x; dnode->point.y = eh->y; dnode->point.z = eh->z; dnode->type = 0; /* Not used in Rhea. */ dnode->local_anode_id[0] = eh->p.piggy.depends[0]; dnode->local_anode_id[1] = eh->p.piggy.depends[1]; dnode->local_anode_id[2] = dnode->local_anode_id[3] = -1; node_pids[n] = (trilinear_mesh_pid_t) eh->p.piggy.which_tree; } P4EST_ASSERT (n == mesh->local_node_num); /* Assign the remaining variables. */ mesh->mpicomm = p4est->mpicomm; mesh->mpisize = (int32_t) num_procs; mesh->mpirank = (int32_t) rank; mesh->recsize = (int32_t) p4est->data_size; mesh->destructor = p8est_trilinear_mesh_destroy; /* These members are incomplete and need to be filled later. */ memset (mesh->bounds, 0, 6 * sizeof (int)); memset (mesh->sizes, 0, 3 * sizeof (int)); mesh->minsize = mesh->maxsize = 0; mesh->ticksize = 0.; mesh->extra_info = NULL; mesh->gid = -1; /* We are done */ p4est_log_indent_pop (); P4EST_GLOBAL_PRODUCTIONF ("Done trilinear_mesh_extract" " with %lld anodes %lld %lld\n", (long long) mesh->total_anode_num, (long long) global_borrowed, (long long) global_shared); return mesh; }
/** Timestep the advection problem. * * Update the state, refine, repartition, and write the solution to file. * * \param [in,out] p4est the forest, whose state is updated * \param [in] time the end time */ static void step3_timestep (p4est_t * p4est, double time) { double t = 0.; double dt = 0.; int i; step3_data_t *ghost_data; step3_ctx_t *ctx = (step3_ctx_t *) p4est->user_pointer; int refine_period = ctx->refine_period; int repartition_period = ctx->repartition_period; int write_period = ctx->write_period; int recursive = 0; int allowed_level = P4EST_QMAXLEVEL; int allowcoarsening = 1; int callbackorphans = 0; int mpiret; double orig_max_err = ctx->max_err; double umax, global_umax; p4est_ghost_t *ghost; /* create the ghost quadrants */ ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL); /* create space for storing the ghost data */ ghost_data = P4EST_ALLOC (step3_data_t, ghost->ghosts.elem_count); /* synchronize the ghost data */ p4est_ghost_exchange_data (p4est, ghost, ghost_data); /* initialize du/dx estimates */ p4est_iterate (p4est, ghost, (void *) ghost_data, /* pass in ghost data that we just exchanged */ step3_reset_derivatives, /* blank the previously calculated derivatives */ step3_minmod_estimate, /* compute the minmod estimate of each cell's derivative */ #ifdef P4_TO_P8 NULL, /* there is no callback for the edges between quadrants */ #endif NULL); /* there is no callback for the corners between quadrants */ for (t = 0., i = 0; t < time; t += dt, i++) { P4EST_GLOBAL_PRODUCTIONF ("time %f\n", t); /* refine */ if (!(i % refine_period)) { if (i) { /* compute umax */ umax = 0.; /* initialize derivative estimates */ p4est_iterate (p4est, NULL, (void *) &umax, /* pass in ghost data that we just exchanged */ step3_compute_max, /* blank the previously calculated derivatives */ NULL, /* there is no callback for the faces between quadrants */ #ifdef P4_TO_P8 NULL, /* there is no callback for the edges between quadrants */ #endif NULL); /* there is no callback for the corners between quadrants */ mpiret = sc_MPI_Allreduce (&umax, &global_umax, 1, sc_MPI_DOUBLE, sc_MPI_MAX, p4est->mpicomm); SC_CHECK_MPI (mpiret); ctx->max_err = orig_max_err * global_umax; P4EST_GLOBAL_PRODUCTIONF ("u_max %f\n", global_umax); /* adapt */ p4est_refine_ext (p4est, recursive, allowed_level, step3_refine_err_estimate, NULL, step3_replace_quads); p4est_coarsen_ext (p4est, recursive, callbackorphans, step3_coarsen_err_estimate, NULL, step3_replace_quads); p4est_balance_ext (p4est, P4EST_CONNECT_FACE, NULL, step3_replace_quads); p4est_ghost_destroy (ghost); P4EST_FREE (ghost_data); ghost = NULL; ghost_data = NULL; } dt = step3_get_timestep (p4est); } /* repartition */ if (i && !(i % repartition_period)) { p4est_partition (p4est, allowcoarsening, NULL); if (ghost) { p4est_ghost_destroy (ghost); P4EST_FREE (ghost_data); ghost = NULL; ghost_data = NULL; } } /* write out solution */ if (!(i % write_period)) { step3_write_solution (p4est, i); } /* synchronize the ghost data */ if (!ghost) { ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL); ghost_data = P4EST_ALLOC (step3_data_t, ghost->ghosts.elem_count); p4est_ghost_exchange_data (p4est, ghost, ghost_data); } /* compute du/dt */ /* *INDENT-OFF* */ p4est_iterate (p4est, /* the forest */ ghost, /* the ghost layer */ (void *) ghost_data, /* the synchronized ghost data */ step3_quad_divergence, /* callback to compute each quad's interior contribution to du/dt */ step3_upwind_flux, /* callback to compute each quads' faces' contributions to du/du */ #ifdef P4_TO_P8 NULL, /* there is no callback for the edges between quadrants */ #endif NULL); /* there is no callback for the corners between quadrants */ /* *INDENT-ON* */ /* update u */ p4est_iterate (p4est, NULL, /* ghosts are not needed for this loop */ (void *) &dt, /* pass in dt */ step3_timestep_update, /* update each cell */ NULL, /* there is no callback for the faces between quadrants */ #ifdef P4_TO_P8 NULL, /* there is no callback for the edges between quadrants */ #endif NULL); /* there is no callback for the corners between quadrants */ /* synchronize the ghost data */ p4est_ghost_exchange_data (p4est, ghost, ghost_data); /* update du/dx estimate */ p4est_iterate (p4est, ghost, (void *) ghost_data, /* pass in ghost data that we just exchanged */ step3_reset_derivatives, /* blank the previously calculated derivatives */ step3_minmod_estimate, /* compute the minmod estimate of each cell's derivative */ #ifdef P4_TO_P8 NULL, /* there is no callback for the edges between quadrants */ #endif NULL); /* there is no callback for the corners between quadrants */ } P4EST_FREE (ghost_data); p4est_ghost_destroy (ghost); }