50 for (
unsigned i=0;
i<n_data;
i++)
56 unsigned n_prev=
Solid_data_pt[
i]->time_stepper_pt()->nprev_values();
64 for (
unsigned k=0;k<n_value;k++)
100 for (
unsigned i=0;
i<orig_n_sub_mesh;
i++)
172 for (
unsigned i=0;
i<n_data;
i++)
178 for (
unsigned k=0;k<n_value;k++)
197 for (
unsigned i=0;
i<n_data;
i++)
203 for (
unsigned k=0;k<n_value;k++)
230 for (
unsigned i=0;
i<n_data;
i++)
236 for (
unsigned k=0;k<n_value;k++)
256 for (
unsigned i=0;
i<n_data;
i++)
262 for (
unsigned k=0;k<n_value;k++)
288 unsigned value_count=0;
294 for (
unsigned i=0;
i<n_data;
i++)
300 for (
unsigned k=0;k<n_value;k++)
332 double& rms_change,
double& max_change,
double& rms_norm)
341 unsigned value_count=0;
347 for (
unsigned i=0;
i<n_data;
i++)
353 for (
unsigned k=0;k<n_value;k++)
361 if (std::fabs(change)>max_change) max_change=std::fabs(change);
364 rms_change+=pow(change,2);
375 rms_change=sqrt(rms_change/
double(value_count));
376 rms_norm=sqrt(rms_norm/
double(value_count));
397 unsigned value_count=0;
403 for (
unsigned i=0;
i<n_data;
i++)
409 for (
unsigned k=0;k<n_value;k++)
418 double change=old_solid_value-new_solid_value;
433 crit+=std::fabs(change);
457 for (
unsigned i=0;
i<n_data;
i++)
463 for (
unsigned k=0;k<n_value;k++)
489 unsigned value_count=0;
495 for (
unsigned i=0;
i<n_data;
i++)
501 for (
unsigned k=0;k<n_value;k++)
528 unsigned value_count=0;
534 for (
unsigned i=0;
i<n_data;
i++)
540 for (
unsigned k=0;k<n_value;k++)
549 double max_diff=std::max(std::fabs(v1-v0),std::fabs(v2-v1));
550 if (max_diff>1.0
e-10)
552 new_value=v2-std::pow((v2-v1),
int(2))/(v2-2.0*v1+v0);
579 clock_t t_total_start = clock();
586 get_max_global_residual=
true;
593 double cpu_for_global_residual=0.0;
600 bool converged=
false;
604 double tol_achieved=0.0;
622 double max_res = 0.0;
623 if (get_max_global_residual)
625 clock_t t_start = clock();
635 max_res = residual.
max();
636 clock_t t_end = clock();
637 cpu_for_global_residual+=double(t_end-t_start)/CLOCKS_PER_SEC;
640 oomph_info <<
"==================================================\n";
649 if (get_max_global_residual)
652 << max_res << std::endl;
654 oomph_info <<
"==================================================\n\n";
663 <<
"\n\n\n////////////////////////////////////////////////////////" 664 <<
"\nPicard iteration converged after " 665 << 0 <<
" steps!" << std::endl
666 <<
"Convergence was based on max. residual of coupled eqns \n" 668 <<
"////////////////////////////////////////////////////////\n\n\n" 682 goto jump_out_of_picard;
745 if (get_max_global_residual)
747 clock_t t_start = clock();
763 max_res = residual.
max();
765 clock_t t_end = clock();
766 cpu_for_global_residual+=double(t_end-t_start)/CLOCKS_PER_SEC;
769 oomph_info <<
"==================================================\n";
771 << iter << std::endl;
773 << rms_change << std::endl;
775 << max_change << std::endl;
777 << rms_norm << std::endl;
778 if (get_max_global_residual)
781 << max_res << std::endl;
783 oomph_info <<
"==================================================\n\n";
790 tol_achieved=max_change;
794 <<
"\n\n\n////////////////////////////////////////////////////////" 795 <<
"\nPicard iteration converged after " 796 << iter <<
" steps!" << std::endl
797 <<
"Convergence was based on absolute change in solid dofs \n" 799 <<
"////////////////////////////////////////////////////////\n\n\n" 807 tol_achieved=std::fabs(rms_change/rms_norm);
811 <<
"\n\n\n///////////////////////////////////////////////////////" 812 <<
"\nPicard iteration converged after " 813 << iter <<
" steps!" << std::endl
814 <<
"Convergence was based on relative change in solid dofs \n" 816 <<
"////////////////////////////////////////////////////////\n\n\n" 823 tol_achieved=max_res;
827 <<
"\n\n\n////////////////////////////////////////////////////////" 828 <<
"\nPicard iteration converged after " 829 << iter <<
" steps!" << std::endl
830 <<
"Convergence was based on max. residual of coupled eqns \n" 832 <<
"////////////////////////////////////////////////////////\n\n\n" 853 goto jump_out_of_picard;
903 conv_data.
niter()=iter_taken;
906 clock_t t_total_end = clock();
907 conv_data.
cpu_total()=double(t_total_end-t_total_start)/
927 <<
"\n\n\n////////////////////////////////////////////////////////" 928 <<
"\nPicard iteration did not converge after " 929 << iter_taken <<
" steps!" << std::endl
930 <<
"Convergence was based on absolute change in solid dofs \n" 932 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
933 <<
"////////////////////////////////////////////////////////\n\n\n" 949 <<
"\n\n\n///////////////////////////////////////////////////////" 950 <<
"\nPicard iteration did not converge after " 951 << iter_taken <<
" steps!" << std::endl
952 <<
"Convergence was based on relative change in solid dofs \n" 954 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
955 <<
"////////////////////////////////////////////////////////\n\n\n" 970 <<
"\n\n\n////////////////////////////////////////////////////////" 971 <<
"\nPicard iteration did not converge after " 972 << iter_taken <<
" steps!" << std::endl
973 <<
"Convergence was based on max. residual of coupled eqns \n" 975 <<
"but we achieved only " << tol_achieved <<
"." << std::endl
977 <<
"////////////////////////////////////////////////////////\n\n\n" 1010 std::vector<bool> was_steady(n_time_steppers);
1013 for(
unsigned i=0;
i<n_time_steppers;
i++)
1032 std::ostringstream error_stream;
1033 error_stream <<
"Error occured in Segregated solver. " 1036 OOMPH_CURRENT_FUNCTION,
1037 OOMPH_EXCEPTION_LOCATION);
1041 oomph_info <<
"Note: Ran out of iterations but continuing anyway" 1049 for(
unsigned i=0;
i<n_time_steppers;
i++)
1087 const double& dt,
const bool &shift_values)
1100 for(
unsigned i=0;
i<n_time_steppers;
i++)
1125 std::ostringstream error_stream;
1126 error_stream <<
"Error occured in Segregated solver. " 1129 OOMPH_CURRENT_FUNCTION,
1130 OOMPH_EXCEPTION_LOCATION);
1134 oomph_info <<
"Note: Ran out of iterations but continuing anyway" 1152 const bool &full_setup_of_fluid_and_solid_dofs)
1155 if(full_setup_of_fluid_and_solid_dofs)
1166 << std::endl << std::endl
1167 <<
"Warning: Your implementation of the pure virtual\n" 1168 <<
" function identify_fluid_and_solid_dofs(...)\n" 1169 <<
" returned a NULL pointer for Fluid_mesh_pt.\n" 1170 <<
" --> The fluid elements will remain activated\n" 1171 <<
" during the solid solve. This is inefficient!\n" 1172 <<
" You should combine all fluid elements into a combined\n" 1173 <<
" mesh and specify this mesh in your\n" 1174 <<
" implementation of \n\n" 1175 <<
" SegregatableFSIProblem::identify_fluid_and_solid_dofs(...)" 1176 << std::endl << std::endl;
1183 << std::endl << std::endl
1184 <<
"Warning: Your implementation of the pure virtual\n" 1185 <<
" function identify_fluid_and_solid_dofs(...)\n" 1186 <<
" returned a NULL pointer for Solid_mesh_pt.\n" 1187 <<
" --> The solid elements will remain activated\n" 1188 <<
" during the fluid solve. This is inefficient!\n" 1189 <<
" You should combine all solid elements into a combined\n" 1190 <<
" mesh and specify this mesh in your\n" 1191 <<
" implementation of \n\n" 1192 <<
" SegregatableFSIProblem::identify_fluid_and_solid_dofs(...)" 1193 << std::endl << std::endl;
1200 for (
unsigned i=0;
i<orig_n_sub_mesh;
i++)
1213 unsigned n_fluid_data=fluid_data_pt.size();
1218 unsigned n_fluid_values=0;
1221 for (
unsigned i=0;
i<n_fluid_data;
i++)
1227 unsigned n_value=fluid_data_pt[
i]->nvalue();
1231 for (
unsigned k=0;k<n_value;k++)
1234 fluid_data_pt[
i]->is_pinned(k);
1253 unsigned n_solid_data=solid_data_pt.size();
1256 unsigned nsolid_data=solid_data_pt.size();
1261 unsigned n_solid_values=0;
1264 for (
unsigned i=0;
i<n_solid_data;
i++)
1270 unsigned n_value=solid_data_pt[
i]->nvalue();
1274 for (
unsigned k=0;k<n_value;k++)
1277 solid_data_pt[
i]->is_pinned(k);
1297 for (
unsigned i=0;
i<n_solid_values;
i++)
unsigned & niter()
Number of iterations performed.
virtual void actions_before_segregated_solve()
This function is called once at the start of each segregated solve.
void make_steady()
Function to make the time stepper temporarily steady. This is trivially achieved by setting all the w...
void under_relax_solid()
Under-relax the most recently computed solid variables, either by classical relaxation or by Irons & ...
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 newton_solve()
Use Newton method to solve the problem.
Vector< Vector< double > > Pointwise_aitken_solid_value
Vector of Vectors containing up to three previous iterates for the solid dofs; used for pointwise Ait...
Vector< double > Del_irons_and_tuck
Vector of changes in Irons and Tuck under-relaxation.
bool Ran_out_of_iterations
Vector< Mesh * > Orig_sub_mesh_pt
Backup for the pointers to the submeshes in the original problem.
virtual void actions_after_segregated_solve()
This function is called once at the end of each segregated solve.
double R_irons_and_tuck
Irons and Tuck relaxation factor.
bool Recheck_convergence_after_pointwise_aitken
Have we just done a pointwise Aitken step.
double & cpu_for_global_residual()
CPU time for computation of global residual vectors Note: This time is contained in Total_CPU and is ...
unsigned ntime_stepper() const
Return the number of time steppers.
unsigned Max_picard
Max. number of Picard iterations.
void set_solver_converged()
Set the flag to indicate that the solver has converged.
double t_spent_on_actual_solve()
Total elapsed time since start of solve.
PicardConvergenceData unsteady_segregated_solve(const double &dt)
Unsteady segregated solver, advance time by dt and solve by the segregated solver. The time values are always shifted by this function. Returns PicardConvergenceData object that contains the vital stats of the iteration.
void rebuild_monolithic_mesh()
Rebuild global mesh for monolithic discretisation.
double Convergence_tolerance
Convergence tolerance for Picard iteration.
Mesh *& mesh_pt()
Return a pointer to the global mesh.
double & tol_achieved()
Final tolerance achieved by the iteration.
virtual void shift_time_values()
Shift all values along to prepare for next timestep.
void pin_solid_dofs()
Pin solid dofs.
double & cpu_total()
Total CPU time for segregated solve.
bool Use_pointwise_aitken
Use pointwise Aitken extrapolation?
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 restore_fluid_dofs()
Restore pinned status of fluid dofs.
void pin_fluid_dofs()
Pin fluid dofs.
void assign_initial_values_impulsive()
Initialise data and nodal positions to simulate impulsive start from initial configuration/solution.
int Convergence_criterion
Convergence criterion (enumerated flag)
void restore_solid_dofs()
Restore pinned status of solid dofs.
int Pointwise_aitken_counter
Number of Aitken histories available (int because after extrapolation it's re-initialised to -1 to fo...
virtual void set_weights()=0
Function to set the weights for present timestep (don't need to pass present timestep or previous tim...
void reset_timer()
Reset timer.
A class to handle errors in the Segregated solver.
bool Use_irons_and_tuck_extrapolation
Boolean flag to indicate use of Irons and Tuck's extrapolation for solid values.
double & dt(const unsigned &t=0)
PicardConvergenceData segregated_solve()
Segregated solver. Peform a segregated step from the present state of the system. Returns PicardConve...
void pointwise_aitken_extrapolate()
Do pointwise Aitken extrapolation for solid.
void store_solid_dofs()
Store the current solid values as reference values for future convergence check. Also add another ent...
Time *& time_pt()
Return a pointer to the global time object.
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 actions_before_segregated_convergence_check()
This function is to be filled with actions that take place before the check for convergence of the en...
TimeStepper *& time_stepper_pt()
Access function for the pointer to the first (presumably only) timestepper.
double Omega_relax
Under-relaxation parameter. (1.0: no under-relaxation; 0.0: Freeze wall shape)
Vector< double > Previous_solid_value
Vector storing the previous solid values – used for convergence check.
double & time()
Return the current value of the continuous time.
void use_only_solid_elements()
Only include solid elements in the Problem's mesh. This is called before the segregated solid solve...
PicardConvergenceData steady_segregated_solve()
Steady version of segregated solver. Makes all timesteppers steady before solving. Returns PicardConvergenceData object that contains the vital stats of the iteration.
bool Doc_max_global_residual
Doc maximum global residual during iteration? (default: false)
int Solve_type
Solve that is taking place (enumerated flag)
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)...
virtual void undo_make_steady()
Reset the is_steady status of a specific TimeStepper to its default and re-assign the weights...
Vector< Data * > Solid_data_pt
Vector storing the Data objects associated with the solid problem: Typically the positional data of s...
Vector< std::vector< bool > > Fluid_value_is_pinned
Vector of vectors that store the pinned status of fluid Data values.
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(...) function for FiniteElements and doesn't do anything for other element types. If a MacroElement pointer has been set for a FiniteElement, the MacroElement representation is used to update the nodal positions; if not get_x(...) uses the FE interpolation and thus leaves the nodal positions unchanged. Virtual, so it can be overloaded by specific meshes, such as AlgebraicMeshes or SpineMeshes. Generally, this function updates the position of all nodes in response to changes in the boundary position. However, we ignore all SolidNodes since their position is computed as part of the solution – unless the bool flag is set to true. Such calls are typically made when the initial mesh is created and/or after a mesh has been refined repeatedly before the start of the computation.
void flush_sub_meshes()
Flush the problem's collection of sub-meshes. Must be followed by call to rebuild_global_mesh().
void use_only_fluid_elements()
Only include fluid elements in the Problem's mesh. This is called before the segregated fluid solve...
Object that collates convergence data of Picard iteration.
unsigned Pointwise_aitken_start
Start pointwise Aitken extrpolation after specified number of Picard iterations.
Vector< std::vector< bool > > Solid_value_is_pinned
Vector of vectors that store the pinned status of solid Data values.
Vector< Data * > Fluid_data_pt
Vector storing the Data objects associated with the fluid problem: Tyically the nodal and internal da...
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...
bool is_steady() const
Flag to indicate if a timestepper has been made steady (possibly temporarily to switch off time-depen...
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 ...
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
unsigned nsub_mesh() const
Return number of submeshes.
Mesh * Fluid_mesh_pt
Mesh containing only fluid elements – the elements in this Mesh will be excluded from the assembly p...
double & essential_cpu_total()
Total essential CPU time for segregated solve (excluding any actions that merely doc the progress of ...
void extrapolate_solid_data()
Extrapolate solid data and update fluid mesh during unsteady run.
Mesh * Solid_mesh_pt
Mesh containing only solid elements – the elements in this mesh will be excluded from the assembly p...
virtual void actions_after_implicit_timestep()
Actions that should be performed after each implicit time step. This is needed when one wants to solv...
void rebuild_global_mesh()
If one of the submeshes has changed (e.g. by mesh adaptation) we need to update the global mesh...
virtual void actions_before_implicit_timestep()
Actions that should be performed before each implicit time step. This is needed when one wants to sol...
double max() const
returns the maximum coefficient