@@ -2629,6 +2629,92 @@ namespace aspect
26292629 return initial_newton_residual;
26302630 }
26312631
2632+ /* *
2633+ * Performs a Newton line search for the do_one_defect_correction_Stokes_step function
2634+ */
2635+ template <int dim>
2636+ double Simulator<dim>::perform_line_search(const DefectCorrectionResiduals &dcr,
2637+ const bool use_picard,
2638+ LinearAlgebra::BlockVector &search_direction)
2639+ {
2640+ LinearAlgebra::BlockVector backup_linearization_point (introspection.index_sets .stokes_partitioning , mpi_communicator);
2641+ double step_length_factor = 1.0 ;
2642+ unsigned int line_search_iteration = 0 ;
2643+ // Many parts of the solver depend on the block layout (velocity = 0,
2644+ // pressure = 1). For example the linearized_stokes_initial_guess vector or the StokesBlock matrix
2645+ // wrapper. Let us make sure that this holds (and shorten their names):
2646+ const unsigned int pressure_block_index = (parameters.include_melt_transport ) ?
2647+ introspection.variable (" fluid pressure" ).block_index
2648+ : introspection.block_indices .pressure ;
2649+ const unsigned int velocity_block_index = introspection.block_indices .velocities ;
2650+ Assert (velocity_block_index == 0 , ExcNotImplemented ());
2651+ Assert (pressure_block_index == 1 , ExcNotImplemented ());
2652+ (void ) pressure_block_index;
2653+ // Do the loop for the line search at least once with the full step length.
2654+ // If line search is disabled we will exit the loop in the first iteration.
2655+
2656+ do
2657+ {
2658+ if (line_search_iteration == 0 )
2659+ {
2660+ // backup our starting point for the line search
2661+ backup_linearization_point.block (pressure_block_index) = current_linearization_point.block (pressure_block_index);
2662+ backup_linearization_point.block (velocity_block_index) = current_linearization_point.block (velocity_block_index);
2663+ }
2664+ else
2665+ {
2666+ // undo the last iteration and try again with smaller step length
2667+ current_linearization_point.block (pressure_block_index) = backup_linearization_point.block (pressure_block_index);
2668+ current_linearization_point.block (velocity_block_index) = backup_linearization_point.block (velocity_block_index);
2669+ search_direction.block (pressure_block_index) *= step_length_factor;
2670+ search_direction.block (velocity_block_index) *= step_length_factor;
2671+ }
2672+
2673+ // Update the current linearization point with the search direction
2674+ current_linearization_point.block (pressure_block_index) += search_direction.block (pressure_block_index);
2675+ current_linearization_point.block (velocity_block_index) += search_direction.block (velocity_block_index);
2676+
2677+ // Rebuild the rhs to determine the new residual.
2678+ assemble_newton_stokes_matrix = rebuild_stokes_preconditioner = false ;
2679+ rebuild_stokes_matrix = !boundary_velocity_manager.get_prescribed_boundary_velocity_indicators ().empty ();
2680+
2681+ assemble_stokes_system ();
2682+
2683+ const double test_velocity_residual = system_rhs.block (velocity_block_index).l2_norm ();
2684+ const double test_pressure_residual = system_rhs.block (pressure_block_index).l2_norm ();
2685+ const double test_residual = std::sqrt (test_velocity_residual * test_velocity_residual
2686+ + test_pressure_residual * test_pressure_residual);
2687+
2688+ // Determine if the residual has decreased sufficiently.
2689+ const double alpha = 1e-4 ;
2690+ if (test_residual < (1.0 - alpha * step_length_factor) * dcr.residual
2691+ ||
2692+ line_search_iteration >= newton_handler->parameters .max_newton_line_search_iterations
2693+ ||
2694+ use_picard)
2695+ {
2696+ pcout << " Newton system information: Norm of the rhs: " << test_residual
2697+ << " , Derivative scaling factor: " << newton_handler->parameters .newton_derivative_scaling_factor << std::endl;
2698+ return test_residual;
2699+ }
2700+ else
2701+ {
2702+ pcout << " Line search iteration " << line_search_iteration << " , with norm of the rhs "
2703+ << test_residual << " and going to " << (1.0 - alpha * step_length_factor) * dcr.residual
2704+ << " , relative residual: " << test_residual/dcr.initial_residual << std::endl;
2705+
2706+ // The current search direction has not decreased the residual
2707+ // enough, so we take a smaller step and try again.
2708+ // TODO: make a parameter out of this.
2709+ step_length_factor = 2.0 /3.0 ;
2710+ }
2711+
2712+ ++line_search_iteration;
2713+ Assert (line_search_iteration <= newton_handler->parameters .max_newton_line_search_iterations ,
2714+ ExcInternalError ());
2715+ }
2716+ while (true );
2717+ }
26322718
26332719
26342720 template <int dim>
@@ -2779,6 +2865,9 @@ namespace aspect
27792865 template void Simulator<dim>::restore_outflow_boundary_ids(const unsigned int boundary_id_offset); \
27802866 template void Simulator<dim>::check_consistency_of_boundary_conditions() const ; \
27812867 template double Simulator<dim>::compute_initial_newton_residual(); \
2868+ template double Simulator<dim>::perform_line_search(const DefectCorrectionResiduals &dcr, \
2869+ const bool use_picard, \
2870+ LinearAlgebra::BlockVector &search_direction); \
27822871 template double Simulator<dim>::compute_Eisenstat_Walker_linear_tolerance(const bool EisenstatWalkerChoiceOne, \
27832872 const double maximum_linear_stokes_solver_tolerance, \
27842873 const double linear_stokes_solver_tolerance, \
0 commit comments