On Thu, 22 Jan 2009, Tim Kroeger wrote:
On Thu, 22 Jan 2009, Roy Stogner wrote:
and I'm not a fan of trial-and-error coding and debugging.
I agree than one shouldn't, but sometimes I tend to do so. (-:
It's especially a problem when you're stymied by the errors.
Currently, ex10 on 2 CPUs dies after the first refinement, when
operator() fails at TransientSystem::old_local_solution.operator()(i),
where i is outside of the local dofs on that processor, because at the
time the _global_to_local_map is empty.
I think I understand why it's failing now: because although with the
patch we initialize old_local_solution as a ghosted vector in
TransientSystem::init_data(), those vectors are getting reinitialized
as distributed vectors in System::project_vector() - the code tests
size() against local_size() to determine whether a vector is serial or
distributed, and when it sees a ghost vector it incorrectly concludes
the latter.
The offending code is lines 100-118 of system_projection.C, which I
think is some of the least comprehensible code I've ever added to
libMesh. And off the top of my head I'm not sure what the right
solution is.
Eventually we'll want to replace all distributed vectors with ghosted
vectors and get rid of all serial vectors, which would make things
pretty easy, but that's much too big a change to make all at once,
especially before we have Trilinos & DistributedVector support.
Anyway, if you want to mull over the problem too (or if you just want
to test and see how well we're working on non-adaptive problems), the
newest patch is attached.
---
Roy
Index: include/numerics/petsc_vector.h
===================================================================
--- include/numerics/petsc_vector.h (revision 3225)
+++ include/numerics/petsc_vector.h (working copy)
@@ -654,6 +654,13 @@
int petsc_n=static_cast<int>(n);
int petsc_n_local=static_cast<int>(n_local);
int petsc_n_ghost=static_cast<int>(ghost.size());
+
+ // If the mesh is disjoint, the following assertion will fail.
+ // If the mesh is not disjoint, every processor will either have
+ // all the dofs, none of the dofs, or some non-zero dofs at the
+ // boundary between processors.
+ libmesh_assert(n_local == 0 || n_local == n || !ghost.empty());
+
int* petsc_ghost = ghost.empty() ? PETSC_NULL :
const_cast<int*>(reinterpret_cast<const int*>(&ghost[0]));
Index: include/base/dof_map.h
===================================================================
--- include/base/dof_map.h (revision 3225)
+++ include/base/dof_map.h (working copy)
@@ -582,7 +582,7 @@
* when projecting the solution onto the refined mesh, hence the parent's
* DOF indices need to be included in the \p _send_list.
*/
- void augment_send_list_for_projection(const MeshBase &);
+ // void augment_send_list_for_projection(const MeshBase &);
/**
* Fills the vector di with the global degree of freedom indices
@@ -681,12 +681,9 @@
* variable in the system.
* Starts at index next_free_dof, and increments it to
* the post-final index.
- * If build_send_list is true, builds the send list. If
- * false, clears and reserves the send list
*/
void distribute_local_dofs_var_major (unsigned int& next_free_dof,
- MeshBase& mesh,
- const bool build_send_list);
+ MeshBase& mesh);
/**
* Distributes the global degrees of freedom, for dofs on
@@ -701,8 +698,7 @@
* false, clears and reserves the send list
*/
void distribute_local_dofs_node_major (unsigned int& next_free_dof,
- MeshBase& mesh,
- const bool build_send_list);
+ MeshBase& mesh);
/**
* Adds entries to the \p _send_list vector corresponding to DoFs
Index: src/numerics/petsc_vector.C
===================================================================
--- src/numerics/petsc_vector.C (revision 3225)
+++ src/numerics/petsc_vector.C (working copy)
@@ -438,9 +438,11 @@
PetscVector<T>&
PetscVector<T>::operator = (const PetscVector<T>& v)
{
+ if (this->initialized())
+ this->clear();
+
if (v.initialized())
{
- this->init (v.size(), v.local_size());
this->_global_to_local_map = v._global_to_local_map;
this->_is_closed = v._is_closed;
this->_is_initialized = v._is_initialized;
@@ -449,8 +451,12 @@
{
int ierr = 0;
+ ierr = VecDuplicate (v._vec, &this->_vec);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
ierr = VecCopy (v._vec, this->_vec);
CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
}
}
@@ -514,7 +520,7 @@
PetscVector<T>* v_local = libmesh_cast_ptr<PetscVector<T>*>(&v_local_in);
libmesh_assert (v_local != NULL);
- libmesh_assert (v_local->local_size() == this->size());
+ libmesh_assert (v_local->size() == this->size());
int ierr = 0;
const int n = this->size();
@@ -573,19 +579,21 @@
PetscVector<T>* v_local = libmesh_cast_ptr<PetscVector<T>*>(&v_local_in);
libmesh_assert (v_local != NULL);
- libmesh_assert (v_local->local_size() == this->size());
+ libmesh_assert (v_local->size() == this->size());
libmesh_assert (send_list.size() <= v_local->size());
int ierr=0;
- const int n_sl = send_list.size();
+ const unsigned int n_sl = send_list.size();
IS is;
VecScatter scatter;
- std::vector<int> idx(n_sl);
+ std::vector<int> idx(n_sl + this->local_size());
- for (int i=0; i<n_sl; i++)
+ for (unsigned int i=0; i<n_sl; i++)
idx[i] = static_cast<int>(send_list[i]);
+ for (unsigned int i = 0; i != this->local_size(); ++i)
+ idx[n_sl+i] = i + this->first_local_index();
// Create the index set & scatter object
if (idx.empty())
@@ -640,7 +648,7 @@
const std::vector<unsigned int>& send_list)
{
// Only good for serial vectors.
- libmesh_assert (this->size() == this->local_size());
+ // libmesh_assert (this->size() == this->local_size());
libmesh_assert (last_local_idx > first_local_idx);
libmesh_assert (send_list.size() <= this->size());
libmesh_assert (last_local_idx < this->size());
Index: src/base/dof_map.C
===================================================================
--- src/base/dof_map.C (revision 3225)
+++ src/base/dof_map.C (working copy)
@@ -666,9 +666,9 @@
// Set temporary DOF indices on this processor
if (node_major_dofs)
- this->distribute_local_dofs_node_major (next_free_dof, mesh, false);
+ this->distribute_local_dofs_node_major (next_free_dof, mesh);
else
- this->distribute_local_dofs_var_major (next_free_dof, mesh, false);
+ this->distribute_local_dofs_var_major (next_free_dof, mesh);
// Get DOF counts on all processors
std::vector<unsigned int> dofs_on_proc(n_proc, 0);
@@ -692,9 +692,9 @@
// Set permanent DOF indices on this processor
if (node_major_dofs)
- this->distribute_local_dofs_node_major (next_free_dof, mesh, true);
+ this->distribute_local_dofs_node_major (next_free_dof, mesh);
else
- this->distribute_local_dofs_var_major (next_free_dof, mesh, true);
+ this->distribute_local_dofs_var_major (next_free_dof, mesh);
libmesh_assert(next_free_dof == _end_df[proc_id]);
@@ -723,6 +723,8 @@
STOP_LOG("distribute_dofs()", "DofMap");
+ _send_list.clear();
+
// Note that in the add_neighbors_to_send_list nodes on processor
// boundaries that are shared by multiple elements are added for
// each element.
@@ -734,14 +736,13 @@
void DofMap::distribute_local_dofs_node_major(unsigned int &next_free_dof,
- MeshBase& mesh,
- const bool build_send_list)
+ MeshBase& mesh)
{
const unsigned int sys_num = this->sys_number();
const unsigned int n_vars = this->n_variables();
- // Number of elements to add to send_list
- unsigned int send_list_size = 0;
+ // We now only add remote dofs to the _send_list
+ // unsigned int send_list_size = 0;
// _var_first_local_df does not work with node_major dofs
_var_first_local_df.resize(n_vars+1);
@@ -781,17 +782,6 @@
0,
next_free_dof);
next_free_dof += node->n_comp(sys_num,var);
-
- // If we've been requested to, add local dofs to the
- // _send_list
- if (build_send_list)
- for (unsigned int index=0;
index<node->n_comp(sys_num,var);
- index++)
- _send_list.push_back(node->dof_number(sys_num,
- var,
- index));
- else
- send_list_size += node->n_comp(sys_num,var);
}
}
}
@@ -810,17 +800,6 @@
next_free_dof);
next_free_dof += elem->n_comp(sys_num,var);
-
- // If we've been requested to, add local dofs to the
- // _send_list
- if (build_send_list)
- for (unsigned int index=0; index<elem->n_comp(sys_num,var);
- index++)
- _send_list.push_back(elem->dof_number(sys_num,
- var,
- index));
- else
- send_list_size += elem->n_comp(sys_num,var);
}
} // done looping over elements
@@ -845,25 +824,18 @@
}
}
#endif // DEBUG
-
- if (!build_send_list)
- {
- _send_list.clear();
- _send_list.reserve(send_list_size);
- }
}
void DofMap::distribute_local_dofs_var_major(unsigned int &next_free_dof,
- MeshBase& mesh,
- const bool build_send_list)
+ MeshBase& mesh)
{
const unsigned int sys_num = this->sys_number();
const unsigned int n_vars = this->n_variables();
- // Number of elements to add to send_list
- unsigned int send_list_size = 0;
+ // We now only add remote dofs to the _send_list
+ // unsigned int send_list_size = 0;
// We will cache the first local index for each variable
_var_first_local_df.clear();
@@ -909,17 +881,6 @@
0,
next_free_dof);
next_free_dof += node->n_comp(sys_num,var);
-
- // If we've been requested to, add local dofs to the
- // _send_list
- if (build_send_list)
- for (unsigned int index=0; index<node->n_comp(sys_num,var);
- index++)
- _send_list.push_back(node->dof_number(sys_num,
- var,
- index));
- else
- send_list_size += node->n_comp(sys_num,var);
}
}
@@ -935,17 +896,6 @@
next_free_dof);
next_free_dof += elem->n_comp(sys_num,var);
-
- // If we've been requested to, add local dofs to the
- // _send_list
- if (build_send_list)
- for (unsigned int index=0; index<elem->n_comp(sys_num,var);
- index++)
- _send_list.push_back(elem->dof_number(sys_num,
- var,
- index));
- else
- send_list_size += elem->n_comp(sys_num,var);
}
} // end loop on elements
_var_first_local_df.push_back(next_free_dof);
@@ -972,12 +922,6 @@
}
}
#endif // DEBUG
-
- if (!build_send_list)
- {
- _send_list.clear();
- _send_list.reserve(send_list_size);
- }
}
@@ -987,7 +931,6 @@
START_LOG("add_neighbors_to_send_list()", "DofMap");
//-------------------------------------------------------------------------
- // The _send_list now only contains entries from the local processor.
// We need to add the DOFs from elements that live on neighboring processors
// that are neighbors of the elements on the local processor
//-------------------------------------------------------------------------
@@ -1032,10 +975,12 @@
// Get the DOF indices for this neighboring element
this->dof_indices (family[i], di);
- // Insert the DOF indices into the send list
- _send_list.insert (_send_list.end(),
- di.begin(), di.end());
- }
+ // Insert the remote DOF indices into the send list
+ for (unsigned int j=0; j != di.size(); ++j)
+ if (di[j] < this->first_dof() ||
+ di[j] >= this->end_dof())
+ _send_list.push_back(di[j]);
+ }
}
}
@@ -1070,9 +1015,11 @@
// Get the DOF indices for this neighboring element
this->dof_indices (elem, di);
- // Insert the DOF indices into the send list
- _send_list.insert (_send_list.end(),
- di.begin(), di.end());
+ // Insert the remote DOF indices into the send list
+ for (unsigned int j=0; j != di.size(); ++j)
+ if (di[j] < this->first_dof() &&
+ di[j] >= this->end_dof())
+ _send_list.push_back(di[j]);
}
}
@@ -1559,6 +1506,7 @@
+/*
void DofMap::augment_send_list_for_projection(const MeshBase& mesh)
{
// Loop over the active local elements in the mesh.
@@ -1610,6 +1558,7 @@
// The send-list might need to be sorted again.
if (needs_sorting) this->sort_send_list ();
}
+*/
#endif // LIBMESH_ENABLE_AMR
Index: src/solvers/transient_system.C
===================================================================
--- src/solvers/transient_system.C (revision 3225)
+++ src/solvers/transient_system.C (working copy)
@@ -98,8 +98,10 @@
Base::init_data();
// Initialize the old & older solutions
- old_local_solution->init (this->n_dofs());
- older_local_solution->init (this->n_dofs());
+ old_local_solution->init (this->n_dofs(), this->n_local_dofs(),
+ this->get_dof_map().get_send_list());
+ older_local_solution->init (this->n_dofs(), this->n_local_dofs(),
+ this->get_dof_map().get_send_list());
}
Index: src/solvers/unsteady_solver.C
===================================================================
--- src/solvers/unsteady_solver.C (revision 3225)
+++ src/solvers/unsteady_solver.C (working copy)
@@ -58,7 +58,8 @@
first_solve = false;
}
- old_local_nonlinear_solution->init (_system.n_dofs());
+ old_local_nonlinear_solution->init (_system.n_dofs(), _system.n_local_dofs(),
+ _system.get_dof_map().get_send_list());
_system.get_vector("_old_nonlinear_solution").localize
(*old_local_nonlinear_solution,
Index: src/solvers/system.C
===================================================================
--- src/solvers/system.C (revision 3225)
+++ src/solvers/system.C (working copy)
@@ -185,7 +185,8 @@
solution->init (this->n_dofs(), this->n_local_dofs());
// Resize the current_local_solution for the current mesh
- current_local_solution->init (this->n_dofs());
+ current_local_solution->init (this->n_dofs(), this->n_local_dofs(),
+ _dof_map->get_send_list());
// from now on, no chance to add additional vectors
_can_add_vectors = false;
@@ -211,19 +212,22 @@
v->init (this->n_dofs(), this->n_local_dofs());
}
+ const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
+
// Restrict the solution on the coarsened cells
if (_solution_projection)
{
this->project_vector (*solution);
current_local_solution->clear();
- current_local_solution->init(this->n_dofs());
- const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
+ current_local_solution->init(this->n_dofs(),
+ this->n_local_dofs(), send_list);
solution->localize (*current_local_solution, send_list);
}
else
{
current_local_solution->clear();
- current_local_solution->init(this->n_dofs());
+ current_local_solution->init(this->n_dofs(),
+ this->n_local_dofs(), send_list);
}
#endif
}
@@ -257,7 +261,8 @@
solution->init (this->n_dofs(), this->n_local_dofs());
libmesh_assert (solution->size() == current_local_solution->size());
- libmesh_assert (solution->size() == current_local_solution->local_size());
+ // Not true with ghosted vectors
+ // libmesh_assert (solution->size() == current_local_solution->local_size());
const unsigned int first_local_dof = solution->first_local_index();
const unsigned int local_size = solution->local_size();
@@ -275,7 +280,7 @@
const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
// Check sizes
- libmesh_assert (current_local_solution->local_size() == solution->size());
+ libmesh_assert (current_local_solution->size() == solution->size());
// More processors than elements => empty send_list
// libmesh_assert (!send_list.empty());
libmesh_assert (send_list.size() <= solution->size());
@@ -298,8 +303,9 @@
Utility::iota (send_list.begin(), send_list.end(), 0);
// Check sizes
- libmesh_assert (current_local_solution->local_size() == solution->size());
libmesh_assert (current_local_solution->size() == solution->size());
+ // Not true with ghosted vectors
+ // libmesh_assert (current_local_solution->local_size() == solution->size());
libmesh_assert (!send_list.empty());
libmesh_assert (send_list.size() <= solution->size());
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel