45 namespace PressureAdvectionDiffusionValidation
60 wind[0]=sin(6.0*x[1]);
61 wind[1]=cos(6.0*x[0]);
77 u[2]=x[0]*x[0]*pow(1.0-x[0],2.0)*x[1]*x[1]*pow(1.0-x[1],2.0);
81 u[2]=0.1E1-Peclet*x[0]*(0.1E1-0.5*x[0]);
90 u=x[0]*x[0]*pow(1.0-x[0],2.0)*x[1]*x[1]*pow(1.0-x[1],2.0);
94 u=0.1E1-Peclet*x[0]*(0.1E1-0.5*x[0]);
112 Peclet*(sin(0.6E1*x[1])*(2.0*x[0]*pow(1.0-x[0],2.0)*x[1]*x[1]*pow(
113 1.0-x[1],2.0)-2.0*x[0]*x[0]*(1.0-x[0])*x[1]*x[1]*pow(1.0-x[1],2.0))+cos(0.6E1*x
114 [0])*(2.0*x[0]*x[0]*pow(1.0-x[0],2.0)*x[1]*pow(1.0-x[1],2.0)-2.0*x[0]*x[0]*pow(
115 1.0-x[0],2.0)*x[1]*x[1]*(1.0-x[1])))-2.0*pow(1.0-x[0],2.0)*x[1]*x[1]*pow(1.0-x
116 [1],2.0)+8.0*x[0]*(1.0-x[0])*x[1]*x[1]*pow(1.0-x[1],2.0)-2.0*x[0]*x[0]*x[1]*x
117 [1]*pow(1.0-x[1],2.0)-2.0*x[0]*x[0]*pow(1.0-x[0],2.0)*pow(1.0-x[1],2.0)+8.0*x
118 [0]*x[0]*pow(1.0-x[0],2.0)*x[1]*(1.0-x[1])-2.0*x[0]*x[0]*pow(1.0-x[0],2.0)*x[1]
123 source=Peclet*(-0.1E1*Peclet*(0.1E1-0.5*x[0])+0.5*Peclet*x[0])-0.1E1*
Peclet 151 bool doc_block_matrices=
false;
154 bool raytime_flag =
false;
166 double clean_up_memory_time = t_clean_up_memory_end
167 - t_clean_up_memory_start;
171 << clean_up_memory_time << std::endl;
177 if (Navier_stokes_mesh_pt == 0)
179 std::ostringstream error_message;
180 error_message <<
"The navier stokes elements mesh pointer must be set.\n" 181 <<
"Use method set_navier_stokes_mesh(...)";
183 OOMPH_CURRENT_FUNCTION,
184 OOMPH_EXCEPTION_LOCATION);
191 this->set_mesh(0,Navier_stokes_mesh_pt,
192 Allow_multiple_element_type_in_navier_stokes_mesh);
205 std::ostringstream error_message;
207 <<
"NavierStokesSchurComplementPreconditioner only works with " 208 <<
"CRDoubleMatrix matrices" << std::endl;
210 OOMPH_CURRENT_FUNCTION,
211 OOMPH_EXCEPTION_LOCATION);
216 if (doc_block_matrices)
218 std::stringstream junk;
219 junk <<
"j_matrix" << comm_pt()->my_rank()
221 oomph_info <<
"About to output " << junk.str() << std::endl;
223 oomph_info <<
"Done output of " << junk.str() << std::endl;
235 unsigned ndof_types = 0;
237 if (this->is_subsidiary_block_preconditioner())
239 ndof_types = this->ndof_types();
245 ndof_types = this->ndof_types_in_mesh(0);
249 dof_to_block_map[ndof_types-1]=1;
251 this->block_setup(dof_to_block_map);
254 double block_setup_time = t_block_setup_finish - t_block_setup_start;
257 oomph_info <<
"Time for block_setup(...) [sec]: " 258 << block_setup_time <<
"\n";
263 oomph_info <<
"LSC: block_setup: " << block_setup_time << std::endl;
271 F_preconditioner_is_block_preconditioner =
true;
272 if (F_block_preconditioner_pt == 0)
274 F_preconditioner_is_block_preconditioner =
false;
280 this->get_block(1,0,*b_pt);
283 double get_B_time = t_get_B_finish - t_get_B_start;
287 << get_B_time <<
"\n";
292 oomph_info <<
"LSC: get block B get_B_time: " << get_B_time << std::endl;
295 if (doc_block_matrices)
297 std::stringstream junk;
298 junk <<
"b_matrix" << comm_pt()->my_rank()
301 oomph_info <<
"Done output of " << junk.str() << std::endl;
313 assemble_inv_press_and_veloc_mass_matrix_diagonal(inv_p_mass_pt,
320 assemble_inv_press_and_veloc_mass_matrix_diagonal(inv_p_mass_pt,
328 ivmm_assembly_time = ivmm_assembly_finish_t - ivmm_assembly_start_t;
332 oomph_info <<
"Time to assemble inverse diagonal velocity and pressure" 333 <<
"mass matrices) [sec]: " 334 << ivmm_assembly_time <<
"\n";
339 << ivmm_assembly_time << std::endl;
343 if (doc_block_matrices)
345 std::stringstream junk;
346 junk <<
"inv_v_mass_matrix" 347 << comm_pt()->my_rank()
350 oomph_info <<
"Done output of " << junk.str() << std::endl;
357 this->get_block(0,1,*bt_pt);
360 double t_get_Bt_time = t_get_Bt_finish - t_get_Bt_start;
364 << t_get_Bt_time << std::endl;
369 << t_get_Bt_time << std::endl;
372 if (doc_block_matrices)
374 std::stringstream junk;
375 junk <<
"bt_matrix" << comm_pt()->my_rank()
378 oomph_info <<
"Done output of " << junk.str() << std::endl;
388 inv_v_mass_pt->
multiply(*bt_pt, *qbt_pt);
389 delete bt_pt; bt_pt = 0;
395 double t_QBt_time = t_QBt_matrix_finish - t_QBt_matrix_start;
399 << t_QBt_time << std::endl;
401 delete inv_v_mass_pt; inv_v_mass_pt = 0;
404 oomph_info <<
"LSC: t_QBt_time (matrix multiplicaton): " 405 << t_QBt_time << std::endl;
411 b_pt->
multiply(*bt_pt, *p_matrix_pt);
414 double t_p_time = t_p_matrix_finish - t_p_matrix_start;
418 << t_p_time << std::endl;
421 delete b_pt; b_pt = 0;
425 oomph_info <<
"LSC: t_p_time (matrix multiplication): " 426 << t_p_time << std::endl;
433 this->setup_matrix_vector_product(QBt_mat_vec_pt,bt_pt,1);
436 double t_p_time2 = t_QBt_MV_finish - t_QBt_MV_start;
439 oomph_info <<
"Time to build QBt matrix vector operator [sec]: " 440 << t_p_time2 << std::endl;
445 delete bt_pt; bt_pt = 0;
449 oomph_info <<
"LSC: QBt (setup MV product): " << t_p_time2 << std::endl;
459 get_pressure_advection_diffusion_matrix(full_fp_matrix);
463 this->get_block_other_matrix(1,1,&full_fp_matrix,*fp_matrix_pt);
467 double t_get_Fp_time = t_get_Fp_finish - t_get_Fp_start;
469 << t_get_Fp_time << std::endl;
475 fp_matrix_pt->
multiply(*inv_p_mass_pt, *fp_qp_inv_pt);
480 this->setup_matrix_vector_product(E_mat_vec_pt,fp_qp_inv_pt,1);
484 double t_p_time = t_Fp_Qp_inv_MV_finish - t_Fp_Qp_inv_MV_start;
485 oomph_info <<
"Time to build Fp Qp^{-1} matrix vector operator [sec]: " 486 << t_p_time << std::endl;
489 delete inv_p_mass_pt; inv_p_mass_pt = 0;
490 delete fp_qp_inv_pt; fp_qp_inv_pt = 0;
497 this->get_block(0,0,*f_pt);
500 double t_get_F_time = t_get_F_finish - t_get_F_start;
504 << t_get_F_time << std::endl;
509 << t_get_F_time << std::endl;
515 this->setup_matrix_vector_product(F_mat_vec_pt,f_pt,0);
518 double t_F_MV_time = t_F_MV_finish - t_F_MV_start;
521 oomph_info <<
"Time to build F Matrix Vector Operator [sec]: " 522 << t_F_MV_time << std::endl;
526 oomph_info <<
"LSC: MV product setup t_F_MV_time: " 527 << t_F_MV_time << std::endl;
532 if (F_preconditioner_is_block_preconditioner)
534 delete f_pt; f_pt = 0;
541 this->get_block(0,1,*bt_pt);
543 double t_get_Bt_time2 = t_get_Bt_finish - t_get_Bt_start;
548 << t_get_Bt_time2 << std::endl;
552 oomph_info <<
"LSC: get_block t_get_Bt_time2: " 553 << t_get_Bt_time2 << std::endl;
560 this->setup_matrix_vector_product(Bt_mat_vec_pt,bt_pt,1);
568 delete bt_pt; bt_pt = 0;
572 double t_Bt_MV_time = t_Bt_MV_finish - t_Bt_MV_start;
575 oomph_info <<
"LSC: MV product setup t_Bt_MV_time: " 576 << t_Bt_MV_time << std::endl;
580 if (P_preconditioner_pt == 0)
583 Using_default_p_preconditioner =
true;
589 if (doc_block_matrices)
591 std::stringstream junk;
592 junk <<
"p_matrix" << comm_pt()->my_rank()
595 oomph_info <<
"Done output of " << junk.str() << std::endl;
598 P_preconditioner_pt->setup(p_matrix_pt);
599 delete p_matrix_pt; p_matrix_pt = 0;
602 double t_p_prec_time = t_p_prec_finish - t_p_prec_start;
605 oomph_info <<
"P sub-preconditioner setup time [sec]: " 606 << t_p_prec_time <<
"\n";
610 oomph_info <<
"LSC: p_prec setup time: " << t_p_prec_time << std::endl;
618 if (F_preconditioner_pt == 0)
621 Using_default_f_preconditioner =
true;
626 if (F_preconditioner_is_block_preconditioner)
628 unsigned nvelocity_dof_types
629 = Navier_stokes_mesh_pt->finite_element_pt(0)->dim();
632 for (
unsigned i = 0;
i < nvelocity_dof_types;
i++)
637 F_block_preconditioner_pt->
638 turn_into_subsidiary_block_preconditioner(
this,dof_map);
640 F_block_preconditioner_pt->
setup(matrix_pt());
645 F_preconditioner_pt->setup(f_pt);
646 delete f_pt; f_pt = 0;
649 double t_f_prec_time = t_f_prec_finish - t_f_prec_start;
653 oomph_info <<
"F sub-preconditioner setup time [sec]: " 654 << t_f_prec_time <<
"\n";
658 oomph_info <<
"LSC: f_prec setup time: " << t_f_prec_time << std::endl;
664 Preconditioner_has_been_setup =
true;
676 if (Preconditioner_has_been_setup==
false)
678 std::ostringstream error_message;
679 error_message <<
"setup must be called before using preconditioner_solve";
682 OOMPH_CURRENT_FUNCTION,
683 OOMPH_EXCEPTION_LOCATION);
689 std::ostringstream error_message;
690 error_message <<
"The vectors z and r must have the same number of " 694 OOMPH_CURRENT_FUNCTION,
695 OOMPH_EXCEPTION_LOCATION);
717 this->get_block_vector(1,r,temp_vec);
727 if (P_preconditioner_pt==0)
729 std::ostringstream error_message;
730 error_message <<
"P_preconditioner_pt has not been set.";
733 OOMPH_CURRENT_FUNCTION,
734 OOMPH_EXCEPTION_LOCATION);
739 P_preconditioner_pt->preconditioner_solve(temp_vec, another_temp_vec);
745 QBt_mat_vec_pt->multiply(another_temp_vec, temp_vec);
746 another_temp_vec.
clear();
747 F_mat_vec_pt->multiply(temp_vec,another_temp_vec);
749 QBt_mat_vec_pt->multiply_transpose(another_temp_vec, temp_vec);
755 another_temp_vec.
clear();
756 P_preconditioner_pt->preconditioner_solve(temp_vec, another_temp_vec);
768 E_mat_vec_pt->multiply(temp_vec,yet_another_temp_vec);
775 if (P_preconditioner_pt==0)
777 std::ostringstream error_message;
778 error_message <<
"P_preconditioner_pt has not been set.";
781 OOMPH_CURRENT_FUNCTION,
782 OOMPH_EXCEPTION_LOCATION);
787 another_temp_vec.
clear();
788 P_preconditioner_pt->preconditioner_solve(yet_another_temp_vec,
801 temp_vec -= another_temp_vec;
802 return_block_vector(1,temp_vec,z);
813 Bt_mat_vec_pt->multiply(another_temp_vec, temp_vec);
819 another_temp_vec.
clear();
823 get_block_vector(0,r,another_temp_vec);
824 another_temp_vec += temp_vec;
831 if (F_preconditioner_pt==0)
833 std::ostringstream error_message;
834 error_message <<
"F_preconditioner_pt has not been set.";
837 OOMPH_CURRENT_FUNCTION,
838 OOMPH_EXCEPTION_LOCATION);
844 if (F_preconditioner_is_block_preconditioner)
846 return_block_vector(0,another_temp_vec,z);
847 F_preconditioner_pt->preconditioner_solve(z,z);
851 F_preconditioner_pt->preconditioner_solve(another_temp_vec, temp_vec);
852 return_block_vector(0,temp_vec,z);
874 unsigned v_first_row = this->block_distribution_pt(0)->first_row();
875 unsigned v_nrow_local = this->block_distribution_pt(0)->nrow_local();
876 unsigned v_nrow = this->block_distribution_pt(0)->nrow();
879 double* v_values =
new double[v_nrow_local];
880 for (
unsigned i = 0;
i < v_nrow_local;
i++)
887 unsigned p_first_row=0;
888 unsigned p_nrow_local=0;
890 double* p_values = 0;
894 p_first_row = this->block_distribution_pt(1)->first_row();
895 p_nrow_local = this->block_distribution_pt(1)->nrow_local();
896 p_nrow = this->block_distribution_pt(1)->nrow();
899 p_values =
new double[p_nrow_local];
900 for (
unsigned i = 0;
i < p_nrow_local;
i++)
907 bool distributed =
false;
909 if (problem_pt()->distributed() ||
910 this->master_distribution_pt()->distributed())
923 unsigned nproc = comm_pt()->nproc();
926 unsigned my_rank = comm_pt()->my_rank();
933 unsigned first_lookup_row = 0;
934 unsigned last_lookup_row = 0;
935 first_lookup_row = this->master_distribution_pt()->first_row();
936 last_lookup_row = first_lookup_row +
937 this->master_distribution_pt()->nrow_local() - 1;
940 unsigned n_el = Navier_stokes_mesh_pt->nelement();
944 this->master_distribution_pt();
947 unsigned max_block=0;
948 if (!Use_LSC) max_block=1;
949 for (
unsigned block_index=0;block_index<=max_block;block_index++)
953 unsigned v_or_p_first_row=v_first_row;
954 double* v_or_p_values=v_values;
958 v_or_p_first_row=p_first_row;
959 v_or_p_values=p_values;
983 = this->block_distribution_pt(block_index);
986 for (
unsigned e = 0;
e < n_el;
e++)
999 unsigned el_dof = el_pt->
ndof();
1006 unsigned which_one=2;
1007 if (block_index==1) which_one=1;
1015 el_pmm_diagonal,el_vmm_diagonal,which_one);
1019 for (
unsigned i = 0;
i < el_dof;
i++)
1026 if ((eqn_number >= first_lookup_row) &&
1027 (eqn_number <= last_lookup_row) )
1031 if ( this->block_number(eqn_number)==
int(block_index) )
1035 unsigned index = this->index_in_block(eqn_number);
1038 for (
unsigned p = 0; p < nproc; p++)
1040 if ( (index >= velocity_or_press_dist_pt->
first_row(p)) &&
1041 (index < (velocity_or_press_dist_pt->
first_row(p)
1042 +velocity_or_press_dist_pt->
nrow_local(p)) ) )
1051 v_or_p_values[index-v_or_p_first_row]
1052 += el_vmm_diagonal[
i];
1054 else if (block_index==1)
1056 v_or_p_values[index-v_or_p_first_row]
1057 += el_pmm_diagonal[
i];
1065 classified_contributions_send[p]
1066 .push_back(el_vmm_diagonal[
i]);
1067 classified_indices_send[p].push_back(index);
1069 else if (block_index==1)
1071 classified_contributions_send[p]
1072 .push_back(el_pmm_diagonal[
i]);
1073 classified_indices_send[p].push_back(index);
1086 else if (problem_pt()->distributed())
1091 while (!(eqn_number >=master_distribution_pt->
first_row(p) &&
1092 (eqn_number<(master_distribution_pt->
first_row(p)
1101 unclassified_contributions_send[p]
1102 .push_back(el_vmm_diagonal[
i]);
1103 unclassified_indices_send[p].push_back(eqn_number);
1105 else if (block_index==1)
1107 unclassified_contributions_send[p]
1108 .push_back(el_pmm_diagonal[
i]);
1109 unclassified_indices_send[p].push_back(eqn_number);
1122 unsigned* n_unclassified_send =
new unsigned[nproc];
1123 for (
unsigned p = 0; p < nproc; p++)
1127 n_unclassified_send[p] = 0;
1131 n_unclassified_send[p]
1132 = unclassified_contributions_send[p].size();
1137 unsigned* n_unclassified_recv =
new unsigned[nproc];
1138 MPI_Alltoall(n_unclassified_send,1,MPI_UNSIGNED,
1139 n_unclassified_recv,1,MPI_UNSIGNED,
1140 comm_pt()->mpi_comm());
1143 MPI_Aint base_displacement;
1144 MPI_Get_address(v_or_p_values,&base_displacement);
1153 for (
unsigned p = 0; p < nproc; p++)
1158 if (n_unclassified_recv[p] > 0)
1160 unclassified_contributions_recv[p]
1161 =
new double[n_unclassified_recv[p]];
1162 unclassified_indices_recv[p] =
new 1163 unsigned[n_unclassified_recv[p]];
1166 MPI_Datatype recv_types[2];
1167 MPI_Aint recv_displacements[2];
1171 MPI_Type_contiguous(n_unclassified_recv[p],MPI_DOUBLE,
1173 MPI_Type_commit(&recv_types[0]);
1174 MPI_Get_address(unclassified_contributions_recv[p],
1175 &recv_displacements[0]);
1176 recv_displacements[0] -= base_displacement;
1180 MPI_Type_contiguous(n_unclassified_recv[p],MPI_UNSIGNED,
1182 MPI_Type_commit(&recv_types[1]);
1183 MPI_Get_address(unclassified_indices_recv[p],
1184 &recv_displacements[1]);
1185 recv_displacements[1] -= base_displacement;
1189 MPI_Datatype final_recv_type;
1190 MPI_Type_create_struct(2,recv_sz,recv_displacements,recv_types,
1192 MPI_Type_commit(&final_recv_type);
1196 MPI_Irecv(v_or_p_values,1,final_recv_type,p,0,
1197 comm_pt()->mpi_comm(),&req);
1198 unclassified_recv_requests.push_back(req);
1199 unclassified_recv_proc.push_back(p);
1200 MPI_Type_free(&recv_types[0]);
1201 MPI_Type_free(&recv_types[1]);
1202 MPI_Type_free(&final_recv_type);
1206 if (n_unclassified_send[p] > 0)
1209 MPI_Datatype send_types[2];
1210 MPI_Aint send_displacements[2];
1214 MPI_Type_contiguous(n_unclassified_send[p],MPI_DOUBLE,
1216 MPI_Type_commit(&send_types[0]);
1217 MPI_Get_address(&unclassified_contributions_send[p][0],
1218 &send_displacements[0]);
1219 send_displacements[0] -= base_displacement;
1223 MPI_Type_contiguous(n_unclassified_send[p],MPI_UNSIGNED,
1225 MPI_Type_commit(&send_types[1]);
1226 MPI_Get_address(&unclassified_indices_send[p][0],
1227 &send_displacements[1]);
1228 send_displacements[1] -= base_displacement;
1232 MPI_Datatype final_send_type;
1233 MPI_Type_create_struct(2,send_sz,send_displacements,send_types,
1235 MPI_Type_commit(&final_send_type);
1239 MPI_Isend(v_or_p_values,1,final_send_type,p,0,
1240 comm_pt()->mpi_comm(),&req);
1241 unclassified_send_requests.push_back(req);
1242 MPI_Type_free(&send_types[0]);
1243 MPI_Type_free(&send_types[1]);
1244 MPI_Type_free(&final_send_type);
1250 unsigned n_unclassified_recv_req = unclassified_recv_requests.size();
1251 while (n_unclassified_recv_req > 0)
1256 MPI_Waitany(n_unclassified_recv_req,&unclassified_recv_requests[0],
1257 &req_num,MPI_STATUS_IGNORE);
1258 unsigned p = unclassified_recv_proc[req_num];
1259 unclassified_recv_requests.erase(unclassified_recv_requests.begin()
1261 unclassified_recv_proc.erase(unclassified_recv_proc.begin()+req_num);
1262 n_unclassified_recv_req--;
1266 unsigned n_recv = n_unclassified_recv[p];
1267 for (
unsigned i = 0;
i < n_recv;
i++)
1269 unsigned eqn_number = unclassified_indices_recv[p][
i];
1271 if ( this->block_number(eqn_number)==int(block_index) )
1275 unsigned index = this->index_in_block(eqn_number);
1278 for (
unsigned pp = 0; pp < nproc; pp++)
1282 if ( (index >= velocity_or_press_dist_pt->
first_row(pp)) &&
1283 (index < (velocity_or_press_dist_pt->
first_row(pp)
1284 +velocity_or_press_dist_pt->
nrow_local(pp)) ) )
1291 v_or_p_values[index-v_or_p_first_row]
1292 += unclassified_contributions_recv[p][
i];
1297 double v = unclassified_contributions_recv[p][
i];
1298 classified_contributions_send[pp].push_back(v);
1299 classified_indices_send[pp].push_back(index);
1307 delete[] unclassified_contributions_recv[p];
1308 delete[] unclassified_indices_recv[p];
1310 delete[] n_unclassified_recv;
1319 unsigned* n_classified_send =
new unsigned[nproc];
1320 for (
unsigned p = 0; p < nproc; p++)
1324 n_classified_send[p] = 0;
1328 n_classified_send[p]
1329 = classified_contributions_send[p].size();
1334 unsigned* n_classified_recv =
new unsigned[nproc];
1335 MPI_Alltoall(n_classified_send,1,MPI_UNSIGNED,
1336 n_classified_recv,1,MPI_UNSIGNED,
1337 comm_pt()->mpi_comm());
1346 for (
unsigned p = 0; p < nproc; p++)
1351 if (n_classified_recv[p] > 0)
1353 classified_contributions_recv[p]
1354 =
new double[n_classified_recv[p]];
1355 classified_indices_recv[p] =
new unsigned[n_classified_recv[p]];
1358 MPI_Datatype recv_types[2];
1359 MPI_Aint recv_displacements[2];
1363 MPI_Type_contiguous(n_classified_recv[p],MPI_DOUBLE,
1365 MPI_Type_commit(&recv_types[0]);
1366 MPI_Get_address(classified_contributions_recv[p],
1367 &recv_displacements[0]);
1368 recv_displacements[0] -= base_displacement;
1372 MPI_Type_contiguous(n_classified_recv[p],MPI_UNSIGNED,
1374 MPI_Type_commit(&recv_types[1]);
1375 MPI_Get_address(classified_indices_recv[p],
1376 &recv_displacements[1]);
1377 recv_displacements[1] -= base_displacement;
1381 MPI_Datatype final_recv_type;
1382 MPI_Type_create_struct(2,recv_sz,recv_displacements,recv_types,
1384 MPI_Type_commit(&final_recv_type);
1388 MPI_Irecv(v_or_p_values,1,final_recv_type,p,0,
1389 comm_pt()->mpi_comm(),&req);
1390 classified_recv_requests.push_back(req);
1391 classified_recv_proc.push_back(p);
1392 MPI_Type_free(&recv_types[0]);
1393 MPI_Type_free(&recv_types[1]);
1394 MPI_Type_free(&final_recv_type);
1398 if (n_classified_send[p] > 0)
1401 MPI_Datatype send_types[2];
1402 MPI_Aint send_displacements[2];
1406 MPI_Type_contiguous(n_classified_send[p],MPI_DOUBLE,
1408 MPI_Type_commit(&send_types[0]);
1409 MPI_Get_address(&classified_contributions_send[p][0],
1410 &send_displacements[0]);
1411 send_displacements[0] -= base_displacement;
1415 MPI_Type_contiguous(n_classified_send[p],MPI_UNSIGNED,
1417 MPI_Type_commit(&send_types[1]);
1418 MPI_Get_address(&classified_indices_send[p][0],
1419 &send_displacements[1]);
1420 send_displacements[1] -= base_displacement;
1424 MPI_Datatype final_send_type;
1425 MPI_Type_create_struct(2,send_sz,send_displacements,send_types,
1427 MPI_Type_commit(&final_send_type);
1431 MPI_Isend(v_or_p_values,1,final_send_type,p,0,
1432 comm_pt()->mpi_comm(),&req);
1433 classified_send_requests.push_back(req);
1434 MPI_Type_free(&send_types[0]);
1435 MPI_Type_free(&send_types[1]);
1436 MPI_Type_free(&final_send_type);
1442 unsigned n_classified_recv_req = classified_recv_requests.size();
1443 while (n_classified_recv_req > 0)
1448 MPI_Waitany(n_classified_recv_req,&classified_recv_requests[0],
1449 &req_num,MPI_STATUS_IGNORE);
1450 unsigned p = classified_recv_proc[req_num];
1451 classified_recv_requests.erase(classified_recv_requests.begin()
1453 classified_recv_proc.erase(classified_recv_proc.begin()+req_num);
1454 n_classified_recv_req--;
1458 unsigned n_recv = n_classified_recv[p];
1459 for (
unsigned i = 0;
i < n_recv;
i++)
1461 v_or_p_values[classified_indices_recv[p][
i]-v_or_p_first_row]
1462 += classified_contributions_recv[p][
i];
1466 delete[] classified_contributions_recv[p];
1467 delete[] classified_indices_recv[p];
1471 unsigned n_unclassified_send_req = unclassified_send_requests.size();
1472 if (n_unclassified_send_req > 0)
1474 MPI_Waitall(n_unclassified_send_req,&unclassified_send_requests[0],
1477 delete[] unclassified_contributions_send;
1478 delete[] unclassified_indices_send;
1479 delete[] n_unclassified_send;
1482 unsigned n_classified_send_req = classified_send_requests.size();
1483 if (n_classified_send_req > 0)
1485 MPI_Waitall(n_classified_send_req,&classified_send_requests[0],
1488 delete[] classified_indices_send;
1489 delete[] classified_contributions_send;
1490 delete[] n_classified_recv;
1491 delete[] n_classified_send;
1496 v_values=v_or_p_values;
1498 else if (block_index==1)
1500 p_values=v_or_p_values;
1513 unsigned n_el = Navier_stokes_mesh_pt->nelement();
1516 unsigned which_one=0;
1517 if (Use_LSC) which_one=2;
1520 for (
unsigned e = 0;
e < n_el;
e++)
1529 unsigned el_dof = el_pt->
ndof();
1542 el_pmm_diagonal,el_vmm_diagonal,which_one);
1547 std::ostringstream error_message;
1549 <<
"Navier-Stokes mesh contains element that is not of type \n" 1550 <<
"NavierStokesElementWithDiagonalMassMatrices. \n" 1551 <<
"The element is in fact of type " 1552 <<
typeid(*el_pt).name()
1553 <<
"\nWe'll assume that it does not make a used contribution \n" 1554 <<
"to the inverse diagonal mass matrix used in the preconditioner\n" 1555 <<
"and (to avoid divisions by zero) fill in dummy unit entries.\n" 1556 <<
"[This case currently arises with flux control problems\n" 1557 <<
"where for simplicity the NetFluxControlElement has been added \n" 1558 <<
"to the Navier Stokes mesh -- this should probably be changed at\n" 1559 <<
"some point -- if you get this warning in any other context\n" 1560 <<
"you should check your code very carefully]\n";
1562 error_message.str(),
1563 "NavierStokesSchurComplementPreconditioner::assemble_inv_press_and_veloc_mass_matrix_diagonal()",
1564 OOMPH_EXCEPTION_LOCATION);
1568 for (
unsigned j=0;j<el_dof;j++)
1570 el_vmm_diagonal[j]=1.0;
1571 el_pmm_diagonal[j]=1.0;
1576 for (
unsigned i = 0;
i < el_dof;
i++)
1582 if (this->block_number(eqn_number)==0)
1585 unsigned index = this->index_in_block(eqn_number);
1588 if ((index >= v_first_row) &&
1589 (index < (v_first_row + v_nrow_local) ) )
1591 v_values[index-v_first_row] += el_vmm_diagonal[
i];
1595 else if (this->block_number(eqn_number)==1)
1600 unsigned index = this->index_in_block(eqn_number);
1603 if ((index >= p_first_row)&&
1604 (index < (p_first_row + p_nrow_local)) )
1606 p_values[index-p_first_row] += el_pmm_diagonal[
i];
1615 int* v_column_index =
new int[v_nrow_local];
1616 int* v_row_start =
new int[v_nrow_local+1];
1617 for (
unsigned i = 0;
i < v_nrow_local;
i++)
1620 if (v_values[
i]==0.0)
1622 std::ostringstream error_message;
1623 error_message <<
"Zero entry in diagonal of velocity mass matrix\n" 1624 <<
"Index: " <<
i << std::endl;
1626 error_message.str(),
1627 OOMPH_CURRENT_FUNCTION,
1628 OOMPH_EXCEPTION_LOCATION);
1631 v_values[
i] = 1.0/v_values[
i];
1632 v_column_index[
i] = v_first_row +
i;
1635 v_row_start[v_nrow_local] = v_nrow_local;
1638 inv_v_mass_pt =
new CRDoubleMatrix(this->block_distribution_pt(0));
1640 v_values,v_column_index,
1647 int* p_column_index =
new int[p_nrow_local];
1648 int* p_row_start =
new int[p_nrow_local+1];
1649 for (
unsigned i = 0;
i < p_nrow_local;
i++)
1653 if (p_values[
i]==0.0)
1655 std::ostringstream error_message;
1656 error_message <<
"Zero entry in diagonal of pressure mass matrix\n" 1657 <<
"Index: " <<
i << std::endl;
1659 error_message.str(),
1660 OOMPH_CURRENT_FUNCTION,
1661 OOMPH_EXCEPTION_LOCATION);
1664 p_values[
i] = 1.0/p_values[
i];
1666 p_column_index[
i] = p_first_row +
i;
1669 p_row_start[p_nrow_local] = p_nrow_local;
1672 inv_p_mass_pt =
new CRDoubleMatrix(this->block_distribution_pt(1));
1674 p_values,p_column_index,
1686 if (Preconditioner_has_been_setup)
1689 delete Bt_mat_vec_pt;
1692 delete F_mat_vec_pt;
1695 delete QBt_mat_vec_pt;
1698 delete E_mat_vec_pt;
1702 if (Using_default_f_preconditioner)
1704 delete F_preconditioner_pt;
1705 F_preconditioner_pt = 0;
1709 if (Using_default_p_preconditioner)
1711 delete P_preconditioner_pt;
1712 P_preconditioner_pt = 0;
A Generalised Element class.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to Vector r.
void clear()
wipes the DoubleVector
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
virtual void get_pressure_and_velocity_mass_matrix_diagonal(Vector< double > &press_mass_diag, Vector< double > &veloc_mass_diag, const unsigned &which_one=0)=0
Compute the diagonal of the velocity/pressure mass matrices. If which one=0, both are computed...
void clean_up_memory()
Helper function to delete preconditioner data.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector.
void sparse_indexed_output_with_offset(std::string filename)
Indexed output function to print a matrix to a file as i,j,a(i,j) for a(i,j)!=0 only. Specify filename. This uses acual global row numbers.
bool is_halo() const
Is this element a halo?
double Peclet
Peclet number – overwrite with actual Reynolds number.
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero...
unsigned ndof() const
Return the number of equations/dofs in the element.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned...
double timer()
returns the time in seconds after some point in past
void setup(DoubleMatrixBase *matrix_pt)
Setup the preconditioner: store the matrix pointer and the communicator pointer then call preconditio...
unsigned Flag
Flag for solution.
An interface to allow SuperLU to be used as an (exact) Preconditioner.
void setup()
Setup the preconditioner.
unsigned nrow() const
access function to the number of global rows.
Matrix vector product helper class - primarily a wrapper to Trilinos's Epetra matrix vector product m...
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*)
void assemble_inv_press_and_veloc_mass_matrix_diagonal(CRDoubleMatrix *&inv_p_mass_pt, CRDoubleMatrix *&inv_v_mass_pt, const bool &do_both)
Helper function to assemble the inverse diagonals of the pressure and velocity mass matrices from the...
A class for compressed row matrices. This is a distributable object.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
double source_function(const Vector< double > &x_vect)
Source function required to make the solution above an exact solution.
void build_without_copy(const unsigned &ncol, const unsigned &nnz, double *value, int *column_index, int *row_start)
keeps the existing distribution and just matrix that is stored without copying the matrix data ...
void wind_function(const Vector< double > &x, Vector< double > &wind)
Wind.