45 for (
unsigned i = 0;
i < n_data;
i++)
51 unsigned n_prev =
Solid_data_pt[
i]->time_stepper_pt()->nprev_values();
59 for (
unsigned k = 0; k < n_value; k++)
94 for (
unsigned i = 0;
i < orig_n_sub_mesh;
i++)
159 for (
unsigned i = 0;
i < n_data;
i++)
165 for (
unsigned k = 0; k < n_value; k++)
182 for (
unsigned i = 0;
i < n_data;
i++)
188 for (
unsigned k = 0; k < n_value; k++)
212 for (
unsigned i = 0;
i < n_data;
i++)
218 for (
unsigned k = 0; k < n_value; k++)
235 for (
unsigned i = 0;
i < n_data;
i++)
241 for (
unsigned k = 0; k < n_value; k++)
263 unsigned value_count = 0;
269 for (
unsigned i = 0;
i < n_data;
i++)
275 for (
unsigned k = 0; k < n_value; k++)
313 unsigned value_count = 0;
319 for (
unsigned i = 0;
i < n_data;
i++)
325 for (
unsigned k = 0; k < n_value; k++)
332 if (std::fabs(change) > max_change) max_change = std::fabs(change);
335 rms_change += pow(change, 2);
346 rms_change = sqrt(rms_change /
double(value_count));
347 rms_norm = sqrt(rms_norm /
double(value_count));
365 unsigned value_count = 0;
371 for (
unsigned i = 0;
i < n_data;
i++)
377 for (
unsigned k = 0; k < n_value; k++)
386 double change = old_solid_value - new_solid_value;
395 top += del2 * change;
401 crit += std::fabs(change);
425 for (
unsigned i = 0;
i < n_data;
i++)
431 for (
unsigned k = 0; k < n_value; k++)
455 unsigned value_count = 0;
461 for (
unsigned i = 0;
i < n_data;
i++)
467 for (
unsigned k = 0; k < n_value; k++)
493 unsigned value_count = 0;
499 for (
unsigned i = 0;
i < n_data;
i++)
505 for (
unsigned k = 0; k < n_value; k++)
512 double new_value = v2;
514 double max_diff = std::max(std::fabs(v1 - v0), std::fabs(v2 - v1));
515 if (max_diff > 1.0e-10)
517 new_value = v2 - std::pow((v2 - v1),
int(2)) / (v2 - 2.0 * v1 + v0);
543 clock_t t_total_start = clock();
551 get_max_global_residual =
true;
558 double cpu_for_global_residual = 0.0;
565 bool converged =
false;
569 double tol_achieved = 0.0;
577 for (
unsigned iter = 1; iter <=
Max_picard; iter++)
586 double max_res = 0.0;
587 if (get_max_global_residual)
589 clock_t t_start = clock();
599 max_res = residual.
max();
600 clock_t t_end = clock();
601 cpu_for_global_residual += double(t_end - t_start) / CLOCKS_PER_SEC;
604 oomph_info <<
"==================================================\n";
605 oomph_info <<
"Initial iteration : " << 0 << std::endl;
606 oomph_info <<
"RMS change : " << 0 << std::endl;
607 oomph_info <<
"Max. change : " << 0 << std::endl;
608 oomph_info <<
"RMS norm : " << 0 << std::endl;
609 if (get_max_global_residual)
611 oomph_info <<
"Max. global residual : " << max_res
614 oomph_info <<
"==================================================\n\n";
623 <<
"\n\n\n////////////////////////////////////////////////////////"
624 <<
"\nPicard iteration converged after " << 0 <<
" steps!"
626 <<
"Convergence was based on max. residual of coupled eqns \n"
628 <<
"////////////////////////////////////////////////////////\n\n\n"
642 goto jump_out_of_picard;
700 double max_res = 0.0;
705 if (get_max_global_residual)
707 clock_t t_start = clock();
723 max_res = residual.
max();
725 clock_t t_end = clock();
726 cpu_for_global_residual += double(t_end - t_start) / CLOCKS_PER_SEC;
729 oomph_info <<
"==================================================\n";
730 oomph_info <<
"Iteration : " << iter << std::endl;
735 oomph_info <<
"RMS norm : " << rms_norm << std::endl;
736 if (get_max_global_residual)
738 oomph_info <<
"Max. global residual : " << max_res
741 oomph_info <<
"==================================================\n\n";
747 tol_achieved = max_change;
751 <<
"\n\n\n/////////////////////////////////////////////////////"
753 <<
"\nPicard iteration converged after " << iter <<
" steps!"
755 <<
"Convergence was based on absolute change in solid dofs \n"
758 <<
"////////////////////////////////////////////////////////"
767 tol_achieved = std::fabs(rms_change / rms_norm);
771 <<
"\n\n\n/////////////////////////////////////////////////////"
773 <<
"\nPicard iteration converged after " << iter <<
" steps!"
775 <<
"Convergence was based on relative change in solid dofs \n"
778 <<
"////////////////////////////////////////////////////////"
786 tol_achieved = max_res;
790 <<
"\n\n\n/////////////////////////////////////////////////////"
792 <<
"\nPicard iteration converged after " << iter <<
" steps!"
794 <<
"Convergence was based on max. residual of coupled eqns \n"
797 <<
"////////////////////////////////////////////////////////"
818 goto jump_out_of_picard;
867 conv_data.
niter() = iter_taken;
870 clock_t t_total_end = clock();
872 double(t_total_end - t_total_start) / CLOCKS_PER_SEC;
890 <<
"\n\n\n////////////////////////////////////////////////////////"
891 <<
"\nPicard iteration did not converge after " << iter_taken
892 <<
" steps!" << std::endl
893 <<
"Convergence was based on absolute change in solid dofs \n"
895 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
896 <<
"////////////////////////////////////////////////////////\n\n\n"
902 "Error occured in Segregated solver. \n",
903 OOMPH_CURRENT_FUNCTION,
904 OOMPH_EXCEPTION_LOCATION);
909 "Error occured in Segregated solver. \n",
910 OOMPH_CURRENT_FUNCTION,
911 OOMPH_EXCEPTION_LOCATION);
918 <<
"\n\n\n///////////////////////////////////////////////////////"
919 <<
"\nPicard iteration did not converge after " << iter_taken
920 <<
" steps!" << std::endl
921 <<
"Convergence was based on relative change in solid dofs \n"
923 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
924 <<
"////////////////////////////////////////////////////////\n\n\n"
930 "Error occured in Segregated solver. \n",
931 OOMPH_CURRENT_FUNCTION,
932 OOMPH_EXCEPTION_LOCATION);
937 "Error occured in Segregated solver. \n",
938 OOMPH_CURRENT_FUNCTION,
939 OOMPH_EXCEPTION_LOCATION);
945 <<
"\n\n\n////////////////////////////////////////////////////////"
946 <<
"\nPicard iteration did not converge after " << iter_taken
947 <<
" steps!" << std::endl
948 <<
"Convergence was based on max. residual of coupled eqns \n"
950 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
952 <<
"////////////////////////////////////////////////////////\n\n\n"
958 "Error occured in Segregated solver. \n",
959 OOMPH_CURRENT_FUNCTION,
960 OOMPH_EXCEPTION_LOCATION);
965 "Error occured in Segregated solver. \n",
966 OOMPH_CURRENT_FUNCTION,
967 OOMPH_EXCEPTION_LOCATION);
989 std::vector<bool> was_steady(n_time_steppers);
992 for (
unsigned i = 0;
i < n_time_steppers;
i++)
1010 oomph_info <<
"Note: Ran out of iterations but continuing anyway"
1017 for (
unsigned i = 0;
i < n_time_steppers;
i++)
1055 const double& dt,
const bool& shift_values)
1071 for (
unsigned i = 0;
i < n_time_steppers;
i++)
1095 oomph_info <<
"Note: Ran out of iterations but continuing anyway"
1112 const bool& full_setup_of_fluid_and_solid_dofs)
1115 if (full_setup_of_fluid_and_solid_dofs)
1128 <<
"Warning: Your implementation of the pure virtual\n"
1129 <<
" function identify_fluid_and_solid_dofs(...)\n"
1130 <<
" returned a NULL pointer for Fluid_mesh_pt.\n"
1131 <<
" --> The fluid elements will remain activated\n"
1132 <<
" during the solid solve. This is inefficient!\n"
1133 <<
" You should combine all fluid elements into a combined\n"
1134 <<
" mesh and specify this mesh in your\n"
1135 <<
" implementation of \n\n"
1137 "SegregatableFSIProblem::identify_fluid_and_solid_dofs(...)"
1148 <<
"Warning: Your implementation of the pure virtual\n"
1149 <<
" function identify_fluid_and_solid_dofs(...)\n"
1150 <<
" returned a NULL pointer for Solid_mesh_pt.\n"
1151 <<
" --> The solid elements will remain activated\n"
1152 <<
" during the fluid solve. This is inefficient!\n"
1153 <<
" You should combine all solid elements into a combined\n"
1154 <<
" mesh and specify this mesh in your\n"
1155 <<
" implementation of \n\n"
1157 "SegregatableFSIProblem::identify_fluid_and_solid_dofs(...)"
1166 for (
unsigned i = 0;
i < orig_n_sub_mesh;
i++)
1179 unsigned n_fluid_data = fluid_data_pt.size();
1184 unsigned n_fluid_values = 0;
1187 for (
unsigned i = 0;
i < n_fluid_data;
i++)
1193 unsigned n_value = fluid_data_pt[
i]->nvalue();
1197 for (
unsigned k = 0; k < n_value; k++)
1218 unsigned n_solid_data = solid_data_pt.size();
1221 unsigned nsolid_data = solid_data_pt.size();
1226 unsigned n_solid_values = 0;
1229 for (
unsigned i = 0;
i < n_solid_data;
i++)
1235 unsigned n_value = solid_data_pt[
i]->nvalue();
1239 for (
unsigned k = 0; k < n_value; k++)
1261 for (
unsigned i = 0;
i < n_solid_values;
i++)
1275 for (
unsigned i = 0;
i < n_del;
i++)
A vector in the mathematical sense, initially developed for linear algebra type applications....
double max() const
returns the maximum coefficient
virtual void node_update(const bool &update_all_solid_nodes=false)
Update nodal positions in response to changes in the domain shape. Uses the FiniteElement::get_x(....
Object that collates convergence data of Picard iteration.
void set_solver_converged()
Set the flag to indicate that the solver has converged.
unsigned & niter()
Number of iterations performed.
double & cpu_for_global_residual()
CPU time for computation of global residual vectors Note: This time is contained in Total_CPU and is ...
double & tol_achieved()
Final tolerance achieved by the iteration.
double & essential_cpu_total()
Total essential CPU time for segregated solve (excluding any actions that merely doc the progress of ...
double & cpu_total()
Total CPU time for segregated solve.
virtual void actions_after_implicit_timestep()
Actions that should be performed after each implicit time step. This is needed when one wants to solv...
unsigned add_sub_mesh(Mesh *const &mesh_pt)
Add a submesh to the problem and return its number, i, by which it can be accessed via mesh_pt(i).
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Assign all equation numbers for problem: Deals with global data (= data that isn't attached to any el...
void assign_initial_values_impulsive()
Initialise data and nodal positions to simulate impulsive start from initial configuration/solution.
void flush_sub_meshes()
Flush the problem's collection of sub-meshes. Must be followed by call to rebuild_global_mesh().
Time *& time_pt()
Return a pointer to the global time object.
virtual void actions_before_implicit_timestep()
Actions that should be performed before each implicit time step. This is needed when one wants to sol...
void newton_solve()
Use Newton method to solve the problem.
virtual void get_residuals(DoubleVector &residuals)
Return the fully-assembled residuals Vector for the problem: Virtual so it can be overloaded in for m...
virtual void shift_time_values()
Shift all values along to prepare for next timestep.
Mesh *& mesh_pt()
Return a pointer to the global mesh.
void rebuild_global_mesh()
If one of the submeshes has changed (e.g. by mesh adaptation) we need to update the global mesh....
unsigned nsub_mesh() const
Return number of submeshes.
unsigned ntime_stepper() const
Return the number of time steppers.
TimeStepper *& time_stepper_pt()
Access function for the pointer to the first (presumably only) timestepper.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
@ Assess_convergence_based_on_relative_solid_change
@ Assess_convergence_based_on_absolute_solid_change
@ Assess_convergence_based_on_max_global_residual
bool Recheck_convergence_after_pointwise_aitken
Have we just done a pointwise Aitken step.
void extrapolate_solid_data()
Extrapolate solid data and update fluid mesh during unsteady run.
Vector< std::vector< bool > > Solid_value_is_pinned
Vector of vectors that store the pinned status of solid Data values.
void setup_segregated_solver(const bool &full_setup_of_fluid_and_solid_dofs=true)
Setup the segregated solver: Backup the pinned status of the fluid and solid dofs and allocate the in...
void use_only_fluid_elements()
Only include fluid elements in the Problem's mesh. This is called before the segregated fluid solve....
Vector< Mesh * > Orig_sub_mesh_pt
Backup for the pointers to the submeshes in the original problem.
bool Use_pointwise_aitken
Use pointwise Aitken extrapolation?
Vector< Data * > Fluid_data_pt
Vector storing the Data objects associated with the fluid problem: Tyically the nodal and internal da...
bool Use_irons_and_tuck_extrapolation
Boolean flag to indicate use of Irons and Tuck's extrapolation for solid values.
virtual void actions_after_segregated_solve()
This function is called once at the end of each segregated solve.
void use_only_solid_elements()
Only include solid elements in the Problem's mesh. This is called before the segregated solid solve....
void pin_fluid_dofs()
Pin fluid dofs.
Mesh * Solid_mesh_pt
Mesh containing only solid elements – the elements in this mesh will be excluded from the assembly pr...
unsigned Pointwise_aitken_start
Start pointwise Aitken extrpolation after specified number of Picard iterations.
void reset_timer()
Reset timer.
void rebuild_monolithic_mesh()
Rebuild global mesh for monolithic discretisation.
virtual void identify_fluid_and_solid_dofs(Vector< Data * > &fluid_data_pt, Vector< Data * > &solid_data_pt, Mesh *&fluid_mesh_pt, Mesh *&solid_mesh_pt)=0
Identify the fluid and solid Data. This is a pure virtual function that MUST be implemented for every...
void restore_solid_dofs()
Restore pinned status of solid dofs.
Vector< double > Previous_solid_value
Vector storing the previous solid values – used for convergence check.
double R_irons_and_tuck
Irons and Tuck relaxation factor.
PicardConvergenceData segregated_solve()
Segregated solver. Peform a segregated step from the present state of the system. Returns PicardConve...
Vector< double > Del_irons_and_tuck
Vector of changes in Irons and Tuck under-relaxation.
PicardConvergenceData steady_segregated_solve()
Steady version of segregated solver. Makes all timesteppers steady before solving....
int Convergence_criterion
Convergence criterion (enumerated flag)
void pointwise_aitken_extrapolate()
Do pointwise Aitken extrapolation for solid.
void under_relax_solid()
Under-relax the most recently computed solid variables, either by classical relaxation or by Irons & ...
Vector< Vector< double > > Pointwise_aitken_solid_value
Vector of Vectors containing up to three previous iterates for the solid dofs; used for pointwise Ait...
unsigned Max_picard
Max. number of Picard iterations.
Vector< std::vector< bool > > Fluid_value_is_pinned
Vector of vectors that store the pinned status of fluid Data values.
bool Doc_max_global_residual
Doc maximum global residual during iteration? (default: false)
PicardConvergenceData unsteady_segregated_solve(const double &dt)
Unsteady segregated solver, advance time by dt and solve by the segregated solver....
void restore_fluid_dofs()
Restore pinned status of fluid dofs.
virtual void actions_before_segregated_convergence_check()
This function is to be filled with actions that take place before the check for convergence of the en...
Vector< Data * > Solid_data_pt
Vector storing the Data objects associated with the solid problem: Typically the positional data of s...
void pin_solid_dofs()
Pin solid dofs.
void get_solid_change(double &rms_change, double &max_change, double &rms_norm)
Get rms of change in the solid dofs; the max. change of the solid dofs and the rms norm of the solid ...
int Pointwise_aitken_counter
Number of Aitken histories available (int because after extrapolation it's re-initialised to -1 to fo...
double Convergence_tolerance
Convergence tolerance for Picard iteration.
Mesh * Fluid_mesh_pt
Mesh containing only fluid elements – the elements in this Mesh will be excluded from the assembly pr...
double t_spent_on_actual_solve()
Total elapsed time since start of solve.
double Omega_relax
Under-relaxation parameter. (1.0: no under-relaxation; 0.0: Freeze wall shape)
virtual void actions_before_segregated_solve()
This function is called once at the start of each segregated solve.
int Solve_type
Solve that is taking place (enumerated flag)
void store_solid_dofs()
Store the current solid values as reference values for future convergence check. Also add another ent...
////////////////////////////////////////////////////////////////// //////////////////////////////////...
virtual void set_weights()=0
Function to set the weights for present timestep (don't need to pass present timestep or previous tim...
void make_steady()
Function to make the time stepper temporarily steady. This is trivially achieved by setting all the w...
virtual void undo_make_steady()
Reset the is_steady status of a specific TimeStepper to its default and re-assign the weights.
bool is_steady() const
Flag to indicate if a timestepper has been made steady (possibly temporarily to switch off time-depen...
double & dt(const unsigned &t=0)
Return the value of the t-th stored timestep (t=0: present; t>0: previous).
double & time()
Return the current value of the continuous time.
A slight extension to the standard template vector class so that we can include "graceful" array rang...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...