Here is the current state now. I have no more questions (other than
the one which I asked in the previous mail). If Jed says that
everything looks well now, I will do the thing for the missing
overloaded PetscLinearSolver::solve() methods.
--
Dr. Tim Kroeger
CeVis -- Center of Complex Systems and Visualization
University of Bremen [email protected]
Universitaetsallee 29 [email protected]
D-28359 Bremen Phone +49-421-218-7710
Germany Fax +49-421-218-4236
Index: include/enums/enum_subset_solve_mode.h
===================================================================
--- include/enums/enum_subset_solve_mode.h (Revision 0)
+++ include/enums/enum_subset_solve_mode.h (Revision 0)
@@ -0,0 +1,45 @@
+// $Id: enum_norm_type.h 3430 2009-07-17 15:34:59Z roystgnr $
+
+// The libMesh Finite Element Library.
+// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+#ifndef __enum_subset_solve_mode_h__
+#define __enum_subset_solve_mode_h__
+
+// ------------------------------------------------------------
+// enum SubsetSolveMode definition
+namespace libMeshEnums {
+
+ /**
+ * \enum libMeshEnums::SubsetSolveMode defines an \p enum for the
+ * question what happens to the dofs outside the given subset when a
+ * system is solved on a subset.
+ */
+ enum SubsetSolveMode {
+ SUBSET_ZERO = 0, //!< Set dofs outside the subset to zero.
+ SUBSET_COPY_RHS, //!< Set dofs outside the subset to the value of the
corresponding dofs of the right hand side.
+ SUBSET_DONT_TOUCH //!< Leaves dofs outside the subset unchanged. This is
fastest, but also most confusing because it abandons the property that the
solution vector is (theoretically) independent of the initial guess.
+ };
+
+}
+
+using namespace libMeshEnums;
+
+#endif // #ifndef __subset_solve_mode_h__
+
Index: include/systems/system_subset_by_subdomain.h
===================================================================
--- include/systems/system_subset_by_subdomain.h (Revision 0)
+++ include/systems/system_subset_by_subdomain.h (Revision 0)
@@ -0,0 +1,174 @@
+// $Id: system.h 3943 2010-08-26 13:28:04Z knezed01 $
+
+// The libMesh Finite Element Library.
+// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+#ifndef __system_subset_by_subdomain_h__
+#define __system_subset_by_subdomain_h__
+
+// C++ includes
+#include <set>
+
+// Local Includes
+#include "system_subset.h"
+#include "id_types.h"
+
+namespace libMesh
+{
+
+// Forward Declarations
+
+/**
+ * This class represents a subset of the dofs of a \p System, selected
+ * by the \p subdomain_id and possible the variable numbers. The dofs
+ * in the subset will be sorted.
+ *
+ * @author Tim Kroeger, 2010.
+ */
+
+// ------------------------------------------------------------
+// SystemSubset class definition
+class SystemSubsetBySubdomain : public SystemSubset
+{
+public:
+
+ /**
+ * Subclass for user-specified selection of subdomain ids to be
+ * included in a \p SystemSubset.
+ */
+ class SubdomainSelection : public ReferenceCountedObject<SubdomainSelection>
+ {
+ public:
+
+ /**
+ * Constructor.
+ */
+ SubdomainSelection (void);
+
+ /**
+ * Destructor.
+ */
+ virtual ~SubdomainSelection (void);
+
+ /**
+ * Method that decides whether a given subdomain id is included in
+ * the subset or nor.
+ */
+ virtual bool operator()(const subdomain_id_type& subdomain_id)const=0;
+
+ private:
+ /**
+ * This isn't a copyable object, so let's make sure nobody tries.
+ *
+ * We won't even bother implementing this; we'll just make sure
+ * that the compiler doesn't implement a default.
+ */
+ SubdomainSelection(const SubdomainSelection&);
+
+ /**
+ * This isn't a copyable object, so let's make sure nobody tries.
+ *
+ * We won't even bother implementing this; we'll just make sure
+ * that the compiler doesn't implement a default.
+ */
+ SubdomainSelection& operator=(const SubdomainSelection&);
+
+ }; // subclass \p SubdomainSelection
+
+ /**
+ * Selection of subdomain ids by a list.
+ */
+ class SubdomainSelectionByList : public SubdomainSelection
+ {
+ public:
+ /**
+ * Constructor. Does not take a copy of the \p list, so make sure
+ * that the \p list does not go out of scope before \p *this does.
+ */
+ SubdomainSelectionByList (const std::set<subdomain_id_type>& list);
+
+ /**
+ * Method that decides whether a given subdomain id is included in
+ * the subset or nor.
+ */
+ virtual bool operator()(const subdomain_id_type& subdomain_id)const;
+
+ protected:
+ /**
+ * The actual list.
+ */
+ const std::set<subdomain_id_type>& _list;
+ };
+
+ /**
+ * Constructor. The subset will consist of those dofs which are
+ * associated to at least one mesh element that has a subdomain id
+ * contained in the \p subdomain_selection. If \p var_nums is not a
+ * \p NULL pointer, dofs that are associated to a variable number
+ * that is not contained in \p var_nums will not contain to the
+ * subset, no matter what elements they belong to.
+ */
+ SystemSubsetBySubdomain (const System& system,
+ const SubdomainSelection& subdomain_selection,
+ const std::set<unsigned int>* const var_nums = NULL);
+
+ /**
+ * Constructor. The subset will consist of those dofs which are
+ * associated to at least one mesh element that has a subdomain id
+ * contained in the set \p subdomain_ids. If \p var_nums is not a
+ * \p NULL pointer, dofs that are associated to a variable number
+ * that is not contained in \p var_nums will not contain to the
+ * subset, no matter what elements they belong to.
+ */
+ SystemSubsetBySubdomain (const System& system,
+ const std::set<subdomain_id_type>& subdomain_ids,
+ const std::set<unsigned int>* const var_nums = NULL);
+
+ /**
+ * Destructor.
+ */
+ virtual ~SystemSubsetBySubdomain ();
+
+ /**
+ * Method that returns the actual set of dofs that the subset
+ * consists of. The result will contain local dofs on each
+ * processor only and will not contain duplictates.
+ */
+ virtual const std::vector<unsigned int>& dof_ids(void)const;
+
+protected:
+
+ /**
+ * Initializes the class. Will be called by the constructors.
+ */
+ void init (const System& system,
+ const SubdomainSelection& subdomain_selection,
+ const std::set<unsigned int>* const var_nums);
+
+ /**
+ * The actual set of the dof ids.
+ */
+ std::vector<unsigned int> _dof_ids;
+
+}; // class SystemSubset
+
+} // namespace libMesh
+
+#endif
+
Index: include/systems/system.h
===================================================================
--- include/systems/system.h (Revision 3957)
+++ include/systems/system.h (Arbeitskopie)
@@ -31,6 +31,7 @@
#include "elem_range.h"
#include "enum_norm_type.h"
#include "enum_xdr_mode.h"
+#include "enum_subset_solve_mode.h"
#include "fe_type.h"
#include "libmesh_common.h"
#include "tensor_value.h" // For point_hessian
@@ -56,6 +57,7 @@
template <typename T> class VectorValue;
typedef VectorValue<Number> NumberVectorValue;
typedef NumberVectorValue Gradient;
+class SystemSubset;
/**
* This is the base class for classes which contain
@@ -162,6 +164,14 @@
* This method is only implemented in some derived classes.
*/
virtual void assemble_residual_derivatives (const ParameterVector&
parameters);
+
+ /**
+ * After calling this method, any solve will be restricted to the
+ * given subdomain. To disable this mode, call this method with \p
+ * subset being a \p NULL pointer.
+ */
+ virtual void restrict_solve_to (const SystemSubset* subset,
+ const SubsetSolveMode
subset_solve_mode=SUBSET_ZERO);
/**
* Solves the system. Must be overloaded in derived systems.
Index: include/systems/linear_implicit_system.h
===================================================================
--- include/systems/linear_implicit_system.h (Revision 3957)
+++ include/systems/linear_implicit_system.h (Arbeitskopie)
@@ -100,6 +100,14 @@
virtual void assemble () { ImplicitSystem::assemble(); }
/**
+ * After calling this method, any solve will be limited to the given
+ * subset. To disable this mode, call this method with \p subset
+ * being a \p NULL pointer.
+ */
+ virtual void restrict_solve_to (const SystemSubset* subset,
+ const SubsetSolveMode
subset_solve_mode=SUBSET_ZERO);
+
+ /**
* Assembles & solves the linear system A*x=b.
*/
virtual void solve ();
@@ -187,6 +195,16 @@
*/
ShellMatrix<Number>* _shell_matrix;
+ /**
+ * The current subset on which to solve (or \p NULL if none).
+ */
+ const SystemSubset* _subset;
+
+ /**
+ * If restrict-solve-to-subset mode is active, this member decides
+ * what happens with the dofs outside the subset.
+ */
+ SubsetSolveMode _subset_solve_mode;
};
Index: include/systems/system_subset.h
===================================================================
--- include/systems/system_subset.h (Revision 0)
+++ include/systems/system_subset.h (Revision 0)
@@ -0,0 +1,103 @@
+// $Id: system.h 3943 2010-08-26 13:28:04Z knezed01 $
+
+// The libMesh Finite Element Library.
+// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+#ifndef __system_subset_h__
+#define __system_subset_h__
+
+// C++ includes
+#include <vector>
+
+// Local Includes
+#include "reference_counted_object.h"
+
+namespace libMesh
+{
+
+// Forward Declarations
+class System;
+
+/**
+ * This is a base class for classes which represent subsets of the
+ * dofs of a \p System.
+ *
+ * @author Tim Kroeger, 2010.
+ */
+
+// ------------------------------------------------------------
+// SystemSubset class definition
+class SystemSubset : public ReferenceCountedObject<SystemSubset>
+{
+public:
+
+ /**
+ * Constructor.
+ */
+ SystemSubset (const System& system);
+
+public:
+
+ /**
+ * Destructor.
+ */
+ virtual ~SystemSubset (void);
+
+ /**
+ * Method that returns the actual set of dofs that the subset
+ * consists of. The result must contain local dofs on each
+ * processor only and must not contain duplictates.
+ */
+ virtual const std::vector<unsigned int>& dof_ids(void)const=0;
+
+ /**
+ * Returns the \p System to which we belong.
+ */
+ const System& get_system(void)const;
+
+protected:
+
+ /**
+ * A reference to the \p System we belong to.
+ */
+ const System& _system;
+
+private:
+ /**
+ * This isn't a copyable object, so let's make sure nobody tries.
+ *
+ * We won't even bother implementing this; we'll just make sure that
+ * the compiler doesn't implement a default.
+ */
+ SystemSubset(const SystemSubset&);
+
+ /**
+ * This isn't a copyable object, so let's make sure nobody tries.
+ *
+ * We won't even bother implementing this; we'll just make sure that
+ * the compiler doesn't implement a default.
+ */
+ SystemSubset& operator=(const SystemSubset&);
+
+}; // class SystemSubset
+
+} // namespace libMesh
+
+#endif
+
Index: include/solvers/petsc_linear_solver.h
===================================================================
--- include/solvers/petsc_linear_solver.h (Revision 3957)
+++ include/solvers/petsc_linear_solver.h (Arbeitskopie)
@@ -122,7 +122,18 @@
* Initialize data structures if not done so already plus much more
*/
void init (PetscMatrix<T>* matrix);
+
/**
+ * After calling this method, all successive solves will be
+ * restricted to the given set of dofs, which must contain local
+ * dofs on each processor only and not contain any duplicates. This
+ * mode can be disabled by calling this method with \p dofs being a
+ * \p NULL pointer.
+ */
+ virtual void restrict_solve_to (const std::vector<unsigned int>* const dofs,
+ const SubsetSolveMode
subset_solve_mode=SUBSET_ZERO);
+
+ /**
* Call the Petsc solver. It calls the method below, using the
* same matrix for the system and preconditioner matrices.
*/
@@ -253,13 +264,34 @@
* Krylov subspace context
*/
KSP _ksp;
+
+ /**
+ * PETSc index set containing the dofs on which to solve (\p NULL
+ * means solve on all dofs).
+ */
+ IS _restrict_solve_to_is;
+
+ /**
+ * Internal method that returns the local size of \p
+ * _restrict_solve_to_is.
+ */
+ size_t _restrict_solve_to_is_local_size(void)const;
+
+ /**
+ * If restrict-solve-to-subset mode is active, this member decides
+ * what happens with the dofs outside the subset.
+ */
+ SubsetSolveMode _subset_solve_mode;
+
};
/*----------------------- functions ----------------------------------*/
template <typename T>
inline
-PetscLinearSolver<T>::PetscLinearSolver ()
+ PetscLinearSolver<T>::PetscLinearSolver ():
+ _restrict_solve_to_is(NULL),
+ _subset_solve_mode(SUBSET_ZERO)
{
if (libMesh::n_processors() == 1)
this->_preconditioner_type = ILU_PRECOND;
@@ -277,6 +309,23 @@
}
+
+template <typename T>
+inline size_t
+PetscLinearSolver<T>::
+_restrict_solve_to_is_local_size(void)const
+{
+ libmesh_assert(_restrict_solve_to_is!=NULL);
+
+ PetscInt s;
+ int ierr = ISGetLocalSize(_restrict_solve_to_is,&s);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ return static_cast<size_t>(s);
+}
+
+
+
} // namespace libMesh
Index: include/solvers/linear_solver.h
===================================================================
--- include/solvers/linear_solver.h (Revision 3957)
+++ include/solvers/linear_solver.h (Arbeitskopie)
@@ -24,12 +24,14 @@
// C++ includes
+#include <vector>
// Local includes
#include "libmesh_common.h"
#include "enum_solver_package.h"
#include "enum_solver_type.h"
#include "enum_preconditioner_type.h"
+#include "enum_subset_solve_mode.h"
#include "reference_counted_object.h"
#include "libmesh.h"
@@ -117,6 +119,16 @@
void attach_preconditioner(Preconditioner<T> * preconditioner);
/**
+ * After calling this method, all successive solves will be
+ * restricted to the given set of dofs, which must contain local
+ * dofs on each processor only and not contain any duplicates. This
+ * mode can be disabled by calling this method with \p dofs being a
+ * \p NULL pointer.
+ */
+ virtual void restrict_solve_to (const std::vector<unsigned int>* const dofs,
+ const SubsetSolveMode
subset_solve_mode=SUBSET_ZERO);
+
+ /**
* This function calls the solver
* "_solver_type" preconditioned with the
* "_preconditioner_type" preconditioner. Note that this method
Index: src/systems/linear_implicit_system.C
===================================================================
--- src/systems/linear_implicit_system.C (Revision 3957)
+++ src/systems/linear_implicit_system.C (Arbeitskopie)
@@ -28,6 +28,7 @@
#include "numeric_vector.h" // for parameter sensitivity calcs
#include "parameter_vector.h"
#include "sparse_matrix.h" // for get_transpose
+#include "system_subset.h"
namespace libMesh
{
@@ -43,7 +44,9 @@
linear_solver (LinearSolver<Number>::build()),
_n_linear_iterations (0),
_final_linear_residual (1.e20),
- _shell_matrix(NULL)
+ _shell_matrix(NULL),
+ _subset(NULL),
+ _subset_solve_mode(SUBSET_ZERO)
{
}
@@ -61,6 +64,8 @@
{
// clear the linear solver
linear_solver->clear();
+
+ this->restrict_solve_to(NULL);
// clear the parent data
Parent::clear();
@@ -79,6 +84,19 @@
+void LinearImplicitSystem::restrict_solve_to (const SystemSubset* subset,
+ const SubsetSolveMode
subset_solve_mode)
+{
+ _subset = subset;
+ _subset_solve_mode = subset_solve_mode;
+ if(subset!=NULL)
+ {
+ libmesh_assert(&subset->get_system()==this);
+ }
+}
+
+
+
void LinearImplicitSystem::solve ()
{
if (this->assemble_before_solve)
@@ -101,6 +119,11 @@
const unsigned int maxits =
es.parameters.get<unsigned int>("linear solver maximum iterations");
+ if(_subset!=NULL)
+ {
+ linear_solver->restrict_solve_to(&_subset->dof_ids(),_subset_solve_mode);
+ }
+
// Solve the linear system. Several cases:
std::pair<unsigned int, Real> rval = std::make_pair(0,0.0);
if(_shell_matrix)
@@ -110,6 +133,11 @@
// 2.) No shell matrix, with or without user-supplied preconditioner
rval = linear_solver->solve (*matrix,
this->request_matrix("Preconditioner"), *solution, *rhs, tol, maxits);
+ if(_subset!=NULL)
+ {
+ linear_solver->restrict_solve_to(NULL);
+ }
+
// Store the number of linear iterations required to
// solve and the final residual.
_n_linear_iterations = rval.first;
Index: src/systems/system_subset.C
===================================================================
--- src/systems/system_subset.C (Revision 0)
+++ src/systems/system_subset.C (Revision 0)
@@ -0,0 +1,52 @@
+// $Id: system.C 3943 2010-08-26 13:28:04Z knezed01 $
+
+// The libMesh Finite Element Library.
+// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+// C++ includes
+
+
+// Local includes
+#include "system_subset.h"
+
+namespace libMesh
+{
+
+// ------------------------------------------------------------
+// SystemSubset implementation
+ SystemSubset::SystemSubset (const System& system):
+ _system(system)
+ {
+ }
+
+
+ SystemSubset::~SystemSubset (void)
+ {
+ }
+
+
+ const System&
+ SystemSubset::get_system(void)const
+ {
+ return _system;
+ }
+
+
+} // namespace libMesh
+
Index: src/systems/system_subset_by_subdomain.C
===================================================================
--- src/systems/system_subset_by_subdomain.C (Revision 0)
+++ src/systems/system_subset_by_subdomain.C (Revision 0)
@@ -0,0 +1,148 @@
+// $Id: system.C 3943 2010-08-26 13:28:04Z knezed01 $
+
+// The libMesh Finite Element Library.
+// Copyright (C) 2002-2008 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+
+// C++ includes
+
+
+// Local includes
+#include "system_subset_by_subdomain.h"
+#include "system.h"
+#include "dof_map.h"
+
+namespace libMesh
+{
+// ------------------------------------------------------------
+// SubdomainSelectio implementation
+ SystemSubsetBySubdomain::SubdomainSelection::
+ SubdomainSelection (void)
+ {
+ }
+
+ SystemSubsetBySubdomain::SubdomainSelection::
+ ~SubdomainSelection (void)
+ {
+ }
+
+ SystemSubsetBySubdomain::SubdomainSelectionByList::
+ SubdomainSelectionByList (const std::set<subdomain_id_type>& list):
+ _list(list)
+ {
+ }
+
+ bool
+ SystemSubsetBySubdomain::SubdomainSelectionByList::
+ operator()(const subdomain_id_type& subdomain_id)const
+ {
+ return _list.find(subdomain_id)!=_list.end();
+ }
+
+// ------------------------------------------------------------
+// SystemSubsetBySubdomain implementation
+
+ SystemSubsetBySubdomain::
+ SystemSubsetBySubdomain (const System& system,
+ const SubdomainSelection& subdomain_selection,
+ const std::set<unsigned int>* const var_nums):
+ SystemSubset(system),
+ _dof_ids()
+ {
+ this->init(system,subdomain_selection,var_nums);
+ }
+
+ SystemSubsetBySubdomain::
+ SystemSubsetBySubdomain (const System& system,
+ const std::set<subdomain_id_type>& subdomain_ids,
+ const std::set<unsigned int>* const var_nums):
+ SystemSubset(system),
+ _dof_ids()
+ {
+ SubdomainSelectionByList selection(subdomain_ids);
+ this->init(system,selection,var_nums);
+ }
+
+ SystemSubsetBySubdomain::
+ ~SystemSubsetBySubdomain (void)
+ {
+ }
+
+ const std::vector<unsigned int>&
+ SystemSubsetBySubdomain::
+ dof_ids(void)const
+ {
+ return _dof_ids;
+ }
+
+ void
+ SystemSubsetBySubdomain::
+ init (const System& system,
+ const SubdomainSelection& subdomain_selection,
+ const std::set<unsigned int>* const var_nums)
+ {
+ std::set<unsigned int> effective_var_nums;
+ if(var_nums!=NULL)
+ {
+ effective_var_nums = *var_nums;
+ }
+ else
+ {
+ for(unsigned int i=0; i<system.n_vars(); i++)
+ {
+ effective_var_nums.insert(i);
+ }
+ }
+
+ const DofMap & dof_map = system.get_dof_map();
+ std::vector<unsigned int> dof_indices;
+
+ const MeshBase& mesh = system.get_mesh();
+ MeshBase::const_element_iterator el =
mesh.active_local_elements_begin();
+ const MeshBase::const_element_iterator end_el =
mesh.active_local_elements_end();
+ for ( ; el != end_el; ++el)
+ {
+ const Elem* elem = *el;
+ if(subdomain_selection(elem->subdomain_id()))
+ {
+ std::set<unsigned int>::const_iterator it =
effective_var_nums.begin();
+ const std::set<unsigned int>::const_iterator itEnd =
effective_var_nums.end();
+ for (; it!=itEnd; ++it)
+ {
+ dof_map.dof_indices (elem, dof_indices, *it);
+ for(size_t i=0; i<dof_indices.size(); i++)
+ {
+ if((dof_indices[i]>=dof_map.variable_first_local_dof(*it))
&&
+ (dof_indices[i]<dof_map.variable_last_local_dof(*it)))
+ {
+ _dof_ids.push_back(dof_indices[i]);
+ }
+ }
+ }
+ }
+ }
+
+ /* Sort and unique the vector (using the same mechanism as in \p
+ DofMap::prepare_send_list()). */
+ std::sort(_dof_ids.begin(), _dof_ids.end());
+ std::vector<unsigned int>::iterator new_end = std::unique
(_dof_ids.begin(), _dof_ids.end());
+ std::vector<unsigned int> (_dof_ids.begin(), new_end).swap (_dof_ids);
+ }
+
+} // namespace libMesh
+
Index: src/systems/system.C
===================================================================
--- src/systems/system.C (Revision 3957)
+++ src/systems/system.C (Arbeitskopie)
@@ -367,6 +367,17 @@
+void System::restrict_solve_to (const SystemSubset* subset,
+ const SubsetSolveMode /*subset_solve_mode*/)
+{
+ if(subset!=NULL)
+ {
+ libmesh_not_implemented();
+ }
+}
+
+
+
void System::assemble ()
{
// Log how long the user's matrix assembly code takes
Index: src/solvers/petsc_linear_solver.C
===================================================================
--- src/solvers/petsc_linear_solver.C (Revision 3957)
+++ src/solvers/petsc_linear_solver.C (Arbeitskopie)
@@ -98,6 +98,8 @@
{
if (this->initialized())
{
+ this->restrict_solve_to(NULL);
+
this->_is_initialized = false;
int ierr=0;
@@ -294,7 +296,7 @@
CHKERRABORT(libMesh::COMM_WORLD,ierr);
// Set operators. The input matrix works as the preconditioning matrix
- ierr = KSPSetOperators(_ksp, matrix->mat(),
matrix->mat(),SAME_NONZERO_PATTERN);
+ ierr = KSPSetOperators(_ksp, matrix->mat(),
matrix->mat(),DIFFERENT_NONZERO_PATTERN);
CHKERRABORT(libMesh::COMM_WORLD,ierr);
// Set user-specified solver and preconditioner types
@@ -360,9 +362,42 @@
+template <typename T>
+void
+PetscLinearSolver<T>::restrict_solve_to (const std::vector<unsigned int>*
const dofs,
+ const SubsetSolveMode
subset_solve_mode)
+{
+ libmesh_assert(this->initialized());
+ int ierr=0;
+ if(_restrict_solve_to_is!=NULL)
+ {
+ ierr = ISDestroy(_restrict_solve_to_is);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ _restrict_solve_to_is = NULL;
+ }
+ _subset_solve_mode = subset_solve_mode;
+
+ if(dofs!=NULL)
+ {
+ PetscInt* petsc_dofs;
+ ierr = PetscMalloc(dofs->size()*sizeof(PetscInt),&petsc_dofs);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ for(size_t i=0; i<dofs->size(); i++)
+ {
+ petsc_dofs[i] = (*dofs)[i];
+ }
+
+ ierr =
ISCreateGeneralNC(libMesh::COMM_WORLD,dofs->size(),petsc_dofs,&_restrict_solve_to_is);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
+}
+
+
+
template <typename T>
std::pair<unsigned int, Real>
PetscLinearSolver<T>::solve (SparseMatrix<T>& matrix_in,
@@ -406,10 +441,15 @@
// 2.1.x & earlier style
#if PETSC_VERSION_LESS_THAN(2,2,0)
+
+ if(_restrict_solve_to_is!=NULL)
+ {
+ libmesh_not_implemented();
+ }
// Set operators. The input matrix works as the preconditioning matrix
ierr = SLESSetOperators(_sles, matrix->mat(), precond->mat(),
- SAME_NONZERO_PATTERN);
+ DIFFERENT_NONZERO_PATTERN);
CHKERRABORT(libMesh::COMM_WORLD,ierr);
// Set the tolerances for the iterative solver. Use the user-supplied
@@ -431,6 +471,11 @@
// 2.2.0
#elif PETSC_VERSION_LESS_THAN(2,2,1)
+ if(_restrict_solve_to_is!=NULL)
+ {
+ libmesh_not_implemented();
+ }
+
// Set operators. The input matrix works as the preconditioning matrix
//ierr = KSPSetOperators(_ksp, matrix->mat(), precond->mat(),
// SAME_NONZERO_PATTERN);
@@ -475,19 +520,65 @@
// 2.2.1 & newer style
#else
- // Set operators. The input matrix works as the preconditioning matrix
- if(!this->same_preconditioner)
- {
- ierr = KSPSetOperators(_ksp, matrix->mat(), precond->mat(),
- SAME_NONZERO_PATTERN);
- CHKERRABORT(libMesh::COMM_WORLD,ierr);
- }
+ Mat submat = NULL;
+ Mat subprecond = NULL;
+ Vec subrhs;
+ Vec subsolution;
+ VecScatter scatter;
+
+ // Set operators. Also restrict rhs and solution vector to
+ // subdomain if neccessary.
+ if(_restrict_solve_to_is!=NULL)
+ {
+ size_t is_local_size = this->_restrict_solve_to_is_local_size();
+
+ ierr = VecCreate(libMesh::COMM_WORLD,&subrhs);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = VecSetSizes(subrhs,is_local_size,PETSC_DECIDE);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = VecSetFromOptions(subrhs);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = VecCreate(libMesh::COMM_WORLD,&subsolution);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = VecSetSizes(subsolution,is_local_size,PETSC_DECIDE);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = VecSetFromOptions(subsolution);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = VecScatterCreate(rhs->vec(),_restrict_solve_to_is, subrhs,NULL,
&scatter);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr =
VecScatterBegin(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr =
VecScatterEnd(scatter,rhs->vec(),subrhs,INSERT_VALUES,SCATTER_FORWARD);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr =
VecScatterBegin(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr =
VecScatterEnd(scatter,solution->vec(),subsolution,INSERT_VALUES,SCATTER_FORWARD);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = MatGetSubMatrix(matrix->mat(),
+ _restrict_solve_to_is,_restrict_solve_to_is,
+ PETSC_DECIDE,MAT_INITIAL_MATRIX,&submat);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = MatGetSubMatrix(precond->mat(),
+ _restrict_solve_to_is,_restrict_solve_to_is,
+ PETSC_DECIDE,MAT_INITIAL_MATRIX,&subprecond);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = KSPSetOperators(_ksp, submat, subprecond,
+ this->same_preconditioner ? SAME_PRECONDITIONER :
DIFFERENT_NONZERO_PATTERN);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
else
- {
- ierr = KSPSetOperators(_ksp, matrix->mat(), precond->mat(),
- SAME_PRECONDITIONER);
- CHKERRABORT(libMesh::COMM_WORLD,ierr);
- }
+ {
+ ierr = KSPSetOperators(_ksp, matrix->mat(), precond->mat(),
+ this->same_preconditioner ? SAME_PRECONDITIONER :
DIFFERENT_NONZERO_PATTERN);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
// Set the tolerances for the iterative solver. Use the user-supplied
// tolerance for the relative residual & leave the others at default values.
@@ -496,8 +587,16 @@
CHKERRABORT(libMesh::COMM_WORLD,ierr);
// Solve the linear system
- ierr = KSPSolve (_ksp, rhs->vec(), solution->vec());
- CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ if(_restrict_solve_to_is!=NULL)
+ {
+ ierr = KSPSolve (_ksp, subrhs, subsolution);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
+ else
+ {
+ ierr = KSPSolve (_ksp, rhs->vec(), solution->vec());
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
// Get the number of iterations required for convergence
ierr = KSPGetIterationNumber (_ksp, &its);
@@ -507,6 +606,43 @@
ierr = KSPGetResidualNorm (_ksp, &final_resid);
CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ if(_restrict_solve_to_is!=NULL)
+ {
+ switch(_subset_solve_mode)
+ {
+ case SUBSET_ZERO:
+ ierr = VecZeroEntries(solution->vec());
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ break;
+
+ case SUBSET_COPY_RHS:
+ ierr = VecCopy(rhs->vec(),solution->vec());
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ break;
+
+ case SUBSET_DONT_TOUCH:
+ /* Nothing to do here. */
+ break;
+
+ }
+ ierr =
VecScatterBegin(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr =
VecScatterEnd(scatter,subsolution,solution->vec(),INSERT_VALUES,SCATTER_REVERSE);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = VecScatterDestroy(scatter);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+
+ ierr = VecDestroy(subsolution);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = VecDestroy(subrhs);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = MatDestroy(submat);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ ierr = MatDestroy(subprecond);
+ CHKERRABORT(libMesh::COMM_WORLD,ierr);
+ }
+
#endif
STOP_LOG("solve()", "PetscLinearSolver");
@@ -574,7 +710,7 @@
// Set operators. The input matrix works as the preconditioning matrix
ierr = KSPSetOperators(_ksp, mat, mat,
- SAME_NONZERO_PATTERN);
+ DIFFERENT_NONZERO_PATTERN);
CHKERRABORT(libMesh::COMM_WORLD,ierr);
// Set the tolerances for the iterative solver. Use the user-supplied
Index: src/solvers/linear_solver.C
===================================================================
--- src/solvers/linear_solver.C (Revision 3957)
+++ src/solvers/linear_solver.C (Arbeitskopie)
@@ -115,7 +115,19 @@
_preconditioner = preconditioner;
}
+template <typename T>
+void
+LinearSolver<T>::restrict_solve_to(const std::vector<unsigned int>* const dofs,
+ const SubsetSolveMode /*subset_solve_mode*/)
+{
+ if(dofs!=NULL)
+ {
+ libmesh_not_implemented();
+ }
+}
+
+
//------------------------------------------------------------------
// Explicit instantiations
template class LinearSolver<Number>;
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Libmesh-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-users