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