Closed a-colaitis closed 11 months ago
Hi Arnaud,
I have been using p4est for the last 6 months for building an ALE-AMR finite volume radiation hydrodynamics code. Thank you for your work on p4est !
glad to learn about your success, and thanks for the report.
The code is written in Fortran and I have used C interfaces to extract the connectivity and mesh information I need. I then use that information to build my own node numbering due to the unique way the finite volume nodal solver operates, notably on ghost cells and hanging nodes.
To build the node numbering, I use the p8est mesh interface to get a face, edge and corner connectivity on a 2:1 corner-balanced forest.
Lately, I have been having trouble with my numbering algorithm (these occurred when I started testing AMR intensive applications). I have narrowed down the issue to a lack of information in the corneroffset (and other corner...) arrays. The problem arises when I try to access a corner neighbor through an inter-tree boundary, and when that corner is also a hanging edge node in another tree (but not in the corner-opposed quadrant).
I made a simple example to hopefully reproduce the issue. The connectivity is a simple brick connectivity with 4 trees created with:
conn = p8est_connectivity_new_brick ( 2, 2, 1, 0, 0, 0); p4est = p4est_new (mpicomm, conn, 0, NULL, NULL);
(Note that this behavior is also observed in 1 CPU, so the mpi communicator and ghost layer is not really necessary here.)
I then use p4est_refine to refine once tree number 1 and 2, which yields the following arrangement:
I create the ghost layer and mesh:
ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL); mesh = p4est_mesh_new_ext (p4est, ghost, 1, 1, P4EST_CONNECT_FULL);
Finally, inspecting the content of the mesh, notably for inter-tree connections, I get that local_num_corners = 0. I think this is incorrect. For example, the corner neighbor of quadrant 7 in tree 1 (see picture) through corner 2 should be quadrant 10 in tree 2 through corner 5, for which the node is a corner node and not hanging. The corresponding value in quad_to_corner is -1 (which indicates a hanging node).
I somewhat suspect that the issue is that this corner is a edge hanging corner for the single quadrant in tree 0 and 3, as when I refine all trees I get the proper inter-tree information through corners.
I may be doing something wrong, I would very much appreciate your help.
Your messages it timely. My guess is that @hannesbrandt is in the middle of putting together a solution; see #262. Would you feel like adding your minimal test case with a hardcoded check for the desired conditions to our library? Please coordinate with Hannes. Thanks again!
Thank you for your prompt response.
Yes of course, I can help in putting a test in place. I am an in-experienced C programmer, so I may make mistakes. I have attached a simple test case, which I cannot check completely for correctness since I do not have @hannesbrandt solution.
// ===================================================================================================================================
//
//
// ===================================================================================================================================
// -----------------------------------------------------------------------------------------------------------------------------------
// INCLUDES
#include <p4est_to_p8est.h>
#include <p8est_extended.h>
#include <p8est_mesh.h>
// ===================================================================================================================================
// Callback refinement function for the test
//
//
// ===================================================================================================================================
static int
refine_12 (p4est_t * p4est, p4est_topidx_t which_tree,
p4est_quadrant_t * quadrant)
{
// -----------------------------------------------------------------------------------------------------------------------------------
if (which_tree == 1 || which_tree == 2) {
return 1;
}
return 0;
// -----------------------------------------------------------------------------------------------------------------------------------
};
// ===================================================================================================================================
// Test the p4est version to check if it includes corner neighbor tracking
// through edge-hanging nodes
// ===================================================================================================================================
void p4_check_corner_neighbor_through_edge_hanging( )
{
// -----------------------------------------------------------------------------------------------------------------------------------
sc_MPI_Comm mpicomm = MPI_COMM_WORLD;
p4est_connectivity_t *conn = NULL;
p4est_ghost_t *ghost;
p4est_mesh_t *mesh;
p4est_t *p4est;
p4est_locidx_t *quad_to_corner;
p4est_locidx_t *corner_offset;
p4est_locidx_t *corner_quad;
int8_t *corner_corner;
p4est_locidx_t local_num_quadrants;
p4est_locidx_t ghost_num_quadrants;
p4est_locidx_t local_num_corners;
int q_id;
int c_id;
int q_id_opp;
int c_id_opp;
int q_id_test;
int c_id_test;
// create a communicator and initialize p4est
sc_init ( mpicomm, 1, 1, NULL, SC_LP_ESSENTIAL );
p4est_init ( NULL, SC_LP_ESSENTIAL );
// create a 2x2 brick connectivity
conn = p8est_connectivity_new_brick ( 2, 2, 1, 0, 0, 0 );
// create the p4est object
p4est = p4est_new ( mpicomm, conn, 0, NULL, NULL );
// check that we run serial
int mpisize = p4est->mpisize;
SC_CHECK_ABORT ( mpisize == 1 , "this test requires a serial run");
// refine trees 1 and 2. The result forest is corner-balanced
p4est_refine ( p4est, 0, refine_12, NULL );
// create a ghost layer and mesh. We should not need the tree index or level list
int compute_tree_index = 1;
int compute_level_lists = 1;
ghost = p4est_ghost_new (p4est,
P4EST_CONNECT_FULL);
p8est_mesh_params_t params;
p8est_mesh_params_init (¶ms);
params.compute_tree_index = 0;
params.compute_level_lists = 1;
params.btype = P4EST_CONNECT_FULL;
params.edgehanging_corners = 1;
mesh = p8est_mesh_new_params( p4est, ghost, ¶ms);
local_num_quadrants = mesh->local_num_quadrants;
ghost_num_quadrants = mesh->ghost_num_quadrants;
local_num_corners = mesh->local_num_corners;
SC_CHECK_ABORT ( local_num_corners > 0, "local_num_corners should be non-zero" );
// get the corner neighborhood
quad_to_corner = mesh->quad_to_corner;
corner_offset = (p4est_locidx_t *) mesh->corner_offset->array;
corner_quad = (p4est_locidx_t *) mesh->corner_quad->array;
corner_corner = (int8_t *) mesh->corner_corner->array;
// ---------------------
// perform a specific check for which we know the desired behavior
// the node being tested is edge-hanging in quad 0 in tree 0 and quad 17 in tree 3
// ---------------------
int index;
int offset;
// quad 3 in tree 2 should have corner 6 neighbor to quad 14 in tree 3 through corner 1
// ---------------------
q_id = 3;
c_id = 6;
q_id_opp = 14;
c_id_opp = 1;
// index into quad_to_corner
index = quad_to_corner[ q_id*8 + c_id ];
// cannot be -1 or -3
SC_CHECK_ABORT ( index >= 0 , "quad_to_corner should have a valid entry (case 1)" );
// index into corner_offset
index = index - ( local_num_quadrants + ghost_num_quadrants );
offset = corner_offset[ index ];
// corresponding quadrant and corner numbers
c_id_test = corner_corner[ offset ];
q_id_test = corner_quad [ offset ];
SC_CHECK_ABORT ( c_id_test == c_id_opp, "incorrect c_id_test (case 1)" );
SC_CHECK_ABORT ( q_id_test == q_id_opp, "incorrect q_id_test (case 1)" );
// quad 7 in tree 2 should have corner 2 neighbor to quad 10 in tree 3 through corner 5
// ---------------------
q_id = 7;
c_id = 2;
q_id_opp = 10;
c_id_opp = 5;
// index into quad_to_corner
index = quad_to_corner[ q_id*8 + c_id ];
// cannot be -1 or -3
SC_CHECK_ABORT ( index >= 0, "quad_to_corner should have a valid entry (case 2)" );
// index into corner_offset
index = index - ( local_num_quadrants + ghost_num_quadrants );
offset = corner_offset[ index ];
// corresponding quadrant and corner numbers
c_id_test = corner_corner[ offset ];
q_id_test = corner_quad [ offset ];
SC_CHECK_ABORT ( c_id_test == c_id_opp, "incorrect c_id_test (case 2)" );
SC_CHECK_ABORT ( q_id_test == q_id_opp, "incorrect q_id_test (case 2)" );
// ---------------------
// test complete, cleanup
// ---------------------
p4est_ghost_destroy ( ghost );
p4est_mesh_destroy ( mesh );
p4est_destroy ( p4est );
p4est_connectivity_destroy ( conn );
// -----------------------------------------------------------------------------------------------------------------------------------
};
Hi,
I have tested the branch feature hanging-corners from @hannesbrandt and the fix works as intended in my case.
I updated the test above with the correct "params" keywords and tested it.
Arnaud
Thanks for checking! @hannesbrandt 's PR is now merged. You'd be very welcome to create a PR with a test/test_mesh_hedges3.c program to double-check proper operation.
Nice to see the feature works as intended for your test case, thanks for checking!
You'd be very welcome to create a PR with a test/test_mesh_hedges3.c program to double-check proper operation.
During my work on https://github.com/cburstedde/p4est/pull/262 I implemented a test case that checks edgehanging corner neighbors across tree edges and faces. So, parts of this test are similar to the test case described in this issue (although they are based on a different refinement of the trees). What would be the best way to proceed?
It seems like your test is performing the same check in a more general way. I would think it is then not needed to test for my special case, but it is as you wish.
The relevant code is merged in the develop branch. Please keep us posted if anything doesn't seem right. Thanks for the report!
Hi,
I have been using p4est for the last 6 months for building an ALE-AMR finite volume radiation hydrodynamics code. Thank you for your work on p4est !
The code is written in Fortran and I have used C interfaces to extract the connectivity and mesh information I need. I then use that information to build my own node numbering due to the unique way the finite volume nodal solver operates, notably on ghost cells and hanging nodes.
To build the node numbering, I use the p8est mesh interface to get a face, edge and corner connectivity on a 2:1 corner-balanced forest.
Lately, I have been having trouble with my numbering algorithm (these occurred when I started testing AMR intensive applications). I have narrowed down the issue to a lack of information in the corneroffset (and other corner...) arrays. The problem arises when I try to access a corner neighbor through an inter-tree boundary, and when that corner is also a hanging edge node in another tree (but not in the corner-opposed quadrant).
I made a simple example to hopefully reproduce the issue. The connectivity is a simple brick connectivity with 4 trees created with:
conn = p8est_connectivity_new_brick ( 2, 2, 1, 0, 0, 0); p4est = p4est_new (mpicomm, conn, 0, NULL, NULL);
(Note that this behavior is also observed in 1 CPU, so the mpi communicator and ghost layer is not really necessary here.)
I then use p4est_refine to refine once tree number 1 and 2, which yields the following arrangement:
I create the ghost layer and mesh:
ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL); mesh = p4est_mesh_new_ext (p4est, ghost, 1, 1, P4EST_CONNECT_FULL);
Finally, inspecting the content of the mesh, notably for inter-tree connections, I get that local_num_corners = 0. I think this is incorrect. For example, the corner neighbor of quadrant 7 in tree 1 (see picture) through corner 2 should be quadrant 10 in tree 2 through corner 5, for which the node is a corner node and not hanging. The corresponding value in quad_to_corner is -1 (which indicates a hanging node).
I somewhat suspect that the issue is that this corner is a edge hanging corner for the single quadrant in tree 0 and 3, as when I refine all trees I get the proper inter-tree information through corners.
I may be doing something wrong, I would very much appreciate your help.
Thanks in advance Arnaud Colaïtis
Edit: I realize this may be what is referred to in https://github.com/cburstedde/p4est/pull/235 ? If this is the case, has a fix been implemented ?