diff --git a/doc/modules/changes/20250304_gassmoeller b/doc/modules/changes/20250304_gassmoeller
new file mode 100644
index 00000000000..bd81f31e4b1
--- /dev/null
+++ b/doc/modules/changes/20250304_gassmoeller
@@ -0,0 +1,9 @@
+Fixed: The statistics file contained an invalid number of iterations
+for variables that were not solved (e.g. because compositions were
+prescribed, or Stokes was only solved using cheap or only expensive
+iterations). This is confusing, because it looks like an error and for the
+Stokes solver it caused incorrect iteration number to be reported. It is more
+accurate to report 0 iterations if none were made, which is what the
+postprocessor does now.
+
+(Rene Gassmoeller, 2025/03/04)
diff --git a/include/aspect/postprocess/global_statistics.h b/include/aspect/postprocess/global_statistics.h
index 9e643447dad..6ae803a931d 100644
--- a/include/aspect/postprocess/global_statistics.h
+++ b/include/aspect/postprocess/global_statistics.h
@@ -128,16 +128,16 @@ namespace aspect
* A container that stores the advection solver history of the current
* timestep, until it is written into the statistics object
* upon the call to execute(). It is cleared after writing
- * the content. The vector contains pairs, which consist
- * of a column name (for the temperature or one of the
- * compositional fields), and a vector of SolverControl
- * objects (one per nonlinear iteration for this particular
+ * the content. The map contains pairs, which consist
+ * of a unique field index (for the temperature or one of the
+ * compositional fields), and a vector of number of iterations
+ * (one number per nonlinear iteration for this particular
* field). This layout allows storing varying numbers of
* nonlinear iterations for temperature and compositional fields
* (if any nonlinear solver scheme would implement that at
* some point).
*/
- std::vector>> advection_iterations;
+ std::map> advection_iterations;
/**
* Whether to put every nonlinear iteration into a separate
diff --git a/source/postprocess/global_statistics.cc b/source/postprocess/global_statistics.cc
index aae8dd2e811..74eb06c9b11 100644
--- a/source/postprocess/global_statistics.cc
+++ b/source/postprocess/global_statistics.cc
@@ -88,8 +88,20 @@ namespace aspect
{
list_of_S_iterations.push_back(number_S_iterations);
list_of_A_iterations.push_back(number_A_iterations);
- stokes_iterations_cheap.push_back(solver_control_cheap.last_step());
- stokes_iterations_expensive.push_back(solver_control_expensive.last_step());
+
+ // If the solver was skipped, then the solver control
+ // object stores an invalid number of iterations. However, it
+ // is equally true and more intuitive to say that in this case
+ // the solver did not need to do any iterations.
+ if (solver_control_cheap.last_step() == numbers::invalid_unsigned_int)
+ stokes_iterations_cheap.push_back(0);
+ else
+ stokes_iterations_cheap.push_back(solver_control_cheap.last_step());
+
+ if (solver_control_expensive.last_step() == numbers::invalid_unsigned_int)
+ stokes_iterations_expensive.push_back(0);
+ else
+ stokes_iterations_expensive.push_back(solver_control_expensive.last_step());
}
@@ -100,21 +112,19 @@ namespace aspect
const unsigned int compositional_index,
const SolverControl &solver_control)
{
- const std::string column_name = (solved_temperature_field) ?
- "Iterations for temperature solver"
- :
- "Iterations for composition solver " + Utilities::int_to_string(compositional_index+1);
-
- unsigned int column_position = numbers::invalid_unsigned_int;
-
- for (unsigned int i=0; i(1,solver_control.last_step()));
+ const unsigned int column_position = (solved_temperature_field) ?
+ 0 :
+ compositional_index+1;
+
+ // If the solver was not called (e.g. the field
+ // was computed by the material model), then the solver control
+ // object stores an invalid number of iterations. However, it
+ // is equally true and more intuitive to say that in this case
+ // the solver did not need to do any iterations.
+ if (solver_control.last_step() == numbers::invalid_unsigned_int)
+ advection_iterations[column_position].push_back(0);
else
- advection_iterations[column_position].second.push_back(solver_control.last_step());
+ advection_iterations[column_position].push_back(solver_control.last_step());
}
@@ -144,8 +154,15 @@ namespace aspect
for (const auto &advection_iteration : advection_iterations)
if (iteration < advection_iteration.second.size())
- statistics.add_value(advection_iteration.first,
- advection_iteration.second[iteration]);
+ {
+ const std::string column_name = (advection_iteration.first == 0) ?
+ "Iterations for temperature solver"
+ :
+ "Iterations for composition solver " + Utilities::int_to_string(advection_iteration.first);
+
+ statistics.add_value(column_name,
+ advection_iteration.second[iteration]);
+ }
if (iteration < stokes_iterations_cheap.size())
{
@@ -169,9 +186,14 @@ namespace aspect
for (unsigned int iteration = 0; iteration < nonlinear_iterations; ++iteration)
{
- for (unsigned int column=0; column