diff --git a/include/aspect/simulator.h b/include/aspect/simulator.h
index 4d5c99386d4..c28cbf9d5b7 100644
--- a/include/aspect/simulator.h
+++ b/include/aspect/simulator.h
@@ -1300,14 +1300,6 @@ namespace aspect
* "physical" pressure so that all following postprocessing
* steps can use the latter.
*
- * In the case of the surface average, whether a face is part of
- * the surface is determined by asking whether its depth of its
- * midpoint (as determined by the geometry model) is less than
- * 1/3*1/sqrt(dim-1)*diameter of the face. For reasonably curved
- * boundaries, this rules out side faces that are perpendicular
- * to the surface boundary but includes those faces that are
- * along the boundary even if the real boundary is curved.
- *
* Whether the pressure should be normalized based on the
* surface or volume average is decided by a parameter in the
* input file.
@@ -1352,12 +1344,7 @@ namespace aspect
* come out of GMRES, namely the one on which we later called
* normalize_pressure().
*
- * This function modifies @p vector in-place. In some cases, we need
- * locally_relevant values of the pressure. To avoid creating a new vector
- * and transferring data, this function uses a second vector with relevant
- * dofs (@p relevant_vector) for accessing these pressure values. Both
- * @p vector and @p relevant_vector are expected to already contain
- * the correct pressure values.
+ * This function modifies @p vector in-place.
*
* @note The adjustment made in this function is done using the
* negative of the @p pressure_adjustment function argument that
@@ -1371,8 +1358,7 @@ namespace aspect
* source/simulator/helper_functions.cc
.
*/
void denormalize_pressure(const double pressure_adjustment,
- LinearAlgebra::BlockVector &vector,
- const LinearAlgebra::BlockVector &relevant_vector) const;
+ LinearAlgebra::BlockVector &vector) const;
/**
* Apply the bound preserving limiter to the discontinuous Galerkin solutions:
@@ -1780,7 +1766,7 @@ namespace aspect
* Computes the initial Newton residual.
*/
double
- compute_initial_newton_residual (const LinearAlgebra::BlockVector &linearized_stokes_initial_guess);
+ compute_initial_newton_residual ();
/**
* This function computes the Eisenstat Walker linear tolerance used for the Newton iterations
diff --git a/source/simulator/helper_functions.cc b/source/simulator/helper_functions.cc
index 9cebb8efe48..0671bf7ad9b 100644
--- a/source/simulator/helper_functions.cc
+++ b/source/simulator/helper_functions.cc
@@ -1085,8 +1085,7 @@ namespace aspect
void
Simulator::
denormalize_pressure (const double pressure_adjustment,
- LinearAlgebra::BlockVector &vector,
- const LinearAlgebra::BlockVector &relevant_vector) const
+ LinearAlgebra::BlockVector &vector) const
{
if (parameters.pressure_normalization == "no")
return;
@@ -1106,6 +1105,17 @@ namespace aspect
finite_element.base_element(introspection.variable("fluid pressure").base_index).dofs_per_cell
: finite_element.base_element(introspection.base_elements.pressure).dofs_per_cell);
+ // We may touch the same DoF multiple times, so we need to copy the
+ // vector before modifying it to have access to the original value.
+ LinearAlgebra::BlockVector vector_backup;
+ vector_backup.reinit(vector, /* omit_zeroing_entries = */ true);
+ const unsigned int pressure_block_index =
+ parameters.include_melt_transport ?
+ introspection.variable("fluid pressure").block_index
+ :
+ introspection.block_indices.pressure;
+ vector_backup.block(pressure_block_index) = vector.block(pressure_block_index);
+
std::vector local_dof_indices (finite_element.dofs_per_cell);
for (const auto &cell : dof_handler.active_cell_iterators())
if (cell->is_locally_owned())
@@ -1117,11 +1127,15 @@ namespace aspect
= finite_element.component_to_system_index(pressure_component,
/*dof index within component=*/ j);
- // then adjust its value. Note that because we end up touching
+ // Then adjust its value. vector could be a vector with ghost elements
+ // or a fully distributed vector. In the latter case only access dofs that are
+ // locally owned. Note that because we end up touching
// entries more than once, we are not simply incrementing
- // distributed_vector but copy from the unchanged vector.
- vector(local_dof_indices[local_dof_index])
- = relevant_vector(local_dof_indices[local_dof_index]) - pressure_adjustment;
+ // vector but copy from the vector_backup copy.
+ if (vector.has_ghost_elements() ||
+ dof_handler.locally_owned_dofs().is_element(local_dof_indices[local_dof_index]))
+ vector(local_dof_indices[local_dof_index])
+ = vector_backup(local_dof_indices[local_dof_index]) - pressure_adjustment;
}
}
vector.compress(VectorOperation::insert);
@@ -1144,7 +1158,20 @@ namespace aspect
ExcInternalError());
Assert(!parameters.include_melt_transport, ExcNotImplemented());
const unsigned int pressure_component = introspection.component_indices.pressure;
+
+ // We may touch the same DoF multiple times, so we need to copy the
+ // vector before modifying it to have access to the original value.
+ LinearAlgebra::BlockVector vector_backup;
+ vector_backup.reinit(vector, /* omit_zeroing_entries = */ true);
+ const unsigned int pressure_block_index =
+ parameters.include_melt_transport ?
+ introspection.variable("fluid pressure").block_index
+ :
+ introspection.block_indices.pressure;
+ vector_backup.block(pressure_block_index) = vector.block(pressure_block_index);
+
std::vector local_dof_indices (finite_element.dofs_per_cell);
+
for (const auto &cell : dof_handler.active_cell_iterators())
if (cell->is_locally_owned())
{
@@ -1154,12 +1181,11 @@ namespace aspect
= finite_element.component_to_system_index (pressure_component, 0);
// make sure that this DoF is really owned by the current processor
- // and that it is in fact a pressure dof
Assert (dof_handler.locally_owned_dofs().is_element(local_dof_indices[first_pressure_dof]),
ExcInternalError());
// then adjust its value
- vector (local_dof_indices[first_pressure_dof]) = relevant_vector(local_dof_indices[first_pressure_dof])
+ vector (local_dof_indices[first_pressure_dof]) = vector_backup(local_dof_indices[first_pressure_dof])
- pressure_adjustment;
}
@@ -1341,15 +1367,7 @@ namespace aspect
else
linearized_stokes_variables.block (pressure_block_index) = current_linearization_point.block (pressure_block_index);
- // TODO: we don't have .stokes_relevant_partitioning so I am creating a much
- // bigger vector here, oh well.
- LinearAlgebra::BlockVector ghosted (introspection.index_sets.system_partitioning,
- introspection.index_sets.system_relevant_partitioning,
- mpi_communicator);
- // TODO for Timo: can we create the ghost vector inside of denormalize_pressure
- // (only in cases where we need it)
- ghosted.block(pressure_block_index) = linearized_stokes_variables.block(pressure_block_index);
- denormalize_pressure (this->last_pressure_normalization_adjustment, linearized_stokes_variables, ghosted);
+ denormalize_pressure (this->last_pressure_normalization_adjustment, linearized_stokes_variables);
current_constraints.set_zero (linearized_stokes_variables);
linearized_stokes_variables.block (pressure_block_index) /= pressure_scaling;
@@ -2586,23 +2604,22 @@ namespace aspect
template
double
- Simulator::compute_initial_newton_residual(const LinearAlgebra::BlockVector &linearized_stokes_initial_guess)
+ Simulator::compute_initial_newton_residual()
{
- // Store the values of the current_linearization_point and linearized_stokes_initial_guess so we can reset them again.
+ // Store the values of current_linearization_point to be able to restore it later.
LinearAlgebra::BlockVector temp_linearization_point = current_linearization_point;
- LinearAlgebra::BlockVector temp_linearized_stokes_initial_guess = linearized_stokes_initial_guess;
- // Set the velocity initial guess to zero, but we use the initial guess for the pressure.
+ // Set the velocity initial guess to zero.
current_linearization_point.block(introspection.block_indices.velocities) = 0;
- temp_linearized_stokes_initial_guess.block (introspection.block_indices.velocities) = 0;
- denormalize_pressure (last_pressure_normalization_adjustment,
- temp_linearized_stokes_initial_guess,
- current_linearization_point);
-
- // rebuild the whole system to compute the rhs.
+ // Rebuild the whole system to compute the rhs.
assemble_newton_stokes_system = true;
rebuild_stokes_preconditioner = false;
+
+ // Technically we only need the rhs, but we have asserts in place that check if
+ // the system is assembled correctly when boundary conditions are prescribed, so we assemble the whole system.
+ // TODO: This is a waste of time in the first nonlinear iteration. Check if we can modify the asserts in the
+ // assemble_stokes_system() function to only assemble the RHS.
rebuild_stokes_matrix = boundary_velocity_manager.get_active_boundary_velocity_conditions().size()!=0;
assemble_newton_stokes_matrix = boundary_velocity_manager.get_active_boundary_velocity_conditions().size()!=0;
@@ -2740,8 +2757,7 @@ namespace aspect
template struct Simulator::AdvectionField; \
template double Simulator::normalize_pressure(LinearAlgebra::BlockVector &vector) const; \
template void Simulator::denormalize_pressure(const double pressure_adjustment, \
- LinearAlgebra::BlockVector &vector, \
- const LinearAlgebra::BlockVector &relevant_vector) const; \
+ LinearAlgebra::BlockVector &vector) const; \
template double Simulator::compute_pressure_scaling_factor () const; \
template double Simulator::get_maximal_velocity (const LinearAlgebra::BlockVector &solution) const; \
template std::pair Simulator::get_extrapolated_advection_field_range (const AdvectionField &advection_field) const; \
@@ -2766,7 +2782,7 @@ namespace aspect
template void Simulator::replace_outflow_boundary_ids(const unsigned int boundary_id_offset); \
template void Simulator::restore_outflow_boundary_ids(const unsigned int boundary_id_offset); \
template void Simulator::check_consistency_of_boundary_conditions() const; \
- template double Simulator::compute_initial_newton_residual(const LinearAlgebra::BlockVector &linearized_stokes_initial_guess); \
+ template double Simulator::compute_initial_newton_residual(); \
template double Simulator::compute_Eisenstat_Walker_linear_tolerance(const bool EisenstatWalkerChoiceOne, \
const double maximum_linear_stokes_solver_tolerance, \
const double linear_stokes_solver_tolerance, \
diff --git a/source/simulator/solver.cc b/source/simulator/solver.cc
index 219a5c262ff..f6a58fe8fe0 100644
--- a/source/simulator/solver.cc
+++ b/source/simulator/solver.cc
@@ -855,8 +855,7 @@ namespace aspect
// initial residual we could skip all of this stuff.
distributed_stokes_solution.block(velocity_and_pressure_block) = solution.block(velocity_and_pressure_block);
denormalize_pressure (this->last_pressure_normalization_adjustment,
- distributed_stokes_solution,
- solution);
+ distributed_stokes_solution);
current_stokes_constraints.set_zero (distributed_stokes_solution);
// Undo the pressure scaling:
@@ -973,8 +972,7 @@ namespace aspect
linearized_stokes_initial_guess.block (pressure_block_index) = current_linearization_point.block (pressure_block_index);
denormalize_pressure (this->last_pressure_normalization_adjustment,
- linearized_stokes_initial_guess,
- current_linearization_point);
+ linearized_stokes_initial_guess);
}
else
{
diff --git a/source/simulator/solver_schemes.cc b/source/simulator/solver_schemes.cc
index be2268b99e0..d46f7a64752 100644
--- a/source/simulator/solver_schemes.cc
+++ b/source/simulator/solver_schemes.cc
@@ -437,19 +437,13 @@ namespace aspect
: introspection.block_indices.pressure;
Assert(introspection.block_indices.velocities == 0, ExcNotImplemented());
Assert(pressure_block_index == 1, ExcNotImplemented());
+ (void) pressure_block_index;
Assert(!parameters.include_melt_transport
|| introspection.variable("compaction pressure").block_index == 1, ExcNotImplemented());
- // create a completely distributed vector that will be used for
- // the scaled and denormalized solution and later used as a
- // starting guess for the linear solver
- LinearAlgebra::BlockVector linearized_stokes_initial_guess(introspection.index_sets.stokes_partitioning, mpi_communicator);
- linearized_stokes_initial_guess.block(introspection.block_indices.velocities) = current_linearization_point.block(introspection.block_indices.velocities);
- linearized_stokes_initial_guess.block(pressure_block_index) = current_linearization_point.block(pressure_block_index);
-
if (nonlinear_iteration == 0)
{
- dcr.initial_residual = compute_initial_newton_residual(linearized_stokes_initial_guess);
+ dcr.initial_residual = compute_initial_newton_residual();
dcr.switch_initial_residual = dcr.initial_residual;
dcr.residual_old = dcr.initial_residual;
dcr.residual = dcr.initial_residual;
@@ -461,12 +455,6 @@ namespace aspect
{
assemble_newton_stokes_system = assemble_newton_stokes_matrix = false;
}
- else
- {
- denormalize_pressure (last_pressure_normalization_adjustment,
- linearized_stokes_initial_guess,
- current_linearization_point);
- }
if (nonlinear_iteration <= 1)
{
diff --git a/source/simulator/stokes_matrix_free.cc b/source/simulator/stokes_matrix_free.cc
index 7a893f2555e..6ade5af78e7 100644
--- a/source/simulator/stokes_matrix_free.cc
+++ b/source/simulator/stokes_matrix_free.cc
@@ -1919,8 +1919,7 @@ namespace aspect
linearized_stokes_initial_guess.block (block_p) = sim.current_linearization_point.block (block_p);
sim.denormalize_pressure (sim.last_pressure_normalization_adjustment,
- linearized_stokes_initial_guess,
- sim.current_linearization_point);
+ linearized_stokes_initial_guess);
}
else
{