ParallelDofMapping.h 14.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ==  http://www.amdis-fem.org                                              ==
// ==                                                                        ==
// ============================================================================
//
// Software License for AMDiS
//
// Copyright (c) 2010 Dresden University of Technology 
// All rights reserved.
// Authors: Simon Vey, Thomas Witkowski et al.
//
// This file is part of AMDiS
//
// See also license.opensource.txt in the distribution.



/** \file FeSpaceMapping.h */

23
#include <vector>
24
#include <map>
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
25 26
#include <set>
#include "parallel/DofComm.h"
27
#include "parallel/MeshLevelData.h"
28 29
#include "parallel/MpiHelper.h"
#include "parallel/ParallelTypes.h"
30
#include "parallel/StdMpi.h"
31

32 33
#include <petscis.h>

34 35 36 37
#ifndef AMDIS_FE_SPACE_MAPPING_H
#define AMDIS_FE_SPACE_MAPPING_H

namespace AMDiS {
Thomas Witkowski's avatar
Thomas Witkowski committed
38

39 40
  using namespace std;

41
  /** \brief
42 43 44
   * Is used to store matrix indices to all DOFs in rank's subdomain. Thus, the
   * class defines a mapping from component number and DOF index to a global
   * matrix index. This class does not calculate the indices by itself!
45 46 47 48 49 50 51 52 53 54 55 56
   */
  class DofToMatIndex
  {
  public:
    DofToMatIndex() {}

