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

Feature new for hybrid #768

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
b8e3dd4
Add cmesh uniform bounds for hybrid meshes.
Sep 23, 2022
553747c
Add all missing functions to make code compilable
Sep 23, 2022
4616091
Add example
Sep 23, 2022
a853e40
move is_irregular function and use hybrid_bounds only when a forest r…
Sep 23, 2022
6021fe4
Some optimization
Sep 23, 2022
c4d4b3b
use t8_cmesh_uniform_bounds_hybrid in cmesh_partition
Sep 23, 2022
f271d06
Update variables according to their scope and made them const
Sep 23, 2022
9e103cc
Merge branch 'main' into feature-New_for_hybrid
Nov 2, 2022
d15062e
Update to current main and indentation
Nov 3, 2022
f026cde
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Mar 20, 2023
c6d505e
Merge Clean-up
Mar 20, 2023
b95c49a
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Apr 13, 2023
104da7c
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Sep 25, 2023
7c90788
Add missing \ to Makefile
Davknapp Sep 25, 2023
ce05a7d
Update headers used in example
Davknapp Sep 25, 2023
4add0d6
Use hybrid_bounds algorithms
Davknapp Sep 25, 2023
18ebd66
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Oct 23, 2023
1ef18ed
WIP: Debugging cmesh_uniform_bounds_hybrid
Davknapp Oct 23, 2023
58892c8
Fix special cases for empty procs
lukasdreyer Oct 25, 2023
8ce611e
Reintroduce cmeshes with pyramids
lukasdreyer Oct 26, 2023
cbbb980
Fix number of vertices for pyramid cmesh
lukasdreyer Oct 26, 2023
4c26c2f
Fix compiler warnings
lukasdreyer Oct 26, 2023
255fea7
Fix more compiler errors
lukasdreyer Oct 26, 2023
a8314dc
Clean-up
Davknapp Oct 26, 2023
7b22fa0
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Oct 26, 2023
1a2fbef
Added comment to refinement criterion
Davknapp Nov 13, 2023
69fdaf0
Explain formulas in adapt-criterion
Davknapp Nov 13, 2023
916cfdf
Comment adaptation criterion
Davknapp Nov 13, 2023
6cda8b8
Add description
Davknapp Nov 13, 2023
f71b9d1
Update description
Davknapp Nov 13, 2023
2402031
Comment and clean up
Davknapp Nov 13, 2023
2ce5b2c
Apply suggestions from code review
Davknapp Nov 13, 2023
49fb50c
WIP: Minimize example
Davknapp Nov 14, 2023
b2f81b9
Added description to t8_cmesh_uniform_bounds_hybrid
Davknapp Nov 16, 2023
800b716
More const
Davknapp Nov 16, 2023
bf2ca8d
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Nov 16, 2023
a49cbc8
Merge
Davknapp Jan 26, 2024
408954d
Rename function, add assertion
Davknapp Jan 26, 2024
d0539e6
refactor function
Davknapp Jan 26, 2024
69aae13
Apply suggestions from code review
Davknapp Jan 29, 2024
229a1dc
Indentation
Davknapp Jan 29, 2024
f7abc12
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Feb 13, 2024
cf728e8
Resolve merge errors
Davknapp Feb 13, 2024
b92817d
Typo fix
Davknapp Feb 13, 2024
fa967f6
Rename t8_cmesh_uniform_bounds_hybrid
Davknapp Feb 13, 2024
294f50c
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Feb 14, 2024
f8b39d5
Remove comment
Davknapp Feb 14, 2024
ce649eb
Update to main
Davknapp Feb 14, 2024
ef97012
Clean-up
Davknapp Feb 14, 2024
24ca4e9
Simplification of determining send_first
Davknapp Feb 14, 2024
e78a262
break off uniform_bound_from_partition
Davknapp Feb 14, 2024
1cddf65
Seperate sending start message
Davknapp Feb 14, 2024
6ab9dfa
update cmesh_bounds_send_start
Davknapp Feb 15, 2024
1a6df19
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Feb 15, 2024
14af446
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Apr 2, 2024
27da81d
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp Apr 4, 2024
621969d
Merge remote-tracking branch 'origin/main' into feature-New_for_hybrid
Davknapp May 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions example/cmesh/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ bin_PROGRAMS += \
example/cmesh/t8_cmesh_partition \
example/cmesh/t8_cmesh_create_partitioned \
example/cmesh/t8_cmesh_refine \
example/cmesh/t8_cmesh_hybrid_new \
example/cmesh/t8_cmesh_set_join_by_vertices \
example/cmesh/t8_cmesh_geometry_examples \
example/cmesh/t8_cmesh_hypercube_pad
Expand All @@ -15,4 +16,6 @@ example_cmesh_t8_cmesh_refine_SOURCES = example/cmesh/t8_cmesh_refine.cxx
example_cmesh_t8_cmesh_set_join_by_vertices_SOURCES = example/cmesh/t8_cmesh_set_join_by_vertices.cxx
example_cmesh_t8_cmesh_geometry_examples_SOURCES = example/cmesh/t8_cmesh_geometry_examples.cxx
example_cmesh_t8_cmesh_create_partitioned_SOURCES = example/cmesh/t8_cmesh_create_partitioned.cxx
example_cmesh_t8_cmesh_hybrid_new_SOURCES = example/cmesh/t8_cmesh_hybrid_new.cxx
example_cmesh_t8_cmesh_hypercube_pad_SOURCES = example/cmesh/t8_cmesh_hypercube_pad.cxx

