30 #ifndef OOMPH_NAVIER_STOKES_PRECONDITIONERS_HEADER 31 #define OOMPH_NAVIER_STOKES_PRECONDITIONERS_HEADER 36 #include <oomph-lib-config.h> 41 #include "../generic/matrices.h" 42 #include "../generic/assembly_handler.h" 43 #include "../generic/problem.h" 44 #include "../generic/block_preconditioner.h" 45 #include "../generic/preconditioner.h" 46 #include "../generic/SuperLU_preconditioner.h" 47 #include "../generic/matrix_vector_product.h" 67 namespace PressureAdvectionDiffusionValidation
77 extern void wind_function(
const Vector<double>& x, Vector<double>& wind);
80 extern void get_exact_u(
const Vector<double>& x, Vector<double>& u);
83 extern void get_exact_u(
const Vector<double>& x,
double& u);
119 unsigned n_dof=elem_pt->
ndof();
120 for (
unsigned i=0;
i<n_dof;
i++)
126 elem_pt)->fill_in_pressure_advection_diffusion_residuals(residuals);
136 unsigned n_dof=elem_pt->
ndof();
137 for (
unsigned i=0;
i<n_dof;
i++)
140 for (
unsigned j=0;j<n_dof;j++)
147 elem_pt)->fill_in_pressure_advection_diffusion_jacobian(residuals,
169 template<
class ELEMENT>
181 mesh_pt()=navier_stokes_mesh_pt;
185 Orig_problem_pt=orig_problem_pt;
188 Ndim=mesh_pt()->finite_element_pt(0)->dim();
199 pin_all_non_pressure_dofs();
202 unsigned n_dof=assign_eqn_numbers();
203 oomph_info <<
"Eqn numbers after pinning veloc dofs: " 204 << n_dof << std::endl;
208 this->get_jacobian(dummy_residuals,jacobian);
214 oomph_info <<
"Eqn numbers in orig problem after re-assignment: " <<
215 Orig_problem_pt->assign_eqn_numbers() << std::endl;
224 unsigned nnod=mesh_pt()->nnode();
225 for (
unsigned j=0;j<nnod;j++)
227 Node* nod_pt=mesh_pt()->node_pt(j);
228 unsigned nval=nod_pt->
nvalue();
229 for (
unsigned i=0;
i<nval;
i++)
236 unsigned nelem=mesh_pt()->nelement();
237 for (
unsigned e=0;
e<nelem;
e++)
240 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(mesh_pt()->finite_element_pt(
e));
246 std::ostringstream error_message;
247 error_message <<
"Navier Stokes mesh must contain only Navier Stokes" 248 <<
"bulk elements\n";
251 OOMPH_CURRENT_FUNCTION,
252 OOMPH_EXCEPTION_LOCATION);
256 unsigned nint=el_pt->ninternal_data();
257 for (
unsigned j=0;j<nint;j++)
259 Data* data_pt=el_pt->internal_data_pt(j);
260 unsigned nvalue=data_pt->
nvalue();
261 for (
unsigned i=0;
i<nvalue;
i++)
269 Eqn_number_backup.clear();
278 set_pressure_bc_for_validation=
false)
282 unsigned nelem=mesh_pt()->nelement();
283 for (
unsigned e=0;
e<nelem;
e++)
287 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(mesh_pt()->finite_element_pt(
e));
293 std::ostringstream error_message;
294 error_message <<
"Navier Stokes mesh must contain only Navier Stokes" 295 <<
"bulk elements\n";
298 OOMPH_CURRENT_FUNCTION,
299 OOMPH_EXCEPTION_LOCATION);
305 if (el_pt->p_nodal_index_nst()<0)
307 std::ostringstream error_message;
308 error_message <<
"Cannot use Fp preconditioner with discontinuous\n" 311 OOMPH_CURRENT_FUNCTION,
312 OOMPH_EXCEPTION_LOCATION);
317 unsigned nint=el_pt->ninternal_data();
318 for (
unsigned j=0;j<nint;j++)
320 Data* data_pt=el_pt->internal_data_pt(j);
321 if (Eqn_number_backup[data_pt].size()==0)
323 unsigned nvalue=data_pt->
nvalue();
324 Eqn_number_backup[data_pt].resize(nvalue);
325 for (
unsigned i=0;
i<nvalue;
i++)
337 unsigned nnod=el_pt->nnode();
338 for (
unsigned j=0;j<nnod;j++)
340 Node* nod_pt=el_pt->node_pt(j);
341 if (Eqn_number_backup[nod_pt].size()==0)
343 unsigned nvalue=nod_pt->
nvalue();
344 Eqn_number_backup[nod_pt].resize(nvalue);
345 for (
unsigned i=0;
i<nvalue;
i++)
349 if (
int(
i)!=el_pt->p_nodal_index_nst())
359 if (el_pt->p_nodal_index_nst()>=0)
369 if (set_pressure_bc_for_validation)
376 nod_pt->
set_value(el_pt->u_index_nst(0),u[0]);
377 nod_pt->
set_value(el_pt->u_index_nst(1),u[1]);
389 oomph_info <<
"\n\n==============================================\n\n";
390 oomph_info <<
"Doing validation for pressure adv diff problem\n";
397 bool set_pressure_bc_for_validation=
true;
398 pin_all_non_pressure_dofs(set_pressure_bc_for_validation);
407 unsigned nel=mesh_pt()->nelement();
408 for (
unsigned e=0;
e<nel;
e++)
411 ->source_fct_for_pressure_adv_diff()=
416 oomph_info <<
"Eqn numbers after pinning veloc dofs: " 417 << assign_eqn_numbers() << std::endl;
420 unsigned nbound=mesh_pt()->nboundary();
424 for (
unsigned b=0;b<nbound;b++)
427 unsigned n_element = mesh_pt()->nboundary_element(b);
430 for(
unsigned e=0;
e<n_element;
e++)
434 mesh_pt()->boundary_element_pt(b,
e));
437 int face_index=mesh_pt()->face_index_at_boundary(b,
e);
448 std::ofstream outfile;
449 outfile.open(
"robin_elements.dat");
450 for (
unsigned e=0;
e<nel;
e++)
453 output_pressure_advection_diffusion_robin_elements(outfile);
461 doc_solution(doc_info);
467 for (
unsigned b=0;b<nbound;b++)
470 unsigned n_element = mesh_pt()->nboundary_element(b);
473 for(
unsigned e=0;
e<n_element;
e++)
478 mesh_pt()->boundary_element_pt(b,
e));
491 oomph_info <<
"Eqn numbers in orig problem after re-assignment: " <<
492 Orig_problem_pt->assign_eqn_numbers() << std::endl;
495 oomph_info <<
"Done validation for pressure adv diff problem\n";
496 oomph_info <<
"\n\n==============================================\n\n";
505 std::ofstream some_file;
506 std::ostringstream filename;
515 double p=
dynamic_cast<ELEMENT*
>(mesh_pt()->finite_element_pt(0))
516 ->interpolated_p_nst(s);
517 dynamic_cast<ELEMENT*
>(mesh_pt()->finite_element_pt(0))
518 ->interpolated_x(s,x);
525 unsigned nnode=mesh_pt()->nnode();
526 for (
unsigned j=0;j<nnode;j++)
528 if (mesh_pt()->node_pt(j)->nvalue()==3)
530 *(mesh_pt()->node_pt(j)->value_pt(2))-=p-u_exact;
537 some_file.open(filename.str().c_str());
538 some_file.precision(20);
539 mesh_pt()->output(some_file,npts);
543 filename << doc_info.
directory() <<
"/fp_exact_soln" 544 << doc_info.
number() <<
".dat";
545 some_file.open(filename.str().c_str());
546 some_file.precision(20);
547 mesh_pt()->output_fct(some_file,npts,
695 Accept_non_NavierStokesElementWithDiagonalMassMatrices_elements=
false;
698 Use_robin_for_fp=
true;
703 Preconditioner_has_been_setup =
false;
709 Using_default_p_preconditioner=
true;
710 Using_default_f_preconditioner=
true;
713 Pin_first_pressure_dof_in_press_adv_diff=
true;
715 Navier_stokes_mesh_pt = 0;
719 P_preconditioner_pt = 0;
720 F_preconditioner_pt = 0;
739 Allow_multiple_element_type_in_navier_stokes_mesh =
false;
768 {Problem_pt = problem_pt;}
775 std::ostringstream error_msg;
776 error_msg <<
"Problem pointer is null, did you set it yet?";
778 OOMPH_CURRENT_FUNCTION,
779 OOMPH_EXCEPTION_LOCATION);
789 Accept_non_NavierStokesElementWithDiagonalMassMatrices_elements=
true;
797 Accept_non_NavierStokesElementWithDiagonalMassMatrices_elements=
false;
814 void set_navier_stokes_mesh
816 const bool& allow_multiple_element_type_in_navier_stokes_mesh =
false)
819 Navier_stokes_mesh_pt = mesh_pt;
822 Allow_multiple_element_type_in_navier_stokes_mesh
823 = allow_multiple_element_type_in_navier_stokes_mesh;
831 if (Using_default_p_preconditioner)
833 delete P_preconditioner_pt;
835 P_preconditioner_pt = new_p_preconditioner_pt;
836 Using_default_p_preconditioner =
false;
843 if (!Using_default_p_preconditioner)
846 Using_default_p_preconditioner =
true;
855 if (Using_default_f_preconditioner)
857 delete F_preconditioner_pt;
859 F_preconditioner_pt = new_f_preconditioner_pt;
860 Using_default_f_preconditioner =
false;
873 if (!Using_default_f_preconditioner)
876 Using_default_f_preconditioner =
true;
887 void clean_up_memory();
901 {Pin_first_pressure_dof_in_press_adv_diff=
true;}
909 {Pin_first_pressure_dof_in_press_adv_diff=
false;}
913 template<
class ELEMENT>
917 aux_problem(Navier_stokes_mesh_pt,orig_problem_pt);
925 unsigned nelem=Navier_stokes_mesh_pt->nelement();
926 for (
unsigned e=0;
e<nelem;
e++)
931 Navier_stokes_mesh_pt->element_pt(
e));
943 pin_all_non_pressure_dofs();
946 unsigned ndim=Navier_stokes_mesh_pt->finite_element_pt(0)->dim();
950 problem_pt()->assembly_handler_pt();
951 problem_pt()->assembly_handler_pt()=
955 unsigned n_sub_mesh=problem_pt()->nsub_mesh();
957 for (
unsigned i=0;
i<n_sub_mesh;
i++)
959 backed_up_sub_mesh_pt[
i]=problem_pt()->mesh_pt(
i);
963 problem_pt()->flush_sub_meshes();
966 Mesh* backed_up_mesh_pt=problem_pt()->mesh_pt();
967 problem_pt()->mesh_pt()=Navier_stokes_mesh_pt;
975 problem_pt()->get_first_and_last_element_for_assembly(
976 backed_up_first_el_for_assembly,
977 backed_up_last_el_for_assembly);
980 problem_pt()->set_default_first_and_last_element_for_assembly();
985 int pinned_pressure_eqn=-2;
986 if (Pin_first_pressure_dof_in_press_adv_diff)
990 unsigned nel=Navier_stokes_mesh_pt->nelement();
991 for (
unsigned e=0;
e<nel;
e++)
995 Navier_stokes_mesh_pt->element_pt(
e));
999 pinned_pressure_eqn=bulk_elem_pt->
eqn_number(local_eqn);
1006 #ifdef OOMPH_HAS_MPI 1007 if (problem_pt()->distributed())
1009 int pinned_pressure_eqn_local=pinned_pressure_eqn;
1010 int pinned_pressure_eqn_global=pinned_pressure_eqn;
1011 MPI_Allreduce(&pinned_pressure_eqn_local,
1012 &pinned_pressure_eqn_global,1,MPI_INT,MPI_MIN,
1013 this->comm_pt()->mpi_comm());
1014 pinned_pressure_eqn=pinned_pressure_eqn_global;
1023 unsigned nel=Navier_stokes_mesh_pt->nelement();
1024 for (
unsigned e=0;
e<nel;
e++)
1028 Navier_stokes_mesh_pt->element_pt(
e));
1036 unsigned nbound=Navier_stokes_mesh_pt->nboundary();
1037 if (Use_robin_for_fp)
1040 for (
unsigned b=0;b<nbound;b++)
1043 unsigned n_element = Navier_stokes_mesh_pt->nboundary_element(b);
1046 for(
unsigned e=0;
e<n_element;
e++)
1050 Navier_stokes_mesh_pt->boundary_element_pt(b,
e));
1053 int face_index=Navier_stokes_mesh_pt->face_index_at_boundary(b,
e);
1064 problem_pt()->get_jacobian(dummy_residuals,fp_matrix);
1067 if (Use_robin_for_fp)
1070 for (
unsigned b=0;b<nbound;b++)
1073 unsigned n_element = Navier_stokes_mesh_pt->nboundary_element(b);
1076 for(
unsigned e=0;
e<n_element;
e++)
1081 Navier_stokes_mesh_pt->boundary_element_pt(b,
e));
1093 #ifdef OOMPH_HAS_MPI 1097 problem_pt()->set_first_and_last_element_for_assembly(
1098 backed_up_first_el_for_assembly,
1099 backed_up_last_el_for_assembly);
1104 delete problem_pt()->assembly_handler_pt();
1105 problem_pt()->assembly_handler_pt()=backed_up_assembly_handler_pt;
1109 for (
unsigned i=0;
i<n_sub_mesh;
i++)
1111 problem_pt()->add_sub_mesh(backed_up_sub_mesh_pt[
i]);
1116 problem_pt()->mesh_pt()= backed_up_mesh_pt;
1125 unsigned nnod=Navier_stokes_mesh_pt->nnode();
1126 for (
unsigned j=0;j<nnod;j++)
1128 Node* nod_pt=Navier_stokes_mesh_pt->node_pt(j);
1129 unsigned nval=nod_pt->
nvalue();
1130 for (
unsigned i=0;
i<nval;
i++)
1137 if (solid_nod_pt!=0)
1140 unsigned nval=solid_posn_data_pt->
nvalue();
1141 for (
unsigned i=0;
i<nval;
i++)
1144 Eqn_number_backup[solid_posn_data_pt][
i];
1151 unsigned nelem=Navier_stokes_mesh_pt->nelement();
1152 for (
unsigned e=0;
e<nelem;
e++)
1159 for (
unsigned j=0;j<nint;j++)
1162 unsigned nvalue=data_pt->
nvalue();
1163 for (
unsigned i=0;
i<nvalue;
i++)
1171 Eqn_number_backup.clear();
1209 void assemble_inv_press_and_veloc_mass_matrix_diagonal(
1212 const bool& do_both);
1280 template<
typename MATRIX>
A Generalised Element class.
NavierStokesExactPreconditioner(const NavierStokesExactPreconditioner &)
Broken copy constructor.
void enable_accept_non_NavierStokesElementWithDiagonalMassMatrices_elements()
Accept presence of elements that are not of type NavierStokesElementWithDiagonalMassMatrices without ...
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
MatrixVectorProduct * Bt_mat_vec_pt
MatrixVectorProduct operator for Bt.
void reset_pin_status()
Reset pin status of all values.
virtual void build_fp_press_adv_diff_robin_bc_element(const unsigned &face_index)=0
Build FaceElements that apply the Robin boundary condition to the pressure advection diffusion proble...
FpPreconditionerAssemblyHandler(const unsigned &ndim)
Constructor. Pass spatial dimension.
MatrixVectorProduct * QBt_mat_vec_pt
MatrixVectorProduct operator for Qv^{-1} Bt.
void set_problem_pt(Problem *problem_pt)
Broken assignment operator.
Information for documentation of results: Directory and file number to enable output in the form RESL...
unsigned Ndim
The spatial dimension.
std::string directory() const
Output directory.
bool Accept_non_NavierStokesElementWithDiagonalMassMatrices_elements
Boolean to indicate that presence of elements that are not of type NavierStokesElementWithDiagonalMas...
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector.
Problem * Orig_problem_pt
Pointer to orig problem (required so we can re-assign eqn numbers)
void pin_all_non_pressure_dofs()
Pin all non-pressure dofs.
bool Preconditioner_has_been_setup
Control flag is true if the preconditioner has been setup (used so we can wipe the data when the prec...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double Peclet
Peclet number – overwrite with actual Reynolds number.
The exact Navier Stokes preconditioner. This extracts 2x2 blocks (corresponding to the velocity and p...
void set_f_preconditioner(Preconditioner *new_f_preconditioner_pt)
Function to set a new momentum matrix preconditioner (inexact solver)
Preconditioner * P_preconditioner_pt
Pointer to the 'preconditioner' for the pressure matrix.
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
NavierStokesSchurComplementPreconditioner(const NavierStokesSchurComplementPreconditioner &)
Broken copy constructor.
void pin(const unsigned &i)
Pin the i-th stored variable.
void pin_first_pressure_dof_in_press_adv_diff()
Set boolean indicating that we want to pin first pressure dof in Navier Stokes mesh when assembling t...
void disable_doc_time()
Disable documentation of time.
Problem * problem_pt() const
void doc_solution(DocInfo &doc_info)
Doc solution (only needed during development – kept alive in case validation is required during code...
unsigned & number()
Number used (e.g.) for labeling output files.
bool Using_default_p_preconditioner
flag indicating whether the default P preconditioner is used
void setup()
Setup terminate helper.
unsigned ndof() const
Return the number of equations/dofs in the element.
bool Pin_first_pressure_dof_in_press_adv_diff
Boolean indicating if we want to pin first pressure dof in Navier Stokes mesh when assembling the pre...
bool Doc_time
Set Doc_time to true for outputting results of timings.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
virtual ~NavierStokesSchurComplementPreconditioner()
Destructor.
void set_p_preconditioner(Preconditioner *new_p_preconditioner_pt)
Function to set a new pressure matrix preconditioner (inexact solver)
virtual void pin_all_non_pressure_dofs(std::map< Data *, std::vector< int > > &eqn_number_backup)=0
Pin all non-pressure dofs and backup eqn numbers of all Data.
~NavierStokesExactPreconditioner()
Destructor - do nothing.
void get_pressure_advection_diffusion_matrix(CRDoubleMatrix &fp_matrix)
Get the pressure advection diffusion matrix.
The least-squares commutator (LSC; formerly BFBT) Navier Stokes preconditioner. It uses blocks corres...
virtual int p_local_eqn(const unsigned &n) const =0
Access function for the local equation number information for the pressure. p_local_eqn[n] = local eq...
MatrixVectorProduct * F_mat_vec_pt
MatrixVectorProduct operator for F.
NavierStokesSchurComplementPreconditioner(Problem *problem_pt)
Constructor - sets defaults for control flags.
void reset_pin_status()
Reset pin status of all values.
void get_jacobian(GeneralisedElement *const &elem_pt, Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the elemental Jacobian matrix "d equation / d variable" for elem_pt.
void set_f_superlu_preconditioner()
Function to (re-)set momentum matrix preconditioner (inexact solver) to SuperLU.
virtual void delete_pressure_advection_diffusion_robin_elements()=0
Delete the FaceElements that apply the Robin boundary condition to the pressure advection diffusion p...
Preconditioner * F_preconditioner_pt
Pointer to the 'preconditioner' for the F matrix.
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
void enable_robin_for_fp()
Use Robin BC elements for the Fp preconditioner.
virtual int & pinned_fp_pressure_eqn()=0
Global eqn number of pressure dof that's pinned in pressure adv diff problem.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
void set_p_superlu_preconditioner()
Function to (re-)set pressure matrix preconditioner (inexact solver) to SuperLU.
A class that represents a collection of data; each Data object may contain many different individual ...
MATRIX P_matrix
Preconditioner matrix.
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
void unpin_first_pressure_dof_in_press_adv_diff()
Set boolean indicating that we do not want to pin first pressure.
std::map< Data *, std::vector< int > > Eqn_number_backup
Map to store original eqn numbers of various Data values when assembling pressure advection diffusion...
A class that is used to define the functions used to assemble the elemental contributions to the resi...
void pin_all_non_pressure_dofs(const bool &set_pressure_bc_for_validation=false)
Pin all non-pressure dofs and (if boolean flag is set to true also all pressure dofs along domain bou...
bool Use_robin_for_fp
Use Robin BC elements for Fp preconditoner?
void use_lsc()
Use LSC version of the preconditioner.
Auxiliary Problem that can be used to assemble the pressure advection diffusion matrix needed by the ...
unsigned Flag
Flag for solution.
An interface to allow SuperLU to be used as an (exact) Preconditioner.
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
void validate(DocInfo &doc_info, Problem *orig_problem_pt)
Validate auxiliary pressure advection diffusion problem in 2D.
bool Allow_multiple_element_type_in_navier_stokes_mesh
Flag to indicate if there are multiple element types in the Navier-Stokes mesh.
void get_pressure_advection_diffusion_jacobian(CRDoubleMatrix &jacobian)
Get the pressure advection diffusion Jacobian.
MatrixVectorProduct * E_mat_vec_pt
MatrixVectorProduct operator for E = Fp Qp^{-1} (only for Fp variant)
void use_fp()
Use Fp version of the preconditioner.
unsigned ninternal_data() const
Return the number of internal data objects.
A Class for nodes that deform elastically (i.e. position is an unknown in the problem). The idea is that the Eulerian positions are stored in a Data object and the Lagrangian coordinates are stored in addition. The pointer that addresses the Eulerian positions is set to the pointer to Value in the Data object. Hence, SolidNode uses knowledge of the internal structure of Data and must be a friend of the Data class. In order to allow a mesh to deform via an elastic-style equation in deforming-domain problems, the positions are stored separately from the values, so that elastic problems may be combined with any other type of problem.
std::map< Data *, std::vector< int > > Eqn_number_backup
Map to store original equation numbers.
FpPressureAdvectionDiffusionProblem(Mesh *navier_stokes_mesh_pt, Problem *orig_problem_pt)
Constructor: Pass Navier-Stokes mesh and pointer to orig problem.
void validate(DocInfo &doc_info)
Validate pressure advection diffusion problem and doc exact and computed solution in directory specif...
void get_residuals(GeneralisedElement *const &elem_pt, Vector< double > &residuals)
Return the contribution to the residuals of the element elem_pt.
Matrix vector product helper class - primarily a wrapper to Trilinos's Epetra matrix vector product m...
bool Use_LSC
Boolean to indicate use of LSC (true) or Fp (false) variant.
bool F_preconditioner_is_block_preconditioner
Boolean indicating whether the momentum system preconditioner is a block preconditioner.
Mesh * Navier_stokes_mesh_pt
the pointer to the mesh of block preconditionable Navier Stokes elements.
virtual void setup()=0
Setup the preconditioner. Pure virtual generic interface function.
void disable_robin_for_fp()
Don't use Robin BC elements for the Fp preconditioenr.
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*)
virtual ~FpPreconditionerAssemblyHandler()
Empty virtual destructor.
bool Using_default_f_preconditioner
flag indicating whether the default F preconditioner is used
A class for compressed row matrices. This is a distributable object.
double source_function(const Vector< double > &x_vect)
Source function required to make the solution above an exact solution.
NavierStokesExactPreconditioner()
Constructor - do nothing.
void disable_accept_non_NavierStokesElementWithDiagonalMassMatrices_elements()
Do not accept presence of elements that are not of type NavierStokesElementWithDiagonalMassMatrices w...
void wind_function(const Vector< double > &x, Vector< double > &wind)
Wind.
void enable_doc_time()
Enable documentation of time.