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 point_is_in_domain function #5509

Merged
merged 22 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
59 changes: 52 additions & 7 deletions source/geometry_model/box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <aspect/geometry_model/box.h>
#include <aspect/geometry_model/initial_topography_model/zero_topography.h>
#include <aspect/mesh_deformation/interface.h>
#include <aspect/simulator_signals.h>

#include <deal.II/grid/grid_generator.h>
Expand Down Expand Up @@ -316,16 +317,60 @@ namespace aspect
bool
Box<dim>::point_is_in_domain(const Point<dim> &point) const
{
AssertThrow(!this->get_parameters().mesh_deformation_enabled ||
this->simulator_is_past_initialization() == false,
ExcMessage("After displacement of the free surface, this function can no longer be used to determine whether a point lies in the domain or not."));
// If mesh deformation occurs over time, and we're past the
// first timestep (during which no mesh deformation is applied),
// we can no longer use the original extents of the model domain
// to check whether the point lies in the domain.
// Initial mesh deformation is applied during the first
// timestep, but this function might be called before the
// simulator is initialized and thus before we can ask whether initial
// or time-dependent mesh deformation is applied.
// Therefore, when any mesh deformation is enabled,
// we loop over all the current grid cells to see if the point
// lies within the domain.
// Do note that this function can be called before mesh deformation
// is applied in the first timestep, and therefore there is no guarantee
// that the point will lie in the domain after initial mesh deformation.
// For example, boundary traction plugins are initialized before
// mesh deformation plugins and the initial_lithostatic_pressure
// plugin calls this function while the simulator is being initialized.
// However, if the simulator has not been initialized,
// no mesh deformation has been applied and we can use the geometry model's
// extents to check whether a point lies in the domain.
anne-glerum marked this conversation as resolved.
Show resolved Hide resolved
if (this->get_parameters().mesh_deformation_enabled &&
this->simulator_is_past_initialization())
{
std::pair<const typename parallel::distributed::Triangulation<dim>::active_cell_iterator,
Point<dim>> it =
GridTools::find_active_cell_around_point<> (this->get_mapping(), this->get_triangulation(), point);
anne-glerum marked this conversation as resolved.
Show resolved Hide resolved

if (it.first.state() == IteratorState::valid)
return true;
else
return false;
}

// The maximal extents of the unperturbed box domain.
anne-glerum marked this conversation as resolved.
Show resolved Hide resolved
Point<dim> max_point = extents+box_origin;

AssertThrow(Plugins::plugin_type_matches<const InitialTopographyModel::ZeroTopography<dim>>(this->get_initial_topography_model()),
ExcMessage("After adding topography, this function can no longer be used "
"to determine whether a point lies in the domain or not."));
// If mesh deformation is not enabled, but initial topography
// was/will be applied to the mesh, include this topography in the
// extent of the domain.
if (!Plugins::plugin_type_matches<const InitialTopographyModel::ZeroTopography<dim>>(this->get_initial_topography_model()))
{
// Get the surface x (,y) point
Point<dim-1> surface_point;
for (unsigned int d=0; d<dim-1; ++d)
surface_point[d] = point[d];

// Get the surface topography at this point
const double topo = topo_model->value(surface_point);
max_point[dim-1] += topo;
}

// Check whether point lies within the min/max coordinates of the domain including initial topography.
for (unsigned int d = 0; d < dim; ++d)
if (point[d] > extents[d]+box_origin[d]+std::numeric_limits<double>::epsilon()*extents[d] ||
if (point[d] > max_point[d]+std::numeric_limits<double>::epsilon()*extents[d] ||
point[d] < box_origin[d]-std::numeric_limits<double>::epsilon()*extents[d])
return false;

Expand Down
26 changes: 19 additions & 7 deletions source/geometry_model/chunk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -697,13 +697,25 @@ namespace aspect
bool
Chunk<dim>::point_is_in_domain(const Point<dim> &point) const
{
AssertThrow(!this->get_parameters().mesh_deformation_enabled ||
this->simulator_is_past_initialization() == false,
ExcMessage("After displacement of the free surface, this function can no longer be used to determine whether a point lies in the domain or not."));

AssertThrow(Plugins::plugin_type_matches<const InitialTopographyModel::ZeroTopography<dim>>(this->get_initial_topography_model()),
ExcMessage("After adding topography, this function can no longer be used to determine whether a point lies in the domain or not."));

// If mesh deformation has possibly been applied,
// e.g. initial mesh deformation after the simulator
// has been initialized or time-dependent mesh deformation
// after timestep 0, we cannot use information from the
// geometry model to determine whether the point lies in
// the model domain. Instead, we loop over all cells
// to check whether the point lies in one of them.
anne-glerum marked this conversation as resolved.
Show resolved Hide resolved
if (this->get_parameters().mesh_deformation_enabled &&
this->simulator_is_past_initialization())
{
std::pair<const typename parallel::distributed::Triangulation<dim>::active_cell_iterator,
Point<dim>> it =
GridTools::find_active_cell_around_point<> (this->get_mapping(), this->get_triangulation(), point);

if (it.first.state() == IteratorState::valid)
return true;
else
return false;
}
const Point<dim> spherical_point = manifold->pull_back(point);

for (unsigned int d = 0; d < dim; ++d)
Expand Down
76 changes: 76 additions & 0 deletions tests/airy_isostasy_initial_topo.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
Copyright (C) 2022 by the authors of the ASPECT code.

This file is part of ASPECT.

ASPECT 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, or (at your option)
any later version.

ASPECT 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 ASPECT; see the file LICENSE. If not see
<http://www.gnu.org/licenses/>.
*/

#include <aspect/postprocess/interface.h>
#include <aspect/simulator_access.h>


namespace aspect
{
namespace Postprocess
{
template <int dim>
class PointIsInDomain : public Interface<dim>, public ::aspect::SimulatorAccess<dim>
{
public:
virtual
std::pair<std::string,std::string>
execute (TableHandler &);
};
}
}


namespace aspect
{
namespace Postprocess
{
template <int dim>
std::pair<std::string,std::string>
PointIsInDomain<dim>::execute(TableHandler &)
{
// The airy isostasy box domain is 1x1 with max 0.05 topography.
const Point<dim> point_in_domain(0.1, 0.1);
const Point<dim> point_not_in_domain(0.1, 2.0);
const Point<dim> point_not_in_domain_2(2.0, 0.01);

std::ostringstream screen_text;
screen_text << std::boolalpha << this->get_geometry_model().point_is_in_domain(point_in_domain) ;
screen_text << std::boolalpha << this->get_geometry_model().point_is_in_domain(point_not_in_domain);
screen_text << std::boolalpha << this->get_geometry_model().point_is_in_domain(point_not_in_domain_2);

return std::pair<std::string, std::string> ("Points lie in domain: ",
screen_text.str());
}
}
}


// explicit instantiations
namespace aspect
{
namespace Postprocess
{
ASPECT_REGISTER_POSTPROCESSOR(PointIsInDomain,
"point is in domain",
"A postprocessor that tests whether certain points "
"lie within the domain.")
}
}
5 changes: 5 additions & 0 deletions tests/airy_isostasy_initial_topo.prm
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ subsection Boundary traction model
set Function expression = 0;10
end
end

# Also test the point_is_in_domain function of the geometry model.
subsection Postprocess
set List of postprocessors = velocity statistics, pressure statistics, topography, point is in domain
end
40 changes: 40 additions & 0 deletions tests/airy_isostasy_initial_topo_lithostatic_pressure.prm
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# We setup three columns, of which the middle column has a higher density
# and viscosity. By choosing a free surface in combination with a
# prescribed lithostatic pressure,
# we see the middle column sink until isostasy is reached (if end time is increased)
# Compared to airy_isostasy.prm, we start off with a nonzero initial topography.
# This test in particular tests the point_is_in_domain function of the geometry
# model. It should take into account the initial topography and find that the
# Representative point lies within the domain. At x = 0.2, the initial topography
# is namely 0.02948.

include $ASPECT_SOURCE_DIR/tests/airy_isostasy.prm

set Dimension = 2
# The point_is_in_domain function is only called in
# timestep 0, so we do not need to run the test further.
set End time = 0

subsection Geometry model
subsection Initial topography model
set Model name = function

subsection Function
set Function constants = L=1, R=0.05, C=0.5
set Function expression = R * cos(pi*(x-C)/(L))
set Maximum topography value = 0.05
end
end
end

# The representative point determines where the pressure
# profile is calculated. We pick a point in the left
# column which has some initial topography prescribed.
subsection Boundary traction model
set Prescribed traction boundary indicators = 2 y: initial lithostatic pressure

subsection Initial lithostatic pressure
set Number of integration points = 260
set Representative point = 0.2,1.02
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

Number of active cells: 1,024 (on 6 levels)
Number of degrees of freedom: 17,989 (8,450+1,089+4,225+4,225)

Number of mesh deformation degrees of freedom: 2,178
Solving mesh displacement system... 0 iterations.
*** Timestep 0: t=0 years, dt=0 years
Solving mesh displacement system... 0 iterations.
Skipping temperature solve because RHS is zero.
Solving C_1 system ... 0 iterations.
Rebuilding Stokes preconditioner...
Solving Stokes system... 200+8 iterations.

Number of active cells: 1,204 (on 7 levels)
Number of degrees of freedom: 21,360 (10,034+1,292+5,017+5,017)

Number of mesh deformation degrees of freedom: 2,584
Solving mesh displacement system... 0 iterations.
*** Timestep 0: t=0 years, dt=0 years
Solving mesh displacement system... 0 iterations.
Skipping temperature solve because RHS is zero.
Solving C_1 system ... 0 iterations.
Rebuilding Stokes preconditioner...
Solving Stokes system... 167+0 iterations.

Number of active cells: 1,948 (on 8 levels)
Number of degrees of freedom: 34,621 (16,270+2,081+8,135+8,135)

Number of mesh deformation degrees of freedom: 4,162
Solving mesh displacement system... 0 iterations.
*** Timestep 0: t=0 years, dt=0 years
Solving mesh displacement system... 0 iterations.
Skipping temperature solve because RHS is zero.
Solving C_1 system ... 0 iterations.
Rebuilding Stokes preconditioner...
Solving Stokes system... 200+6 iterations.

Postprocessing:
RMS, max velocity: 6.63e+05 m/year, 8.88e+05 m/year
Pressure min/avg/max: -0.6507 Pa, 5.005 Pa, 10 Pa
Topography min/max: 0 m, 0 m

Termination requested by criterion: end time



20 changes: 20 additions & 0 deletions tests/airy_isostasy_initial_topo_lithostatic_pressure/statistics
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 1: Time step number
# 2: Time (years)
# 3: Time step size (years)
# 4: Number of mesh cells
# 5: Number of Stokes degrees of freedom
# 6: Number of temperature degrees of freedom
# 7: Number of degrees of freedom for all compositions
# 8: Iterations for temperature solver
# 9: Iterations for composition solver 1
# 10: Iterations for Stokes solver
# 11: Velocity iterations in Stokes preconditioner
# 12: Schur complement iterations in Stokes preconditioner
# 13: RMS velocity (m/year)
# 14: Max. velocity (m/year)
# 15: Minimal pressure (Pa)
# 16: Average pressure (Pa)
# 17: Maximal pressure (Pa)
# 18: Minimum topography (m)
# 19: Maximum topography (m)
0 0.000000000000e+00 0.000000000000e+00 1948 18351 8135 8135 0 0 206 444 840 6.62545995e+05 8.87572504e+05 -6.50724076e-01 5.00501899e+00 1.00000000e+01 0.00000000e+00 0.00000000e+00
45 changes: 45 additions & 0 deletions tests/chunk_lithostatic_pressure_2d_initial_topography.prm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# In this variation on chunk_lithostatic_pressure_2d.prm
# we test whether the point_is_in_domain function
# handles the initial topography correctly. We therefore
# add an initial topography and pick a representative point
# for the initial lithostatic pressure that lies above
# the unperturbed surface but below the surface plus
# initial topography.

include $ASPECT_SOURCE_DIR/tests/chunk_lithostatic_pressure_2d.prm

set Dimension = 3
set End time = 0

subsection Geometry model
set Model name = chunk

subsection Chunk
set Chunk inner radius = 3471000
set Chunk outer radius = 6371000
set Chunk minimum longitude = 10
set Chunk maximum longitude = 50
set Chunk minimum latitude = 0
set Chunk maximum latitude = 40
end

subsection Initial topography model
set Model name = function

subsection Function
set Function expression = 5000
set Maximum topography value = 5000
end
end
end


subsection Boundary traction model
set Prescribed traction boundary indicators = east: initial lithostatic pressure

# Set a radius between 6371 and 6376 km (surface radius
# without and with initial topography.
subsection Initial lithostatic pressure
set Representative point = 6374000, 50, 40
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

Number of active cells: 8 (on 2 levels)
Number of degrees of freedom: 652 (375+27+125+125)

*** Timestep 0: t=0 years, dt=0 years
Solving temperature system... 0 iterations.
Solving C_1 system ... 11 iterations.
Rebuilding Stokes preconditioner...
Solving Stokes system... 22+0 iterations.

Postprocessing:
RMS, max velocity: 0.309 m/year, 1.86 m/year
Pressure min/avg/max: -1.965e+07 Pa, 3.29e+10 Pa, 9.157e+10 Pa
Writing graphical output: output-chunk_lithostatic_pressure_2d/solution/solution-00000

Termination requested by criterion: end time



Loading
Loading