Hi,
I have had to make a few changes to the dof_map and petsc_matrix
files (both .h and .C) to accommodate some needs of my work. I am
solving a heat transfer problem, which involves conduction (solved
using finite elements) and internal cavity radiation due to heat
emission/absorption/reflection. Due to this, hundreds of nodes get
coupled with each other and the sparsity pattern has a large number of
non-zeros per row.
I am using petsc as the solver and for my application, and I have
found that providing the detailed sparsity pattern to the matrix
creation routine becomes important. Also, due to the way Petsc adds
new non-zeros in each row, I found it was important to specify all the
non-zero columns per row during the initialization (it improved the
performance of my code by an order of magnitude). Since the library
did not have an update-sparsity pattern for the petsc-matrix, I
implemented it and have attached it the following diffs.
The change in dof_map is not really necessary, but since I am
initializing a few matrices much deeper into the code (rather than
only the beginning), I made this change to store the sparsity_pattern
in the dof_map object.
Please use / ignore them as you see fit.
Regards,
Manav
Index: /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/
include/base/dof_map.h
===================================================================
--- /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/include/
base/dof_map.h (revision 3098)
+++ /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/include/
base/dof_map.h (working copy)
@@ -274,6 +274,16 @@
*/
void compute_sparsity (const MeshBase&);
+ /**
+ * @returns \p SparsityPattern::Graph object of this \p DofMap
+ */
+ const SparsityPattern::Graph& get_sparsity_pattern() const
+ {
+ libmesh_assert(this->_sp.get() != NULL);
+ return this->_sp->sparsity_pattern;
+ }
+
+
/**
* Returns a constant reference to the \p _send_list for this
processor. The
* \p _send_list contains the global indices of all the variables
in the
@@ -783,6 +793,11 @@
PeriodicBoundaries _periodic_boundaries;
#endif
+ /**
+ * sparsity pattern graph object for this dof map
+ */
+ AutoPtr<SparsityPattern::Build> _sp;
+
friend class SparsityPattern::Build;
};
Index: /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/
base/dof_map.C
===================================================================
--- /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/base/
dof_map.C (revision 3069)
+++ /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/base/
dof_map.C (working copy)
@@ -1116,26 +1116,37 @@
// Even better, if the full sparsity pattern is not needed then
// the number of nonzeros per row can be estimated from the
// sparsity patterns created on each thread.
- SparsityPattern::Build sp (mesh,
- *this,
- _dof_coupling,
- implicit_neighbor_dofs,
- need_full_sparsity_pattern);
+ // *** this has been changed to a member of the object since it
will be stored
+ // and used for matrices beyond this function ***
+ this->_sp.reset(new SparsityPattern::Build(mesh,
+ *this,
+ _dof_coupling,
+ implicit_neighbor_dofs,
+
need_full_sparsity_pattern));
Threads::parallel_reduce (ConstElemRange
(mesh.active_elements_begin(),
- mesh.active_elements_end()), sp);
+
mesh.active_elements_end()), *(this->_sp.get()));
#ifndef NDEBUG
// Avoid declaring these variables unless asserts are enabled.
const unsigned int proc_id = mesh.processor_id();
const unsigned int n_dofs_on_proc = this-
>n_dofs_on_processor(proc_id);
#endif
- libmesh_assert (sp.sparsity_pattern.size() == n_dofs_on_proc);
+ libmesh_assert (this->_sp->sparsity_pattern.size() ==
n_dofs_on_proc);
// steal the n_nz and n_oz arrays from sp -- it won't need them
any more,
// and this is more efficient than copying them.
- _n_nz.swap(sp.n_nz);
- _n_oz.swap(sp.n_oz);
+ //_n_nz.swap(sp.n_nz);
+ //_n_oz.swap(sp.n_oz);
+ // *** this has been changed to copy since the sparsity pattern is
being stored
+ // in this object. This is because the matrices will not
necessarily be initialized
+ // only once through this method, but at arbitrary times through
the sparsity_pattern***
+ _n_nz.resize(this->_sp->n_nz.size());
+ _n_oz.resize(this->_sp->n_oz.size());
+ for (unsigned int i=0; i< _n_nz.size(); i++)
+ _n_nz[i] = this->_sp->n_nz[i];
+ for (unsigned int i=0; i< _n_oz.size(); i++)
+ _n_oz[i] = this->_sp->n_oz[i];
STOP_LOG("compute_sparsity()", "DofMap");
@@ -1147,7 +1158,7 @@
end = _matrices.end();
for (; pos != end; ++pos)
- (*pos)->update_sparsity_pattern (sp.sparsity_pattern);
+ (*pos)->update_sparsity_pattern (this->_sp->sparsity_pattern);
}
Index: /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/
include/numerics/petsc_matrix.h
===================================================================
--- /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/include/
numerics/petsc_matrix.h (revision 3062)
+++ /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/include/
numerics/petsc_matrix.h (working copy)
@@ -32,9 +32,11 @@
+
+ /**
+ * The \p PetscMatrix needs the full sparsity pattern.
+ */
+ bool need_full_sparsity_pattern () const
+ { return true; }
+
+ /**
+ * Updates the matrix sparsity pattern.
+ */
+ virtual void update_sparsity_pattern (const SparsityPattern::Graph
&);
+
Index: /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/
numerics/petsc_matrix.C
===================================================================
--- /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/
numerics/petsc_matrix.C (revision 3062)
+++ /Users/manav/Documents/codes/fem/FESystem/contrib/libmesh/src/
numerics/petsc_matrix.C (working copy)
@@ -164,12 +164,106 @@
CHKERRABORT(libMesh::COMM_WORLD,ierr);
}
+ // now update the sparsity pattern
+ const SparsityPattern::Graph& sparsity_pattern =
+ this->_dof_map->get_sparsity_pattern();
+ this->update_sparsity_pattern(sparsity_pattern);
+
this->zero();
}
+
template <typename T>
+void PetscMatrix<T>::update_sparsity_pattern
+(const SparsityPattern::Graph &sparsity_pattern)
+{
+ // make sure that the matrix has been initialized
+ assert (this->initialized());
+ unsigned int first_local_dof = this->_dof_map->first_dof();
+ unsigned int last_local_dof = this->_dof_map->last_dof();
+
+#ifdef DEBUG
+ assert ((last_local_dof - first_local_dof + 1) ==
sparsity_pattern.size());
+
+ // it is assumed that the values are sorted, but it can be checked
for debugging
+ for (unsigned int i=0; i < sparsity_pattern.size(); i++)
+ {
+ for (unsigned int j=1; j < sparsity_pattern[i].size(); j++)
+ assert (sparsity_pattern[i][j-1] < sparsity_pattern[i][j]);
+ }
+#endif
+
+
+ PetscErrorCode ierr=0;
+ std::vector<double> vals;
+ unsigned int row_id = 0;
+
+ ierr = MatSetOption (_mat, MAT_YES_NEW_NONZERO_LOCATIONS);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ // iterate over all rows, and add the entries to the
+ for (unsigned int i=0; i < sparsity_pattern.size(); i++)
+ {
+ if (vals.size() != sparsity_pattern[i].size())
+ {
+ vals.resize(sparsity_pattern[i].size());
+ std::fill(vals.begin(), vals.end(), 1.0);
+ }
+
+ row_id = first_local_dof + i;
+
+ // now tell the matrix to set the values for this row
+ ierr = MatSetValues (_mat,
+ 1, (PetscInt*) &row_id,
+ sparsity_pattern[i].size(), (PetscInt*)
&sparsity_pattern[i][0],
+ (PetscScalar*) &vals[0], INSERT_VALUES);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
+
+ ierr = MatSetOption (_mat, MAT_NEW_NONZERO_LOCATION_ERR);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = MatSetOption (_mat, MAT_KEEP_ZEROED_ROWS);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ // finally, call the assemble functions
+ ierr = MatAssemblyBegin (_mat, MAT_FLUSH_ASSEMBLY);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = MatAssemblyEnd (_mat, MAT_FLUSH_ASSEMBLY);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ this->zero();
+}
+
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Libmesh-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-users