@@ -530,6 +530,7 @@ namespace aspect
530530 }
531531
532532
533+
533534 template <int dim>
534535 void Simulator<dim>::do_one_defect_correction_Stokes_step(DefectCorrectionResiduals &dcr,
535536 const bool use_picard)
@@ -547,6 +548,49 @@ namespace aspect
547548 Assert (!parameters.include_melt_transport
548549 || introspection.variable (" compaction pressure" ).block_index == 1 , ExcNotImplemented ());
549550
551+ // Define some lambda functions here for readability
552+ auto update_residuals = [&]()
553+ {
554+ dcr.velocity_residual = system_rhs.block (velocity_block_index).l2_norm ();
555+ dcr.pressure_residual = system_rhs.block (pressure_block_index).l2_norm ();
556+ dcr.residual = std::sqrt (dcr.velocity_residual * dcr.velocity_residual +
557+ dcr.pressure_residual * dcr.pressure_residual );
558+ };
559+
560+ // Eisenstat Walker method for determining the linear solver tolerance
561+ auto update_Eisenstat_Walker_tolerance = [&]()
562+ {
563+ const bool EisenstatWalkerChoiceOne = true ;
564+ parameters.linear_stokes_solver_tolerance = compute_Eisenstat_Walker_linear_tolerance (EisenstatWalkerChoiceOne,
565+ newton_handler->parameters .maximum_linear_stokes_solver_tolerance ,
566+ parameters.linear_stokes_solver_tolerance ,
567+ dcr.stokes_residuals .second ,
568+ dcr.residual ,
569+ dcr.residual_old );
570+
571+ pcout << " The linear solver tolerance is set to "
572+ << parameters.linear_stokes_solver_tolerance
573+ << " . " ;
574+ if (!use_picard)
575+ {
576+ pcout << " Stabilization Preconditioner is "
577+ << Newton::to_string (newton_handler->parameters .preconditioner_stabilization )
578+ << " and A block is "
579+ << Newton::to_string (newton_handler->parameters .velocity_block_stabilization )
580+ << ' .' ;
581+ }
582+ pcout << std::endl;
583+ };
584+
585+ // build the preconditioner
586+ auto build_preconditioner = [&]()
587+ {
588+ if (stokes_matrix_free)
589+ stokes_matrix_free->build_preconditioner ();
590+ else
591+ build_stokes_preconditioner ();
592+ };
593+
550594 // Re-compute the pressure scaling factor for the Stokes assembly
551595 pressure_scaling = compute_pressure_scaling_factor ();
552596
@@ -588,10 +632,7 @@ namespace aspect
588632
589633 assemble_stokes_system ();
590634
591- // recompute rhs
592- dcr.velocity_residual = system_rhs.block (velocity_block_index).l2_norm ();
593- dcr.pressure_residual = system_rhs.block (pressure_block_index).l2_norm ();
594- dcr.residual = std::sqrt (dcr.velocity_residual * dcr.velocity_residual + dcr.pressure_residual * dcr.pressure_residual );
635+ update_residuals ();
595636
596637 // Test whether the rhs has dropped so much that we can assume that the iteration is done.
597638 if (dcr.residual < dcr.residual_old * 1e-8 )
@@ -607,38 +648,15 @@ namespace aspect
607648 }
608649
609650
610- // Eisenstat Walker method for determining the linear solver tolerance
611651 if (nonlinear_iteration > 1 )
612652 {
613653 if (!use_picard || newton_handler->parameters .use_Eisenstat_Walker_method_for_Picard_iterations )
614654 {
615- const bool EisenstatWalkerChoiceOne = true ;
616- parameters.linear_stokes_solver_tolerance = compute_Eisenstat_Walker_linear_tolerance (EisenstatWalkerChoiceOne,
617- newton_handler->parameters .maximum_linear_stokes_solver_tolerance ,
618- parameters.linear_stokes_solver_tolerance ,
619- dcr.stokes_residuals .second ,
620- dcr.residual ,
621- dcr.residual_old );
622-
623- pcout << " The linear solver tolerance is set to "
624- << parameters.linear_stokes_solver_tolerance
625- << " . " ;
626- if (!use_picard)
627- {
628- pcout << " Stabilization Preconditioner is "
629- << Newton::to_string (newton_handler->parameters .preconditioner_stabilization )
630- << " and A block is "
631- << Newton::to_string (newton_handler->parameters .velocity_block_stabilization )
632- << ' .' ;
633- }
634- pcout << std::endl;
655+ update_Eisenstat_Walker_tolerance ();
635656 }
636657 }
637658
638- if (stokes_matrix_free)
639- stokes_matrix_free->build_preconditioner ();
640- else
641- build_stokes_preconditioner ();
659+ build_preconditioner ();
642660
643661 // The solution of the defect correction solver is an update direction
644662 LinearAlgebra::BlockVector search_direction;
@@ -694,29 +712,16 @@ namespace aspect
694712 */
695713 if (nonlinear_iteration > 1 )
696714 {
697- dcr.velocity_residual = system_rhs.block (velocity_block_index).l2_norm ();
698- dcr.pressure_residual = system_rhs.block (pressure_block_index).l2_norm ();
699- dcr.residual = std::sqrt (dcr.velocity_residual * dcr.velocity_residual + dcr.pressure_residual * dcr.pressure_residual );
715+ update_residuals ();
700716
701717 // Eisenstat Walker method for determining the linear solver tolerance
702718 if (!use_picard)
703719 {
704- const bool EisenstatWalkerChoiceOne = true ;
705- parameters.linear_stokes_solver_tolerance = compute_Eisenstat_Walker_linear_tolerance (EisenstatWalkerChoiceOne,
706- newton_handler->parameters .maximum_linear_stokes_solver_tolerance ,
707- parameters.linear_stokes_solver_tolerance ,
708- dcr.stokes_residuals .second ,
709- dcr.residual ,
710- dcr.residual_old );
711-
712- pcout << " The linear solver tolerance is set to " << parameters.linear_stokes_solver_tolerance << std::endl;
720+ update_Eisenstat_Walker_tolerance ();
713721 }
714722 }
715723
716- if (stokes_matrix_free)
717- stokes_matrix_free->build_preconditioner ();
718- else
719- build_stokes_preconditioner ();
724+ build_preconditioner ();
720725
721726 // Give this another try:
722727 dcr.stokes_residuals = solve_stokes (search_direction);
@@ -744,79 +749,11 @@ namespace aspect
744749 dcr.residual_old = dcr.residual ;
745750
746751 // We have computed an update. Prepare for a line search.
747- LinearAlgebra::BlockVector backup_linearization_point (introspection.index_sets .stokes_partitioning , mpi_communicator);
748-
749- double step_length_factor = 1.0 ;
750- unsigned int line_search_iteration = 0 ;
751-
752- // Do the loop for the line search at least once with the full step length.
753- // If line search is disabled we will exit the loop in the first iteration.
754- do
755- {
756- if (line_search_iteration == 0 )
757- {
758- // backup our starting point for the line search
759- backup_linearization_point.block (pressure_block_index) = current_linearization_point.block (pressure_block_index);
760- backup_linearization_point.block (velocity_block_index) = current_linearization_point.block (velocity_block_index);
761- }
762- else
763- {
764- // undo the last iteration and try again with smaller step length
765- current_linearization_point.block (pressure_block_index) = backup_linearization_point.block (pressure_block_index);
766- current_linearization_point.block (velocity_block_index) = backup_linearization_point.block (velocity_block_index);
767- search_direction.block (pressure_block_index) *= step_length_factor;
768- search_direction.block (velocity_block_index) *= step_length_factor;
769- }
770-
771- // Update the current linearization point with the search direction
772- current_linearization_point.block (pressure_block_index) += search_direction.block (pressure_block_index);
773- current_linearization_point.block (velocity_block_index) += search_direction.block (velocity_block_index);
774-
775- // Rebuild the rhs to determine the new residual.
776- assemble_newton_stokes_matrix = rebuild_stokes_preconditioner = false ;
777- rebuild_stokes_matrix = !boundary_velocity_manager.get_prescribed_boundary_velocity_indicators ().empty ();
778-
779- assemble_stokes_system ();
780-
781- const double test_velocity_residual = system_rhs.block (velocity_block_index).l2_norm ();
782- const double test_pressure_residual = system_rhs.block (pressure_block_index).l2_norm ();
783- const double test_residual = std::sqrt (test_velocity_residual * test_velocity_residual
784- + test_pressure_residual * test_pressure_residual);
785-
786- // Determine if the residual has decreased sufficiently.
787- const double alpha = 1e-4 ;
788- if (test_residual < (1.0 - alpha * step_length_factor) * dcr.residual
789- ||
790- line_search_iteration >= newton_handler->parameters .max_newton_line_search_iterations
791- ||
792- use_picard)
793- {
794- pcout << " Newton system information: Norm of the rhs: " << test_residual
795- << " , Derivative scaling factor: " << newton_handler->parameters .newton_derivative_scaling_factor << std::endl;
796- dcr.residual = test_residual;
797- break ;
798- }
799- else
800- {
801- pcout << " Line search iteration " << line_search_iteration << " , with norm of the rhs "
802- << test_residual << " and going to " << (1.0 - alpha * step_length_factor) * dcr.residual
803- << " , relative residual: " << test_residual/dcr.initial_residual << std::endl;
804-
805- // The current search direction has not decreased the residual
806- // enough, so we take a smaller step and try again.
807- // TODO: make a parameter out of this.
808- step_length_factor = 2.0 /3.0 ;
809- }
810-
811- ++line_search_iteration;
812- Assert (line_search_iteration <= newton_handler->parameters .max_newton_line_search_iterations ,
813- ExcInternalError ());
814- }
815- while (true );
752+ dcr.residual = perform_line_search (dcr, use_picard, search_direction);
816753 }
817754
818755
819- if (use_picard == true )
756+ if (use_picard)
820757 {
821758 // When we are using (defect corrected) Picard, keep the
822759 // newton_derivative_scaling_factor at zero. The newton_derivative_scaling_factor
0 commit comments