244 changes: 244 additions & 0 deletions example/cmesh/t8_cmesh_hybrid_new.cxx
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add a comment to the file what this example demonstrates.

Copy link
Collaborator

Choose a reason for hiding this comment

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

still open

Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
This file is part of t8code.
t8code is a C library to manage a collection (a forest) of multiple
connected adaptive space-trees of general element types in parallel.

Copyright (C) 2015 the developers

t8code is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

t8code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with t8code; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

#include <sc_options.h>
#include <sc_flops.h>
#include <sc_refcount.h>
#include <t8_schemes/t8_default/t8_default_cxx.hxx>
#include <t8_schemes/t8_default/t8_default_tet/t8_dtet.h>
#include <t8_schemes/t8_default/t8_default_prism/t8_dprism.h>
#include <t8_schemes/t8_default/t8_default_pyramid/t8_dpyramid.h>
#include <t8_forest/t8_forest.h>
#include <t8_cmesh/t8_cmesh_examples.h>
#include <t8_cmesh/t8_cmesh_partition.h>
#include <t8_cmesh_readmshfile.h>
#include <t8_cmesh_vtk_writer.h>
#include <sc_statistics.h>

holke marked this conversation as resolved.
Show resolved Hide resolved
/**
* Adaptation criterion for a forest containing hexahedra, tetrahedra, prisms and/or pryramids.
* Refines every second element, except for pyramids.
* Refines every pyramid
*
* \param [in] forest the forest
* \param [in] forest_from
* \param [in] which_tree The local id of the tree
* \param [in] lelement_id the local id of the element
* \param [in] ts the scheme to use
* \param [in] is_family flag, if the \a elements form a family
* \param [in] num_elements number of elements
* \param [in] elements A single element or a collection of \a num_elements
* \return int
*/
static int
t8_basic_hybrid_refine (t8_forest_t forest, t8_forest_t forest_from, t8_locidx_t which_tree, t8_locidx_t lelement_id,
t8_eclass_scheme_c *ts, int is_family, int num_elements, t8_element_t *elements[])
{
int level, id;
/*If the level is equal or higher than given by the user do not refine*/
level = ts->t8_element_level (elements[0]);
if (level >= *(int *) t8_forest_get_user_data (forest)) {
return 0;
}
else {
/*Refine every second element */
switch (ts->t8_element_shape (elements[0])) {
case T8_ECLASS_HEX:
id = ts->t8_element_child_id (elements[0]);
return id % 2 == 0 ? 1 : 0;
case T8_ECLASS_TET:
id = ts->t8_element_child_id (elements[0]);
return id % 2 == 0 ? 1 : 0;
case T8_ECLASS_PRISM:
id = ts->t8_element_child_id (elements[0]);
return id % 2 == 0 ? 1 : 0;
holke marked this conversation as resolved.
Show resolved Hide resolved
case T8_ECLASS_PYRAMID:
/* Refine every element. */
return 1;
default:
return 1;
}
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Comment what this function does.

/**
* Creates a cmesh and forest using this cmesh and times all high-level algorithms (new, adapt, ghost, partition, ...)
Davknapp marked this conversation as resolved.
Show resolved Hide resolved
*
* \param[in] level The initial level of forest
* \param[in] endlvl The maximal level of the forest
* \param[in] do_vtk Flag, if vtk-output should be produced
*/
static void
Copy link
Collaborator

Choose a reason for hiding this comment

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

This function seems very long and full of features.
Are they all necessary to demonstrate the hybrid_new function?
Can we shorten this function or write a shorter example?

Copy link
Collaborator

Choose a reason for hiding this comment

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

For example: Do we really need a switch for cmesh partition or can we just stick to one mode in this example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I slimmed down the example

t8_basic_hybrid (const int level, int endlvl, const int do_vtk)
{
/* Create and initialize timing stats */
sc_statinfo_t times[6];
sc_stats_init (&times[0], "new");
sc_stats_init (&times[1], "adapt");
sc_stats_init (&times[2], "ghost");
sc_stats_init (&times[3], "partition");
sc_stats_init (&times[4], "total");
double total_time = -sc_MPI_Wtime ();

t8_cmesh_t cmesh;
/* Create the cmesh */
t8_global_productionf ("Constructing full hybrid mesh.\n");
cmesh = t8_cmesh_new_full_hybrid (sc_MPI_COMM_WORLD);

/* Partition the cmesh */
t8_cmesh_t cmesh_partition;
t8_cmesh_init (&cmesh_partition);
t8_cmesh_set_derive (cmesh_partition, cmesh);
t8_cmesh_set_partition_uniform (cmesh_partition, level, t8_scheme_new_default_cxx ());
t8_cmesh_commit (cmesh_partition, sc_MPI_COMM_WORLD);
cmesh = cmesh_partition;

/* Save the cmesh and create vtk output if the flag is set. */
char vtuname[BUFSIZ];
char cmesh_file[BUFSIZ];
snprintf (cmesh_file, BUFSIZ, "cmesh_hybrid");
snprintf (vtuname, BUFSIZ, "cmesh_hybrid");
t8_cmesh_save (cmesh, cmesh_file);
if (t8_cmesh_vtk_write_file (cmesh, vtuname, 1.0) == 0) {
t8_debugf ("Output to %s\n", vtuname);
}
else {
t8_debugf ("Error in output\n");
}

/* Create the forest and measure the time needed for the initial refinement*/
t8_forest_t forest;
t8_forest_init (&forest);
t8_forest_set_profiling (forest, 1);
t8_forest_set_cmesh (forest, cmesh, sc_MPI_COMM_WORLD);
t8_forest_set_scheme (forest, t8_scheme_new_default_cxx ());
t8_forest_set_level (forest, level);
double new_time = -sc_MPI_Wtime ();
t8_forest_commit (forest);
new_time += sc_MPI_Wtime ();

if (do_vtk) {
/* write the initially refined forest into a vtu-file*/
snprintf (vtuname, BUFSIZ, "forest_hybrid");
t8_forest_write_vtk (forest, vtuname);
}

/* Initialize the adapted forest*/
t8_forest_t forest_adapt;
t8_forest_init (&forest_adapt);
t8_forest_set_user_data (forest_adapt, &endlvl);
t8_forest_set_profiling (forest_adapt, 1);

/* Set the adaptation criterion to use. */
t8_forest_set_adapt (forest_adapt, forest, t8_basic_hybrid_refine, 1);

/* Measure the time needed to adapt */
double adapt_time = -sc_MPI_Wtime ();
t8_forest_commit (forest_adapt);
adapt_time += sc_MPI_Wtime ();

/* Initialize the partitioned forest */
t8_forest_t forest_partition;
t8_forest_init (&forest_partition);
t8_forest_set_partition (forest_partition, forest_adapt, 0);

/* We want to compute the ghosts, too */
t8_forest_set_ghost (forest_partition, 1, T8_GHOST_FACES);
/* Use the profiling algorithm to measure the time needed and also how many ghost elements are sent,
* how many procs we sent to and how many rounds we need to balance the forest. */
t8_forest_set_profiling (forest_partition, 1);
t8_forest_commit (forest_partition);

/* Write vtk-output*/
if (do_vtk) {
snprintf (vtuname, BUFSIZ, "forest_hybrid_partition");
t8_forest_write_vtk (forest_partition, vtuname);
}
total_time += sc_MPI_Wtime ();
int procs_sent; /* Procs we sent to during forest_partition */
t8_locidx_t ghost_sent; /* Number of ghost-elements we sent */
t8_forest_print_profile (forest_partition);
const double partition_time = t8_forest_profile_get_partition_time (forest_partition, &procs_sent);
const double ghost_time = t8_forest_profile_get_ghost_time (forest_partition, &ghost_sent);

/* Accumulate the timings over all procs and print the stats */
sc_stats_accumulate (&times[0], new_time);
sc_stats_accumulate (&times[1], adapt_time);
sc_stats_accumulate (&times[2], ghost_time);
sc_stats_accumulate (&times[3], partition_time);
sc_stats_accumulate (&times[4], total_time);
sc_stats_compute (sc_MPI_COMM_WORLD, 5, times);
sc_stats_print (t8_get_package_id (), SC_LP_ESSENTIAL, 5, times, 1, 1);

t8_forest_unref (&forest_partition);
}

int
main (int argc, char **argv)
{
int level;
int endlvl;
int helpme;
int do_vtk;
sc_options_t *opt;
char help[BUFSIZ];

/* long help message */
snprintf (help, BUFSIZ,
"ADD EXAMPLE DESCRIPTION.\n\n"
"Usage:\t%s <OPTIONS>\n\t%s -h\t"
"for a brief overview of all options.\n",
basename (argv[0]), basename (argv[0]));
int mpiret = sc_MPI_Init (&argc, &argv);
SC_CHECK_MPI (mpiret);

sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL);
t8_init (SC_LP_DEFAULT);

opt = sc_options_new (argv[0]);
sc_options_add_switch (opt, 'h', "help", &helpme, "Display a short help message.");
sc_options_add_int (opt, 'l', "level", &level, 0, "The refinement level of the mesh.");
sc_options_add_int (opt, 'f', "final-level", &endlvl, 1, "The final refinement level of the mesh.");
sc_options_add_switch (opt, 'v', "vtk", &do_vtk, "Enable vtk-output.");

const int parsed = sc_options_parse (t8_get_package_id (), SC_LP_DEFAULT, opt, argc, argv);
if (helpme) {
/* display help message and usage */
t8_global_productionf ("%s\n", help);
sc_options_print_usage (t8_get_package_id (), SC_LP_ERROR, opt, NULL);
}
else if (parsed >= 0 && 0 <= level) {
t8_basic_hybrid (level, endlvl, do_vtk);
}
else {
/* wrong usage */
t8_global_productionf ("\n\t ERROR: Wrong usage.\n\n");
sc_options_print_usage (t8_get_package_id (), SC_LP_ERROR, opt, NULL);
}
sc_options_destroy (opt);
sc_finalize ();

mpiret = sc_MPI_Finalize ();
SC_CHECK_MPI (mpiret);

return 0;
}
7 changes: 7 additions & 0 deletions src/t8.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,10 @@ t8_sc_array_index_locidx (const sc_array_t *array, const t8_locidx_t it)

return array->array + array->elem_size * (size_t) it;
}

