Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce populate functionality according to cmesh borders #998

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

lukasdreyer
Copy link
Collaborator

Describe your changes here:
Unclean version of creating a forest according to the partitioned cmesh boundaries (cmesh elements are not allowed to be shared).
For discussions with @CsatiZoltan about whether this satisfies his requirements.

All these boxes must be checked by the reviewers before merging the pull request:

As a reviewer please read through all the code lines and make sure that the code is fully understood, bug free, well-documented and well-structured.

General

  • The reviewer executed the new code features at least once and checked the results manually

  • The code follows the t8code coding guidelines

  • New source/header files are properly added to the Makefiles

  • The code is well documented

  • All function declarations, structs/classes and their members have a proper doxygen documentation

  • All new algorithms and data structures are sufficiently optimal in terms of memory and runtime (If this should be merged, but there is still potential for optimization, create a new issue)

Tests

  • The code is covered in an existing or new test case using Google Test

Github action

  • The code compiles without warning in debugging and release mode, with and without MPI (this should be executed automatically in a github action)

  • All tests pass (in various configurations, this should be executed automatically in a github action)

    If the Pull request introduces code that is not covered by the github action (for example coupling with a new library):

    • Should this use case be added to the github action?
    • If not, does the specific use case compile and all tests pass (check manually)

Scripts and Wiki

  • If a new directory with source-files is added, it must be covered by the script/find_all_source_files.scp to check the indentation of these files.
  • If this PR introduces a new feature, it must be covered in an example/tutorial and a Wiki article.

Licence

  • The author added a BSD statement to doc/ (or already has one)

t8code is a C library to manage a collection (a forest) of multiple
connected adaptive space-trees of general element classes in parallel.

Copyright (C) 2015 the developers
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change the date to 2024?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I already have the template for VScode that creates the header for new files, but this file was still created via copy paste before, so I will change it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you create a template for these things in VS Code (I'm curious because I use that editor too)?

@CsatiZoltan
Copy link
Collaborator

CsatiZoltan commented Mar 25, 2024

Here are two additional tests with three quadratic quads. The two_one_quad should fail, theone_two_quad test should pass.

TEST (t8_forest_new_from_partition, one_two_quad)
{
  /* Current process */
  int rank, size;
  sc_MPI_Comm_size (sc_MPI_COMM_WORLD, &size);
  sc_MPI_Comm_rank (sc_MPI_COMM_WORLD, &rank);

  /* Geometry */
  int degree = 2;
  std::vector<std::vector<double>> cells;
  cells.push_back (std::vector<double> { -1, 1.2, 0,   0, 1.2,  0,   -1, 3,    0, 0, 3,    0,   -1, 2.1,
                                         0,  0,   2.1, 0, -0.5, 1.2, 0,  -0.5, 3, 0, -0.5, 2.1, 0 });
  cells.push_back (std::vector<double> { 0, 1.2, 0,   2, 1.5, 0,    0, 3, 0, 2, 3,   0,   0, 2.1,
                                         0, 1.7, 2.1, 0, 1,   1.55, 0, 1, 3, 0, 0.9, 2.1, 0 });
  cells.push_back (
    std::vector<double> { 2, 1.5, 0, 4, 0, 0, 2, 3, 0, 4, 3, 0, 1.7, 2.1, 0, 4, 1.5, 0, 3, 1, 0, 3, 3, 0, 3, 2, 0 });

  /* Create a partitioned cmesh */
  t8_cmesh_t cmesh;
  t8_cmesh_init (&cmesh);
  if (size != 2)
    SC_ABORT ("Program must be run on two MPI processes.\n");
  else {
    if (rank == 0) {
      t8_cmesh_set_tree_class (cmesh, 0, T8_ECLASS_QUAD);
      t8_cmesh_set_tree_class (cmesh, 1, T8_ECLASS_QUAD);
      t8_cmesh_set_tree_vertices (cmesh, 0, cells[0].data (), cells[0].size ());
      t8_cmesh_set_tree_vertices (cmesh, 1, cells[1].data (), cells[1].size ());
      t8_cmesh_set_attribute (cmesh, 0, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree, sizeof (int), 1);
      t8_cmesh_set_attribute (cmesh, 1, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree, sizeof (int), 1);
      t8_cmesh_set_join (cmesh, 0, 1, 1, 0, 0);
      t8_cmesh_set_partition_range (cmesh, 3, 0, 0);
    }
    else if (rank == 1) {
      for (size_t itree = 0; itree < 3; ++itree) {
        t8_cmesh_set_tree_class (cmesh, itree, T8_ECLASS_QUAD);
        t8_cmesh_set_tree_vertices (cmesh, itree, cells[itree].data (), cells[itree].size ());
        t8_cmesh_set_attribute (cmesh, itree, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree,
                                sizeof (int), 1);
      }
      t8_cmesh_set_join (cmesh, 0, 1, 1, 0, 0);
      t8_cmesh_set_join (cmesh, 1, 2, 1, 0, 0);
      t8_cmesh_set_partition_range (cmesh, 3, 1, 2);
    }
  }
  t8_cmesh_register_geometry<t8_geometry_lagrange> (cmesh, 2);
  t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD);
  t8_cmesh_vtk_write_file (cmesh, "cmesh");
  t8_forest_t forest
    = t8_forest_new_uniform_with_cmesh_partition (cmesh, t8_scheme_new_default_cxx (), 0, 0, sc_MPI_COMM_WORLD);
  // t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 1, sc_MPI_COMM_WORLD);
  t8_forest_write_vtk (forest, "forest");
  t8_cmesh_destroy (&cmesh);
}