    /// Reset the data structure.
    inline void clear()
    {
      data.clear();
    }

57 58 59 60 61 62 63
    /** Add a new mapping for a given DOF.
     * 
     * \param[in]   component       Component number for which the mapping 
     *                              is defined.
     * \param[in]   dof             DOF index
     * \param[in]   globalMatIndex  Global matrix index.
     */
64 65 66 67 68
    inline void add(int component, DegreeOfFreedom dof, int globalMatIndex)
    {
      data[component][dof] = globalMatIndex;
    }

69
    /// Maps a global DOF index to the global matrix index for a specific 
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    /// system component number.
    inline int get(int component, DegreeOfFreedom dof)
    {
      FUNCNAME("DofToMatIndex::get()");

      TEST_EXIT_DBG(data.count(component))
	("No mapping data for component %d available!\n", component);

      TEST_EXIT_DBG(data[component].count(dof))
	("Mapping for DOF %d in component %d does not exists!\n",
	 dof, component);

      return data[component][dof];
    }

85 86 87 88 89
    /// Returns for a given matrix index the component and (local or global) DOF
    /// index. As the data structure is not made for this kind of reverse
    /// search, this is very slow and should be only used for debugging.
    void getReverse(int rowIndex, int &component, int &dofIndex);

90 91 92 93 94 95 96
  private:
    /// The mapping data. For each system component there is a specific map that
    /// maps global DOF indices to global matrix indices.
    map<int, map<DegreeOfFreedom, int> > data;
  };


97 98 99 100 101 102
  /**
   * This class defines the parallel mapping of DOFs for one FE space. It is used
   * by the class \ref ParallelDofMapping to specifiy the mapping for a set of 
   * FE spaces.
   */
  class FeSpaceDofMap
103 104
  {
  public:
105 106
    /// This constructor exists only to create std::map of this class and make
    /// use of the operator [] for read access. Should never be called.
107
    FeSpaceDofMap() 
108 109 110
    {
      ERROR_EXIT("Should not be called!\n");
    }
111 112
     
    /// This is the only valid constructur to be used. 
113 114
    FeSpaceDofMap(MeshLevelData* ld)
      : levelData(ld),
115
	dofComm(NULL),
116
	feSpace(NULL),
Thomas Witkowski's avatar
Thomas Witkowski committed
117
	needGlobalMapping(false),
118
	hasNonLocalDofs(false)
119 120 121
    {
      clear();
    }
122 123

    /// Clears all data of the mapping.
124
    void clear();
125

126 127
    /// Maps a DOF index to both, the local and global index of the mapping. The
    /// global index must not be set.
Thomas Witkowski's avatar
Thomas Witkowski committed
128
    MultiIndex& operator[](DegreeOfFreedom d)
129
    {
130
      TEST_EXIT_DBG(dofMap.count(d))("DOF %d is not in map!\n", d);
131

132
      return dofMap[d];
133
    }
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

    /** \brief
     * Searchs the map for a given DOF. It does not fail, if the DOF is not 
     * mapped by this mapping. In this case, it returns false. If the DOF is 
     * mapped, the result is stored and the function returns true.
     *
     * \param[in]    dof     DOF index for which a mapping is searched.
     * \param[out]   index   In the case that the DOF is mapped, the result
     *                       is stored here.
     */
    inline bool find(DegreeOfFreedom dof, MultiIndex& index)
    {
      DofMap::iterator it = dofMap.find(dof);
      if (it == dofMap.end())
	return false;

      index = it->second;
      return true;
    }
153
    
154 155
    /// Inserts a new DOF to rank's mapping. The DOF is assumed to be owend by
    /// the rank.
156
    void insertRankDof(DegreeOfFreedom dof0, DegreeOfFreedom dof1 = -1)
157
    {
158
      FUNCNAME("FeSpaceDofMap::insertRankDof()");
159
      
160
      TEST_EXIT_DBG(dofMap.count(dof0) == 0)("Should not happen!\n");
161
      
162 163
      dofMap[dof0].local = dof1;
      nLocalDofs++;
Thomas Witkowski's avatar
Thomas Witkowski committed
164
      if (dof1 != -1)
165
	nRankDofs++;
166 167
    }
    
168 169
    /// Inserts a new DOF to rank's mapping. The DOF exists in rank's subdomain
    /// but is owned by a different rank, thus it is part of an interior boundary.
170
    void insertNonRankDof(DegreeOfFreedom dof0, DegreeOfFreedom dof1 = -1)
171
    {
172
      FUNCNAME("FeSpaceDofMap::insertNonRankDof()");
173
      
174
      TEST_EXIT_DBG(dofMap.count(dof0) == 0)("Should not happen!\n");
175
      
176 177 178
      dofMap[dof0].local = dof1;
      nLocalDofs++;
      nonRankDofs.insert(dof0);
179 180
    }
    
181
    /// Checks if a given DOF is in the DOF mapping.
182
    bool isSet(DegreeOfFreedom dof)
183
    {
184
      return static_cast<bool>(dofMap.count(dof));
185
    }
186

187 188 189
    /// Checks if a given DOF is a rank owned DOF of the DOF mapping. The DOF must
    /// a DOF of the mapping (this is not checked here), otherwise the result is
    /// meaningsless.
190
    bool isRankDof(DegreeOfFreedom dof)
191
    {
192
      return !(static_cast<bool>(nonRankDofs.count(dof)));
193
    }
194
    
195
    /// Returns number of DOFs in the mapping.
196
    unsigned int size()
197
    {
198
      return dofMap.size();
199 200
    }
    
201
    /// Returns the raw data of the mapping.
202
    DofMap& getMap()
203
    {
204
      return dofMap;
205
    }
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
206

207 208
    /// Recomputes the mapping.
    void update();
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
209

210
    /// Sets the FE space this mapping corresponds to.
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
211 212 213 214 215
    void setFeSpace(const FiniteElemSpace *fe)
    {
      feSpace = fe;
    }

216 217
    /// Informs the mapping whether the mapping will include DOFs that are not
    /// owned by the rank.
218
    void setNonLocalDofs(bool b)
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
219
    {
220
      hasNonLocalDofs = b;
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
221 222
    }

223
    /// Informs the mapping whether a global index must be computed.
224
    void setNeedGlobalMapping(bool b)
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
225
    {
226
      needGlobalMapping = b;
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
227 228
    }

229
    /// Sets the DOF communicators.
230
    void setDofComm(DofComm &dc)
Thomas Witkowski's avatar
Thomas Witkowski committed
231
    {
232
      dofComm = &dc;
Thomas Witkowski's avatar
Thomas Witkowski committed
233 234
    }

235 236 237 238 239 240
    void setMpiComm(MPI::Intracomm &m, int l)
    {
      mpiComm = m;
      meshLevel = l;
    }

241
  private:
242
    /// Computes a global mapping from the local one.
243
    void computeGlobalMapping();
244 245 246

    /// Computes the global indices of all DOFs in the mapping that are not owned
    /// by the rank.
247
    void computeNonLocalIndices();
248 249

  private:
250
    MeshLevelData *levelData;
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
251

252 253
    /// DOF communicator for all DOFs on interior boundaries.
    DofComm *dofComm;
254

255 256 257 258
    MPI::Intracomm mpiComm;

    int meshLevel;

259
    /// The FE space this mapping belongs to. This is used only the get the
260
    /// correct DOF communicator in \ref dofComm.
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
261 262
    const FiniteElemSpace *feSpace;

263
    /// Mapping data from DOF indices to local and global indices.
264
    DofMap dofMap;
265

266
    /// Set of all DOFs that are in mapping but are not owned by the rank.
267
    std::set<DegreeOfFreedom> nonRankDofs;
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
268

269
    /// If true, a global index mapping will be computed for all DOFs.
Thomas Witkowski's avatar
Thomas Witkowski committed
270
    bool needGlobalMapping;
Thomas Witkowski's avatar
FETI-DP  
Thomas Witkowski committed
271

272 273 274 275
    /// Is true if there are DOFs in at least one subdomain that are not owned
    /// by the rank. If the value is false, each rank contains only DOFs that
    /// are also owned by this rank.
    bool hasNonLocalDofs;
276

277 278
  public:
    /// 
279
    int nRankDofs, nLocalDofs, nOverallDofs, rStartDofs;
280 281
  };
  
282 283 284 285 286 287
  
