From 0196fdfaa6ef172e57c01d57bbd429a543717428 Mon Sep 17 00:00:00 2001 From: Bernd Flemisch <bernd@iws.uni-stuttgart.de> Date: Tue, 23 Oct 2012 15:27:09 +0000 Subject: [PATCH] Enable parallelism for decoupled 2p2c. Requires AMGBackend and patches for pdelab and istl. Can therefore only be used from devel (currently). Reviewed by Benjamin. git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@9414 2fb0f335-1f38-0410-981e-8018bf24f1b0 --- dumux/decoupled/2p2c/fvtransport2p2c.hh | 17 ++++ dumux/decoupled/common/fv/fvpressure.hh | 125 +++++++++++++----------- dumux/linear/vectorexchange.hh | 90 +++++++++++++++++ 3 files changed, 176 insertions(+), 56 deletions(-) create mode 100644 dumux/linear/vectorexchange.hh diff --git a/dumux/decoupled/2p2c/fvtransport2p2c.hh b/dumux/decoupled/2p2c/fvtransport2p2c.hh index 4514d0ecf4..01c30333a7 100644 --- a/dumux/decoupled/2p2c/fvtransport2p2c.hh +++ b/dumux/decoupled/2p2c/fvtransport2p2c.hh @@ -23,6 +23,7 @@ #include <dumux/decoupled/2p2c/2p2cproperties.hh> #include <dumux/material/constraintsolvers/compositionalflash.hh> #include <dumux/common/math.hh> +#include <dumux/linear/vectorexchange.hh> /** * @file @@ -300,6 +301,22 @@ void FVTransport2P2C<TypeTag>::update(const Scalar t, Scalar& dt, restrictingCell= globalIdxI; } } // end grid traversal + +#if HAVE_MPI + // communicate updated values + typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes; + typedef typename SolutionTypes::ElementMapper ElementMapper; + typedef VectorExchange<ElementMapper, Dune::BlockVector<Dune::FieldVector<Scalar, 1> > > DataHandle; + for (int i = 0; i < updateVec.size(); i++) + { + DataHandle dataHandle(problem_.variables().elementMapper(), updateVec[i]); + problem_.gridView().template communicate<DataHandle>(dataHandle, + Dune::InteriorBorder_All_Interface, + Dune::ForwardCommunication); + } + dt = problem_.gridView().comm().min(dt); +#endif + if(impet) { Dune::dinfo << "Timestep restricted by CellIdx " << restrictingCell << " leads to dt = " diff --git a/dumux/decoupled/common/fv/fvpressure.hh b/dumux/decoupled/common/fv/fvpressure.hh index 2fec2e5975..1b05b20502 100644 --- a/dumux/decoupled/common/fv/fvpressure.hh +++ b/dumux/decoupled/common/fv/fvpressure.hh @@ -366,77 +366,90 @@ void FVPressure<TypeTag>::assemble(bool first) ElementIterator eItEnd = problem_.gridView().template end<0>(); for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eItEnd; ++eIt) { - // cell information + // get the global index of the cell int globalIdxI = problem_.variables().index(*eIt); - CellData& cellDataI = problem_.variables().cellData(globalIdxI); - EntryType entries(0.); + // assemble interior element contributions + if (eIt->partitionType() == Dune::InteriorEntity) + { + // get the cell data + CellData& cellDataI = problem_.variables().cellData(globalIdxI); - /***** source term ***********/ - asImp_().getSource(entries, *eIt, cellDataI, first); - f_[globalIdxI] += entries[rhs]; + EntryType entries(0.); - /***** flux term ***********/ - // iterate over all faces of the cell - IntersectionIterator isItEnd = problem_.gridView().iend(*eIt); - for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItEnd; ++isIt) - { - /************* handle interior face *****************/ - if (isIt->neighbor()) + /***** source term ***********/ + asImp_().getSource(entries, *eIt, cellDataI, first); + f_[globalIdxI] += entries[rhs]; + + /***** flux term ***********/ + // iterate over all faces of the cell + IntersectionIterator isItEnd = problem_.gridView().iend(*eIt); + for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItEnd; ++isIt) { - ElementPointer elementNeighbor = isIt->outside(); + /************* handle interior face *****************/ + if (isIt->neighbor()) + { + ElementPointer elementNeighbor = isIt->outside(); - int globalIdxJ = problem_.variables().index(*elementNeighbor); + int globalIdxJ = problem_.variables().index(*elementNeighbor); - //check for hanging nodes - //take a hanging node never from the element with smaller level! - bool haveSameLevel = (eIt->level() == elementNeighbor->level()); - //calculate only from one side, but add matrix entries for both sides - if (GET_PROP_VALUE(TypeTag, VisitFacesOnlyOnce) && (globalIdxI > globalIdxJ) && haveSameLevel) - continue; + //check for hanging nodes + //take a hanging node never from the element with smaller level! + bool haveSameLevel = (eIt->level() == elementNeighbor->level()); + //calculate only from one side, but add matrix entries for both sides + if (GET_PROP_VALUE(TypeTag, VisitFacesOnlyOnce) && (globalIdxI > globalIdxJ) && haveSameLevel) + continue; - //check for hanging nodes - entries = 0; - asImp_().getFlux(entries, *isIt, cellDataI, first); + //check for hanging nodes + entries = 0; + asImp_().getFlux(entries, *isIt, cellDataI, first); - //set right hand side - f_[globalIdxI] -= entries[rhs]; + //set right hand side + f_[globalIdxI] -= entries[rhs]; - // set diagonal entry - A_[globalIdxI][globalIdxI] += entries[matrix]; + // set diagonal entry + A_[globalIdxI][globalIdxI] += entries[matrix]; - // set off-diagonal entry - A_[globalIdxI][globalIdxJ] -= entries[matrix]; + // set off-diagonal entry + A_[globalIdxI][globalIdxJ] -= entries[matrix]; - if (GET_PROP_VALUE(TypeTag, VisitFacesOnlyOnce)) - { - f_[globalIdxJ] += entries[rhs]; - A_[globalIdxJ][globalIdxJ] += entries[matrix]; - A_[globalIdxJ][globalIdxI] -= entries[matrix]; - } + if (GET_PROP_VALUE(TypeTag, VisitFacesOnlyOnce)) + { + f_[globalIdxJ] += entries[rhs]; + A_[globalIdxJ][globalIdxJ] += entries[matrix]; + A_[globalIdxJ][globalIdxI] -= entries[matrix]; + } - } // end neighbor + } // end neighbor - /************* boundary face ************************/ - else - { - entries = 0; - asImp_().getFluxOnBoundary(entries, *isIt, cellDataI, first); + /************* boundary face ************************/ + else + { + entries = 0; + asImp_().getFluxOnBoundary(entries, *isIt, cellDataI, first); - //set right hand side - f_[globalIdxI] += entries[rhs]; - // set diagonal entry - A_[globalIdxI][globalIdxI] += entries[matrix]; - } - } //end interfaces loop -// printmatrix(std::cout, A_, "global stiffness matrix", "row", 11, 3); - - /***** storage term ***********/ - entries = 0; - asImp_().getStorage(entries, *eIt, cellDataI, first); - f_[globalIdxI] += entries[rhs]; -// set diagonal entry - A_[globalIdxI][globalIdxI] += entries[matrix]; + //set right hand side + f_[globalIdxI] += entries[rhs]; + // set diagonal entry + A_[globalIdxI][globalIdxI] += entries[matrix]; + } + } //end interfaces loop + // printmatrix(std::cout, A_, "global stiffness matrix", "row", 11, 3); + + /***** storage term ***********/ + entries = 0; + asImp_().getStorage(entries, *eIt, cellDataI, first); + f_[globalIdxI] += entries[rhs]; + // set diagonal entry + A_[globalIdxI][globalIdxI] += entries[matrix]; + } + // assemble overlap and ghost element contributions + else + { + A_[globalIdxI] = 0.0; + A_[globalIdxI][globalIdxI] = 1.0; + f_[globalIdxI] = pressure_[globalIdxI]; + } } // end grid traversal // printmatrix(std::cout, A_, "global stiffness matrix after assempling", "row", 11,3); // printvector(std::cout, f_, "right hand side", "row", 10); diff --git a/dumux/linear/vectorexchange.hh b/dumux/linear/vectorexchange.hh new file mode 100644 index 0000000000..ece6fc1104 --- /dev/null +++ b/dumux/linear/vectorexchange.hh @@ -0,0 +1,90 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef DUMUX_VECTOR_EXCHANGE_HH +#define DUMUX_VECTOR_EXCHANGE_HH + +#include <dune/grid/common/datahandleif.hh> + +namespace Dumux +{ + +// A DataHandle class to exchange entries of a vector +template<class Mapper, class Vector> // mapper type and vector type +class VectorExchange + : public Dune::CommDataHandleIF<VectorExchange<Mapper,Vector>, + typename Vector::value_type> +{ +public: + //! export type of data for message buffer + typedef typename Vector::value_type DataType; + + //! returns true if data for this codim should be communicated + bool contains (int dim, int codim) const + { + return (codim == 0); + } + + //! returns true if size per entity of given dim and codim is a constant + bool fixedsize (int dim, int codim) const + { + return true; + } + + /*! how many objects of type DataType have to be sent for a given entity + + Note: Only the sender side needs to know this size. + */ + template<class Entity> + size_t size (Entity& entity) const + { + return 1; + } + + //! pack data from user to message buffer + template<class MessageBuffer, class Entity> + void gather (MessageBuffer& buff, const Entity& entity) const + { + buff.write(dataVector_[mapper_.map(entity)]); + } + + /*! unpack data from message buffer to user + + n is the number of objects sent by the sender + */ + template<class MessageBuffer, class Entity> + void scatter (MessageBuffer& buff, const Entity& entity, size_t n) + { + DataType x; + buff.read(x); + dataVector_[mapper_.map(entity)] = x; + } + + //! constructor + VectorExchange (const Mapper& mapper, Vector& dataVector) + : mapper_(mapper), dataVector_(dataVector) + {} + +private: + const Mapper& mapper_; + Vector& dataVector_; +}; + +} + +#endif -- GitLab