void *
t8_sc_array_index_gloidx (const sc_array_t *array, const t8_gloidx_t it)
{
T8_ASSERT (it >= 0 && (size_t) it < array->elem_count);
return array->array + array->elem_size * (size_t) it;
}
11 changes: 11 additions & 0 deletions src/t8.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ typedef int64_t t8_gloidx_t;
#define T8_MPI_GLOIDX sc_MPI_LONG_LONG_INT
/** Macro to get the absolute value of a t8_gloidx_t */
#define T8_GLOIDX_ABS(x) ((t8_gloidx_t) llabs ((long long) (x)))
/** Maximum possible value of a t8_gloidx_t*/
#define T8_GLOIDX_MAX INT64_MAX
/** Comparison function for t8_gloidx_t */
#define t8_compare_gloidx(v, w) sc_int64_compare (v, w)

Expand Down Expand Up @@ -129,6 +131,8 @@ typedef enum {
T8_MPI_PARTITION_FOREST, /**< Used for forest partitioning */
T8_MPI_GHOST_FOREST, /**< Used for for ghost layer creation */
T8_MPI_GHOST_EXC_FOREST, /**< Used for ghost data exchange */
T8_MPI_CMESH_UNIFORM_BOUNDS_START, /**< Used for cmesh uniform bounds computation. */
T8_MPI_CMESH_UNIFORM_BOUNDS_END, /**< Used for cmesh uniform bounds computation. */
T8_MPI_TAG_LAST
} t8_MPI_tag_t;