  /**
   * Implements the mapping from sets of distributed DOF indices to local and
   * global indices. The mapping works for a given set of FE spaces. Furthermore,
   * this class may compute the matrix indices of the set of DOF indices.
   */
Thomas Witkowski's avatar
Thomas Witkowski committed
288
  class ParallelDofMapping
289 290
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
291
    ParallelDofMapping() 
292
      : levelData(NULL),
293
	hasNonLocalDofs(false),
294 295
	needMatIndex(false),
	needMatIndexFromGlobal(false),
296
	feSpaces(0),
297 298 299 300 301
	nRankDofs(1),
	nLocalDofs(1),
	nOverallDofs(1),
	rStartDofs(1)
    {
302 303 304 305
      nRankDofs = -1;
      nLocalDofs = -1;
      nOverallDofs = -1;
      rStartDofs = -1;
306
    } 
307

308 309 310 311
    /** \brief Initialize the parallel DOF mapping.
     *
     * \param[in]  m                  MPI communicator.
     * \param[in]  fe                 The FE spaces of all components of the 
312 313 314 315
     *                                PDE to be solved.
     * \param[in]  uniqueFe           Unique list of FE spaces. Thus, two
     *                                arbitrary elements of this list are always
     *                                different.
316 317 318 319 320
     * \param[in]  needGlobalMapping  If true, the mapping computes also a global
     *                                index for the DOFs.
     * \param[in]  bNonLocalDofs      If true, at least one rank's mapping con-
     *                                taines DOFs that are not owend by the rank.
     */
321
    void init(MeshLevelData& mld,
322
	      vector<const FiniteElemSpace*> &fe,
323
	      vector<const FiniteElemSpace*> &uniqueFe,
324 325
	      bool needGlobalMapping,
	      bool bNonLocalDofs);
326 327

    void setMpiComm(MPI::Intracomm &m, int l);
328 329 330
    
    /// Clear all data.
    void clear();
331 332 333

