64 unsigned nnodes=all_tree_nodes_pt.size();
65 for (
unsigned e=0;
e<nnodes;
e++)
67 unsigned level=all_tree_nodes_pt[
e]->level();
68 if (level>max_level) max_level=level;
72 to_be_refined.clear();
73 to_be_refined.resize(max_level);
78 for (
unsigned l=0;l<max_level;l++)
85 for (
unsigned l=0;l<max_level;l++)
88 for (
unsigned e=0;
e<nnodes;
e++)
91 unsigned level=all_tree_nodes_pt[
e]->level();
96 if ((level==l)||((level<l)&&(all_tree_nodes_pt[
e]->is_leaf())))
100 if ((level==l)&&(!all_tree_nodes_pt[
e]->is_leaf()))
104 to_be_refined[l].push_back(el_count[l]);
119 unsigned& refinement_level,
127 unsigned nnodes=all_tree_nodes_pt.size();
128 for (
unsigned e=0;
e<nnodes;
e++)
130 unsigned level=all_tree_nodes_pt[
e]->level();
131 if (level==refinement_level)
133 level_elements.push_back(dynamic_cast<RefineableElement*>
134 (all_tree_nodes_pt[
e]->object_pt()));
148 unsigned my_max,my_min;
152 unsigned my_max_level=to_be_refined.size();
154 unsigned global_max=0;
155 unsigned global_max_level=0;
158 data[1]=my_max_level;
163 MPI_Allreduce(&data[0],&global_data[0],2,MPI_UNSIGNED,MPI_MAX,
165 global_max=global_data[0];
166 global_max_level=global_data[1];
173 global_max_level=my_max_level;
177 for (
unsigned i=0;
i<global_max;
i++)
183 for (
unsigned l=0;l<global_max_level;l++)
186 unsigned n_to_be_refined=0;
187 if (l<my_max_level) n_to_be_refined=to_be_refined[l].size();
190 for (
unsigned i=0;
i<n_to_be_refined;
i++)
193 this->
element_pt(to_be_refined[l][
i]))->select_for_refinement();
232 unsigned max_level=to_be_refined.size();
233 outfile << max_level <<
" # max. refinement level " << std::endl;
236 for (
unsigned l=0;l<max_level;l++)
239 unsigned n_to_be_refined=to_be_refined[l].size();
240 outfile << n_to_be_refined <<
" # number of elements to be refined. " 241 <<
"What follows are the numbers of the elements. " << std::endl;
244 for (
unsigned i=0;
i<n_to_be_refined;
i++)
246 outfile << to_be_refined[l][
i] << std::endl;
265 getline(restart_file,input_string,
'#');
268 restart_file.ignore(80,
'\n');
271 unsigned max_level=std::atoi(input_string.c_str());
274 to_be_refined.resize(max_level);
277 for (
unsigned l=0;l<max_level;l++)
281 getline(restart_file,input_string,
'#');
284 restart_file.ignore(80,
'\n');
287 unsigned n_to_be_refined=atoi(input_string.c_str());;
290 to_be_refined[l].resize(n_to_be_refined);
293 for (
unsigned i=0;
i<n_to_be_refined;
i++)
295 restart_file >> to_be_refined[l][
i];
330 if (refine_tol<=unrefine_tol)
332 std::ostringstream error_stream;
333 error_stream <<
"Refinement tolerance <= Unrefinement tolerance" 334 << refine_tol <<
" " << unrefine_tol << std::endl
335 <<
"doesn't make sense and will almost certainly crash" 337 <<
"this beautiful code!" << std::endl;
340 OOMPH_CURRENT_FUNCTION,
341 OOMPH_EXCEPTION_LOCATION);
353 std::map<RefineableElement*,bool> wants_to_be_unrefined;
359 unsigned long Nelement=this->
nelement();
360 for (
unsigned long e=0;
e<Nelement;
e++)
370 if(elemental_error[
e] > refine_tol)
390 if ((elemental_error[
e]<unrefine_tol)&&
398 for (
unsigned ison=0;ison<n_sons;ison++)
412 if(unrefine) {wants_to_be_unrefined[el_pt]=
true;}
413 else {wants_to_be_unrefined[el_pt]=
false;}
417 oomph_info <<
" \n Number of elements to be refined: " 418 << n_refine << std::endl;
419 oomph_info <<
" \n Number of elements whose refinement was overruled: " 426 unsigned n_unrefine=0;
427 for (
unsigned long e=0;
e<Nelement;
e++)
445 for (
unsigned ison=0;ison<n_sons;ison++)
447 if (!(wants_to_be_unrefined[
448 dynamic_cast<RefineableElement*>
461 select_sons_for_unrefinement();
462 n_unrefine += n_sons;
468 deselect_sons_for_unrefinement();
472 oomph_info <<
" \n Number of elements to be merged : " 473 << n_unrefine << std::endl << std::endl;
491 unsigned total_n_refine=0;
496 MPI_Allreduce(&n_refine,&total_n_refine,1,MPI_UNSIGNED,MPI_SUM,
501 total_n_refine=n_refine;
504 total_n_refine=n_refine;
515 unsigned total_n_unrefine=0;
520 MPI_Allreduce(&n_unrefine,&total_n_unrefine,1,MPI_UNSIGNED,MPI_SUM,
525 total_n_unrefine=n_unrefine;
528 total_n_unrefine=n_unrefine;
531 oomph_info <<
"---> " << total_n_refine <<
" elements to be refined, and " 532 << total_n_unrefine <<
" to be unrefined, in total.\n" << std::endl;
549 int my_rank=
Comm_pt->my_rank();
555 for (
int d=0; d<n_proc; d++)
567 unsigned nhalo=halo_elem_pt.size();
569 for (
unsigned e=0;
e<nhalo;
e++)
571 if (dynamic_cast<RefineableElement*>(halo_elem_pt[
e])
572 ->sons_to_be_unrefined())
574 halo_to_be_unrefined[
e]=1;
583 MPI_Send(&halo_to_be_unrefined[0],nhalo,MPI_INT,
592 for (
int dd=0; dd<n_proc; dd++)
604 unsigned nhaloed=haloed_elem_pt.size();
610 MPI_Recv(&halo_to_be_unrefined[0],nhaloed,MPI_INT,dd,0,
615 for (
unsigned e=0;
e<nhaloed;
e++)
617 if ( ( (halo_to_be_unrefined[
e]==0)&&
618 (dynamic_cast<RefineableElement*>(haloed_elem_pt[
e])->
619 sons_to_be_unrefined()) ) ||
620 ( (halo_to_be_unrefined[
e]==1)&&
621 (!dynamic_cast<RefineableElement*>(haloed_elem_pt[e])->
622 sons_to_be_unrefined()) ) )
624 std::ostringstream error_message;
626 <<
"Error in unrefinement: \n" 627 <<
"Haloed element: " << e <<
" on proc " << my_rank<<
" \n" 628 <<
"wants to be unrefined whereas its halo counterpart on\n" 629 <<
"proc " << dd <<
" doesn't (or vice versa)...\n" 630 <<
"This is most likely because the error estimator\n" 631 <<
"has not assigned the same errors to halo and haloed\n" 632 <<
"elements -- it ought to!\n";
635 OOMPH_CURRENT_FUNCTION,
636 OOMPH_EXCEPTION_LOCATION);
650 for (
int d=0; d<n_proc; d++)
662 unsigned nhalo=halo_elem_pt.size();
664 for (
unsigned e=0;
e<nhalo;
e++)
666 if (dynamic_cast<RefineableElement*>(halo_elem_pt[
e])
669 halo_to_be_refined[
e]=1;
678 MPI_Send(&halo_to_be_refined[0],nhalo,MPI_INT,
687 for (
int dd=0; dd<n_proc; dd++)
699 unsigned nhaloed=haloed_elem_pt.size();
705 MPI_Recv(&halo_to_be_refined[0],nhaloed,MPI_INT,dd,0,
710 for (
unsigned e=0;
e<nhaloed;
e++)
712 if ( ( (halo_to_be_refined[
e]==0)&&
713 (dynamic_cast<RefineableElement*>(haloed_elem_pt[
e])->
714 to_be_refined()) ) ||
715 ( (halo_to_be_refined[
e]==1)&&
716 (!dynamic_cast<RefineableElement*>(haloed_elem_pt[e])->
719 std::ostringstream error_message;
721 <<
"Error in refinement: \n" 722 <<
"Haloed element: " << e <<
" on proc " << my_rank<<
" \n" 723 <<
"wants to be refined whereas its halo counterpart on\n" 724 <<
"proc " << dd <<
" doesn't (or vice versa)...\n" 725 <<
"This is most likely because the error estimator\n" 726 <<
"has not assigned the same errors to halo and haloed\n" 727 <<
"elements -- it ought to!\n";
730 OOMPH_CURRENT_FUNCTION,
731 OOMPH_EXCEPTION_LOCATION);
787 <<
" Not enough benefit in adapting mesh." 788 << std::endl << std::endl;
805 min_refinement_level=UINT_MAX;
806 max_refinement_level=0;
809 unsigned long n_element=this->
nelement();
812 min_refinement_level=0;
813 max_refinement_level=0;
817 for (
unsigned long e=0;
e<n_element;
e++)
823 if (level>max_refinement_level) max_refinement_level=level;
824 if (level<min_refinement_level) min_refinement_level=level;
915 double t_start = 0.0;
929 oomph_info <<
"Time for split_elements_if_required: " 930 << t_end-t_start << std::endl;
944 oomph_info <<
"Time for stick_leaves_into_vector: " 945 << t_end-t_start << std::endl;
950 std::ostringstream fullname;
951 std::ofstream new_nodes_file;
954 fullname << doc_info.
directory() <<
"/new_nodes" 955 << doc_info.
number() <<
".dat";
956 new_nodes_file.open(fullname.str().c_str());
965 bool was_already_built;
966 unsigned long num_tree_nodes=leaf_nodes_pt.size();
967 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
970 leaf_nodes_pt[
e]->object_pt()->pre_build(mesh_pt,new_node_pt);
972 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
975 leaf_nodes_pt[
e]->object_pt()
976 ->build(mesh_pt,new_node_pt,was_already_built,new_nodes_file);
984 oomph_info <<
"Time for building " << num_tree_nodes <<
" new elements: " 985 << t_end-t_start << std::endl;
1014 const unsigned n_boundary = this->
nboundary();
1018 unsigned long n_node=this->
nnode();
1019 for (
unsigned long n=0;n<n_node;n++)
1025 unsigned n_value=nod_pt->
nvalue();
1030 for(
unsigned n=0;n<n_value;n++)
1044 unsigned n_dim=nod_pt->
ndim();
1047 for(
unsigned t=0;
t<nt;
t++)
1050 for(
unsigned i=0;
i<n_value;
i++)
1055 for(
unsigned i=0;
i<n_dim;
i++)
1057 nod_pt->
x(
t,
i)=position[
i];
1065 bool update_all_time_levels=
true;
1073 if(solid_node_pt!=0)
1075 unsigned n_lagrangian = solid_node_pt->
nlagrangian();
1076 for(
unsigned i=0;
i<n_lagrangian;
i++)
1092 std::set<unsigned>* boundaries_pt;
1094 if(boundaries_pt!=0)
1098 for(std::set<unsigned>::iterator it=boundaries_pt->begin();
1099 it!=boundaries_pt->end();++it)
1101 hanging_nodes_on_boundary_pt[*it].insert(nod_pt);
1117 oomph_info <<
"Time for sorting out initial hanging status: " 1118 << t_end-t_start << std::endl;
1138 << t_end-t_start << std::endl;
1151 num_tree_nodes=tree_nodes_pt.size();
1153 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
1168 unsigned n_node=this_el_pt->
nnode();
1169 for (
unsigned n=0;n<n_node;n++)
1179 oomph_info <<
"Time for adding elements to mesh: " 1180 << t_end-t_start << std::endl;
1198 for(
unsigned long e=0;
e<num_tree_nodes;
e++)
1201 tree_nodes_pt[
e]->object_pt()->setup_hanging_nodes(hanging_output_files);
1203 tree_nodes_pt[
e]->object_pt()->further_setup_hanging_nodes();
1215 <<
"Time for setup_hanging_nodes() and further_setup_hanging_nodes() for " 1216 << num_tree_nodes <<
" elements: " 1217 << t_end-t_start << std::endl;
1223 unsigned ncont_interpolated_values=
1224 tree_nodes_pt[0]->object_pt()->ncont_interpolated_values();
1234 <<
"Time for complete_hanging_nodes: " 1235 << t_end-t_start << std::endl;
1252 <<
"Time for boundary element info: " 1253 << t_end-t_start << std::endl;
1272 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
1274 double max_el_error;
1275 tree_nodes_pt[
e]->object_pt()->check_integrity(max_el_error);
1278 if(max_el_error > max_error) {max_error=max_el_error;}
1283 std::ostringstream error_stream;
1284 error_stream <<
"Mesh refined: Max. error in integrity check: " 1285 << max_error <<
" is too big\n";
1287 <<
"i.e. bigger than RefineableElement::max_integrity_tolerance()=" 1290 std::ofstream some_file;
1291 some_file.open(
"ProblemMesh.dat");
1292 for (
unsigned long n=0;n<n_node;n++)
1297 unsigned n_dim = nod_pt->
ndim();
1299 for(
unsigned i=0;
i<n_dim;
i++)
1301 some_file << this->
node_pt(n)->
x(
i) <<
" ";
1303 some_file << std::endl;
1307 error_stream <<
"Doced problem mesh in ProblemMesh.dat" << std::endl;
1310 OOMPH_CURRENT_FUNCTION,
1311 OOMPH_EXCEPTION_LOCATION);
1315 oomph_info <<
"Mesh refined: Max. error in integrity check: " 1316 << max_error <<
" is OK" << std::endl;
1318 <<
"i.e. less than RefineableElement::max_integrity_tolerance()=" 1327 <<
"Time for (paranoid only) checking of integrity: " 1328 << t_end-t_start << std::endl;
1351 oomph_info <<
"Time for deactivating objects and pruning nodes: " 1352 << t_end-t_start << std::endl;
1366 << t_end-t_start << std::endl;
1376 for(
unsigned b=0;b<n_boundary;b++)
1380 unsigned n_del=deleted_node_pt.size();
1381 for (
unsigned j=0;j<n_del;j++)
1383 hanging_nodes_on_boundary_pt[b].erase(deleted_node_pt[j]);
1388 for(std::set<Node*>::iterator
1389 it=hanging_nodes_on_boundary_pt[b].begin();
1390 it!=hanging_nodes_on_boundary_pt[b].end();)
1392 if((*it)->is_hanging())
1393 {hanging_nodes_on_boundary_pt[b].erase(it++);}
1402 if(hanging_nodes_on_boundary_pt[b].size()>0)
1406 for(
unsigned e=0;
e<n_boundary_element;++
e)
1430 unsigned n_el_node = el_pt->
nnode();
1431 for(
unsigned n=0;n<n_el_node;n++)
1438 std::set<Node*>::iterator it =
1439 hanging_nodes_on_boundary_pt[b].find(nod_pt);
1443 if(it!=hanging_nodes_on_boundary_pt[b].end())
1453 const unsigned ntstorage = nod_pt->
ntstorage();
1473 for(
unsigned i=0;
i<3;
i++) {solid_node_pt->
xi(
i) = xi[
i];}
1479 for(
unsigned t=0;
t<ntstorage;
t++)
1486 for(
unsigned i=0;
i<3;
i++) {nod_pt->
x(
t,
i) = x[
i];}
1491 hanging_nodes_on_boundary_pt[b].erase(it);
1494 if(hanging_nodes_on_boundary_pt[b].size()==0)
1495 {
e=n_boundary_element;
break;}
1519 unsigned max_nval=0;
1520 for (
unsigned n=0;n<el_pt->
nnode();n++)
1527 std::ofstream bcs_file;
1531 bcs_file.open(fullname.str().c_str());
1534 for(
unsigned long e=0;
e<num_tree_nodes;
e++)
1536 el_pt = tree_nodes_pt[
e]->object_pt();
1538 unsigned n_nod=el_pt->
nnode();
1539 for(
unsigned n=0;n<n_nod;n++)
1544 unsigned n_dim = nod_pt->
ndim();
1546 for(
unsigned i=0;
i<n_dim;
i++)
1547 {bcs_file << nod_pt->
x(
i) <<
" ";}
1550 for(
unsigned i=0;
i<max_nval;
i++)
1553 if (i<nod_pt->nvalue())
1563 bcs_file << std::endl;
1570 std::ofstream all_nodes_file;
1572 fullname << doc_info.
directory() <<
"/all_nodes" 1573 << doc_info.
number() <<
".dat";
1574 all_nodes_file.open(fullname.str().c_str());
1576 all_nodes_file <<
"ZONE \n";
1580 n_node = this->
nnode();
1581 for(
unsigned long n=0;n<n_node;n++)
1584 unsigned n_dim = nod_pt->
ndim();
1585 for(
unsigned i=0;
i<n_dim;
i++)
1587 all_nodes_file << this->
node_pt(n)->
x(
i) <<
" ";
1589 all_nodes_file << std::endl;
1592 all_nodes_file.close();
1597 std::ofstream some_file;
1599 fullname << doc_info.
directory() <<
"/all_hangnodes" 1600 << doc_info.
number() <<
".dat";
1601 some_file.open(fullname.str().c_str());
1602 for(
unsigned long n=0;n<n_node;n++)
1608 unsigned n_dim = nod_pt->
ndim();
1609 for(
unsigned i=0;
i<n_dim;
i++)
1611 some_file << nod_pt->
x(
i) <<
" ";
1615 if(this->
node_pt(n)->nvalue() > 0)
1617 some_file <<
" " << nod_pt->
raw_value(0);
1619 some_file << std::endl;
1628 <<
"/geometric_hangnodes_withmasters" 1629 << doc_info.
number() <<
".dat";
1630 some_file.open(fullname.str().c_str());
1631 for(
unsigned long n=0;n<n_node;n++)
1636 unsigned n_dim = nod_pt->
ndim();
1638 some_file <<
"ZONE I="<<nmaster+1 << std::endl;
1639 for(
unsigned i=0;
i<n_dim;
i++)
1641 some_file << nod_pt->
x(
i) <<
" ";
1643 some_file <<
" 2 " << std::endl;
1645 for (
unsigned imaster=0;imaster<nmaster;imaster++)
1647 Node* master_nod_pt =
1649 unsigned n_dim = master_nod_pt->
ndim();
1650 for(
unsigned i=0;
i<n_dim;
i++)
1652 some_file << master_nod_pt->
x(
i) <<
" ";
1654 some_file <<
" 1 " << std::endl;
1662 for(
unsigned i=0;
i<ncont_interpolated_values;
i++)
1666 <<
"/nonstandard_hangnodes_withmasters" <<
i <<
"_" 1667 << doc_info.
number() <<
".dat";
1668 some_file.open(fullname.str().c_str());
1669 unsigned n_nod=this->
nnode();
1670 for(
unsigned long n=0;n<n_nod;n++)
1678 some_file <<
"ZONE I="<<nmaster+1 << std::endl;
1679 unsigned n_dim = nod_pt->
ndim();
1680 for(
unsigned j=0;j<n_dim;j++)
1682 some_file << nod_pt->
x(j) <<
" ";
1684 some_file <<
" 2 " << std::endl;
1685 for (
unsigned imaster=0;imaster<nmaster;imaster++)
1687 Node* master_nod_pt =
1689 unsigned n_dim = master_nod_pt->
ndim();
1690 for(
unsigned j=0;j<n_dim;j++)
1694 some_file <<
" 1 " << std::endl;
1705 #ifdef OOMPH_HAS_MPI 1725 unsigned long Nelement=this->
nelement();
1726 for (
unsigned long e=0;
e<Nelement;
e++)
1744 unsigned long Nelement=this->
nelement();
1745 for (
unsigned long e=0;
e<Nelement;
e++)
1771 #ifdef OOMPH_HAS_MPI 1774 std::ostringstream warn_stream;
1775 warn_stream <<
"You are attempting to refine selected elements of a " 1777 <<
"distributed mesh. This may have undesired effects." 1781 "TreeBasedRefineableMeshBase::refine_selected_elements()",
1782 OOMPH_EXCEPTION_LOCATION);
1787 unsigned long nref=elements_to_be_refined.size();
1788 for (
unsigned long e=0;
e<nref;
e++)
1791 (this->
element_pt(elements_to_be_refined[
e]))->select_for_refinement();
1809 #ifdef OOMPH_HAS_MPI 1812 std::ostringstream warn_stream;
1813 warn_stream <<
"You are attempting to refine selected elements of a " 1815 <<
"distributed mesh. This may have undesired effects." 1819 "TreeBasedRefineableMeshBase::refine_selected_elements()",
1820 OOMPH_EXCEPTION_LOCATION);
1825 unsigned long nref=elements_to_be_refined_pt.size();
1826 for (
unsigned long e=0;
e<nref;
e++)
1828 elements_to_be_refined_pt[
e]->select_for_refinement();
1872 unsigned nrefinement_levels=to_be_refined.size();
1876 if (nrefinement_levels==0)
1885 to_be_refined.resize(nrefinement_levels-1);
1905 oomph_info <<
"WARNING : This has not been checked comprehensively yet" 1907 <<
"Check it and remove this break " << std::endl;
1908 pause(
"Yes really pause");
1913 unsigned my_min,my_max;
1916 unsigned ref_min,ref_max;
1919 if (ref_max!=my_max+1)
1921 std::ostringstream error_stream;
1923 <<
"Meshes definitely don't differ by one refinement level \n" 1924 <<
"max. refinement levels: "<< ref_max <<
" " << my_max << std::endl;
1927 OOMPH_CURRENT_FUNCTION,
1928 OOMPH_EXCEPTION_LOCATION);
1937 std::map<Tree*,unsigned> father_element_included;
1942 stick_leaves_into_vector(leaf_nodes_pt);
1946 unsigned nelem=leaf_nodes_pt.size();
1947 for (
unsigned e=0;
e<nelem;
e++)
1950 Tree* leaf_pt=leaf_nodes_pt[
e];
1959 coarse_elements_pt.push_back(leaf_pt);
1965 bool can_unrefine=
true;
1966 unsigned n_sons = father_pt->
nsons();
1967 for (
unsigned i=0;
i<n_sons;
i++)
1977 if (father_element_included[father_pt]==0)
1979 coarse_elements_pt.push_back(father_pt);
1980 father_element_included[father_pt]=1;
1986 coarse_elements_pt.push_back(leaf_pt);
1992 unsigned nel_coarse=coarse_elements_pt.size();
2000 oomph_info <<
"Number of elements in uniformly unrefined reference mesh: " 2001 << nel_coarse<< std::endl;
2002 oomph_info <<
"Number of elements in 'this' mesh: " 2003 << nel_coarse<< std::endl;
2014 for (
unsigned i=0;
i<nel_coarse;
i++)
2016 if (father_element_included[coarse_elements_pt[
i]]==1)
2018 elements_to_be_refined.push_back(
i);
2027 std::ofstream some_file;
2028 some_file.open(
"orig_mesh.dat");
2031 oomph_info <<
"Documented original ('this')mesh in orig_mesh.dat" 2046 for (
unsigned e=0;
e<nelem;
e++)
2053 unsigned nnod=ref_el_pt->
nnode();
2054 for (
unsigned j=0;j<nnod;j++)
2062 unsigned ndim=node_pt->
ndim();
2063 for (
unsigned i=0;
i<ndim;
i++)
2065 error+=pow(node_pt->
x(
i)-ref_node_pt->
x(
i),2);
2071 oomph_info <<
"Error in nodal position of node " << j <<
": " 2072 << error <<
" [tol=" << tol<<
"]" << std::endl;
2082 std::ofstream some_file;
2083 some_file.open(
"refined_mesh.dat");
2087 some_file.open(
"finer_mesh.dat");
2088 ref_mesh_pt->
output(some_file);
2092 "Bailing out. Doced refined_mesh.dat finer_mesh.dat\n",
2093 OOMPH_CURRENT_FUNCTION,
2094 OOMPH_EXCEPTION_LOCATION);
2119 unsigned long Nelement=this->
nelement();
2134 for (
unsigned long e=0;
e<Nelement;
e++)
2136 elemental_error[
e]=error;
2145 adapt(elemental_error);
2184 unsigned nmaster=hang_pt->
nmaster();
2186 for(
unsigned m=0;m<nmaster;m++)
2196 int first_new_node=master_nodes.size();
2200 master_nodes,hang_weights,i);
2204 unsigned n_new_master_node = master_nodes.size();
2208 for(
unsigned k=first_new_node;k<n_new_master_node;k++)
2210 hang_weights[k]=mtr_weight*hang_weights[k];
2217 master_nodes.push_back(nod_pt);
2218 hang_weights.push_back(1.0);
2235 unsigned long n_node=this->
nnode();
2236 double min_weight=1.0e-8;
2239 for (
unsigned long n=0;n<n_node;n++)
2246 for(
int i=-1;
i<ncont_interpolated_values;
i++)
2260 master_nodes,hanging_weights,
i);
2264 std::map<Node*,double> hang_weights;
2265 unsigned n_master=master_nodes.size();
2266 for(
unsigned k=0;k<n_master;k++)
2268 if(std::fabs(hanging_weights[k])>min_weight)
2269 hang_weights[master_nodes[k]]+=hanging_weights[k];
2275 unsigned hang_weights_index=0;
2277 typedef std::map<Node*,double>::iterator IT;
2278 for (IT it=hang_weights.begin();it!=hang_weights.end();++it)
2282 ++hang_weights_index;
2297 for (
int i=-1;
i<ncont_interpolated_values;
i++)
2300 for (
unsigned long n=0;n<n_node;n++)
2310 for (
unsigned imaster=0;imaster<nmaster;imaster++)
2314 if (std::fabs(sum-1.0)>1.0
e-7)
2316 oomph_info <<
"WARNING: Sum of master node weights fabs(sum-1.0) " 2317 << std::fabs(sum-1.0) <<
" for node number " << n
2318 <<
" at value " <<
i << std::endl;
2330 #ifdef OOMPH_HAS_MPI 2337 (
const unsigned& ncont_interpolated_values)
2342 int my_rank=
Comm_pt->my_rank();
2344 double t_start = 0.0;
2352 unsigned nnode_still_requiring_synchronisation=0;
2360 int ncont_inter_values=ncont_interpolated_values;
2364 for (
int d=0; d<n_proc; d++)
2374 for (
unsigned j=0;j<nh;j++)
2381 for (
int icont=-1; icont<ncont_inter_values; icont++)
2387 haloed_hanging[d].push_back(n_master);
2391 haloed_hanging[d].push_back(0);
2397 unsigned count_haloed=haloed_hanging[d].size();
2402 MPI_Recv(&tmp,1,MPI_UNSIGNED,d,0,
Comm_pt->mpi_comm(),&status);
2403 if (tmp!=count_haloed)
2405 std::ostringstream error_stream;
2406 error_stream <<
"Number of halo data, " << tmp
2407 <<
", does not match number of haloed data, " 2408 << count_haloed << std::endl;
2411 OOMPH_CURRENT_FUNCTION,
2412 OOMPH_EXCEPTION_LOCATION);
2417 if (count_haloed!=0)
2419 halo_hanging[d].resize(count_haloed);
2420 MPI_Recv(&halo_hanging[d][0],count_haloed,MPI_INT,d,0,
2428 for (
int dd=0; dd<n_proc; dd++)
2439 for (
unsigned j=0;j<nh;j++)
2446 for (
int icont=-1; icont<ncont_inter_values; icont++)
2452 local_halo_hanging.push_back(n_master);
2456 local_halo_hanging.push_back(0);
2463 unsigned count_halo=local_halo_hanging.size();
2467 MPI_Send(&count_halo,1,MPI_UNSIGNED,dd,0,
Comm_pt->mpi_comm());
2473 MPI_Send(&local_halo_hanging[0],count_halo,MPI_INT,
2484 oomph_info <<
"Time for first all-to-all in synchronise_hanging_nodes(): " 2485 << t_end-t_start << std::endl;
2503 for (
int d=0;d<n_proc;d++)
2506 for (
unsigned jj=0;jj<n;jj++)
2516 for (
int d=0; d<n_proc; d++)
2522 unsigned discrepancy_count=0;
2523 unsigned discrepancy_count_buff=0;
2539 unsigned discrepancy=0;
2540 unsigned discrepancy_buff=0;
2544 for (
unsigned j=0;j<nh;j++)
2551 for (
int icont=-1; icont<ncont_inter_values; icont++)
2558 if ((haloed_hanging[d][count]>0)&&
2559 (haloed_hanging[d][count]!=halo_hanging[d][count]))
2562 discrepancy_count_buff++;
2565 bool found_all_masters=
true;
2569 unsigned nhd_master=hang_pt->
nmaster();
2572 send_data_buff.push_back(nhd_master);
2575 for (
unsigned m=0; m<nhd_master; m++)
2625 std::map<Node*,unsigned>::iterator it=
2626 shared_node_map[d].find(master_nod_pt);
2630 if (it!=shared_node_map[d].end())
2635 send_data_buff.push_back(my_rank);
2639 send_data_buff.push_back((*it).second);
2657 if (non_halo_proc_id<0)
2669 if (shared_node_map[non_halo_proc_id].size()>0)
2671 std::map<Node*,unsigned>::iterator it=
2672 shared_node_map[non_halo_proc_id].find(master_nod_pt);
2676 if (it!=shared_node_map[non_halo_proc_id].end())
2682 send_data_buff.push_back(non_halo_proc_id);
2686 send_data_buff.push_back((*it).second);
2902 found_all_masters=
false;
2912 if(found_all_masters)
2915 discrepancy = discrepancy_buff;
2916 discrepancy_count += discrepancy_count_buff;
2917 for(
unsigned i=0;
i<send_data_buff.size();
i++)
2919 send_data.push_back(send_data_buff[
i]);
2921 for(
unsigned i=0;
i<send_double_data_buff.size();
i++)
2923 send_double_data.push_back(send_double_data_buff[
i]);
2927 discrepancy_buff = 0;
2928 discrepancy_count_buff = 0;
2929 send_data_buff.clear();
2930 send_double_data_buff.clear();
2937 send_data.push_back(0);
2940 discrepancy_buff = 0;
2941 discrepancy_count_buff = 0;
2942 send_data_buff.clear();
2943 send_double_data_buff.clear();
2946 nnode_still_requiring_synchronisation++;
2953 else if ((haloed_hanging[d][count]==0) &&
2954 (halo_hanging[d][count]>0))
2957 discrepancy_count++;
2958 send_data.push_back(-1);
2962 else if (haloed_hanging[d][count]==
2963 halo_hanging[d][count])
2965 send_data.push_back(0);
2969 std::ostringstream error_stream;
2970 error_stream <<
"Never get here!\n " 2971 <<
"haloed_hanging[d][count]=" << haloed_hanging[d][count]
2972 <<
"; halo_hanging[d][count]=" << halo_hanging[d][count]
2976 OOMPH_CURRENT_FUNCTION,
2977 OOMPH_EXCEPTION_LOCATION);
2989 MPI_Send(&n_all_send[0],2,MPI_UNSIGNED,d,0,
Comm_pt->mpi_comm());
2994 n_all_send[0]=send_data.size();
2995 n_all_send[1]=send_double_data.size();
2996 MPI_Send(&n_all_send[0],2,MPI_UNSIGNED,d,0,
Comm_pt->mpi_comm());
2999 if (n_all_send[0]!=0)
3001 MPI_Send(&send_data[0],n_all_send[0],MPI_INT,d,1,
3006 if (n_all_send[1]!=0)
3008 MPI_Send(&send_double_data[0],n_all_send[1],MPI_DOUBLE,d,1,
3017 for (
int dd=0; dd<n_proc; dd++)
3025 MPI_Recv(&n_all_recv[0],2,MPI_UNSIGNED,dd,0,
3033 if (n_all_recv[0]!=0)
3036 receive_data.resize(n_all_recv[0]);
3037 MPI_Recv(&receive_data[0],n_all_recv[0],MPI_INT,dd,1,
3042 if (n_all_recv[1]!=0)
3045 receive_double_data.resize(n_all_recv[1]);
3046 MPI_Recv(&receive_double_data[0],n_all_recv[1],MPI_DOUBLE,dd,1,
3051 if (n_all_recv[0]!=0)
3055 unsigned count_double=0;
3059 for (
unsigned j=0;j<nh;j++)
3066 for (
int icont=-1; icont<ncont_inter_values; icont++)
3070 int next_entry=receive_data[count++];
3076 unsigned nhd_master=unsigned(next_entry);
3082 for (
unsigned m=0; m<nhd_master; m++)
3089 unsigned shared_node_proc=unsigned(receive_data[count++]);
3092 unsigned shared_node_id=unsigned(receive_data[count++]);
3095 double mtr_weight=receive_double_data[count_double++];
3099 if (shared_node_proc==
unsigned(dd))
3126 hang_info.push_back(tmp);
3136 else if (next_entry<0)
3154 oomph_info <<
"Time for second all-to-all in synchronise_hanging_nodes() " 3155 << t_end-t_start << std::endl;
3163 unsigned n=hang_info.size();
3166 unsigned global_n=0;
3167 MPI_Allreduce(&n,&global_n,1,MPI_UNSIGNED,MPI_MAX,
3172 <<
"No need for reconciliation of wrongly synchronised hang nodes\n";
3179 <<
"Need to reconcile of wrongly syncronised hang nodes\n";
3205 for(
int rank=0;rank<n_proc;rank++)
3208 send_displacement[rank] = send_data.size();
3219 for (
unsigned i=0;
i<n;
i++)
3234 hang_info_index_for_proc[rank].push_back(
i);
3240 send_n[rank] = send_data.size() - send_displacement[rank];
3248 MPI_Alltoall(&send_n[0],1,MPI_INT,&receive_n[0],1,MPI_INT,
3254 int receive_data_count=0;
3255 for(
int rank=0;rank<n_proc;++rank)
3258 receive_displacement[rank] = receive_data_count;
3259 receive_data_count += receive_n[rank];
3264 if(receive_data_count==0) {++receive_data_count;}
3269 if(send_data.size()==0) {send_data.resize(1);}
3272 MPI_Alltoallv(&send_data[0],&send_n[0],&send_displacement[0],
3274 &receive_data[0],&receive_n[0],
3275 &receive_displacement[0],
3280 for (
int send_rank=0;send_rank<n_proc;send_rank++)
3284 if((send_rank != my_rank) && (receive_n[send_rank] != 0))
3287 unsigned count=receive_displacement[send_rank];
3290 unsigned n_rec=unsigned(receive_n[send_rank]);
3291 for (
unsigned i=0;
i<n_rec/2;
i++)
3295 unsigned orig_sending_proc=receive_data[count];
3301 unsigned shared_node_id_on_orig_sending_proc=
3302 receive_data[count];
3306 Node* master_nod_pt=
3308 shared_node_id_on_orig_sending_proc);
3313 std::map<Node*,unsigned>::iterator it=
3314 shared_node_map[send_rank].find(master_nod_pt);
3318 if (it!=shared_node_map[send_rank].end())
3321 translated_entry[send_rank].push_back((*it).second);
3328 translated_entry[send_rank].push_back(-1);
3361 oomph_info <<
"Time for third all-to-all in synchronise_hanging_nodes() " 3362 << t_end-t_start << std::endl;
3382 for(
int rank=0;rank<n_proc;rank++)
3385 send_displacement[rank] = send_data.size();
3393 unsigned n=translated_entry[rank].size();
3394 for (
unsigned j=0;j<n;j++)
3396 send_data.push_back(translated_entry[rank][j]);
3401 send_n[rank] = send_data.size() - send_displacement[rank];
3409 MPI_Alltoall(&send_n[0],1,MPI_INT,&receive_n[0],1,MPI_INT,
3415 int receive_data_count=0;
3416 for(
int rank=0;rank<n_proc;++rank)
3419 receive_displacement[rank] = receive_data_count;
3420 receive_data_count += receive_n[rank];
3425 if(receive_data_count==0) {++receive_data_count;}
3430 if(send_data.size()==0) {send_data.resize(1);}
3433 MPI_Alltoallv(&send_data[0],&send_n[0],&send_displacement[0],
3435 &receive_data[0],&receive_n[0],
3436 &receive_displacement[0],
3441 for (
int send_rank=0;send_rank<n_proc;send_rank++)
3445 if((send_rank != my_rank) && (receive_n[send_rank] != 0))
3448 unsigned count=receive_displacement[send_rank];
3451 unsigned n_rec=unsigned(receive_n[send_rank]);
3452 for (
unsigned i=0;
i<n_rec;
i++)
3457 int index=receive_data[count];
3464 unsigned hang_info_index=hang_info_index_for_proc[send_rank][
i];
3468 Node* master_nod_pt=
3473 master_nod_pt,tmp.
Weight);
3482 unsigned hang_info_index=hang_info_index_for_proc[send_rank][
i];
3492 nnode_still_requiring_synchronisation++;
3506 <<
"Time for fourth all-to-all in synchronise_hanging_nodes() " 3507 << t_end-t_start << std::endl;
3518 unsigned global_nnode_still_requiring_synchronisation=0;
3519 MPI_Allreduce(&nnode_still_requiring_synchronisation,
3520 &global_nnode_still_requiring_synchronisation,
3521 1,MPI_UNSIGNED,MPI_MAX,
Comm_pt->mpi_comm());
3522 if (global_nnode_still_requiring_synchronisation>0)
3525 double tt_start = 0.0;
3531 oomph_info <<
"Need to do additional synchronisation of hanging nodes" 3542 <<
"Time for RefineableMesh::additional_synchronise_hanging_nodes() " 3543 <<
"in TreeBasedRefineableMeshBase::synchronise_hanging_nodes(): " 3544 << tt_end-tt_start << std::endl;
3551 oomph_info <<
"No need to do additional synchronisation of hanging nodes" 3568 int my_rank=
Comm_pt->my_rank();
3570 double t_start = 0.0;
3585 for (
int d=0; d<n_proc; d++)
3594 unsigned recv_unsigneds_count=0;
3595 MPI_Recv(&recv_unsigneds_count,1,MPI_UNSIGNED,d,0,
Comm_pt->mpi_comm(),&status);
3596 unsigned recv_doubles_count=0;
3597 MPI_Recv(&recv_doubles_count,1,MPI_UNSIGNED,d,1,
Comm_pt->mpi_comm(),&status);
3600 if (recv_unsigneds_count!=0)
3602 recv_unsigneds[d].resize(recv_unsigneds_count);
3603 MPI_Recv(&recv_unsigneds[d][0],recv_unsigneds_count,MPI_UNSIGNED,d,0,
3606 if (recv_doubles_count!=0)
3608 recv_doubles[d].resize(recv_doubles_count);
3609 MPI_Recv(&recv_doubles[d][0],recv_doubles_count,MPI_DOUBLE,d,1,
3614 unsigned recv_unsigneds_index = 0;
3615 double recv_doubles_index = 0;
3621 while(recv_unsigneds_index<recv_unsigneds_count)
3626 halo_element_pt[recv_unsigneds[d][recv_unsigneds_index++]]);
3632 unsigned n_dim = el_pt->
dim();
3635 Node* nod_pt=el_pt->
node_pt(recv_unsigneds[d][recv_unsigneds_index++]);
3639 for(
unsigned dir=0; dir<n_dim; dir++)
3641 x_cur[dir] = nod_pt->
x(dir);
3646 for(
unsigned dir=0; dir<n_dim; dir++)
3648 x_rec[dir] = recv_doubles[d][recv_doubles_index+dir];
3652 bool node_pos_differs=
false;
3653 for(
unsigned dir=0; dir<n_dim; dir++)
3655 node_pos_differs = node_pos_differs
3656 || (std::fabs(x_cur[dir]-x_rec[dir])>1.0e-14);
3661 for(
unsigned dir=0; dir<n_dim; dir++)
3663 nod_pt->
x(dir) = recv_doubles[d][recv_doubles_index++];
3668 if(recv_unsigneds_count!=recv_unsigneds_index)
3670 std::ostringstream error_stream;
3671 error_stream <<
"recv_unsigneds_count != recv_unsigneds_index ( " 3672 << recv_unsigneds_count <<
" != " 3673 << recv_unsigneds_index <<
")" << std::endl;
3676 "TreeBasedRefineableMeshBase::synchronise_nonhanging_nodes()",
3677 OOMPH_EXCEPTION_LOCATION);
3685 for (
int dd=0; dd<n_proc; dd++)
3696 std::set<Node*> nodes_requiring_adjustment;
3702 unsigned nh=haloed_element_pt.size();
3703 for (
unsigned e=0;
e<nh;
e++)
3712 unsigned n_dim = el_pt->
dim();
3715 unsigned n_node = el_pt->
nnode();
3716 for (
unsigned j=0;j<n_node;j++)
3729 for(
unsigned t=0;
t<nt;
t++)
3738 for(
unsigned dir=0; dir<n_dim; dir++)
3740 x_act[dir] = nod_pt->
x(dir);
3744 bool node_pos_differs=
false;
3745 for(
unsigned dir=0; dir<n_dim; dir++)
3747 node_pos_differs = node_pos_differs
3748 || (std::fabs(x_act[dir]-x_exp[dir])>1.0e-14);
3754 if(node_pos_differs)
3757 if(nodes_requiring_adjustment.insert(nod_pt).second)
3760 send_unsigneds.push_back(
e);
3762 send_unsigneds.push_back(j);
3764 for(
unsigned dir=0; dir<n_dim; dir++)
3766 send_doubles.push_back(x_act[dir]);
3777 unsigned send_unsigneds_count=send_unsigneds.size();
3778 unsigned send_doubles_count=send_doubles.size();
3780 if(send_unsigneds_count>0)
3786 MPI_Send(&send_unsigneds_count,1,MPI_UNSIGNED,dd,0,
Comm_pt->mpi_comm());
3787 MPI_Send(&send_doubles_count,1,MPI_UNSIGNED,dd,1,
Comm_pt->mpi_comm());
3790 if (send_unsigneds_count!=0)
3792 MPI_Send(&send_unsigneds[0],send_unsigneds_count,MPI_UNSIGNED,
3795 if (send_doubles_count!=0)
3797 MPI_Send(&send_doubles[0],send_doubles_count,MPI_DOUBLE,
3809 oomph_info <<
"Time for synchronise_nonhanging_nodes(): " 3810 << t_end-t_start << std::endl;
3844 else {local_doc_info=this->
doc_info();}
3848 if (refine_tol<=unrefine_tol)
3850 std::ostringstream error_stream;
3851 error_stream <<
"Refinement tolerance <= Unrefinement tolerance" 3852 << refine_tol <<
" " << unrefine_tol << std::endl
3853 <<
"doesn't make sense and will almost certainly crash" 3855 <<
"this beautiful code!" << std::endl;
3858 OOMPH_CURRENT_FUNCTION,
3859 OOMPH_EXCEPTION_LOCATION);
3869 unsigned n_refine=0;
3870 unsigned n_unrefine=0;
3872 unsigned long Nelement=this->
nelement();
3873 for (
unsigned long e=0;
e<Nelement;
e++)
3887 if(elemental_error[
e] > refine_tol)
3903 if(elemental_error[
e] < unrefine_tol)
3925 oomph_info <<
"p-refinement is not possible for these elements" 3933 <<
" \n Number of elements to be refined: " << n_refine << std::endl;
3934 oomph_info <<
" \n Number of elements whose refinement was overruled: " 3937 oomph_info <<
" \n Number of elements to be unrefined : " 3938 << n_unrefine << std::endl << std::endl;
3957 unsigned total_n_refine=0;
3958 #ifdef OOMPH_HAS_MPI 3962 MPI_Allreduce(&n_refine,&total_n_refine,1,MPI_INT,MPI_SUM,
3967 total_n_refine=n_refine;
3970 total_n_refine=n_refine;
3981 unsigned total_n_unrefine=0;
3982 #ifdef OOMPH_HAS_MPI 3986 MPI_Allreduce(&n_unrefine,&total_n_unrefine,1,MPI_INT,MPI_SUM,
3991 total_n_unrefine=n_unrefine;
3994 total_n_unrefine=n_unrefine;
3997 oomph_info <<
"---> " << total_n_refine <<
" elements to be refined, and " 3998 << total_n_unrefine <<
" to be unrefined, in total." << std::endl;
4004 #ifdef OOMPH_HAS_MPI 4014 int my_rank=
Comm_pt->my_rank();
4017 for (
int d=0;d<n_proc;d++)
4030 unsigned nhalo=halo_elem_pt.size();
4032 for (
unsigned e=0;
e<nhalo;
e++)
4034 if (dynamic_cast<PRefineableElement*>(halo_elem_pt[
e])
4035 ->to_be_p_unrefined())
4037 halo_to_be_unrefined[
e]=1;
4046 MPI_Send(&halo_to_be_unrefined[0],nhalo,MPI_INT,
4059 unsigned nhaloed=haloed_elem_pt.size();
4064 MPI_Recv(&halo_to_be_unrefined[0],nhaloed,MPI_INT,d,0,
4069 for (
unsigned e=0;
e<nhaloed;
e++)
4071 if ( ( (halo_to_be_unrefined[
e]==0)&&
4072 (dynamic_cast<PRefineableElement*>(haloed_elem_pt[
e])->
4073 to_be_p_unrefined()) ) ||
4074 ( (halo_to_be_unrefined[
e]==1)&&
4075 (!dynamic_cast<PRefineableElement*>(haloed_elem_pt[e])->
4076 to_be_p_unrefined()) ) )
4078 std::ostringstream error_message;
4080 <<
"Error in refinement: \n" 4081 <<
"Haloed element: " << e <<
" on proc " << my_rank <<
" \n" 4082 <<
"wants to be unrefined whereas its halo counterpart on\n" 4083 <<
"proc " << d <<
" doesn't (or vice versa)...\n" 4084 <<
"This is most likely because the error estimator\n" 4085 <<
"has not assigned the same errors to halo and haloed\n" 4086 <<
"elements -- it ought to!\n";
4088 OOMPH_CURRENT_FUNCTION,
4089 OOMPH_EXCEPTION_LOCATION);
4100 for (
int d=0;d<n_proc;d++)
4113 unsigned nhalo=halo_elem_pt.size();
4115 for (
unsigned e=0;
e<nhalo;
e++)
4117 if (dynamic_cast<PRefineableElement*>(halo_elem_pt[
e])
4118 ->to_be_p_refined())
4120 halo_to_be_refined[
e]=1;
4127 MPI_Send(&halo_to_be_refined[0],nhalo,MPI_INT,
4140 unsigned nhaloed=haloed_elem_pt.size();
4144 MPI_Recv(&halo_to_be_refined[0],nhaloed,MPI_INT,d,0,
4149 for (
unsigned e=0;
e<nhaloed;
e++)
4151 if ( ( (halo_to_be_refined[
e]==0)&&
4152 (dynamic_cast<PRefineableElement*>(haloed_elem_pt[
e])->
4153 to_be_p_refined()) ) ||
4154 ( (halo_to_be_refined[
e]==1)&&
4155 (!dynamic_cast<PRefineableElement*>(haloed_elem_pt[e])->
4156 to_be_p_refined()) ) )
4158 std::ostringstream error_message;
4160 <<
"Error in refinement: \n" 4161 <<
"Haloed element: " << e <<
" on proc " << my_rank <<
" \n" 4162 <<
"wants to be refined whereas its halo counterpart on\n" 4163 <<
"proc " << d <<
" doesn't (or vice versa)...\n" 4164 <<
"This is most likely because the error estimator\n" 4165 <<
"has not assigned the same errors to halo and haloed\n" 4166 <<
"elements -- it ought to!\n";
4168 OOMPH_CURRENT_FUNCTION,
4169 OOMPH_EXCEPTION_LOCATION);
4192 #ifdef OOMPH_HAS_MPI 4206 #ifdef OOMPH_HAS_MPI 4224 <<
"\n Not enough benefit in adapting mesh. " 4225 << std::endl << std::endl;
4295 #ifdef OOMPH_HAS_MPI 4306 double t_start = 0.0;
4318 oomph_info <<
"Time for p-refinement/unrefinement: " 4319 << t_end-t_start << std::endl;
4345 const unsigned n_boundary = this->
nboundary();
4349 unsigned long n_node=this->
nnode();
4350 for (
unsigned long n=0;n<n_node;n++)
4356 unsigned n_value=nod_pt->
nvalue();
4361 for(
unsigned n=0;n<n_value;n++)
4375 unsigned n_dim=nod_pt->
ndim();
4378 for(
unsigned t=0;
t<nt;
t++)
4383 for(
unsigned i=0;
i<n_dim;
i++) {nod_pt->
x(
t,
i)=position[
i];}
4390 bool update_all_time_levels=
true;
4398 if(solid_node_pt!=0)
4400 unsigned n_lagrangian = solid_node_pt->
nlagrangian();
4401 for(
unsigned i=0;
i<n_lagrangian;
i++)
4417 std::set<unsigned>* boundaries_pt;
4419 if(boundaries_pt!=0)
4423 for(std::set<unsigned>::iterator it=boundaries_pt->begin();
4424 it!=boundaries_pt->end();++it)
4426 hanging_nodes_on_boundary_pt[*it].insert(nod_pt);
4443 oomph_info <<
"Time for sorting out initial hanging status: " 4444 << t_end-t_start << std::endl;
4453 unsigned long num_tree_nodes=tree_nodes_pt.size();
4455 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
4461 unsigned n_node=this_el_pt->
nnode();
4462 for (
unsigned n=0;n<n_node;n++)
4489 for(
unsigned long e=0;
e<num_tree_nodes;
e++)
4492 tree_nodes_pt[
e]->object_pt()->setup_hanging_nodes(hanging_output_files);
4494 tree_nodes_pt[
e]->object_pt()->further_setup_hanging_nodes();
4506 <<
"Time for setup_hanging_nodes() and further_setup_hanging_nodes() for " 4507 << num_tree_nodes <<
" elements: " 4508 << t_end-t_start << std::endl;
4514 unsigned ncont_interpolated_values=
4515 tree_nodes_pt[0]->object_pt()->ncont_interpolated_values();
4526 <<
"Time for complete_hanging_nodes: " 4527 << t_end-t_start << std::endl;
4543 <<
"Time for boundary element info: " 4544 << t_end-t_start << std::endl;
4554 if(first_macro_el_pt!=0)
4589 for (
unsigned long e=0;
e<num_tree_nodes;
e++)
4591 double max_el_error;
4592 tree_nodes_pt[
e]->object_pt()->check_integrity(max_el_error);
4595 if(max_el_error > max_error) {max_error=max_el_error;}
4600 std::ostringstream error_stream;
4601 error_stream <<
"Mesh refined: Max. error in integrity check: " 4602 << max_error <<
" is too big" 4603 <<
"\ni.e. bigger than RefineableElement::" 4604 <<
"max_integrity_tolerance()=" 4608 std::ofstream some_file;
4609 some_file.open(
"ProblemMesh.dat");
4610 for (
unsigned long n=0;n<n_node;n++)
4615 unsigned n_dim = nod_pt->
ndim();
4617 for(
unsigned i=0;
i<n_dim;
i++)
4619 some_file << this->
node_pt(n)->
x(
i) <<
" ";
4621 some_file << std::endl;
4625 error_stream <<
"Documented problem mesh in ProblemMesh.dat" << std::endl;
4628 OOMPH_CURRENT_FUNCTION,
4629 OOMPH_EXCEPTION_LOCATION);
4633 oomph_info <<
"Mesh refined: Max. error in integrity check: " 4634 << max_error <<
" is OK" << std::endl;
4635 oomph_info <<
"i.e. less than RefineableElement::max_integrity_tolerance()=" 4637 <<
"\n" << std::endl;
4645 <<
"Time for (paranoid only) checking of integrity: " 4646 << t_end-t_start << std::endl;
4670 oomph_info <<
"Time for deactivating objects and pruning nodes: " 4671 << t_end-t_start << std::endl;
4685 << t_end-t_start << std::endl;
4695 for(
unsigned b=0;b<n_boundary;b++)
4699 unsigned n_del=deleted_node_pt.size();
4700 for (
unsigned j=0;j<n_del;j++)
4702 hanging_nodes_on_boundary_pt[b].erase(deleted_node_pt[j]);
4707 for(std::set<Node*>::iterator
4708 it=hanging_nodes_on_boundary_pt[b].begin();
4709 it!=hanging_nodes_on_boundary_pt[b].end();)
4711 if((*it)->is_hanging())
4712 {hanging_nodes_on_boundary_pt[b].erase(it++);}
4721 if(hanging_nodes_on_boundary_pt[b].size()>0)
4725 for(
unsigned e=0;
e<n_boundary_element;++
e)
4749 unsigned n_el_node = el_pt->
nnode();
4750 for(
unsigned n=0;n<n_el_node;n++)
4757 std::set<Node*>::iterator it =
4758 hanging_nodes_on_boundary_pt[b].find(nod_pt);
4761 if(it!=hanging_nodes_on_boundary_pt[b].end())
4769 const unsigned ntstorage = nod_pt->
ntstorage();
4790 for(
unsigned i=0;
i<3;
i++) {solid_node_pt->
xi(
i) = xi[
i];}
4796 for(
unsigned t=0;
t<ntstorage;
t++)
4803 for(
unsigned i=0;
i<3;
i++) {nod_pt->
x(
t,
i) = x[
i];}
4808 hanging_nodes_on_boundary_pt[b].erase(it);
4810 if(hanging_nodes_on_boundary_pt[b].size()==0)
4811 {
e=n_boundary_element;
break;}
4834 unsigned max_nval=0;
4835 for (
unsigned n=0;n<el_pt->
nnode();n++)
4842 std::ostringstream fullname;
4843 std::ofstream bcs_file;
4847 bcs_file.open(fullname.str().c_str());
4850 for(
unsigned long e=0;
e<num_tree_nodes;
e++)
4852 el_pt = tree_nodes_pt[
e]->object_pt();
4854 unsigned n_nod=el_pt->
nnode();
4855 for(
unsigned n=0;n<n_nod;n++)
4860 unsigned n_dim = nod_pt->
ndim();
4862 for(
unsigned i=0;
i<n_dim;
i++)
4863 {bcs_file << nod_pt->
x(
i) <<
" ";}
4866 for(
unsigned i=0;
i<max_nval;
i++)
4869 if (i<nod_pt->nvalue())
4879 bcs_file << std::endl;
4886 std::ofstream all_nodes_file;
4888 fullname << doc_info.
directory() <<
"/all_nodes" 4889 << doc_info.
number() <<
".dat";
4890 all_nodes_file.open(fullname.str().c_str());
4892 all_nodes_file <<
"ZONE \n";
4896 n_node = this->
nnode();
4897 for(
unsigned long n=0;n<n_node;n++)
4900 unsigned n_dim = nod_pt->
ndim();
4901 for(
unsigned i=0;
i<n_dim;
i++)
4903 all_nodes_file << this->
node_pt(n)->
x(
i) <<
" ";
4905 all_nodes_file << std::endl;
4908 all_nodes_file.close();
4913 std::ofstream some_file;
4915 fullname << doc_info.
directory() <<
"/all_hangnodes" 4916 << doc_info.
number() <<
".dat";
4917 some_file.open(fullname.str().c_str());
4918 for(
unsigned long n=0;n<n_node;n++)
4924 unsigned n_dim = nod_pt->
ndim();
4925 for(
unsigned i=0;
i<n_dim;
i++)
4927 some_file << nod_pt->
x(
i) <<
" ";
4931 if(this->
node_pt(n)->nvalue() > 0)
4933 some_file <<
" " << nod_pt->
raw_value(0);
4935 some_file << std::endl;
4944 <<
"/geometric_hangnodes_withmasters" 4945 << doc_info.
number() <<
".dat";
4946 some_file.open(fullname.str().c_str());
4947 for(
unsigned long n=0;n<n_node;n++)
4952 unsigned n_dim = nod_pt->
ndim();
4954 some_file <<
"ZONE I="<<nmaster+1 << std::endl;
4955 for(
unsigned i=0;
i<n_dim;
i++)
4957 some_file << nod_pt->
x(
i) <<
" ";
4959 some_file <<
" 2 " << std::endl;
4961 for (
unsigned imaster=0;imaster<nmaster;imaster++)
4963 Node* master_nod_pt =
4965 unsigned n_dim = master_nod_pt->
ndim();
4966 for(
unsigned i=0;
i<n_dim;
i++)
4968 some_file << master_nod_pt->
x(
i) <<
" ";
4970 some_file <<
" 1 " << std::endl;
4978 for(
unsigned i=0;
i<ncont_interpolated_values;
i++)
4982 <<
"/nonstandard_hangnodes_withmasters" <<
i <<
"_" 4983 << doc_info.
number() <<
".dat";
4984 some_file.open(fullname.str().c_str());
4985 unsigned n_nod=this->
nnode();
4986 for(
unsigned long n=0;n<n_nod;n++)
4994 some_file <<
"ZONE I="<<nmaster+1 << std::endl;
4995 unsigned n_dim = nod_pt->
ndim();
4996 for(
unsigned j=0;j<n_dim;j++)
4998 some_file << nod_pt->
x(j) <<
" ";
5000 some_file <<
" 2 " << std::endl;
5001 for (
unsigned imaster=0;imaster<nmaster;imaster++)
5003 Node* master_nod_pt =
5005 unsigned n_dim = master_nod_pt->
ndim();
5006 for(
unsigned j=0;j<n_dim;j++)
5010 some_file <<
" 1 " << std::endl;
5046 #ifdef OOMPH_HAS_MPI 5066 unsigned long Nelement=this->
nelement();
5067 for (
unsigned long e=0;
e<Nelement;
e++)
5091 #ifdef OOMPH_HAS_MPI 5094 std::ostringstream warn_stream;
5095 warn_stream <<
"You are attempting to refine selected elements of a " 5097 <<
"distributed mesh. This may have undesired effects." 5101 "TreeBasedRefineableMeshBase::refine_selected_elements()",
5102 OOMPH_EXCEPTION_LOCATION);
5107 unsigned long nref=elements_to_be_refined.size();
5108 for (
unsigned long e=0;
e<nref;
e++)
5133 #ifdef OOMPH_HAS_MPI 5136 std::ostringstream warn_stream;
5137 warn_stream <<
"You are attempting to refine selected elements of a " 5139 <<
"distributed mesh. This may have undesired effects." 5143 "TreeBasedRefineableMeshBase::refine_selected_elements()",
5144 OOMPH_EXCEPTION_LOCATION);
5149 unsigned long nref=elements_to_be_refined_pt.size();
5150 for (
unsigned long e=0;
e<nref;
e++)
5152 elements_to_be_refined_pt[
e]->select_for_p_refinement();
void p_refine_uniformly()
p-refine mesh uniformly
void node_update(const bool &update_all_time_levels_for_new_node=false)
Broken assignment operator.
double raw_value(const unsigned &i) const
Return the i-th value stored at the Node. This interface does NOT take the hanging status of the Node...
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
unsigned nsons() const
Return number of sons (zero if it's a leaf node)
Node * haloed_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th haloed node in this Mesh whose halo counterpart is held on processor p...
virtual unsigned initial_p_order() const =0
unsigned ntree()
Number of trees in forest.
void get_x(const Vector< double > &s, Vector< double > &x) const
Global coordinates as function of local coordinates. Either via FE representation or via macro-elemen...
virtual void local_coordinate_of_node(const unsigned &j, Vector< double > &s) const
Get local coordinates of node j in the element; vector sets its own size (broken virtual) ...
virtual void split_elements_if_required()=0
Split all the elements in the mesh if required. This template free interface will be overloaded in Re...
void synchronise_nonhanging_nodes()
std::map< unsigned, Vector< Node * > > Shared_node_pt
Vector< GeneralisedElement * > halo_element_pt(const unsigned &p)
Return vector of halo elements in this Mesh whose non-halo counterpart is held on processor p...
void deselect_for_p_unrefinement()
Deselect the element for p-unrefinement.
void refine_uniformly()
Refine mesh uniformly.
void select_for_p_refinement()
Select the element for p-refinement.
void deselect_for_refinement()
Deselect the element for refinement.
bool is_doc_enabled() const
Are we documenting?
void refine_base_mesh(Vector< Vector< unsigned > > &to_be_refined)
Refine base mesh according to specified refinement pattern.
void deactivate_object()
Call the RefineableElement's deactivate_element() function.
TreeRoot * tree_pt(const unsigned &i) const
Return pointer to i-th tree in forest.
double & max_error()
Access fct for max. actual error in present solution (i.e. before re-solve on adapted mesh) ...
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
void set_nonhanging()
Label node as non-hanging node by removing all hanging node data.
double & max_permitted_error()
Access fct for max. error (i.e. split elements if their error is larger)
Information for documentation of results: Directory and file number to enable output in the form RESL...
unsigned & p_order()
Access function to P_order.
std::string directory() const
Output directory.
unsigned Master_node_index
virtual void get_refinement_levels(unsigned &min_refinement_level, unsigned &max_refinement_level)
Get max/min refinement levels in mesh.
void p_unrefine_uniformly(DocInfo &doc_info)
p-unrefine mesh uniformly
void stick_all_tree_nodes_into_vector(Vector< Tree * > &all_forest_nodes)
Traverse forest and stick pointers to all "nodes" into Vector.
TreeForest * forest_pt()
Return pointer to the Forest represenation of the mesh.
A general Finite Element class.
unsigned & nrefinement_overruled()
Number of elements that would have liked to be refined further but can't because they've reached the ...
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo node; negative if not a halo...
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
virtual void open_hanging_node_files(DocInfo &doc_info, Vector< std::ofstream *> &output_stream)=0
Open output files that will store any hanging nodes in the forest. Return a vector of the output stre...
void stick_leaves_into_vector(Vector< Tree * > &forest_nodes)
Traverse forst and stick pointers to leaf "nodes" into Vector.
unsigned & min_refinement_level()
Access fct for min. permissible refinement level (relative to base mesh)
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
unsigned nmaster() const
Return the number of master nodes.
unsigned & max_keep_unrefined()
Max. number of elements that we allow to remain unrefined if no other mesh adaptation is required (to...
Vector< GeneralisedElement * > haloed_element_pt(const unsigned &p)
Return vector of haloed elements in this Mesh whose haloing counterpart is held on processor p...
unsigned Shared_node_proc
bool is_hanging() const
Test whether the node is geometrically hanging.
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
void set_master_node_pt(const unsigned &i, Node *const &master_node_pt, const double &weight)
Set the pointer to the i-th master node and its weight.
virtual void refine_as_in_reference_mesh(TreeBasedRefineableMeshBase *const &ref_mesh_pt)
Refine mesh once so that its topology etc becomes that of the (finer!) reference mesh – if possible!...
bool Lookup_for_elements_next_boundary_is_setup
bool Doc_comprehensive_timings
Global boolean to switch on comprehensive timing – can probably be declared const false when develop...
virtual void refine_selected_elements(const Vector< unsigned > &elements_to_be_refined)
Refine mesh by splitting the elements identified by their numbers.
MacroElement * undeformed_macro_elem_pt()
Access function to pointer to "undeformed" macro element.
void merge_sons_if_required(Mesh *&mesh_pt)
If required, merge the four sons for unrefinement – criterion: bool object_pt()-> sons_to_be_unrefin...
void synchronise_hanging_nodes(const unsigned &ncont_interpolated_values)
Synchronise the hanging nodes if the mesh is distributed.
TreeForest * Forest_pt
Forest representation of the mesh.
unsigned & number()
Number used (e.g.) for labeling output files.
void set_obsolete()
Mark node as obsolete.
unsigned long nelement() const
Return number of elements in the mesh.
void complete_hanging_nodes(const int &ncont_interpolated_values)
Complete the hanging node scheme recursively.
unsigned & max_refinement_level()
Access fct for max. permissible refinement level (relative to base mesh)
void output(std::ostream &outfile)
Output for all elements.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
unsigned Sending_processor
void adapt(const Vector< double > &elemental_error)
Adapt mesh: Refine elements whose error is lager than err_max and (try to) unrefine those whose error...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
virtual void adapt_mesh()
Perform the actual tree-based mesh adaptation. A simple wrapper to call the function without document...
unsigned nhalo_node()
Total number of halo nodes in this Mesh.
void complete_hanging_nodes_recursively(Node *&nod_pt, Vector< Node *> &master_nodes, Vector< double > &hang_weights, const int &ival)
Auxiliary routine for recursive hanging node completion.
unsigned & max_p_refinement_level()
Access fct for max. permissible p-refinement level (relative to base mesh)
virtual void p_refine_elements_if_required()=0
p-refine all the elements in the mesh if required. This template free interface will be overloaded in...
Helper struct to collate data required during TreeBasedRefineableMeshBase::synchronise_hanging_nodes...
bool is_mesh_distributed() const
Boolean to indicate if Mesh has been distributed.
Base class for tree-based refineable meshes.
void classify_halo_and_haloed_nodes(DocInfo &doc_info, const bool &report_stats)
unsigned nboundary() const
Return number of boundaries.
Tree * tree_pt()
Access function: Pointer to quadtree representation of this element.
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...
Vector< Node * > prune_dead_nodes()
Prune nodes. Nodes that have been marked as obsolete are removed from the mesh (and its boundary-node...
Node * shared_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th shared node in this Mesh who has a counterpart on processor p...
void position(Vector< double > &pos) const
Compute Vector of nodal positions either directly or via hanging node representation.
void deselect_for_p_refinement()
Deselect the element for p-refinement.
void p_adapt_mesh()
Perform the actual tree-based mesh p-adaptation. A simple wrapper to call the function without docume...
unsigned unrefine_uniformly()
Unrefine mesh uniformly: Return 0 for success, 1 for failure (if unrefinement has reached the coarses...
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
bool p_refinement_is_enabled()
Flag to indicate suppression of any refinement.
static double & max_integrity_tolerance()
Max. allowed discrepancy in element integrity check.
unsigned refinement_level() const
Return the Refinement level.
bool refinement_is_enabled()
Flag to indicate suppression of any refinement.
double lagrangian_position(const unsigned &i) const
Return lagrangian coordinate either directly or via hanging node representation.
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
virtual void dump_refinement(std::ostream &outfile)
Dump refinement pattern to allow for rebuild.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
double timer()
returns the time in seconds after some point in past
Vector< GeomObject * > & geom_object_pt()
Vector of (pointers to) geometric objects involved in node update function.
unsigned nhaloed_node()
Total number of haloed nodes in this Mesh.
MacroElement * macro_elem_pt()
Access function to pointer to macro element.
void close_hanging_node_files(DocInfo &doc_info, Vector< std::ofstream *> &output_stream)
Close output files that will store any hanging nodes in the forest and delete any associated storage...
Class that contains data for hanging nodes.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
unsigned long nnode() const
Return number of nodes in the mesh.
unsigned ntstorage() const
Return total number of doubles stored per value to record time history of each value (one for steady ...
void p_refine_selected_elements(const Vector< unsigned > &elements_to_be_refined)
p-refine mesh by refining the elements identified by their numbers.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
virtual void get_x_and_xi(const Vector< double > &s, Vector< double > &x_fe, Vector< double > &x, Vector< double > &xi_fe, Vector< double > &xi) const
Eulerian and Lagrangian coordinates as function of the local coordinates: The Eulerian position is re...
DocInfo *& doc_info_pt()
Access fct for pointer to DocInfo.
void select_for_refinement()
Select the element for refinement.
virtual void additional_synchronise_hanging_nodes(const unsigned &ncont_interpolated_values)=0
virtual void refine_base_mesh_as_in_reference_mesh(TreeBasedRefineableMeshBase *const &ref_mesh_pt)
Refine base mesh to same degree as reference mesh (relative to original unrefined mesh)...
void disable_doc()
Disable documentation.
void set_hanging_pt(HangInfo *const &hang_pt, const int &i)
Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
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.
Base class for elements that allow MacroElement-based node update.
void traverse_all(Tree::VoidMemberFctPt member_function)
Traverse the tree and execute void Tree member function member_function() at all its "nodes"...
Tree * son_pt(const int &son_index) const
Return pointer to the son for a given index. Note that to aid code readability specific enums have be...
Tree * father_pt() const
Return pointer to father: NULL if it's a root node.
virtual void get_elements_at_refinement_level(unsigned &refinement_level, Vector< RefineableElement *> &level_elements)
Extract the elements at a particular refinement level in the refinement pattern - used in Mesh::redis...
virtual void set_node_update_info(const Vector< GeomObject *> &geom_object_pt)=0
Set node update information: Pass the vector of (pointers to) the geometric objects that affect the n...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
DocInfo doc_info()
Access fct for DocInfo.
p-refineable version of RefineableElement
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
virtual void setup_boundary_element_info()
Interface for function that is used to setup the boundary information (Empty virtual function – impl...
unsigned Shared_node_id_on_sending_processor
virtual void read_refinement(std::ifstream &restart_file, Vector< Vector< unsigned > > &to_be_refined)
Read refinement pattern to allow for rebuild.
void pause(std::string message)
Pause and display message.
virtual void reorder_nodes(const bool &use_old_ordering=true)
Re-order nodes in the order in which they appear in elements – can be overloaded for more efficient ...
virtual void refine(std::ifstream &restart_file)
Refine mesh according to refinement pattern in restart file.
virtual void check_all_neighbours(DocInfo &doc_info)=0
Document/check the neighbours of all the nodes in the forest. This must be overloaded for different t...
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary, so return false. This will be overloaded by BoundaryNodes.
unsigned Nunrefined
Stats: Number of elements that were unrefined.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
int son_type() const
Return son type.
RefineableElement * object_pt() const
Return the pointer to the object (RefineableElement) represented by the tree.
unsigned Nrefined
Stats: Number of elements that were refined.
unsigned nlagrangian() const
Return number of lagrangian coordinates.
void set_non_obsolete()
Mark node as non-obsolete.
bool is_leaf()
Return true if the tree is a leaf node.
unsigned nnode() const
Return the number of nodes.
void delete_all_external_storage()
Wipe the storage for all externally-based elements.
OomphCommunicator * Comm_pt
Pointer to communicator – set to NULL if mesh is not distributed.
double & min_permitted_error()
Access fct for min. error (i.e. (try to) merge elements if their error is smaller) ...
virtual void get_refinement_pattern(Vector< Vector< unsigned > > &to_be_refined)
Extract refinement pattern: Consider the hypothetical mesh obtained by truncating the refinement of t...
SolidFiniteElement class.
unsigned & min_p_refinement_level()
Access fct for min. permissible p-refinement level (relative to base mesh)
void select_for_p_unrefinement()
Select the element for p-unrefinement.
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
virtual bool refine_base_mesh_as_in_reference_mesh_minus_one(TreeBasedRefineableMeshBase *const &ref_mesh_pt)
Refine base mesh to same degree as reference mesh minus one level of refinement (relative to original...
Node * halo_node_pt(const unsigned &p, const unsigned &j)
Access fct to the j-th halo node in this Mesh whose non-halo counterpart is held on processor p...
void p_adapt(const Vector< double > &elemental_error)
p-adapt mesh: Refine elements whose error is lager than err_max and (try to) unrefine those whose err...