Expand Down Expand Up @@ -266,6 +270,13 @@ t8_init (int log_threshold);
void *
t8_sc_array_index_locidx (const sc_array_t *array, const t8_locidx_t it);

/** Return a pointer to an array element indexed by a t8_gloidx_t.
* \param [in] index needs to be in [0]..[elem_count-1].
* \return A void * pointing to entry \a it in \a array.
*/
void *
t8_sc_array_index_gloidx (const sc_array_t *array, const t8_gloidx_t it);

/* call this at the end of a header file to match T8_EXTERN_C_BEGIN (). */
T8_EXTERN_C_END ();

Expand Down
26 changes: 25 additions & 1 deletion src/t8_cmesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -668,13 +668,37 @@ t8_cmesh_get_partition_table (t8_cmesh_t cmesh);
* the calling processor anymore. Not computed if NULL.
* \param [out] first_tree_shared If not NULL, 1 or 0 is stored here depending on whether \a first_local_tree is the
* same as \a last_local_tree on the next process.
* \a cmesh must be committed before calling this function. *
* \a cmesh must be committed before calling this function.
*/
void
t8_cmesh_uniform_bounds (t8_cmesh_t cmesh, int level, t8_scheme_cxx_t *ts, t8_gloidx_t *first_local_tree,
t8_gloidx_t *child_in_tree_begin, t8_gloidx_t *last_local_tree, t8_gloidx_t *child_in_tree_end,
int8_t *first_tree_shared);