    /// Set the DOF communicator objects that are required to exchange information
    /// about DOFs that are on interior boundaries.
334
    void setDofComm(DofComm &dofComm);
335

336 337 338 339 340 341
    void setComputeMatIndex(bool b, bool global = false)
    {
      needMatIndex = b;
      needMatIndexFromGlobal = global;
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
342 343 344 345 346
    inline bool isMatIndexFromGlobal()
    {
      return needMatIndexFromGlobal;
    }

347 348
    /// Access the DOF mapping for a given FE space.
    inline FeSpaceDofMap& operator[](const FiniteElemSpace* feSpace)
349
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
350
      FUNCNAME("ParallelDofMapping::operator[]()");
351

352 353
      TEST_EXIT_DBG(data.count(feSpace))
	("No data for FE space at address %p!\n", feSpace);
354 355 356 357

      return data.find(feSpace)->second;
    }

358
    /// Returns \ref nRankDofs, thus the number of DOFs owned by the rank.
359
    inline int getRankDofs()
360
    {
361
      TEST_EXIT_DBG(nRankDofs >= 0)("Should not happen!\n");
362

363
      return nRankDofs;
364 365
    }

366
    /// Returns \ref nLocalDofs, thus the number of DOFs in ranks subdomain.
367
    inline int getLocalDofs()
Thomas Witkowski's avatar
Thomas Witkowski committed
368
    {
369
      TEST_EXIT_DBG(nLocalDofs >= 0)("Should not happen!\n");
Thomas Witkowski's avatar
Thomas Witkowski committed
370

371
      return nLocalDofs;
Thomas Witkowski's avatar
Thomas Witkowski committed
372 373
    }

374
    /// Returns \ref nOverallDofs, thus the number of all DOFs in this mapping.
375
    inline int getOverallDofs()
376
    {
377
      TEST_EXIT_DBG(nOverallDofs >= 0)("Should not happen!\n");
378

379
      return nOverallDofs;
380 381
    }

382 383
    /// Returns \ref rStartDofs, thus the smallest global index of a DOF that is
    /// owned by the rank.
384
    inline int getStartDofs()
385
    {
386
      TEST_EXIT_DBG(rStartDofs >= 0)("Should not happen!\n");
387

388
      return rStartDofs;
389 390
    }

391
    /// Update the mapping.
Thomas Witkowski's avatar
Thomas Witkowski committed
392
    void update();
393

394 395 396
    /// Update the mapping.
    void update(vector<const FiniteElemSpace*>& feSpaces);

397 398
    /// Returns the global matrix index of a given DOF for a given 
    /// component number.
399
    inline int getMatIndex(int ithComponent, DegreeOfFreedom d)
Thomas Witkowski's avatar
Thomas Witkowski committed
400
    {
401
      return dofToMatIndex.get(ithComponent, d);
Thomas Witkowski's avatar
Thomas Witkowski committed
402 403
    }

404 405 406 407 408 409 410
    /// Returns the component number and local/global DOF index for a given
    /// matrix row index. Should be used for debugging only!
    inline void getReverseMatIndex(int index, int &component, int &dofIndex)
    {
      dofToMatIndex.getReverse(index, component, dofIndex);
    }

411 412
    /// Returns the local matrix index of a given DOF for a given 
    /// component number.
413
    inline int getLocalMatIndex(int ithComponent, DegreeOfFreedom d)
414
    {
Thomas Witkowski's avatar
Thomas Witkowski committed
415
      FUNCNAME("ParallelDofMapping::getLocalMatIndex()");
416

417
      TEST_EXIT_DBG(data[feSpaces[ithComponent]].isRankDof(d))
418 419
	("Should not happen!\n");

420
      return dofToMatIndex.get(ithComponent, d) - rStartDofs;
421 422
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
423 424 425 426 427 428 429 430 431 432 433 434
    // Writes all data of this object to an output stream.
    void serialize(ostream &out)
    {
      ERROR_EXIT("MUST BE IMPLEMENTED!\n");
    }

    // Reads the object data from an input stream.
    void deserialize(istream &in)
    {
      ERROR_EXIT("MUST BE IMPLEMENTED!\n");
    }

435
    /// Compute local and global matrix indices.
436
    void computeMatIndex(bool globalIndex);
437

438 439 440 441
    void createIndexSet(IS &is, 
			int firstComponent, 
			int nComponents);

442 443 444 445 446
  protected:
    /// Insert a new FE space DOF mapping for a given FE space.
    void addFeSpace(const FiniteElemSpace* feSpace);

    /// Compute \ref nRankDofs.
447
    int computeRankDofs();
448 449

    /// Compute \ref nLocalDofs.
450
    int computeLocalDofs();
451 452

    /// Compute \ref nOverallDofs.
453
    int computeOverallDofs();
454 455

    /// Compute \ref rStartDofs.
456
    int computeStartDofs();
457

458
  private:
459 460 461 462
    MPI::Intracomm mpiComm;

    int meshLevel;

463
    MeshLevelData *levelData;
464

465 466
    /// DOF communicator for all DOFs on interior boundaries.
    DofComm *dofComm;
467

468 469 470 471
    /// Is true if there are DOFs in at least one subdomain that are not owned
    /// by the rank. If the value is false, each rank contains only DOFs that
    /// are also owned by this rank.
    bool hasNonLocalDofs;
472

473 474 475 476 477 478 479 480
    /// If true, matrix indeces for the stored DOFs are computed, see
    /// \ref computeMatIndex.
    bool needMatIndex;

    /// If matrix indices should be computed, this variable defines if the
    /// mapping from DOF indices to matrix row indices is defined on local
    /// or global DOF indices. If true, the mapping is to specify and to use
    /// on global ones, otherwise on local DOF indices.
Thomas Witkowski's avatar
Thomas Witkowski committed
481 482 483 484 485
    /// In most scenarios the mapping stored on local DOF indices is what we
    /// want to have. Only when periodic boundary conditions are used together
    /// with some global matrix approache, the matrix indices must be stored
    /// also for DOFs that are not part of the local subdomain. Thus, the
    /// mapping will be stored on global DOF indices.
486 487
    bool needMatIndexFromGlobal;

488 489 490 491
    /// Maps from FE space pointers to DOF mappings.
    map<const FiniteElemSpace*, FeSpaceDofMap> data;

    /// The FE spaces for all components.
492 493
    vector<const FiniteElemSpace*> feSpaces;

494 495
    /// The set of all FE spaces. It uniquly contains all different FE spaces
    /// from \ref feSpaces.
496
    vector<const FiniteElemSpace*> feSpacesUnique;
Thomas Witkowski's avatar
Thomas Witkowski committed
497

498
    /// Number of DOFs owned by rank.
499
    int nRankDofs;
500 501

    /// Number of DOFs in rank's subdomain.
502
    int nLocalDofs;
503 504

    /// Number of global DOFs (this value is thus the same on all ranks).
505
    int nOverallDofs;
506 507

    /// Smallest global index of a DOF owned by the rank.
508
    int rStartDofs;
509 510 511

    /// Mapping from global DOF indices to global matrix indices under 
    /// consideration of possibly multiple components.
512
    DofToMatIndex dofToMatIndex;
513 514 515 516 517
  };

}

#endif