TEST (t8_forest_new_from_partition, two_one_quad)
{
  /* Current process */
  int rank, size;
  sc_MPI_Comm_size (sc_MPI_COMM_WORLD, &size);
  sc_MPI_Comm_rank (sc_MPI_COMM_WORLD, &rank);

  /* Geometry */
  int degree = 2;
  std::vector<std::vector<double>> cells;
  cells.push_back (std::vector<double> { -1, 1.2, 0,   0, 1.2,  0,   -1, 3,    0, 0, 3,    0,   -1, 2.1,
                                         0,  0,   2.1, 0, -0.5, 1.2, 0,  -0.5, 3, 0, -0.5, 2.1, 0 });
  cells.push_back (std::vector<double> { 0, 1.2, 0,   2, 1.5, 0,    0, 3, 0, 2, 3,   0,   0, 2.1,
                                         0, 1.7, 2.1, 0, 1,   1.55, 0, 1, 3, 0, 0.9, 2.1, 0 });
  cells.push_back (
    std::vector<double> { 2, 1.5, 0, 4, 0, 0, 2, 3, 0, 4, 3, 0, 1.7, 2.1, 0, 4, 1.5, 0, 3, 1, 0, 3, 3, 0, 3, 2, 0 });

  /* Create a partitioned cmesh */
  t8_cmesh_t cmesh;
  t8_cmesh_init (&cmesh);
  if (size != 2)
    SC_ABORT ("Program must be run on two MPI processes.\n");
  else {
    if (rank == 0) {
      for (size_t itree = 0; itree < 3; ++itree) {
        t8_cmesh_set_tree_class (cmesh, itree, T8_ECLASS_QUAD);
        t8_cmesh_set_tree_vertices (cmesh, itree, cells[itree].data (), cells[itree].size ());
        t8_cmesh_set_attribute (cmesh, itree, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree,
                                sizeof (int), 1);
      }
      t8_cmesh_set_join (cmesh, 0, 1, 1, 0, 0);
      t8_cmesh_set_join (cmesh, 1, 2, 1, 0, 0);
      t8_cmesh_set_partition_range (cmesh, 3, 0, 1);
    }
    else if (rank == 1) {
      t8_cmesh_set_tree_class (cmesh, 1, T8_ECLASS_QUAD);
      t8_cmesh_set_tree_class (cmesh, 2, T8_ECLASS_QUAD);
      t8_cmesh_set_tree_vertices (cmesh, 1, cells[1].data (), cells[1].size ());
      t8_cmesh_set_tree_vertices (cmesh, 2, cells[2].data (), cells[2].size ());
      t8_cmesh_set_attribute (cmesh, 1, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree, sizeof (int), 1);
      t8_cmesh_set_attribute (cmesh, 2, t8_get_package_id (), T8_CMESH_LAGRANGE_POLY_DEGREE, &degree, sizeof (int), 1);
      t8_cmesh_set_join (cmesh, 1, 2, 1, 0, 0);
      t8_cmesh_set_partition_range (cmesh, 3, 2, 2);
    }
  }
  t8_cmesh_register_geometry<t8_geometry_lagrange> (cmesh, 2);
  t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD);
  t8_cmesh_vtk_write_file (cmesh, "cmesh");
  t8_forest_t forest
    = t8_forest_new_uniform_with_cmesh_partition (cmesh, t8_scheme_new_default_cxx (), 0, 0, sc_MPI_COMM_WORLD);
  // t8_forest_t forest = t8_forest_new_uniform (cmesh, t8_scheme_new_default_cxx (), 0, 1, sc_MPI_COMM_WORLD);
  t8_forest_write_vtk (forest, "forest");
  t8_cmesh_destroy (&cmesh);
}

