31 #ifndef OOMPH_BLOCK_PRECONDITION_HEADER 32 #define OOMPH_BLOCK_PRECONDITION_HEADER 37 #include <oomph-lib-config.h> 139 this->
build(0,0,
false);
154 std::ostringstream err_msg;
155 err_msg <<
"Trying to construct a BlockSelector object with:\n" 156 <<
"replacement_block_pt != 0 and wanted == false" 157 <<
"If you require the block, please set wanted == true.\n";
159 OOMPH_CURRENT_FUNCTION,
160 OOMPH_EXCEPTION_LOCATION);
178 std::ostringstream warning_msg;
179 warning_msg <<
"Warning: BlockSelector destructor is called but...\n" 180 <<
"replacement_block_pt() is not null.\n" 181 <<
"Please remember to null this via the function\n" 182 <<
"BlockSelector::null_replacement_block_pt()\n" 187 OOMPH_CURRENT_FUNCTION,
188 OOMPH_EXCEPTION_LOCATION);
202 std::ostringstream err_msg;
203 err_msg <<
"Trying to select block with:\n" 204 <<
"replacement_block_pt != 0 and wanted == false" 205 <<
"If you require the block, please set wanted == true.\n" 206 <<
"row_index: " << row_index <<
"\n" 207 <<
"column_index: " << column_index <<
"\n";
209 OOMPH_CURRENT_FUNCTION,
210 OOMPH_EXCEPTION_LOCATION);
230 std::ostringstream warning_msg;
231 warning_msg <<
"Trying to set Wanted = false, but replacement_block_pt is not null.\n" 232 <<
"Please call null_replacement_block_pt()\n" 233 <<
"(remember to free memory if necessary)\n" 237 OOMPH_CURRENT_FUNCTION,
238 OOMPH_EXCEPTION_LOCATION);
259 std::ostringstream err_msg;
260 err_msg <<
"Trying to set replacement_block_pt, but Wanted == false.\n" 261 <<
"Please call want_block()\n" 265 OOMPH_CURRENT_FUNCTION,
266 OOMPH_EXCEPTION_LOCATION);
317 o_stream <<
"Row_index = " << block_selector.
row_index() <<
"\n" 318 <<
"Column_index = " << block_selector.
column_index() <<
"\n" 319 <<
"Wanted = " << block_selector.
wanted() <<
"\n" 320 <<
"Replacement_block_pt = ";
349 std::ostringstream err_msg;
350 err_msg <<
"Trying to set replacement_block_pt, but Wanted == false.\n" 351 <<
"Please either not set the replacement_block_pt or call the function\n" 352 <<
"do_not_want_block()\n" 356 OOMPH_CURRENT_FUNCTION,
357 OOMPH_EXCEPTION_LOCATION);
427 template<
typename MATRIX>
434 : Ndof_types_in_mesh(0)
439 Master_block_preconditioner_pt = 0;
464 Internal_preconditioner_matrix_distribution_pt = 0;
467 Preconditioner_matrix_distribution_pt = 0;
481 Internal_nblock_types=0;
488 Internal_ndof_types=0;
491 Block_distribution_pt.resize(0);
494 Internal_block_distribution_pt.resize(0);
498 Dof_block_distribution_pt.resize(0);
502 Block_to_dof_map_coarse.resize(0);
503 Block_to_dof_map_fine.resize(0);
506 Recursive_debug_flag =
false;
517 this->clear_block_preconditioner_base();
537 if(is_subsidiary_block_preconditioner())
539 return master_block_preconditioner_pt()->matrix_pt();
547 std::ostringstream error_msg;
548 error_msg <<
"Matrix is not correct type.";
550 OOMPH_CURRENT_FUNCTION,
551 OOMPH_EXCEPTION_LOCATION);
563 Recursive_debug_flag =
true;
564 if(is_subsidiary_block_preconditioner())
565 this->master_block_preconditioner_pt()
566 ->turn_on_recursive_debug_flag();
573 Recursive_debug_flag =
false;
574 if(is_subsidiary_block_preconditioner())
575 this->master_block_preconditioner_pt()
576 ->turn_off_recursive_debug_flag();
610 void turn_into_subsidiary_block_preconditioner
652 void turn_into_subsidiary_block_preconditioner
672 virtual void block_setup();
693 MATRIX& output_matrix,
694 const bool& ignore_replacement_block =
false)
const 698 unsigned n_block_types = this->nblock_types();
699 if((i > n_block_types) || (j > n_block_types))
701 std::ostringstream err_msg;
702 err_msg <<
"Requested block("<< i <<
","<< j <<
")"<<
"\n" 703 <<
"but nblock_types() is " << n_block_types <<
".\n" 704 <<
"Maybe your argument to block_setup(...) is incorrect?" 707 OOMPH_CURRENT_FUNCTION,
708 OOMPH_EXCEPTION_LOCATION);
792 const unsigned ndofblock_in_row = Block_to_dof_map_coarse[
i].size();
793 const unsigned ndofblock_in_col = Block_to_dof_map_coarse[j].size();
797 if(ndofblock_in_row == 1 && ndofblock_in_col == 1)
800 const unsigned wanted_dof_row = Block_to_dof_map_coarse[
i][0];
801 const unsigned wanted_dof_col = Block_to_dof_map_coarse[j][0];
807 if((Replacement_dof_block_pt.get(wanted_dof_row,wanted_dof_col) == 0) ||
808 ignore_replacement_block)
810 get_dof_level_block(wanted_dof_row, wanted_dof_col,
811 output_matrix, ignore_replacement_block);
819 Replacement_dof_block_pt.get(wanted_dof_row, wanted_dof_col),
843 for (
unsigned row_dofblock = 0; row_dofblock < ndofblock_in_row;
848 const unsigned wanted_dof_row
849 = Block_to_dof_map_coarse[
i][row_dofblock];
851 for (
unsigned col_dofblock = 0; col_dofblock < ndofblock_in_col;
856 const unsigned wanted_dof_col
857 = Block_to_dof_map_coarse[j][col_dofblock];
860 tmp_blocks_pt(row_dofblock,col_dofblock)
861 = Replacement_dof_block_pt.get(wanted_dof_row,wanted_dof_col);
866 if((tmp_blocks_pt(row_dofblock,col_dofblock) == 0) ||
867 ignore_replacement_block)
871 new_block[row_dofblock][col_dofblock] = 1;
878 get_dof_level_block(wanted_dof_row,
880 *tmp_blocks_pt(row_dofblock,col_dofblock),
881 ignore_replacement_block);
945 for (
unsigned row_dof_i = 0; row_dof_i < ndofblock_in_row; row_dof_i++)
947 const unsigned mapped_dof_i = Block_to_dof_map_coarse[
i][row_dof_i];
948 if(is_master_block_preconditioner())
950 tmp_row_dist_pt[row_dof_i]
951 = Internal_block_distribution_pt[mapped_dof_i];
955 tmp_row_dist_pt[row_dof_i]
956 = Dof_block_distribution_pt[mapped_dof_i];
964 for (
unsigned col_dof_i = 0; col_dof_i < ndofblock_in_col; col_dof_i++)
966 const unsigned mapped_dof_j = Block_to_dof_map_coarse[j][col_dof_i];
967 if(is_master_block_preconditioner())
969 tmp_col_dist_pt[col_dof_i]
970 = Internal_block_distribution_pt[mapped_dof_j];
974 tmp_col_dist_pt[col_dof_i]
975 = Dof_block_distribution_pt[mapped_dof_j];
986 for (
unsigned row_i = 0; row_i < ndofblock_in_row; row_i++)
988 for (
unsigned col_i = 0; col_i < ndofblock_in_col; col_i++)
990 if(new_block[row_i][col_i])
992 delete tmp_blocks_pt(row_i,col_i);
1005 const bool& ignore_replacement_block =
false)
const 1007 MATRIX output_matrix;
1008 get_block(i, j, output_matrix, ignore_replacement_block);
1009 return output_matrix;
1015 if(is_subsidiary_block_preconditioner())
1017 master_block_preconditioner_pt()
1018 ->set_master_matrix_pt(in_matrix_pt);
1022 this->set_matrix_pt(in_matrix_pt);
1029 MATRIX* in_matrix_pt,
1030 MATRIX& output_matrix)
1032 MATRIX* backup_matrix_pt = matrix_pt();
1033 set_master_matrix_pt(in_matrix_pt);
1034 get_block(i, j, output_matrix,
true);
1035 set_master_matrix_pt(backup_matrix_pt);
1064 void get_dof_level_block(
const unsigned&
i,
const unsigned& j,
1065 MATRIX& output_block,
1066 const bool& ignore_replacement_block =
false)
const;
1151 unsigned const para_selected_block_nrow = selected_block.
nrow();
1152 unsigned const para_selected_block_ncol = selected_block.
ncol();
1153 unsigned const para_nblocks = this->nblock_types();
1156 if(para_selected_block_nrow == 0)
1158 std::ostringstream error_msg;
1159 error_msg <<
"selected_block has nrow = 0.\n";
1161 OOMPH_CURRENT_FUNCTION,
1162 OOMPH_EXCEPTION_LOCATION);
1169 if((para_selected_block_nrow > para_nblocks) ||
1170 (para_selected_block_ncol > para_nblocks))
1172 std::ostringstream error_msg;
1173 error_msg <<
"Trying to concatenate a " 1174 << para_selected_block_nrow <<
" by " 1175 << para_selected_block_ncol
1176 <<
" block matrix,\n" 1177 <<
"but there are only " 1178 << para_nblocks <<
" block types.\n";
1180 OOMPH_CURRENT_FUNCTION,
1181 OOMPH_EXCEPTION_LOCATION);
1190 for (
unsigned row_i = 0; row_i < para_selected_block_nrow; row_i++)
1192 const unsigned col_0_row_index = selected_block[row_i][0].row_index();
1194 for (
unsigned col_i = 0; col_i < para_selected_block_ncol; col_i++)
1196 const unsigned para_b_i = selected_block[row_i][col_i].row_index();
1197 const unsigned para_b_j = selected_block[row_i][col_i].column_index();
1199 if(col_0_row_index != para_b_i)
1201 std::ostringstream err_msg;
1202 err_msg <<
"Block index for block(" << row_i <<
"," << col_i <<
") " 1203 <<
"contains block indices (" << para_b_i <<
"," 1204 << para_b_j <<
").\n" 1205 <<
"But the row index for the first column is " 1206 << col_0_row_index <<
", they must be the same!\n";
1208 OOMPH_CURRENT_FUNCTION,
1209 OOMPH_EXCEPTION_LOCATION);
1217 for (
unsigned col_i = 0; col_i < para_selected_block_ncol; col_i++)
1219 const unsigned row_0_col_index = selected_block[0][col_i].column_index();
1221 for (
unsigned row_i = 0; row_i < para_selected_block_nrow; row_i++)
1223 const unsigned para_b_i = selected_block[row_i][col_i].row_index();
1224 const unsigned para_b_j = selected_block[row_i][col_i].column_index();
1226 if(row_0_col_index != para_b_j)
1228 std::ostringstream err_msg;
1229 err_msg <<
"Block index for block(" << row_i <<
"," << col_i <<
") " 1230 <<
"contains block indices (" << para_b_i <<
"," 1231 << para_b_j <<
").\n" 1232 <<
"But the col index for the first row is " 1233 << row_0_col_index <<
", they must be the same!\n";
1235 OOMPH_CURRENT_FUNCTION,
1236 OOMPH_EXCEPTION_LOCATION);
1250 for (
unsigned row_i = 0; row_i < para_selected_block_nrow; row_i++)
1252 const unsigned para_b_i = selected_block[row_i][0].row_index();
1253 const unsigned para_b_j = selected_block[row_i][0].column_index();
1254 if(para_b_i > para_nblocks)
1256 std::ostringstream err_msg;
1257 err_msg <<
"Block index for block(" << row_i <<
",0) " 1258 <<
"contains block indices (" << para_b_i <<
"," 1259 << para_b_j <<
").\n" 1260 <<
"But there are only " << para_nblocks
1261 <<
" nblock_types().\n";
1263 OOMPH_CURRENT_FUNCTION,
1264 OOMPH_EXCEPTION_LOCATION);
1270 for (
unsigned col_i = 0; col_i < para_selected_block_ncol; col_i++)
1272 const unsigned para_b_i = selected_block[0][col_i].row_index();
1273 const unsigned para_b_j = selected_block[0][col_i].column_index();
1274 if(para_b_j > para_nblocks)
1276 std::ostringstream err_msg;
1277 err_msg <<
"Block index for block(0," << col_i <<
") " 1278 <<
"contains block indices (" << para_b_i <<
"," 1279 << para_b_j <<
").\n" 1280 <<
"But there are only " << para_nblocks
1281 <<
" nblock_types().\n";
1283 OOMPH_CURRENT_FUNCTION,
1284 OOMPH_EXCEPTION_LOCATION);
1290 std::set<unsigned> row_index_set;
1291 for (
unsigned row_i = 0; row_i < para_selected_block_nrow; row_i++)
1293 std::pair<std::set<unsigned>::iterator,
bool> row_index_set_ret;
1295 const unsigned row_i_index = selected_block[row_i][0].row_index();
1298 = row_index_set.insert(row_i_index);
1300 if(!row_index_set_ret.second)
1302 std::ostringstream err_msg;
1303 err_msg <<
"The row " << row_i_index <<
" is already inserted.\n";
1305 OOMPH_CURRENT_FUNCTION,
1306 OOMPH_EXCEPTION_LOCATION);
1312 std::set<unsigned> col_index_set;
1313 for (
unsigned col_i = 0; col_i < para_selected_block_ncol; col_i++)
1315 std::pair<std::set<unsigned>::iterator,
bool> col_index_set_ret;
1317 const unsigned col_i_index = selected_block[0][col_i].column_index();
1320 = col_index_set.insert(col_i_index);
1322 if(!col_index_set_ret.second)
1324 std::ostringstream err_msg;
1325 err_msg <<
"The col " << col_i_index <<
" is already inserted.\n";
1327 OOMPH_CURRENT_FUNCTION,
1328 OOMPH_EXCEPTION_LOCATION);
1336 for (
unsigned block_i = 0; block_i < para_selected_block_nrow; block_i++)
1338 for (
unsigned block_j = 0; block_j < para_selected_block_ncol; block_j++)
1341 = selected_block[block_i][block_j].replacement_block_pt();
1343 if(tmp_block_pt != 0)
1345 if(!tmp_block_pt->
built())
1347 std::ostringstream err_msg;
1348 err_msg <<
"The matrix pointed to by block(" 1349 << block_i <<
"," << block_j <<
") is not built.\n";
1351 OOMPH_CURRENT_FUNCTION,
1352 OOMPH_EXCEPTION_LOCATION);
1358 const unsigned row_selected_block
1359 = selected_block[block_i][block_j].row_index();
1362 = block_distribution_pt(row_selected_block);
1364 if(*tmp_block_dist_pt != *another_tmp_block_dist_pt)
1366 std::ostringstream err_msg;
1367 err_msg <<
"block_distribution_pt " << row_selected_block <<
"\n" 1368 <<
"does not match the distribution from the block_pt() " 1369 <<
" in selected_block[" 1370 << block_i <<
"][" << block_j <<
"].\n";
1372 OOMPH_CURRENT_FUNCTION,
1373 OOMPH_EXCEPTION_LOCATION);
1388 for (
unsigned block_i = 0; block_i < para_selected_block_nrow; block_i++)
1390 for (
unsigned block_j = 0; block_j < para_selected_block_ncol; block_j++)
1394 = selected_block[block_i][block_j].replacement_block_pt();
1396 if(tmp_block_pt != 0)
1398 const unsigned tmp_block_ncol = tmp_block_pt->
ncol();
1400 const unsigned selected_block_col
1401 = selected_block[block_i][block_j].column_index();
1404 const unsigned another_tmp_block_ncol
1405 = block_distribution_pt(selected_block_col)->
nrow();
1407 if(tmp_block_ncol != another_tmp_block_ncol)
1409 std::ostringstream err_msg;
1410 err_msg <<
"block_pt in selected_block[" 1411 << block_i <<
"][" << block_j <<
"] " 1412 <<
"has ncol = " << tmp_block_ncol <<
".\n" 1413 <<
"But the corresponding block_distribution_pt(" 1414 << selected_block_col <<
") has nrow = " 1415 << another_tmp_block_ncol
1418 OOMPH_CURRENT_FUNCTION,
1419 OOMPH_EXCEPTION_LOCATION);
1427 MATRIX output_matrix;
1430 const unsigned nblock_row = selected_block.
nrow();
1431 const unsigned nblock_col = selected_block.
ncol();
1441 for (
unsigned row_i = 0; row_i < nblock_row; row_i++)
1443 const unsigned selected_row_index
1444 = selected_block[row_i][0].row_index();
1446 row_dist_pt[row_i] = Block_distribution_pt[selected_row_index];
1447 block_row_index[row_i] = selected_row_index;
1452 for (
unsigned col_i = 0; col_i < nblock_col; col_i++)
1454 const unsigned selected_col_index
1455 = selected_block[0][col_i].column_index();
1457 col_dist_pt[col_i] = Block_distribution_pt[selected_col_index];
1458 block_col_index[col_i] = selected_col_index;
1469 std::map<Vector<unsigned>,
1472 iter = Auxiliary_block_distribution_pt.find(block_row_index);
1474 if(iter != Auxiliary_block_distribution_pt.end())
1476 output_matrix.
build(iter->second);
1482 insert_auxiliary_block_distribution(block_row_index,tmp_dist_pt);
1483 output_matrix.build(tmp_dist_pt);
1488 iter = Auxiliary_block_distribution_pt.find(block_col_index);
1489 if(iter == Auxiliary_block_distribution_pt.end())
1493 insert_auxiliary_block_distribution(block_col_index,tmp_dist_pt);
1508 for (
unsigned block_i = 0; block_i < nblock_row; block_i++)
1510 for (
unsigned block_j = 0; block_j < nblock_col; block_j++)
1512 const bool block_wanted = selected_block[block_i][block_j].wanted();
1517 = selected_block[block_i][block_j].replacement_block_pt();
1519 if(tmp_block_pt == 0)
1521 new_block[block_i][block_j] = 1;
1526 const unsigned tmp_block_i = block_row_index[block_i];
1527 const unsigned tmp_block_j = block_col_index[block_j];
1530 this->get_block(tmp_block_i,tmp_block_j,
1531 *block_pt(block_i,block_j));
1535 block_pt(block_i,block_j) = tmp_block_pt;
1548 for (
unsigned block_i = 0; block_i < nblock_row; block_i++)
1550 for (
unsigned block_j = 0; block_j < nblock_col; block_j++)
1552 if(new_block[block_i][block_j])
1554 delete block_pt(block_i,block_j);
1559 return output_matrix;
1569 void get_concatenated_block_vector(
const Vector<unsigned>& block_vec_number,
1580 void return_concatenated_block_vector(
1635 void get_block_vector(
const unsigned& n,
const DoubleVector& v,
1644 void return_block_vector(
const unsigned& n,
const DoubleVector& b,
1672 void get_block_ordered_preconditioner_vector(
const DoubleVector& v,
1687 void return_block_ordered_preconditioner_vector(
const DoubleVector& w,
1694 if(Block_to_dof_map_coarse.size() == 0)
1696 std::ostringstream error_msg;
1697 error_msg <<
"The Block_to_dof_map_coarse vector is not setup for \n" 1698 <<
"this block preconditioner.\n\n" 1700 <<
"This vector is always set up within block_setup(...).\n" 1701 <<
"If block_setup() is already called, then perhaps there is\n" 1702 <<
"something wrong with your block preconditionable elements.\n" 1705 OOMPH_CURRENT_FUNCTION,
1706 OOMPH_EXCEPTION_LOCATION);
1711 return Block_to_dof_map_coarse.size();
1719 if (this->is_master_block_preconditioner())
1721 std::ostringstream err_msg;
1725 err_msg <<
"No meshes have been set for this block preconditioner!\n" 1726 <<
"Set one with set_nmesh(...), set_mesh(...)" << std::endl;
1728 OOMPH_CURRENT_FUNCTION,
1729 OOMPH_EXCEPTION_LOCATION);
1730 for (
unsigned m=0;m<n;m++)
1734 err_msg <<
"The mesh pointer to mesh " << m <<
" is null!\n" 1735 <<
"Set a non-null one with set_mesh(...)" << std::endl;
1737 OOMPH_CURRENT_FUNCTION,
1738 OOMPH_EXCEPTION_LOCATION);
1754 if(is_subsidiary_block_preconditioner())
1757 if(Doftype_coarsen_map_coarse.size() == 0)
1759 std::ostringstream error_msg;
1760 error_msg <<
"The Doftype_coarsen_map_coarse vector is not setup for \n" 1761 <<
"this SUBSIDIARY block preconditioner.\n\n" 1763 <<
"For SUBSIDARY block preconditioners at any level, this\n" 1764 <<
"vector is set up in the function \n" 1765 <<
"turn_into_subsidiary_block_preconditioner(...).\n\n" 1767 <<
"Being a SUBSIDIARY block preconditioner means that \n" 1768 <<
"(Master_block_preconditioner_pt == 0) is true.\n" 1769 <<
"The Master_block_preconditioner_pt MUST be set in the " 1771 <<
"turn_into_subsidiary_block_preconditioner(...).\n\n" 1773 <<
"Somewhere, the Master_block_preconditioner_pt pointer is\n" 1774 <<
"set but not by the function\n" 1775 <<
"turn_into_subsidiary_block_preconditioner(...).\n" 1778 OOMPH_CURRENT_FUNCTION,
1779 OOMPH_EXCEPTION_LOCATION);
1783 return Doftype_coarsen_map_coarse.size();
1790 return internal_ndof_types();
1808 if(is_subsidiary_block_preconditioner())
1810 std::ostringstream error_msg;
1811 error_msg <<
"The mesh_pt() function should not be called on a\n" 1812 <<
"subsidiary block preconditioner." << std::endl;
1814 OOMPH_CURRENT_FUNCTION,
1815 OOMPH_EXCEPTION_LOCATION);
1819 const Mesh* mesh_i_pt = Mesh_pt[
i];
1824 std::ostringstream error_msg;
1825 error_msg <<
"Mesh pointer " << mesh_i_pt <<
" is null.";
1827 OOMPH_CURRENT_FUNCTION,
1828 OOMPH_EXCEPTION_LOCATION);
1843 return Mesh_pt.size();
1849 int internal_block_number = this->internal_block_number(i_dof);
1851 if(internal_block_number == -1)
1853 return internal_block_number;
1859 unsigned block_i = 0;
1860 while(std::find(Block_to_dof_map_fine[block_i].begin(),
1861 Block_to_dof_map_fine[block_i].end(),
1862 internal_block_number)
1863 == Block_to_dof_map_fine[block_i].end())
1878 int internal_dof_block_number = this->internal_dof_number(i_dof);
1880 if(internal_dof_block_number >= 0)
1883 unsigned ex_blk_number = this->block_number(i_dof);
1885 int internal_index_in_dof = this->internal_index_in_dof(i_dof);
1889 = internal_block_distribution_pt(internal_dof_block_number)
1890 ->rank_of_global_row(internal_index_in_dof);
1893 const unsigned ndof_in_block
1894 = Block_to_dof_map_fine[ex_blk_number].size();
1897 for (
unsigned dof_i = 0; dof_i < ndof_in_block; dof_i++)
1899 index += internal_block_distribution_pt(
1900 Block_to_dof_map_fine[ex_blk_number][dof_i])
1901 ->first_row(block_proc);
1907 while(
int(Block_to_dof_map_fine[ex_blk_number][j])!= internal_dof_block_number)
1909 index += internal_block_distribution_pt(
1910 Block_to_dof_map_fine[ex_blk_number][j])->nrow_local(block_proc);
1915 index += (internal_index_in_dof -
1916 internal_block_distribution_pt(
1917 internal_dof_block_number)
1918 ->first_row(block_proc));
1931 if(Block_distribution_pt.size() == 0)
1933 std::ostringstream error_msg;
1934 error_msg <<
"Block distributions are not set up.\n" 1935 <<
"Have you called block_setup(...)?\n" 1938 OOMPH_CURRENT_FUNCTION,
1939 OOMPH_EXCEPTION_LOCATION);
1941 if(b > nblock_types())
1943 std::ostringstream error_msg;
1944 error_msg <<
"You requested the distribution for the block " 1946 <<
"But there are only " << nblock_types() <<
" block types.\n" 1949 OOMPH_CURRENT_FUNCTION,
1950 OOMPH_EXCEPTION_LOCATION);
1954 return Block_distribution_pt[b];
1962 if(Block_distribution_pt.size() == 0)
1964 std::ostringstream error_msg;
1965 error_msg <<
"Block distributions are not set up.\n" 1966 <<
"Have you called block_setup(...)?\n" 1969 OOMPH_CURRENT_FUNCTION,
1970 OOMPH_EXCEPTION_LOCATION);
1972 if(b > nblock_types())
1974 std::ostringstream error_msg;
1975 error_msg <<
"You requested the distribution for the block " 1977 <<
"But there are only " << nblock_types() <<
" block types.\n" 1980 OOMPH_CURRENT_FUNCTION,
1981 OOMPH_EXCEPTION_LOCATION);
1985 return Block_distribution_pt[b];
1993 if(b > ndof_types())
1995 std::ostringstream error_msg;
1996 error_msg <<
"You requested the distribution for the dof block " 1998 <<
"But there are only " << ndof_types() <<
" DOF types.\n" 2001 OOMPH_CURRENT_FUNCTION,
2002 OOMPH_EXCEPTION_LOCATION);
2007 if(is_master_block_preconditioner())
2010 if(Internal_block_distribution_pt.size() == 0)
2012 std::ostringstream error_msg;
2013 error_msg <<
"Internal block distributions are not set up.\n" 2014 <<
"Have you called block_setup(...)?\n" 2017 OOMPH_CURRENT_FUNCTION,
2018 OOMPH_EXCEPTION_LOCATION);
2024 return Internal_block_distribution_pt[b];
2029 if(Dof_block_distribution_pt.size() == 0)
2031 std::ostringstream error_msg;
2032 error_msg <<
"Dof block distributions are not set up.\n" 2033 <<
"Have you called block_setup(...)?\n" 2036 OOMPH_CURRENT_FUNCTION,
2037 OOMPH_EXCEPTION_LOCATION);
2040 return Dof_block_distribution_pt[b];
2050 if (is_master_block_preconditioner())
2052 return this->distribution_pt();
2056 return Master_block_preconditioner_pt->master_distribution_pt();
2071 if (is_subsidiary_block_preconditioner())
2073 std::ostringstream err_msg;
2074 err_msg <<
"A subsidiary block preconditioner should not care about\n" 2075 <<
"anything to do with meshes.";
2077 OOMPH_EXCEPTION_LOCATION);
2080 if(Ndof_types_in_mesh.size() == 0)
2082 return mesh_pt(i)->ndof_types();
2086 return Ndof_types_in_mesh[
i];
2094 return (this->Master_block_preconditioner_pt != 0);
2101 return (this->Master_block_preconditioner_pt == 0);
2109 Output_base_filename = basefilename;
2115 Output_base_filename.clear();
2121 return Output_base_filename.size() > 0;
2127 const unsigned& precision = 8)
const 2129 unsigned nblocks = internal_nblock_types();
2131 for(
unsigned i=0; i<nblocks; i++)
2133 for(
unsigned j=0; j<nblocks; j++)
2141 get_block(i,j).sparse_indexed_output(filename, precision,
true);
2153 if (is_master_block_preconditioner())
2155 Index_in_dof_block_dense.clear();
2156 Dof_number_dense.clear();
2157 #ifdef OOMPH_HAS_MPI 2158 Index_in_dof_block_sparse.clear();
2159 Dof_number_sparse.clear();
2160 Global_index_sparse.clear();
2161 Index_in_dof_block_sparse.clear();
2162 Dof_number_sparse.clear();
2164 Dof_dimension.clear();
2166 Ndof_in_block.clear();
2167 Dof_number_to_block_number_lookup.clear();
2168 Block_number_to_dof_number_lookup.clear();
2175 if (is_master_block_preconditioner())
2177 std::ostringstream error_message;
2178 error_message <<
"This block preconditioner does not have " 2179 <<
"a master preconditioner.";
2180 throw OomphLibError(error_message.str(), OOMPH_CURRENT_FUNCTION,
2181 OOMPH_EXCEPTION_LOCATION);
2184 return Master_block_preconditioner_pt;
2192 Replacement_dof_block_pt.clear();
2195 this->clear_distribution();
2196 unsigned nblock = Internal_block_distribution_pt.size();
2197 for (
unsigned b = 0; b < nblock; b++)
2199 delete Internal_block_distribution_pt[b];
2201 Internal_block_distribution_pt.resize(0);
2204 Global_index.clear();
2207 this->post_block_matrix_assembly_partial_clear();
2209 #ifdef OOMPH_HAS_MPI 2211 unsigned nr = Rows_to_send_for_get_block.nrow();
2212 unsigned nc = Rows_to_send_for_get_block.ncol();
2213 for (
unsigned p = 0; p < nc; p++)
2215 delete[] Rows_to_send_for_get_ordered[p];
2216 delete[] Rows_to_recv_for_get_ordered[p];
2217 for (
unsigned b = 0; b < nr; b++)
2219 delete[] Rows_to_recv_for_get_block(b,p);
2220 delete[] Rows_to_send_for_get_block(b,p);
2223 Rows_to_recv_for_get_block.resize(0,0);
2224 Nrows_to_recv_for_get_block.resize(0,0);
2225 Rows_to_send_for_get_block.resize(0,0);
2226 Nrows_to_send_for_get_block.resize(0,0);
2227 Rows_to_recv_for_get_ordered.clear();
2228 Nrows_to_recv_for_get_ordered.clear();
2229 Rows_to_send_for_get_ordered.clear();
2230 Nrows_to_send_for_get_ordered.clear();
2235 if (is_master_block_preconditioner())
2238 Internal_ndof_types = 0;
2239 Internal_nblock_types = 0;
2243 delete Internal_preconditioner_matrix_distribution_pt;
2244 Internal_preconditioner_matrix_distribution_pt = 0;
2245 delete Preconditioner_matrix_distribution_pt;
2246 Preconditioner_matrix_distribution_pt = 0;
2249 const unsigned n_existing_block_dist
2250 = Block_distribution_pt.size();
2251 for (
unsigned dist_i = 0; dist_i < n_existing_block_dist; dist_i++)
2253 delete Block_distribution_pt[dist_i];
2257 Block_distribution_pt.clear();
2262 for (
unsigned i = 0; i < n_existing_block_dist; i++)
2264 preconditioner_matrix_key[
i] =
i;
2271 = Auxiliary_block_distribution_pt.begin();
2273 while(iter != Auxiliary_block_distribution_pt.end())
2275 if(iter->first != preconditioner_matrix_key)
2277 delete iter->second;
2287 Auxiliary_block_distribution_pt.
clear();
2290 const unsigned ndof_block_dist = Dof_block_distribution_pt.size();
2291 for (
unsigned dof_i = 0; dof_i < ndof_block_dist; dof_i++)
2293 delete Dof_block_distribution_pt[dof_i];
2295 Dof_block_distribution_pt.clear();
2304 oomph_info <<
"===========================================" << std::endl;
2305 oomph_info <<
"Block Preconditioner Documentation" << std::endl
2307 oomph_info <<
"Number of DOF types: " << internal_ndof_types() << std::endl;
2308 oomph_info <<
"Number of block types: " << internal_nblock_types()
2311 if (is_subsidiary_block_preconditioner())
2313 for (
unsigned d = 0; d < Internal_ndof_types; d++)
2315 oomph_info <<
"Master DOF number " << d <<
" : " 2316 << this->internal_master_dof_number(d) << std::endl;
2320 for (
unsigned b = 0; b < internal_nblock_types(); b++)
2322 oomph_info <<
"Block " << b <<
" DOF types:";
2323 for (
unsigned i = 0; i < Block_number_to_dof_number_lookup[b].size();
2326 oomph_info <<
" " << Block_number_to_dof_number_lookup[b][
i];
2331 oomph_info <<
"Master block preconditioner distribution:" << std::endl;
2332 oomph_info << *master_distribution_pt() << std::endl;
2333 oomph_info <<
"Internal preconditioner matrix distribution:" << std::endl;
2334 oomph_info << *internal_preconditioner_matrix_distribution_pt() << std::endl;
2335 oomph_info <<
"Preconditioner matrix distribution:" << std::endl;
2336 oomph_info << *preconditioner_matrix_distribution_pt() << std::endl;
2337 for (
unsigned b = 0; b < Internal_nblock_types; b++)
2339 oomph_info <<
"Internal block " << b <<
" distribution:" << std::endl;
2340 oomph_info << *Internal_block_distribution_pt[b] << std::endl;
2342 for (
unsigned b = 0; b < nblock_types(); b++)
2344 oomph_info <<
"Block " << b <<
" distribution:" << std::endl;
2345 oomph_info << *Block_distribution_pt[b] << std::endl;
2358 oomph_info <<
"===========================================" << std::endl;
2366 return Doftype_coarsen_map_fine;
2374 const unsigned n_dof_types = ndof_types();
2376 if(i >= n_dof_types)
2378 std::ostringstream err_msg;
2379 err_msg <<
"Trying to get the most fine grain dof types in dof type " 2380 << i <<
",\nbut there are only " << n_dof_types
2381 <<
" number of dof types.\n";
2383 OOMPH_CURRENT_FUNCTION,
2384 OOMPH_EXCEPTION_LOCATION);
2387 return Doftype_coarsen_map_fine[
i];
2395 const unsigned n_dof_types = ndof_types();
2397 if(i >= n_dof_types)
2399 std::ostringstream err_msg;
2400 err_msg <<
"Trying to get the number of most fine grain dof types " 2401 <<
"in dof type " << i <<
",\n" 2402 <<
"but there are only " << n_dof_types
2403 <<
" number of dof types.\n";
2405 OOMPH_CURRENT_FUNCTION,
2406 OOMPH_EXCEPTION_LOCATION);
2409 return Doftype_coarsen_map_fine[
i].size();
2415 return Replacement_dof_block_pt;
2433 const unsigned nblock = block_col_indices.size();
2437 const unsigned col_index = block_col_indices[0];
2438 matvec_prod_pt->
setup(block_pt,
2439 Block_distribution_pt[col_index]);
2443 std::map<Vector<unsigned>,
2446 iter = Auxiliary_block_distribution_pt.find(block_col_indices);
2447 if(iter != Auxiliary_block_distribution_pt.end())
2449 matvec_prod_pt->
setup(block_pt,iter->second);
2454 for (
unsigned b = 0; b < nblock; b++)
2456 tmp_vec_dist_pt[b] = Block_distribution_pt[block_col_indices[b]];
2462 insert_auxiliary_block_distribution(block_col_indices,tmp_dist_pt);
2463 matvec_prod_pt->
setup(block_pt,tmp_dist_pt);
2472 const unsigned& block_col_index)
2475 setup_matrix_vector_product(matvec_prod_pt,block_pt,col_index_vector);
2514 void internal_get_block_ordered_preconditioner_vector(
const DoubleVector& v,
2534 void internal_return_block_ordered_preconditioner_vector(
2557 if(Internal_nblock_types == 0)
2559 std::ostringstream err_msg;
2560 err_msg <<
"(Internal_nblock_types == 0) is true. \n" 2561 <<
"Did you remember to call the function block_setup(...)?\n\n" 2563 <<
"This variable is always set up within block_setup(...).\n" 2564 <<
"If block_setup() is already called, then perhaps there is\n" 2565 <<
"something wrong with your block preconditionable elements.\n" 2568 OOMPH_CURRENT_FUNCTION,
2569 OOMPH_EXCEPTION_LOCATION);
2572 if(Internal_nblock_types != internal_ndof_types())
2574 std::ostringstream err_msg;
2575 err_msg <<
"The number of internal block types and " 2576 <<
"internal dof types does not match... \n\n" 2577 <<
"Internally, the number of block types and the number of dof " 2578 <<
"types must be the same.\n" 2581 OOMPH_CURRENT_FUNCTION,
2582 OOMPH_EXCEPTION_LOCATION);
2587 return Internal_nblock_types;
2598 if (is_subsidiary_block_preconditioner())
2603 if(Internal_ndof_types == 0)
2605 std::ostringstream error_msg;
2606 error_msg <<
"(Internal_ndof_types == 0) is true.\n" 2607 <<
"This means that the Master_block_preconditioner_pt pointer is\n" 2608 <<
"set but possibly not by the function\n" 2609 <<
"turn_into_subsidiary_block_preconditioner(...).\n\n" 2611 <<
"This goes against the block preconditioning framework " 2613 <<
"Many machinery relies on the look up lists set up by the \n" 2614 <<
"function turn_into_subsidiary_block_preconditioner(...) \n" 2615 <<
"between the parent and child block preconditioners.\n" 2618 OOMPH_CURRENT_FUNCTION,
2619 OOMPH_EXCEPTION_LOCATION);
2622 return Internal_ndof_types;
2629 for (
unsigned i = 0; i < nmesh(); i++)
2630 {ndof += ndof_types_in_mesh(i);}
2645 void internal_return_block_vector(
const unsigned& n,
2654 void internal_get_block_vector(
2667 void internal_get_block_vectors(
2682 void internal_get_block_vectors(
2689 void internal_return_block_vectors(
2700 void internal_return_block_vectors(
2706 void internal_get_block(
const unsigned& i,
const unsigned& j,
2707 MATRIX& output_block)
const;
2719 int dn = internal_dof_number(i_dof);
2726 return Dof_number_to_block_number_lookup[dn];
2736 unsigned index = internal_index_in_dof(i_dof);
2739 int internal_dof_block_number = internal_dof_number(i_dof);
2740 if (internal_dof_block_number >= 0)
2744 unsigned blk_number = internal_block_number(i_dof);
2748 while (
int(Block_number_to_dof_number_lookup[blk_number][j]) !=
2749 internal_dof_block_number)
2752 internal_dof_block_dimension
2753 (Block_number_to_dof_number_lookup[blk_number][j]);
2768 if(Internal_block_distribution_pt.size() == 0)
2770 std::ostringstream error_msg;
2771 error_msg <<
"Internal block distributions are not set up.\n" 2772 <<
"Have you called block_setup(...)?\n" 2775 OOMPH_CURRENT_FUNCTION,
2776 OOMPH_EXCEPTION_LOCATION);
2778 if(b > internal_nblock_types())
2780 std::ostringstream error_msg;
2781 error_msg <<
"You requested the distribution for the internal block " 2782 << b <<
".\n" <<
"But there are only " 2783 << internal_nblock_types()
2784 <<
" block types.\n" << std::endl;
2786 OOMPH_CURRENT_FUNCTION,
2787 OOMPH_EXCEPTION_LOCATION);
2790 return Internal_block_distribution_pt[b];
2805 const unsigned max_block_number
2806 = *std::max_element(block_vec_number.begin(),
2807 block_vec_number.end());
2809 const unsigned nblocks = nblock_types();
2810 if(max_block_number >= nblocks)
2812 std::ostringstream err_msg;
2813 err_msg <<
"Cannot insert into Auxiliary_block_distribution_pt\n" 2814 <<
"because " << max_block_number <<
" is equal to or \n" 2815 <<
"greater than " << nblocks <<
".\n";
2817 OOMPH_CURRENT_FUNCTION,
2818 OOMPH_EXCEPTION_LOCATION);
2826 std::map<Vector<unsigned>,
2828 = Auxiliary_block_distribution_pt.find(block_vec_number);
2830 if(iter != Auxiliary_block_distribution_pt.end())
2833 std::ostringstream err_msg;
2834 err_msg <<
"Cannot insert into Auxiliary_block_distribution_pt\n" 2835 <<
"because the first in the pair already exists.\n";
2837 OOMPH_CURRENT_FUNCTION,
2838 OOMPH_EXCEPTION_LOCATION);
2842 Auxiliary_block_distribution_pt.insert(
2843 std::make_pair(block_vec_number,
2849 void block_matrix_test(
const unsigned& i,
2851 const MATRIX* block_matrix_pt)
const;
2861 template<
typename myType>
2864 const bool sorted =
false)
const 2869 = std::lower_bound(vec.begin(),vec.end(),val);
2871 return (low == vec.end() || *low != val) ? -1 : (low - vec.begin());
2875 int pos = std::find(vec.begin(),vec.end(),val) - vec.begin();
2876 return (pos <
int(vec.size()) && pos >=0) ? pos : -1;
2890 Mesh_pt.resize(n,0);
2891 Allow_multiple_element_type_in_mesh.resize(n,0);
2904 const bool &allow_multiple_element_type_in_mesh =
false)
2910 std::ostringstream err_msg;
2912 <<
"The mesh pointer has space for " << nmesh()
2913 <<
" meshes.\n" <<
"Cannot store a mesh at entry " << i <<
"\n" 2914 <<
"Has set_nmesh(...) been called?";
2916 OOMPH_CURRENT_FUNCTION,
2917 OOMPH_EXCEPTION_LOCATION);
2923 std::ostringstream err_msg;
2925 <<
"Tried to set the " << i <<
"-th mesh pointer, but it is null.";
2927 OOMPH_CURRENT_FUNCTION,
2928 OOMPH_EXCEPTION_LOCATION);
2936 Allow_multiple_element_type_in_mesh[
i]
2937 = unsigned(allow_multiple_element_type_in_mesh);
2951 const unsigned &block_j,
2956 if(nblock_types() == 0)
2958 std::ostringstream err_msg;
2959 err_msg <<
"nblock_types() is 0, has block_setup(...) been called?\n";
2961 OOMPH_CURRENT_FUNCTION,
2962 OOMPH_EXCEPTION_LOCATION);
2967 unsigned para_ndof_types = this->ndof_types();
2969 if((block_i >= para_ndof_types) ||
2970 (block_j >= para_ndof_types))
2972 std::ostringstream err_msg;
2973 err_msg <<
"Replacement dof block (" 2974 << block_i <<
"," << block_j <<
") is outside of range:\n" 2977 OOMPH_CURRENT_FUNCTION,
2978 OOMPH_EXCEPTION_LOCATION);
2996 if(replacement_dof_block_pt == 0)
2998 std::ostringstream err_msg;
2999 err_msg <<
"Replacing block(" << block_i <<
"," << block_i <<
")\n" 3000 <<
" but the pointer is NULL." << std::endl;
3002 OOMPH_CURRENT_FUNCTION,
3003 OOMPH_EXCEPTION_LOCATION);
3007 if(!replacement_dof_block_pt->
built())
3009 std::ostringstream err_msg;
3010 err_msg <<
"Replacement block(" << block_i <<
"," << block_i <<
")" 3011 <<
" is not built." << std::endl;
3013 OOMPH_CURRENT_FUNCTION,
3014 OOMPH_EXCEPTION_LOCATION);
3021 const unsigned para_dof_block_i = block_i;
3023 if(*dof_block_distribution_pt(para_dof_block_i) !=
3026 std::ostringstream err_msg;
3027 err_msg <<
"The distribution of the replacement dof_block_pt\n" 3028 <<
"is different from the Dof_block_distribution_pt[" 3029 << para_dof_block_i<<
"].\n";
3031 OOMPH_CURRENT_FUNCTION,
3032 OOMPH_EXCEPTION_LOCATION);
3037 const unsigned para_dof_block_j = block_j;
3038 unsigned para_replacement_block_ncol = replacement_dof_block_pt->
ncol();
3039 unsigned para_required_ncol
3040 = dof_block_distribution_pt(para_dof_block_j)->nrow();
3041 if(para_replacement_block_ncol != para_required_ncol)
3043 std::ostringstream err_msg;
3044 err_msg <<
"Replacement dof block has ncol = " 3045 << para_replacement_block_ncol <<
".\n" 3046 <<
"But required ncol is " << para_required_ncol <<
".\n";
3048 OOMPH_CURRENT_FUNCTION,
3049 OOMPH_EXCEPTION_LOCATION);
3064 Replacement_dof_block_pt(block_i,block_j)
3065 = replacement_dof_block_pt;
3072 #ifdef OOMPH_HAS_MPI 3074 for(
unsigned i=0, n=nmesh(); i<n; i++)
3076 if(mesh_pt(i)->is_mesh_distributed()) {
return true; }
3090 if (is_master_block_preconditioner())
3092 #ifdef OOMPH_HAS_MPI 3093 unsigned first_row = this->distribution_pt()->first_row();
3094 unsigned nrow_local = this->distribution_pt()->nrow_local();
3095 unsigned last_row = first_row+nrow_local-1;
3096 if (i_dof >= first_row && i_dof <= last_row)
3098 return static_cast<int>(Dof_number_dense[i_dof-first_row]);
3103 int index = get_index_of_value<unsigned>(Global_index_sparse,i_dof,
true);
3106 return Dof_number_sparse[index];
3111 unsigned my_rank = comm_pt()->my_rank();
3112 std::ostringstream error_message;
3114 <<
"Proc " << my_rank<<
": Requested internal_dof_number(...) for global DOF " 3116 <<
"cannot be found.\n";
3118 error_message.str(),
3119 OOMPH_CURRENT_FUNCTION,
3120 OOMPH_EXCEPTION_LOCATION);
3123 return static_cast<int>(Dof_number_dense[i_dof]);
3131 unsigned blk_num = Master_block_preconditioner_pt->internal_dof_number(i_dof);
3135 for (
unsigned i = 0; i < this->internal_ndof_types(); i++)
3137 if (Doftype_in_master_preconditioner_fine[i] == blk_num)
3138 {
return static_cast<int>(
i);}
3146 OOMPH_CURRENT_FUNCTION,
3147 OOMPH_EXCEPTION_LOCATION);
3156 if (is_master_block_preconditioner())
3158 #ifdef OOMPH_HAS_MPI 3159 unsigned first_row = this->distribution_pt()->first_row();
3160 unsigned nrow_local = this->distribution_pt()->nrow_local();
3161 unsigned last_row = first_row+nrow_local-1;
3162 if (i_dof >= first_row && i_dof <= last_row)
3164 return static_cast<int>(Index_in_dof_block_dense[i_dof-first_row]);
3169 int index = get_index_of_value<unsigned>(Global_index_sparse,i_dof,
true);
3172 return Index_in_dof_block_sparse[index];
3177 std::ostringstream error_message;
3179 <<
"Requested internal_index_in_dof(...) for global DOF " << i_dof <<
"\n" 3180 <<
"cannot be found.\n";
3182 error_message.str(),
3183 OOMPH_CURRENT_FUNCTION,
3184 OOMPH_EXCEPTION_LOCATION);
3187 return Index_in_dof_block_dense[i_dof];
3192 return Master_block_preconditioner_pt->internal_index_in_dof(i_dof);
3197 OOMPH_CURRENT_FUNCTION,
3198 OOMPH_EXCEPTION_LOCATION);
3210 const unsigned i_nblock_types = internal_nblock_types();
3211 if(b >= i_nblock_types)
3213 std::ostringstream err_msg;
3214 err_msg <<
"Trying to get internal block dimension for \n" 3215 <<
"internal block " << b <<
".\n" 3216 <<
"But there are only " << i_nblock_types
3217 <<
" internal dof types.\n";
3219 OOMPH_CURRENT_FUNCTION,
3220 OOMPH_EXCEPTION_LOCATION);
3223 return Internal_block_distribution_pt[b]->nrow();
3233 const unsigned i_n_dof_types = internal_ndof_types();
3234 if(i >= i_n_dof_types)
3236 std::ostringstream err_msg;
3237 err_msg <<
"Trying to get internal dof block dimension for \n" 3238 <<
"internal dof block " << i <<
".\n" 3239 <<
"But there are only " << i_n_dof_types
3240 <<
" internal dof types.\n";
3242 OOMPH_CURRENT_FUNCTION,
3243 OOMPH_EXCEPTION_LOCATION);
3249 if(is_master_block_preconditioner())
3251 return Dof_dimension[
i];
3255 unsigned master_i = internal_master_dof_number(i);
3256 return Master_block_preconditioner_pt->internal_dof_block_dimension(master_i);
3267 if (is_master_block_preconditioner())
3273 return (this->Master_block_preconditioner_pt->master_nrow());
3283 if (is_master_block_preconditioner())
3286 return Doftype_in_master_preconditioner_fine[b];
3298 if (is_master_block_preconditioner())
3299 return Internal_preconditioner_matrix_distribution_pt;
3301 return this->distribution_pt();
3313 return Preconditioner_matrix_distribution_pt;
3466 #ifdef OOMPH_HAS_MPI 3522 #ifdef OOMPH_HAS_MPI
virtual DoubleMatrixBase * matrix_pt() const
Get function for matrix pointer.
const LinearAlgebraDistribution * preconditioner_matrix_distribution_pt() const
Access function to the preconditioner matrix distribution pointer. This is the concatenation of the b...
void set_replacement_block_pt(CRDoubleMatrix *replacement_block_pt)
set Replacement_block_pt.
bool block_output_on() const
Test if output of blocks is on or not.
unsigned internal_block_dimension(const unsigned &b) const
Return the number of degrees of freedom in block b. Note that if this preconditioner acts as a subsid...
unsigned Column_index
Column index of the block.
Vector< unsigned > Global_index_sparse
For global indices outside of the range this->first_row() to this->first_row()+this->nrow_local(), the Index_in_dof_block and Dof_number are stored sparsely in the vectors:
Vector< int * > Rows_to_send_for_get_ordered
The global rows to be sent to processor p for get_block_ordered_... type methods. ...
void clear_block_preconditioner_base()
Clears all BlockPreconditioner data. Called by the destructor and the block_setup(...) methods.
Vector< const Mesh * > Mesh_pt
Vector of pointers to the meshes containing the elements used in the block preconditioner. Const pointers to prevent modification of the mesh by the preconditioner (this could be relaxed if needed). If this is a subsidiary preconditioner, then the information is looked up in the master preconditioner.
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
Vector< Vector< unsigned > > doftype_coarsen_map_fine() const
Access function for the Doftype_coarsen_map_fine variable.
Vector< unsigned > Nrows_to_recv_for_get_ordered
The number of preconditioner rows to be received from processor p for get_block_ordered_... type methods.
bool any_mesh_distributed() const
Check if any of the meshes are distributed. This is equivalent to problem.distributed() and is used a...
int index_in_block(const unsigned &i_dof) const
Given a global dof number, returns the index in the block it belongs to. This is the overall index...
Vector< unsigned > get_fine_grain_dof_types_in(const unsigned &i) const
Returns the most fine grain dof types in a (possibly coarsened) dof type.
friend std::ostream & operator<<(std::ostream &o_stream, const BlockSelector &block_selector)
Output function, outputs the Row_index, Column_index, Wanted and the address of the Replacement_block...
int internal_dof_number(const unsigned &i_dof) const
Return the number of the block associated with global unknown i_dof. If this preconditioner is a subs...
void set_column_index(const unsigned &column_index)
Set the column index.
Vector< unsigned > Dof_number_to_block_number_lookup
Vector to the mapping from DOF number to block number.
void insert_auxiliary_block_distribution(const Vector< unsigned > &block_vec_number, LinearAlgebraDistribution *dist_pt)
insert a Vector<unsigned> and LinearAlgebraDistribution* pair into Auxiliary_block_distribution_pt. The Auxiliary_block_distribution_pt should only contain pointers to distributions concatenated at this block level. We try to ensure this by checking if the block_vec_number vector is within the range nblock_types(). Of course, this does not guarantee correctness, but this is the least we can do.
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i...
LinearAlgebraDistribution * Internal_preconditioner_matrix_distribution_pt
The distribution of the (internal) preconditioner matrix. This is formed by concatenating the distrib...
unsigned internal_index_in_dof(const unsigned &i_dof) const
Return the row/column number of global unknown i_dof within it's block.
Vector< LinearAlgebraDistribution * > Block_distribution_pt
The distribution for the blocks.
LinearAlgebraDistribution * block_distribution_pt(const unsigned b)
Access function to the block distributions (non-const version).
void turn_off_debug_flag()
Toggles off the debug flag.
bool Wanted
Bool to indicate if we require this block.
LinearAlgebraDistribution * Preconditioner_matrix_distribution_pt
The distribution of the preconditioner matrix. This is the concatenation of the block distribution...
void concatenate(const Vector< LinearAlgebraDistribution *> &in_distribution_pt, LinearAlgebraDistribution &out_distribution)
Takes a vector of LinearAlgebraDistribution objects and concatenates them such that the nrow_local of...
bool Debug_flag
Debugging variable. Set true or false via the access functions turn_on_debug_flag(...) turn_off_debug_flag(...)
Vector< unsigned > Allow_multiple_element_type_in_mesh
Vector of unsigned to indicate which meshes contain multiple element types.
void do_not_want_block()
Indicate that we do not want the block (set Wanted to false).
CRDoubleMatrix * replacement_block_pt() const
Returns Replacement_block_pt.
BlockSelector()
Default constructor, initialise block index i, j to 0 and bool to false.
const bool & wanted() const
returns whether the block is wanted or not.
Vector< unsigned > Ndof_in_block
Number of types of degree of freedom associated with each block.
void build(const OomphCommunicator *const comm_pt, const unsigned &first_row, const unsigned &nrow_local, const unsigned &nrow=0)
Sets the distribution. Takes first_row, nrow_local and nrow as arguments. If nrow is not provided or ...
int get_index_of_value(const Vector< myType > &vec, const myType val, const bool sorted=false) const
Get the index of first occurrence of value in a vector. If the element does not exist, -1 is returned. The optional parameter indicates of the Vector is sorted or not. Complexity: if the Vector is sorted, then on average, logarithmic in the distance between first and last: Performs approximately log2(N)+2 element comparisons. Otherwise, up to linear in the distance between first and last: Compares elements until a match is found.
MapMatrix< unsigned, CRDoubleMatrix * > replacement_dof_block_pt() const
Access function to the replaced dof-level blocks.
unsigned master_nrow() const
Return the number of dofs (number of rows or columns) in the overall problem. The prefix "master_" is...
Vector< unsigned > Index_in_dof_block_dense
This was uncommented Presumably a non-distributed analogue of Index_in_dof_block_sparse.
void turn_on_debug_flag()
Toggles on the debug flag.
Vector< unsigned > Nrows_to_send_for_get_ordered
The number global rows to be sent to processor p for get_block_ordered_... type methods.
MapMatrix< unsigned, CRDoubleMatrix * > Replacement_dof_block_pt
The replacement dof-level blocks.
Vector< unsigned > Dof_number_dense
Vector to store the mapping from the global DOF number to its block. Empty if this preconditioner has...
Vector< unsigned > Index_in_dof_block_sparse
Vector to store the mapping from the global DOF number to the index (row/column number) within its bl...
void null_replacement_block_pt()
Set Replacement_block_pt to null.
void setup_matrix_vector_product(MatrixVectorProduct *matvec_prod_pt, CRDoubleMatrix *block_pt, const Vector< unsigned > &block_col_indices)
Setup a matrix vector product. matvec_prod_pt is a pointer to the MatrixVectorProduct, block_pt is a pointer to the block matrix, block_col_indices is a vector indicating which block indices does the RHS vector we want to multiply the matrix by.
Vector< Vector< unsigned > > Doftype_coarsen_map_coarse
Mapping for dof types within THIS precondition. This is usually passed down from the parent precondit...
unsigned ndof_types() const
Return the total number of DOF types.
Vector< unsigned > Doftype_in_master_preconditioner_fine
The map between the dof types in this preconditioner and the master preconditioner. If there is no master preconditioner it remains empty. This list contains the mapping for the underlying dof types.
const Mesh * mesh_pt(const unsigned &i) const
Access to i-th mesh (of the various meshes that contain block preconditionable elements of the same n...
BlockSelector(const unsigned &row_index, const unsigned &column_index, const bool &wanted, CRDoubleMatrix *replacement_block_pt=0)
Constructor, takes the row and column indices and a boolean indicating if the block is required or no...
Vector< Vector< unsigned > > Global_index
Vectors of vectors for the mapping from block number and block row to global row number. Empty if this preconditioner has a master preconditioner as this information is obtain from the master preconditioner.
void operator=(const BlockPreconditioner &)
Broken assignment operator.
static bool Run_block_matrix_test
Static boolean to allow block_matrix_test(...) to be run. Defaults to false.
bool is_subsidiary_block_preconditioner() const
Return true if this preconditioner is a subsidiary preconditioner.
CRDoubleMatrix * Replacement_block_pt
Pointer to the block.
const LinearAlgebraDistribution * master_distribution_pt() const
Access function to the distribution of the master preconditioner. If this preconditioner does not hav...
const LinearAlgebraDistribution * block_distribution_pt(const unsigned &b) const
Access function to the block distributions (const version).
unsigned Nrow
Number of DOFs (# of rows or columns in the matrix) in this preconditioner. Note that this informatio...
void build(const unsigned &row_index, const unsigned &column_index, const bool &wanted, CRDoubleMatrix *replacement_block_pt=0)
void set_replacement_dof_block(const unsigned &block_i, const unsigned &block_j, CRDoubleMatrix *replacement_dof_block_pt)
Set replacement dof-level blocks. Only dof-level blocks can be set. This is important due to how the ...
void output_blocks_to_files(const std::string &basefilename, const unsigned &precision=8) const
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
int internal_index_in_block(const unsigned &i_dof) const
Return the index in the block corresponding to a global block number i_dof. The index returned corres...
void post_block_matrix_assembly_partial_clear()
A helper method to reduce the memory requirements of block preconditioners. Once the methods get_bloc...
void setup_matrix_vector_product(MatrixVectorProduct *matvec_prod_pt, CRDoubleMatrix *block_pt, const unsigned &block_col_index)
Setup matrix vector product. This is simply a wrapper around the other setup_matrix_vector_product fu...
void want_block()
Indicate that we require the block (set Wanted to true).
unsigned long ncol() const
Return the number of columns of the matrix.
BlockPreconditioner()
Constructor.
void turn_on_recursive_debug_flag()
Toggles on the recursive debug flag. The change goes up the block preconditioning hierarchy...
virtual ~BlockSelector()
Default destructor.
void deep_copy(const CRDoubleMatrix *const in_matrix_pt, CRDoubleMatrix &out_matrix)
Create a deep copy of the matrix pointed to by in_matrix_pt.
bool Recursive_debug_flag
Debugging variable. Set true or false via the access functions turn_on_recursive_debug_flag(...) turn_off_recursive_debug_flag(...) These will turn on/off the debug flag up the hierarchy.
int block_number(const unsigned &i_dof) const
Return the block number corresponding to a global index i_dof.
MATRIX * matrix_pt() const
Access function to matrix_pt. If this is the master then cast the matrix pointer to MATRIX*...
virtual ~BlockPreconditioner()
Destructor.
void get_block(const unsigned &i, const unsigned &j, MATRIX &output_matrix, const bool &ignore_replacement_block=false) const
Put block (i,j) into output_matrix. This block accounts for any coarsening of dof types and any repla...
unsigned internal_ndof_types() const
Return the number of internal dof types. This is the number of most fine grain dof types...
unsigned nmesh() const
Return the number of meshes in Mesh_pt.
void get_block_other_matrix(const unsigned &i, const unsigned &j, MATRIX *in_matrix_pt, MATRIX &output_matrix)
Get a block from a different matrix using the blocking scheme that has already been set up...
void set_nmesh(const unsigned &n)
Specify the number of meshes required by this block preconditioner. Note: elements in different meshe...
unsigned Internal_nblock_types
Number of different block types in this preconditioner. Note that this information is maintained if u...
const unsigned & row_index() const
returns the row index.
std::string Output_base_filename
String giving the base of the files to write block data into. If empty then do not output blocks...
std::map< Vector< unsigned >, LinearAlgebraDistribution * > Auxiliary_block_distribution_pt
Stores any block-level distributions / concatenation of block-level distributions required...
unsigned internal_master_dof_number(const unsigned &b) const
Takes the block number within this preconditioner and returns the corresponding block number in the m...
void setup(CRDoubleMatrix *matrix_pt, const LinearAlgebraDistribution *col_dist_pt=0)
Setup the matrix vector product operator. WARNING: This class is wrapper to Trilinos Epetra matrix ve...
void set_mesh(const unsigned &i, const Mesh *const mesh_pt, const bool &allow_multiple_element_type_in_mesh=false)
Set the i-th mesh for this block preconditioner. Note: The method set_nmesh(...) must be called befor...
Vector< LinearAlgebraDistribution * > Internal_block_distribution_pt
Storage for the default distribution for each internal block.
void set_block_output_to_files(const std::string &basefilename)
Set the base part of the filename to output blocks to. If it is set then all blocks will be output at...
void select_block(const unsigned &row_index, const unsigned &column_index, const bool &wanted, CRDoubleMatrix *replacement_block_pt=0)
Select a block.
Vector< Vector< unsigned > > Block_to_dof_map_fine
Mapping for the block types to the most fine grain dof types.
unsigned nblock_types() const
Return the number of block types.
BlockPreconditioner< MATRIX > * Master_block_preconditioner_pt
If the block preconditioner is acting a subsidiary block preconditioner then a pointer to the master ...
DenseMatrix< unsigned > Nrows_to_send_for_get_block
The number of global rows to be sent of block b to processor p (matrix indexed [b][p]).
DenseMatrix< int * > Rows_to_recv_for_get_block
The block rows to be received from processor p for block b (matrix indexed [b][p]).
const unsigned nrow() const
returns the number of rows. This is the outer Vector size.
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
LinearAlgebraDistribution * dof_block_distribution_pt(const unsigned &b)
Access function to the dof-level block distributions.
Vector< unsigned > Dof_number_sparse
Vector to store the mapping from the global DOF number to its block (empty if this preconditioner has...
Vector< int * > Rows_to_recv_for_get_ordered
The preconditioner rows to be received from processor p for get_block_ordered_... type methods...
unsigned internal_dof_block_dimension(const unsigned &i) const
Return the size of the dof "block" i, i.e. how many degrees of freedom are associated with it...
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
void document()
debugging method to document the setup. Should only be called after block_setup(...).
unsigned Internal_ndof_types
Number of different DOF types in this preconditioner. Note that this information is maintained if use...
int internal_block_number(const unsigned &i_dof) const
Return the block number corresponding to a global index i_dof. This returns the block number correspo...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
Matrix vector product helper class - primarily a wrapper to Trilinos's Epetra matrix vector product m...
Vector< Vector< unsigned > > Block_to_dof_map_coarse
Mapping for block types to dof types. These are the dof types the writer of the preconditioner expect...
unsigned internal_nblock_types() const
Return the number internal blocks. This should be the same as the number of internal dof types...
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
Vector< LinearAlgebraDistribution * > Dof_block_distribution_pt
Storage for the default distribution for each dof block at this level.
Vector< Vector< unsigned > > Block_number_to_dof_number_lookup
Vector of vectors to store the mapping from block number to the DOF number (each element could be a v...
unsigned nfine_grain_dof_types_in(const unsigned &i) const
Access function for the number of most fine grain dof types in a (possibly coarsened) dof type...
Vector< Vector< unsigned > > Doftype_coarsen_map_fine
Mapping the dof types within this preconditioner. The values in here refers to the most grain dof typ...
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*)
DenseMatrix< unsigned > Nrows_to_recv_for_get_block
The number of block rows to be received from processor p for block b (matrix indexed [b][p])...
void clear()
clears the distribution
Vector< unsigned > Doftype_in_master_preconditioner_coarse
The map between the dof types in this preconditioner and the master preconditioner. If there is no master preconditioner, it remains empty. This is the version for which the master preconditioner expects. The dof types in here may or may not be coarsened in the preconditioner above this one.
unsigned Row_index
Row index of the block.
bool is_master_block_preconditioner() const
Return true if this preconditioner is the master block preconditioner.
Vector< unsigned > Dof_dimension
Vector containing the size of each block, i.e. the number of global DOFs associated with it...
MATRIX get_block(const unsigned &i, const unsigned &j, const bool &ignore_replacement_block=false) const
Return block (i,j). If the optional argument ignore_replacement_block is true, then any blocks in Rep...
Data structure to store information about a certain "block" or sub-matrix from the overall matrix in ...
void set_master_matrix_pt(MATRIX *in_matrix_pt)
Set the matrix_pt in the upper-most master preconditioner.
const unsigned ncol() const
return the number of columns. This is the size of the first inner vectors, or returns 0 if the outer ...
void concatenate_without_communication(const Vector< LinearAlgebraDistribution *> &row_distribution_pt, const Vector< LinearAlgebraDistribution *> &col_distribution_pt, const DenseMatrix< CRDoubleMatrix *> &matrix_pt, CRDoubleMatrix &result_matrix)
Concatenate CRDoubleMatrix matrices.
BlockPreconditioner(const BlockPreconditioner &)
Broken copy constructor.
unsigned ndof_types_in_mesh(const unsigned &i) const
Return the number of DOF types in mesh i. WARNING: This should only be used by the upper-most master ...
A class for compressed row matrices. This is a distributable object.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
void disable_block_output_to_files()
Turn off output of blocks (by clearing the basefilename string).
Vector< unsigned > Ndof_types_in_mesh
Storage for number of types of degree of freedom of the elements in each mesh.
DenseMatrix< int * > Rows_to_send_for_get_block
The global rows to be sent of block b to processor p (matrix indexed [b][p]).
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types)...
BlockPreconditioner< MATRIX > * master_block_preconditioner_pt() const
Access function to the master block preconditioner pt.
const LinearAlgebraDistribution * internal_preconditioner_matrix_distribution_pt() const
access function to the internal preconditioner matrix distribution pt. preconditioner_matrix_distribu...
MATRIX get_concatenated_block(const VectorMatrix< BlockSelector > &selected_block)
Returns a concatenation of the block matrices specified by the argument selected_block. The VectorMatrix selected_block must be correctly sized as it is used to determine the number of sub block matrices to concatenate.
const LinearAlgebraDistribution * internal_block_distribution_pt(const unsigned &b) const
Access function to the internal block distributions.
const unsigned & column_index() const
returns the column index.
void set_row_index(const unsigned &row_index)
Set the row index.
void turn_off_recursive_debug_flag()
Toggles off the recursive debug flag. The change goes up the block preconditioning hierarchy...