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

update number of the corner of the second vertex #977

Merged
merged 19 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 10 additions & 10 deletions example/cmesh/t8_cmesh_hypercube_pad.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,18 @@
#include <t8_cmesh.h>
#include <t8_cmesh_vtk_writer.h>
#include <t8_cmesh/t8_cmesh_examples.h>

#include <t8_schemes/t8_default/t8_default_cxx.hxx>
#include <t8_forest/t8_forest_general.h>
#include <t8_forest/t8_forest_vtk.h>
int
main (int argc, char **argv)
{
/* The prefix for our output files. */
const char prefix[BUFSIZ] = "t8_cmesh_hypercube_pad";
const char prefix[BUFSIZ] = "t8_forest_hypercube_pad";
t8_locidx_t local_num_trees;
t8_gloidx_t global_num_trees;

const double boundary_coords[24] = { 1, 0, 0, 4, 0, 0, 0, 6, 0, 5, 5, 0, -1, -2, 8, 9, 0, 10, 0, 8, 9, 10, 10, 10 };

const double boundary_coords[24] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1 };
/* Initialize MPI. This has to happen before we initialize sc or t8code. */
int mpiret = sc_MPI_Init (&argc, &argv);
/* Error check the MPI return value. */
Expand All @@ -44,20 +45,19 @@ main (int argc, char **argv)
sc_init (sc_MPI_COMM_WORLD, 1, 1, NULL, SC_LP_ESSENTIAL);
/* Initialize t8code with log level SC_LP_PRODUCTION. See sc.h for more info on the log levels. */
t8_init (SC_LP_PRODUCTION);

/* Add hypercube with given element class. */
t8_cmesh_t cmesh = t8_cmesh_new_hypercube_pad (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, boundary_coords, 3, 3, 3, 0);
t8_cmesh_t cmesh = t8_cmesh_new_hypercube_pad (T8_ECLASS_HEX, sc_MPI_COMM_WORLD, boundary_coords, 3, 3, 3, true);

/* Compute local and global number of trees. */
local_num_trees = t8_cmesh_get_num_local_trees (cmesh);
global_num_trees = t8_cmesh_get_num_trees (cmesh);
t8_global_productionf (" [step1] Created coarse mesh.\n");
t8_global_productionf (" [step1] Local number of trees:\t%i\n", local_num_trees);
t8_global_productionf (" [step1] Global number of trees:\t%li\n", global_num_trees);

t8_cmesh_vtk_write_file (cmesh, prefix);

t8_cmesh_destroy (&cmesh);
t8_scheme_cxx *scheme = t8_scheme_new_default_cxx ();
t8_forest_t forest = t8_forest_new_uniform (cmesh, scheme, 0, 0, sc_MPI_COMM_WORLD);
t8_forest_vtk_write_file (forest, prefix, 1, 1, 1, 1, 0, 0, NULL);
t8_forest_unref (&forest);

sc_finalize ();