/**
* Calculate the section of a uniform hybrid forest for the current rank. Need for hybrid meshes, especially
* meshes where not all elements refine into 1:2^dim manner. The section is calculated without assuming such refinement
* and each process computes its number of elements on the given \var level communicates the number to other processes
* and the correct section is computed based on this information.
*
* \param [in] cmesh The cmesh to be considered.
* \param [in] level The uniform refinement level to be created.
* \param [in] scheme The element scheme for which to compute the bounds.
* \param [out] first_local_tree The global index of the first tree that contains elements belonging to the calling processor.
* \param [out] child_in_tree_begin The global index of the first element belonging to the calling processor. Not computed if NULL.
* \param [out] last_local_tree The global index of the last tree that contains elements belonging to the calling processor.
* \param [out] child_in_tree_end The global index of the first element that does not belonging to
* the calling processor anymore. Not computed if NULL.
* \param [out] first_tree_shared If not NULL, 1 or 0 is stored here depending on whether \a first_local_tree is the
* same as \a last_local_tree on the next process.
Copy link
Collaborator

@holke holke Nov 10, 2023

Choose a reason for hiding this comment

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

I am confused. Need to double check the comment regarding first_tree_shared.
Should it be "same as last_local_tree on the previous process"?
If so, then needs correction in the original uniform_bounds as well.

* \param [in] comm The communicator
*/
holke marked this conversation as resolved.
Show resolved Hide resolved
void
t8_cmesh_uniform_bounds_hybrid (const t8_cmesh_t cmesh, const int level, const t8_scheme_cxx_t *scheme,
Copy link
Collaborator

Choose a reason for hiding this comment

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

we agreed to change the name, since the old version can also be used for hybrid schemes.

t8_gloidx_t *first_local_tree, t8_gloidx_t *child_in_tree_begin,
t8_gloidx_t *last_local_tree, t8_gloidx_t *child_in_tree_end, int8_t *first_tree_shared,
sc_MPI_Comm comm);

/** Increase the reference counter of a cmesh.
* \param [in,out] cmesh On input, this cmesh must exist with positive
* reference count. It may be in any state.
Expand Down
Loading
Loading