@jmark jmark added discussion draft Enhance the visibility that this is a draft. labels Apr 22, 2024
Copy link
Collaborator

@Davknapp Davknapp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A first batch of comments for your code.
I need to review the changes in the t8_forest_populate function, but I need a clear mind for that. Probably will do it tomorrow.

/* create a line cmesh */
int mpirank, mpisize;
sc_MPI_Comm comm = sc_MPI_COMM_WORLD;
sc_MPI_Comm_size (comm, &mpisize);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check the return values after calling this function.

sc_MPI_Comm comm = sc_MPI_COMM_WORLD;
sc_MPI_Comm_size (comm, &mpisize);
sc_MPI_Comm_rank (comm, &mpirank);
int face_knowledge = 3;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int face_knowledge = 3;
const int face_knowledge = 3;

sc_MPI_Comm_size (comm, &mpisize);
sc_MPI_Comm_rank (comm, &mpirank);
int face_knowledge = 3;
int num_trees = 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int num_trees = 2;
const t8_gloidx_t num_trees = 2;

t8_cmesh_set_tree_class (cmesh, second, T8_ECLASS_LINE);
t8_cmesh_set_tree_vertices (cmesh, first, vertices, 2);
t8_cmesh_set_tree_vertices (cmesh, second, vertices + 3, 2);
// t8_cmesh_set_join (cmesh, first, second, 1, 0, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// t8_cmesh_set_join (cmesh, first, second, 1, 0, 0);