Expand Down
2 changes: 1 addition & 1 deletion src/t8_geometry/t8_geometry_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ t8_geom_compute_linear_axis_aligned_geometry (t8_eclass_t tree_class, const doub
const size_t offset_domain_dim = i_coord * T8_ECLASS_MAX_DIM;
for (int i_dim = 0; i_dim < T8_ECLASS_MAX_DIM; ++i_dim) {
out_coords[offset_domain_dim + i_dim] = tree_vertices[i_dim];
out_coords[offset_domain_dim + i_dim] += ref_coords[offset_tree_dim] * vector[i_dim];
out_coords[offset_domain_dim + i_dim] += ref_coords[offset_tree_dim + i_dim] * vector[i_dim];
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,14 @@ t8_geometry_linear_axis_aligned::t8_geom_point_batch_inside_element (t8_forest_t
double v_min[3];
double v_max[3];

const t8_eclass_t elem_class = t8_forest_get_tree_class (forest, ltreeid);
T8_ASSERT (elem_class == T8_ECLASS_LINE || elem_class == T8_ECLASS_HEX || elem_class == T8_ECLASS_QUAD);

const int max_corner_id = (elem_class == T8_ECLASS_LINE) ? 1 : (elem_class == T8_ECLASS_QUAD) ? 3 : 7;

/*Geometry is fully described by v_min and v_max*/
t8_forest_element_coordinate (forest, ltreeid, element, 0, v_min);
t8_forest_element_coordinate (forest, ltreeid, element, 1, v_max);
t8_forest_element_coordinate (forest, ltreeid, element, max_corner_id, v_max);
#if T8_ENABLE_DEBUG
const double coords[6] = { v_min[0], v_min[1], v_min[2], v_max[0], v_max[1], v_max[2] };
T8_ASSERT (correct_point_order (coords));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,88 +25,143 @@
*/

#include <test/t8_gtest_macros.hxx>
#include <test/t8_geometry/t8_gtest_geometry_macros.hxx>
#include <test/t8_gtest_custom_assertion.hxx>
#include <gtest/gtest.h>
#include <t8_eclass.h>
#include <t8_cmesh.hxx>
#include <t8_cmesh/t8_cmesh_examples.h>
#include <t8_geometry/t8_geometry.h>
#include <t8_geometry/t8_geometry_implementations/t8_geometry_linear.hxx>
#include <t8_geometry/t8_geometry_implementations/t8_geometry_linear_axis_aligned.hxx>
#include <t8_element.h>

t8_cmesh_t
t8_geometry_testing_tree_from_class (const t8_eclass_t eclass)
{
t8_cmesh_t cmesh;
t8_cmesh_init (&cmesh);
const int num_vertices = t8_eclass_num_vertices[eclass];
double *vertices = T8_ALLOC (double, T8_ECLASS_MAX_DIM *num_vertices);
for (int i_vertex = 0; i_vertex < num_vertices; ++i_vertex) {
for (int dim = 0; dim < T8_ECLASS_MAX_DIM; ++dim) {
vertices[i_vertex * T8_ECLASS_MAX_DIM + dim] = t8_element_corner_ref_coords[eclass][i_vertex][dim];
class geometry_test: public testing::TestWithParam<std::tuple<int, t8_eclass>> {
public:
static void
SetUpTestSuite ()
{
seed = time (NULL); /* RNG seed */
}
static int seed;

protected:
void
SetUp () override
{
const int geom_int = std::get<0> (GetParam ());
eclass = std::get<1> (GetParam ());
t8_cmesh_init (&cmesh);
if (geom_int == T8_GEOMETRY_TYPE_LINEAR_AXIS_ALIGNED
&& !(eclass == T8_ECLASS_LINE || eclass == T8_ECLASS_QUAD || eclass == T8_ECLASS_HEX)) {
GTEST_SKIP ();
}
lukasdreyer marked this conversation as resolved.
Show resolved Hide resolved

const int num_vertices = t8_eclass_num_vertices[eclass];
t8_cmesh_set_tree_class (cmesh, 0, eclass);
double *vertices = T8_ALLOC_ZERO (double, num_vertices *T8_ECLASS_MAX_DIM);
for (int i_vertex = 0; i_vertex < num_vertices; ++i_vertex) {
for (int dim = 0; dim < T8_ECLASS_MAX_DIM; ++dim) {
vertices[i_vertex * T8_ECLASS_MAX_DIM + dim] = t8_element_corner_ref_coords[eclass][i_vertex][dim];
}
}
switch (geom_int) {
case T8_GEOMETRY_TYPE_LINEAR:
geom = new t8_geometry_linear (t8_eclass_to_dimension[eclass]);
t8_cmesh_register_geometry<t8_geometry_linear> (cmesh, t8_eclass_to_dimension[eclass]);
break;
case T8_GEOMETRY_TYPE_LINEAR_AXIS_ALIGNED:
geom = new t8_geometry_linear_axis_aligned (t8_eclass_to_dimension[eclass]);
/* Copy last vertex to the second position*/
vertices[3] = vertices[3 * (num_vertices - 1)];
vertices[4] = vertices[3 * (num_vertices - 1) + 1];
vertices[5] = vertices[3 * (num_vertices - 1) + 2];

t8_cmesh_register_geometry<t8_geometry_linear_axis_aligned> (cmesh, t8_eclass_to_dimension[eclass]);
break;
default:
break;
}
t8_cmesh_set_tree_vertices (cmesh, 0, vertices,
geom_int == T8_GEOMETRY_TYPE_LINEAR ? t8_eclass_num_vertices[eclass] : 2);
t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD);
T8_FREE (vertices);
}
t8_cmesh_set_tree_class (cmesh, 0, eclass);
t8_cmesh_register_geometry<t8_geometry_linear> (cmesh, t8_eclass_to_dimension[eclass]);
t8_cmesh_set_tree_vertices (cmesh, 0, vertices, t8_eclass_num_vertices[eclass]);
t8_cmesh_commit (cmesh, sc_MPI_COMM_WORLD);
T8_FREE (vertices);
return cmesh;
}
void
TearDown () override
{
t8_cmesh_unref (&cmesh);
}
t8_eclass_t eclass;
t8_geometry_with_vertices *geom;
t8_cmesh_t cmesh;
#ifdef T8_ENABLE_LESS_TESTS
const int num_points = 1000;
#else
const int num_points = 10000;
#endif
};

/* Check whether the linear geometry map is correct.
* We create a cmesh of one tree and unit element
int geometry_test::seed;

/* Check whether the linear axis aligned geometry map is correct.
* We create a cmesh of one tree and unit line, quad or hex
* geometry. We then create random points in a reference tree and
* check whether the evaluation is correct. */
TEST_P (geometry_test, cmesh_geometry_linear)
TEST_P (geometry_test, cmesh_geometry)
{
/* TODO: Add a test for the jacobian, as soon as its implemented. */

t8_debugf ("Testing linear geometry evaluation.\n");

/* Create random points in [0,1]^d and check if they are mapped correctly. */
t8_geometry_linear linear_geom (t8_eclass_to_dimension[eclass]);
t8_cmesh_t cmesh;

double point[3];
double point_mapped[3];
const int seed = 0; /* RNG seed */
const t8_geometry_c *cmesh_geom;

cmesh = t8_geometry_testing_tree_from_class (eclass);

/* Double check that the geometry is the linear geometry. */
/* Double check that the geometry is the linear axis aligned geometry. */
cmesh_geom = t8_cmesh_get_tree_geometry (cmesh, 0);
ASSERT_TRUE (cmesh_geom != NULL) << "Could not get cmesh's geometry.";
int has_same_name = cmesh_geom->t8_geom_get_name () == linear_geom.t8_geom_get_name ();
ASSERT_EQ (has_same_name, 1) << "cmesh's geometry is not the linear geometry.";
ASSERT_EQ (cmesh_geom->t8_geom_get_hash (), geom->t8_geom_get_hash ())
<< "cmesh's geometry is not the expected geometry.";

srand (seed);
for (int ipoint = 0; ipoint < num_points; ++ipoint) {
double point[3] = { 0 };
/* Compute random coordinates in [0,1].
* These are seen as reference coordinates in the single
* cmesh tree. Our geometry will map them into the physical
* space. Since this space is also [0,1] and the cmesh only
* has one tree, the mapped coordinates must be the same as the
* reference coordinates. */
point[0] = (double) rand () / RAND_MAX;
point[1] = (double) rand () / RAND_MAX;
point[2] = (double) rand () / RAND_MAX;
for (int idim = 0; idim < t8_eclass_to_dimension[eclass]; ++idim) {
point[idim] = (double) rand () / RAND_MAX;
}

/* Evaluate the geometry */
t8_geometry_evaluate (cmesh, 0, point, 1, point_mapped);
/* Check that the first dim coordinates are the same */
int idim;
for (idim = 0; idim < t8_eclass_to_dimension[eclass]; ++idim) {
ASSERT_NEAR (point[idim], point_mapped[idim], T8_PRECISION_SQRT_EPS) << "Linear geometry computed wrong value.";
}
/* Check that the remaining entries are 0. */
for (; idim < 3; ++idim) {
ASSERT_EQ (point_mapped[idim], 0) << "Linear geometry computed wrong value.";
}
EXPECT_VEC3_EQ (point, point_mapped, T8_PRECISION_SQRT_EPS);
}
/* Destroy the cmesh */
t8_cmesh_destroy (&cmesh);
}

INSTANTIATE_TEST_SUITE_P (t8_gtest_geometry, geometry_test, AllEclasses);
auto print_test = [] (const testing::TestParamInfo<std::tuple<int, t8_eclass>> &info) {
std::string name;
const int geom_int = std::get<0> (info.param);
const t8_eclass_t eclass = std::get<1> (info.param);
switch (geom_int) {
case T8_GEOMETRY_TYPE_LINEAR:
name = std::string ("linear_geometry_");
break;
case T8_GEOMETRY_TYPE_LINEAR_AXIS_ALIGNED:
name = std::string ("linear_axis_aligned_geometry_");
break;
default:
name = std::string ("geometry_not_allowed_");
break;
}
name += std::string (t8_eclass_to_string[eclass]);
return name;
};

INSTANTIATE_TEST_SUITE_P (
t8_gtest_geometry, geometry_test,
::testing::Combine (::testing::Values (T8_GEOMETRY_TYPE_LINEAR, T8_GEOMETRY_TYPE_LINEAR_AXIS_ALIGNED), AllEclasses),
print_test);
47 changes: 0 additions & 47 deletions test/t8_geometry/t8_gtest_geometry_macros.hxx
Original file line number Diff line number Diff line change
@@ -1,47 +0,0 @@
/*
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 classes in parallel.

Copyright (C) 2024 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.
*/

/** \file t8_gtest_geometry_macros.hxx
* This file contains macros and base classes for geometry tests.
*/

#include <gtest/gtest.h>
#include <t8_eclass.h>

class geometry_test: public testing::TestWithParam<t8_eclass_t> {
protected:
void
SetUp () override
{
eclass = GetParam ();
}
void
TearDown () override
{
}
t8_eclass_t eclass;
#ifdef T8_ENABLE_LESS_TESTS
const int num_points = 1000;
#else
const int num_points = 10000;
#endif
};
17 changes: 14 additions & 3 deletions test/t8_geometry/t8_gtest_point_inside.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -251,10 +251,12 @@ TEST_P (geometry_point_inside, test_point_inside)
num_steps = 2;
}
/* Corrected number of points due to possible rounding errors in pow */
const int min_points_outside = 6;
const int num_points = sc_intpow (num_steps, num_corners - 1);
double *test_point = T8_ALLOC_ZERO (double, num_points * 3);
int *point_is_inside = T8_ALLOC (int, num_points);
int *point_is_recognized_as_inside = T8_ALLOC (int, num_points);
const int total_points = num_points + min_points_outside;
double *test_point = T8_ALLOC_ZERO (double, total_points * 3);
int *point_is_inside = T8_ALLOC (int, total_points);
int *point_is_recognized_as_inside = T8_ALLOC (int, total_points);
double step = (barycentric_range_upper_bound - barycentric_range_lower_bound) / (num_steps - 1);
//t8_debugf ("step size %g, steps %i, points %i (corners %i)\n", step,
// num_steps, num_points, num_corners);
Expand Down Expand Up @@ -301,6 +303,15 @@ TEST_P (geometry_point_inside, test_point_inside)

num_in += point_is_inside ? 1 : 0;
}
/* Create a set of points that are outside of the cube.
* The coordinates are given by the corner points except for one coordinate. For each side of the cube
* we place one point outside of it. */
for (int side = 0; side < min_points_outside; ++side) {
test_point[3 * (num_points + side)] = (side == 0) ? -2.0 : (side == 1) ? 2.0 : -0.1;
test_point[3 * (num_points + side) + 1] = (side == 2) ? -2.0 : (side == 3) ? 2.0 : 0.3;
test_point[3 * (num_points + side) + 2] = (side == 4) ? -2.0 : (side == 5) ? 2.0 : 0.15;
point_is_inside[num_points + side] = false;
}
Davknapp marked this conversation as resolved.
Show resolved Hide resolved
/* We now check whether the point inside function correctly sees whether
* the point is inside the element or not. */
t8_forest_element_points_inside (forest, 0, element, test_point, num_points, point_is_recognized_as_inside,
Expand Down