t8_cmesh_set_partition_range (cmesh, face_knowledge, 0, 1);
}
else {
t8_cmesh_set_dimension (cmesh, 1);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dimension is not set in the first case. It should be set in both cases, I think you can move it out of the if/else part

/* Allocate elements for this processor. */
t8_element_array_init_size (telements, eclass_scheme, end - start);
t8_element_t *element = t8_element_array_index_locidx_mutable (telements, 0);
eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
eclass_scheme->t8_element_set_linear_id (element, forest->set_level, 0);

t8_element_t *element = t8_element_array_index_locidx_mutable (telements, 0);
eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
count_elements++;
for (t8_locidx_t et = start + 1; et < end; et++, count_elements++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for (t8_locidx_t et = start + 1; et < end; et++, count_elements++) {
for (t8_locidx_t et = 1; et < end; et++, count_elements++) {

eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
count_elements++;
for (t8_locidx_t et = start + 1; et < end; et++, count_elements++) {
t8_element_t *element_succ = t8_element_array_index_locidx_mutable (telements, et - start);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t8_element_t *element_succ = t8_element_array_index_locidx_mutable (telements, et - start);
t8_element_t *element_succ = t8_element_array_index_locidx_mutable (telements, et);

t8_element_t *element = t8_element_array_index_locidx_mutable (telements, 0);
eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
count_elements++;
for (t8_locidx_t et = start + 1; et < end; et++, count_elements++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

et is not a good name for a variable

T8_ASSERT (forest->set_level <= forest->maxlevel);
/* populate a new forest with tree and quadrant objects */
if (t8_forest_refines_irregular (forest) && forest->set_level > 0) {
/* On root level we will also use the normal algorithm */
t8_forest_populate_irregular (forest);
t8_forest_populate_irregular (forest, 1);
// t8_forest_populate_irregular (forest, !forest->set_initial_partition_according_to_cmesh);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// t8_forest_populate_irregular (forest, !forest->set_initial_partition_according_to_cmesh);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: investigate further, because it looks like the second argument is not even used in t8_forest_populate_irregular

@lukasdreyer lukasdreyer force-pushed the feature-populate_without_repartition branch from cc579aa to f93958f Compare July 9, 2024 05:42
/* True if the forest has no elements */
is_empty = forest->first_local_tree > forest->last_local_tree
|| (forest->first_local_tree == forest->last_local_tree && child_in_tree_begin >= child_in_tree_end);
t8_gloidx_t cmesh_first_tree = t8_cmesh_get_first_treeid (forest->cmesh);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t8_gloidx_t cmesh_first_tree = t8_cmesh_get_first_treeid (forest->cmesh);
const t8_gloidx_t cmesh_first_tree = t8_cmesh_get_first_treeid (forest->cmesh);

is_empty = forest->first_local_tree > forest->last_local_tree
|| (forest->first_local_tree == forest->last_local_tree && child_in_tree_begin >= child_in_tree_end);
t8_gloidx_t cmesh_first_tree = t8_cmesh_get_first_treeid (forest->cmesh);
t8_gloidx_t cmesh_last_tree = cmesh_first_tree + t8_cmesh_get_num_local_trees (forest->cmesh) - 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t8_gloidx_t cmesh_last_tree = cmesh_first_tree + t8_cmesh_get_num_local_trees (forest->cmesh) - 1;
const t8_gloidx_t cmesh_last_tree = cmesh_first_tree + t8_cmesh_get_num_local_trees (forest->cmesh) - 1;


if (!is_empty) {
/* True if the forest has no elements */
int is_empty
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
int is_empty
const bool is_empty

tree_class = tree->eclass = t8_cmesh_get_tree_class (forest->cmesh, jt - first_ctree);
t8_gloidx_t first_ctree = t8_cmesh_get_first_treeid (forest->cmesh);
t8_locidx_t count_elements = 0;
for (t8_gloidx_t jt = forest->first_local_tree; jt <= forest->last_local_tree; jt++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jt is not a good name for a variable.

for (jt = forest->first_local_tree, count_elements = 0; jt <= forest->last_local_tree; jt++) {
tree = (t8_tree_t) t8_sc_array_index_locidx (forest->trees, jt - forest->first_local_tree);
tree_class = tree->eclass = t8_cmesh_get_tree_class (forest->cmesh, jt - first_ctree);
t8_gloidx_t first_ctree = t8_cmesh_get_first_treeid (forest->cmesh);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t8_gloidx_t first_ctree = t8_cmesh_get_first_treeid (forest->cmesh);
const t8_gloidx_t first_ctree = t8_cmesh_get_first_treeid (forest->cmesh);

eclass_scheme->t8_element_set_linear_id (element, forest->set_level, start);
count_elements++;
for (et = start + 1; et < end; et++, count_elements++) {
element_succ = t8_element_array_index_locidx_mutable (telements, et - start);
for (t8_locidx_t et = start + 1; et < end; et++, count_elements++) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the name of the variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion draft Enhance the visibility that this is a draft.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants