Memosa-FVM  0.2
LinearSystemMerger.cpp
Go to the documentation of this file.
1 // This file os part of FVM
2 // Copyright (c) 2012 FVM Authors
3 // See LICENSE file for terms.
4 
5 #ifdef FVM_PARALLEL
6 
7 #include <iostream>
8 #include <fstream>
9 #include <string>
10 #include <sstream>
11 #include "LinearSystemMerger.h"
12 #include "CRConnectivity.h"
13 #include "StorageSiteMerger.h"
14 
15 
16 using namespace std;
17 
18 LinearSystemMerger::LinearSystemMerger(int target_proc_id, const set<int>& group, LinearSystem& ls )
19 :_targetID(target_proc_id), _groupID(target_proc_id), _group(group), _ls(ls)
20 {
21 
22  init();
23  merge();
24 }
25 
26 LinearSystemMerger::~LinearSystemMerger()
27 {
28 
29 }
30 
31 
32 void
33 LinearSystemMerger::init()
34 {
35 
36  //construct merged Linearsystem
37  _mergeLS = shared_ptr< LinearSystem > ( new LinearSystem() );
38 
39  //subcommunicator
40  int color = _groupID;
41  int key = MPI::COMM_WORLD.Get_rank();
42  _comm = MPI::COMM_WORLD.Split( color, key );
43  _procID = MPI::COMM_WORLD.Get_rank();
44  _totalProcs = _group.size();
45  _totalInterfaces = 0;
46  _totalScatterCells = 0;
47  _totalScatterCellsLocal = 0;
48  _totalGatherCells = 0;
49  _totalGatherCellsLocal = 0;
50  _totalCells = 0;
51  _neighMeshCounts = ArrayIntPtr( new Array<int>(_totalProcs) ); _neighMeshCounts->zero();
52  _scatterSize = ArrayIntPtr( new Array<int>(_totalProcs) ); _scatterSize->zero();
53  _gatherSize = ArrayIntPtr( new Array<int>(_totalProcs) ); _gatherSize->zero();
54  _rowLength = ArrayIntPtr( new Array<int>(_totalProcs) ); _rowLength->zero();//CRConnecivity row_dimension, size = _totalProcs
55  _colLength = ArrayIntPtr( new Array<int>(_totalProcs) ); _colLength->zero();
56  _selfCounts = ArrayIntPtr( new Array<int>(_totalProcs) ); _selfCounts->zero();
57  _scatterCells.reserve( _totalProcs );
58  _gatherCells.reserve( _totalProcs );
59  _gatherIDsLocalToGlobalMap.resize( _totalProcs );
60  //get number of all neightbourhood of a local mesh
61  get_neigh_mesh_counts();
62  get_scatter_cells();
63  get_gather_cells();
64  get_crconnectivity();
65  get_local_to_global_map();
66  set_merged_crconnectivity();
67  set_ls_vectors();
68 
69 }
70 
71 
72 void
73 LinearSystemMerger::merge()
74 {
75 
76 
77  // _comm.Reduce( &self_size , &_mergeSiteSize , 1, MPI::INT, MPI::SUM, _groupID );
78  // _comm.Reduce( &ghost_size, &_mergeSiteGhostSize, 1, MPI::INT, MPI::SUM, _groupID );
79 
80 }
81 
82 
83 
84 void
85 LinearSystemMerger::get_neigh_mesh_counts()
86 {
87 
88  vector<int> siteScatterOffsetLocal;
89  vector<int> siteGatherOffsetLocal;
90  vector<int> scatterMapIDsLocal;
91  vector<int> gatherMapIDsLocal;
92 
93  int nmesh = 0;
94  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
95  foreach( MultiField::ArrayIndex k, arrayIndices ){
96  const StorageSite& site = *k.second;
97  const StorageSite::ScatterMap& scatterMap = site.getScatterMap();
98  foreach( const StorageSite::ScatterMap::value_type& pos, scatterMap ){
99  const StorageSite& site = *pos.first;
100  int neigh_proc_id = site.getGatherProcID(); //neig_proc_id means other mesh, so gatherProcID() will be used for this and gatherMap
101  //if neigh proc belongs to the group, then ok
102  if ( _group.count( neigh_proc_id ) > 0 ){
103  const Array<int>& fromIndices = *pos.second;
104  _totalScatterCellsLocal += fromIndices.getLength();
105  siteScatterOffsetLocal.push_back( fromIndices.getLength() );
106  scatterMapIDsLocal.push_back( neigh_proc_id );
107  nmesh++;
108  }
109  }
110  }
111 
112 
113  _comm.Gather( &nmesh, 1, MPI::INT, _neighMeshCounts->getData(), 1, MPI::INT, _targetID );
114  _comm.Gather( &_totalScatterCellsLocal, 1, MPI::INT, _scatterSize->getData(), 1, MPI::INT, _targetID );
115 
116 
117  foreach( MultiField::ArrayIndex k, arrayIndices ){
118  const StorageSite& site = *k.second;
119  const StorageSite::GatherMap& gatherMap = site.getGatherMap();
120  foreach( const StorageSite::GatherMap::value_type& pos, gatherMap ){
121  const StorageSite& site = *pos.first;
122  int neigh_proc_id = site.getGatherProcID();
123  //if neigh proc belongs to the group, then ok
124  if ( _group.count( neigh_proc_id ) > 0 ){
125  const Array<int>& toIndices = *pos.second;
126  _totalGatherCellsLocal += toIndices.getLength();
127  siteGatherOffsetLocal.push_back( toIndices.getLength() );
128  gatherMapIDsLocal.push_back( neigh_proc_id );
129  }
130  }
131  }
132 
133 
134  _comm.Gather( &_totalGatherCellsLocal, 1, MPI::INT, _gatherSize->getData(), 1, MPI::INT, _targetID );
135  //cout << " procid = " << _procID << " _scatterSize = " << (*_scatterSize)[_procID] << " _gatherSize = " << (*_gatherSize)[_procID] << endl;
136 
137  //total interfaces
138  for ( int i = 0; i < _neighMeshCounts->getLength(); i++ )
139  _totalInterfaces += (*_neighMeshCounts)[i];
140 
141 
142  ArrayIntPtr scatterInterfaceCounts = ArrayIntPtr( new Array<int>( _totalInterfaces) );
143  ArrayIntPtr gatherInterfaceCounts = ArrayIntPtr( new Array<int>( _totalInterfaces) );
144  scatterInterfaceCounts->zero();
145  gatherInterfaceCounts->zero();
146 
147 
148  int displs[ _totalInterfaces ];
149  displs[0] = 0;
150 
151  for ( int i = 1; i < _totalInterfaces; i++ )
152  displs[i] = displs[i-1] + (*_neighMeshCounts)[i-1];
153 
154  //recvcnts = _neighMeshCounts()->getData(),
155  _comm.Gatherv( &siteScatterOffsetLocal[0], nmesh, MPI::INT, scatterInterfaceCounts->getData(), &(*_neighMeshCounts)[0], displs, MPI::INT, _targetID );
156 
157  //recvcnts = _neighMeshCounts()->getData(),
158  _comm.Gatherv( &siteGatherOffsetLocal[0], nmesh, MPI::INT, gatherInterfaceCounts->getData(), &(*_neighMeshCounts)[0], displs, MPI::INT, _targetID );
159 
160  //now filling our convenient variable
161  int indx = 0;
162  foreach ( const set<int>::value_type proc, _group ){
163  int num_interfaces = (*_neighMeshCounts)[proc];
164  ArrayIntPtr scatter_counts ( new Array<int> ( num_interfaces ) );
165  ArrayIntPtr gather_counts ( new Array<int> ( num_interfaces ) );
166  for ( int n = 0; n < num_interfaces; n++ ){
167  (*scatter_counts)[n] = (*scatterInterfaceCounts)[indx];
168  (*gather_counts)[n] = (*gatherInterfaceCounts )[indx];
169  indx++;
170  }
171  _scatterInterfaceCounts[proc] = scatter_counts;
172  _gatherInterfaceCounts[proc] = gather_counts;
173  }
174 
175  for ( int i = 0; i < scatterInterfaceCounts->getLength(); i++ )
176  _totalScatterCells += (*scatterInterfaceCounts)[i];
177 
178  for ( int i = 0; i < gatherInterfaceCounts->getLength(); i++ )
179  _totalGatherCells += (*gatherInterfaceCounts)[i];
180 
181 
182  //recvcnts for scatter
183  int scatter_recvcnts[_totalProcs];
184  for ( int proc = 0; proc < _totalProcs; proc++ )
185  scatter_recvcnts[proc] = _scatterInterfaceCounts[proc]->getLength();
186 
187  //recvncnts for gather
188  int gather_recvcnts[_totalProcs];
189  for ( int proc = 0; proc < _totalProcs; proc++ )
190  gather_recvcnts[proc] = _gatherInterfaceCounts[proc]->getLength();
191 
192  ArrayIntPtr scatterMapIDs( new Array<int>( _totalInterfaces) );
193 
194  //scatter neightbour IDS
195  _comm.Gatherv( &scatterMapIDsLocal[0], nmesh, MPI::INT, scatterMapIDs->getData(), scatter_recvcnts, displs, MPI::INT, _targetID );
196 
197 
198  ArrayIntPtr gatherMapIDs( new Array<int>( _totalInterfaces) );
199  //scatter neighbour IDS
200  _comm.Gatherv( &gatherMapIDsLocal[0], nmesh, MPI::INT, gatherMapIDs->getData(), gather_recvcnts, displs, MPI::INT, _targetID );
201 
202 
203  indx = 0;
204  foreach ( const set<int>::value_type proc, _group ){
205  int num_interfaces = (*_neighMeshCounts)[proc];
206  ArrayIntPtr scatterIDs ( new Array<int> ( num_interfaces ) );
207  ArrayIntPtr gatherIDs ( new Array<int> ( num_interfaces ) );
208  for ( int n = 0; n < num_interfaces; n++ ){
209  (*scatterIDs)[n] = (*scatterMapIDs)[indx];
210  (*gatherIDs )[n] = (*gatherMapIDs )[indx];
211  indx++;
212  }
213  _scatterInterfaceIDs[proc] = scatterIDs;
214  _gatherInterfaceIDs [proc] = gatherIDs;
215  }
216 
217 
218 }
219 
220 //merging scatterArray
221 void
222 LinearSystemMerger::get_scatter_cells()
223 {
224 
225 
226  //fill scatter cells in local for shipping
227 
228  ArrayIntPtr scatterCellsLocal( new Array<int> ( _totalScatterCellsLocal ) );
229  int indx = 0;
230  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
231  foreach( MultiField::ArrayIndex k, arrayIndices ){
232  const StorageSite& site = *k.second;
233  const StorageSite::ScatterMap& scatterMap = site.getScatterMap();
234  foreach( const StorageSite::ScatterMap::value_type& pos, scatterMap ){
235  const StorageSite& site = *pos.first;
236  int neigh_proc_id = site.getGatherProcID();
237  //if neigh proc belongs to the group, then ok
238  if ( _group.count( neigh_proc_id ) > 0 ){
239  const Array<int>& fromIndices = *pos.second;
240  for ( int i = 0; i < fromIndices.getLength(); i++)
241  (*scatterCellsLocal)[indx++] = fromIndices[i];
242  }
243  }
244  }
245 
246  //fill in scatterCells
247  ArrayIntPtr scatterCells( new Array<int> ( _totalScatterCells) );
248 
249 
250  int displs[ _totalProcs ];
251  displs[0] = 0;
252  for ( int i = 1; i < _totalProcs; i++ )
253  displs[i] = displs[i-1] + (*_scatterSize)[i-1];
254 
255 
256  //scatterSize is receive count array,
257  _comm.Gatherv( scatterCellsLocal->getData(), _totalScatterCellsLocal, MPI::INT,
258  scatterCells->getData(), &(*_scatterSize)[0], displs, MPI::INT, _targetID );
259 
260 
261  //convenient storage in map
262  indx = 0;
263  foreach ( const set<int>::value_type proc, _group ){
264  const Array<int>& interfaceIDs = *_scatterInterfaceIDs[proc];
265  const Array<int>& interfaceCounts = *_scatterInterfaceCounts[proc];
266  map<int, ArrayIntPtr> cell_map;
267  for ( int i = 0; i < interfaceIDs.getLength(); i++ ){
268  ArrayIntPtr cells( new Array<int> ( interfaceCounts[i] ) );
269  for ( int n = 0; n < interfaceCounts[i]; n++ )
270  (*cells)[n] = (*scatterCells)[indx++];
271  int interface_id = interfaceIDs[i];
272  cell_map[interface_id] = cells;
273  }
274  _scatterCells.push_back( cell_map );
275  }
276 
277 
278 }
279 
280 
281 //merging scatterArray
282 void
283 LinearSystemMerger::get_gather_cells()
284 {
285 
286  //fill gather cells in local for shipping
287  ArrayIntPtr gatherCellsLocal( new Array<int> ( _totalGatherCellsLocal ) );
288  int indx = 0;
289  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
290  foreach( MultiField::ArrayIndex k, arrayIndices ){
291  const StorageSite& site = *k.second;
292  const StorageSite::GatherMap& gatherMap = site.getGatherMap();
293  foreach( const StorageSite::GatherMap::value_type& pos, gatherMap ){
294  const StorageSite& site = *pos.first;
295  int neigh_proc_id = site.getGatherProcID();
296  //if neigh proc belongs to the group, then ok
297  if ( _group.count( neigh_proc_id ) > 0 ){
298  const Array<int>& toIndices = *pos.second;
299  for ( int i = 0; i < toIndices.getLength(); i++ )
300  (*gatherCellsLocal)[indx++] = toIndices[i];
301  }
302  }
303  }
304 
305  //fill in gatherCells
306  ArrayIntPtr gatherCells ( new Array<int> ( _totalGatherCells ) );
307 
308  int displs[ _totalProcs ];
309  displs[0] = 0;
310  for ( int i = 1; i < _totalProcs; i++ )
311  displs[i] = displs[i-1] + (*_gatherSize)[i-1];
312 
313  //scatterSize is receive count array,
314  _comm.Gatherv( gatherCellsLocal->getData(), _totalGatherCellsLocal, MPI::INT,
315  gatherCells->getData(), &(*_gatherSize)[0], displs, MPI::INT, _targetID );
316 
317  //conveient storage in map
318  indx = 0;
319  foreach ( const set<int>::value_type proc, _group ){
320  const Array<int>& interfaceIDs = *_gatherInterfaceIDs[proc];
321  const Array<int>& interfaceCounts = *_gatherInterfaceCounts[proc];
322  map<int, ArrayIntPtr> cell_map;
323  for ( int i = 0; i < interfaceIDs.getLength(); i++ ){
324  ArrayIntPtr cells( new Array<int> ( interfaceCounts[i] ) );
325  for ( int n = 0; n < interfaceCounts[i]; n++ )
326  (*cells)[n] = (*gatherCells)[indx++];
327 
328  int interface_id = interfaceIDs[i];
329  cell_map[interface_id] = cells;
330  }
331  _gatherCells.push_back( cell_map );
332  }
333 
334 
335 
336 }
337 
338 
339 void
340 LinearSystemMerger::get_crconnectivity()
341 {
342 
343  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
344  foreach( MultiField::ArrayIndex k, arrayIndices ){
345  const CRConnectivity& conn = _ls.getMatrix().getMatrix( k, k).getConnectivity();
346  const StorageSite& site = conn.getRowSite();
347  int inner_cells = site.getSelfCount();
348  int rowLength = conn.getRow().getLength();
349  int colLength = conn.getCol().getLength();
350  _comm.Gather( &rowLength , 1, MPI::INT, _rowLength->getData() , 1, MPI::INT, _targetID );
351  _comm.Gather( &colLength , 1, MPI::INT, _colLength->getData() , 1, MPI::INT, _targetID );
352  _comm.Gather( &inner_cells, 1, MPI::INT, _selfCounts->getData(), 1, MPI::INT, _targetID );
353 
354  }
355 
356  //compute aggloremation size
357  int row_size = 0;
358  int col_size = 0;
359  for ( int i = 0; i < _totalProcs; i++ ){
360  row_size += (*_rowLength)[i];
361  col_size += (*_colLength)[i];
362  }
363 
364 
365  //forming arrays
366  ArrayIntPtr row( new Array<int> ( row_size ) );
367  ArrayIntPtr col( new Array<int> ( col_size ) );
368 
369  int displs_row[ _totalProcs ];
370  int displs_col[ _totalProcs ];
371  displs_row[0] = 0;
372  displs_col[0] = 0;
373  for ( int i = 1; i < _totalProcs; i++ ){
374  displs_row[i] = displs_row[i-1] + (*_rowLength)[i-1];
375  displs_col[i] = displs_col[i-1] + (*_colLength)[i-1];
376  }
377 
378 
379  //getting _row and _col
380  foreach( MultiField::ArrayIndex k, arrayIndices ){
381  const CRConnectivity& conn = _ls.getMatrix().getMatrix( k, k).getConnectivity();
382  const Array<int>& row_local = conn.getRow();
383  const Array<int>& col_local = conn.getCol();
384  int rowLength = row_local.getLength();
385  int colLength = col_local.getLength();
386  _comm.Gatherv( row_local.getData(), rowLength, MPI::INT, row->getData(), &(*_rowLength)[0], displs_row, MPI::INT, _targetID );
387  _comm.Gatherv( col_local.getData(), colLength, MPI::INT, col->getData(), &(*_colLength)[0], displs_col, MPI::INT, _targetID );
388  }
389 
390  //for ( int i = 0; i < col->getLength(); i++ )
391  // cout << " col(" << i << ") = " << (*col)[i] << endl;
392 
393  //copying to map data structures, procid->row, or procid->col
394  int local = 0;
395  foreach ( const set<int>::value_type proc_id, _group ){
396  _row[proc_id] = ArrayIntPtr ( new Array<int> ( (*_rowLength)[local] ) );
397  _col[proc_id] = ArrayIntPtr ( new Array<int> ( (*_colLength)[local] ) );
398  //_colPos[proc_id] = ArrayIntPtr ( new Array<int> ( (*_colLength)[local] ) );
399  local++;
400  }
401 
402  int indx = 0;
403  local = 0;
404  foreach ( const set<int>::value_type proc_id, _group ){
405  for ( int i = 0; i < (*_rowLength)[local]; i++ )
406  (*_row[proc_id])[i] = (*row)[indx++];
407  local++;
408  }
409 
410  indx = 0;
411  local = 0;
412  foreach ( const set<int>::value_type proc_id, _group ){
413  for ( int i = 0; i < (*_colLength)[local]; i++ )
414  (*_col[proc_id])[i] = (*col)[indx++];
415  local++;
416  }
417 
418 // //create colPos data structure, you ask for cellID and returns position in col
419 // indx = 0;
420 // local = 0;
421 // foreach( const set<int>::value_type proc_id, _group ){
422 // for ( int i = 0; i < (*_colLength)[local]; i++ ){
423 // int cell_id = (*col)[indx++];
424 // (*_colPos[proc_id])[cell_id] = i;
425 // }
426 // local++;
427 // }
428 
429 
430 
431 }
432 
433 
434 void
435 LinearSystemMerger::get_local_to_global_map()
436 {
437  //localToGlobal: assuming numbering start with lowest proc ID to the highest one
438  //selfCounts is array from 0, 1, ... NPROCS-1 but groupID is not necessaryl holding that
439  //future we might group processes so it will not be always from 0, 1, .. NPROCS-1
440  int indx = 0;
441  foreach ( const set<int>::value_type proc_id, _group){
442  _localToGlobal[proc_id] = ArrayIntPtr( new Array<int> ( (*_selfCounts)[indx] ) );
443  _totalCells += (*_selfCounts)[indx];
444  indx++;
445  }
446 
447  _globalToProc = ArrayIntPtr( new Array<int> ( _totalCells ) );
448  _globalToLocal = ArrayIntPtr( new Array<int> ( _totalCells ) );
449 
450  indx = 0;
451  int global_id = 0;
452  foreach ( const set<int>::value_type proc_id, _group ){
453  for ( int n = 0; n < (*_selfCounts)[indx]; n++ ){
454  (*_localToGlobal[proc_id])[n] = global_id;
455  (*_globalToProc )[global_id] = proc_id;
456  (*_globalToLocal)[global_id] = n;
457  global_id++;
458  }
459  indx++;
460  }
461 
462 
463 }
464 
465 
466 //merging connectivities
467 void
468 LinearSystemMerger::set_merged_crconnectivity()
469 {
470  //mergin sites
471  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
472  foreach( MultiField::ArrayIndex k, arrayIndices ){
473  const StorageSite& cell_site = *k.second;
474  _siteMerger = shared_ptr< StorageSiteMerger > ( new StorageSiteMerger( _targetID, _group, cell_site) );
475  }
476 
477  //sev
478  _site = _siteMerger->merge();
479  update_gatherCells_from_scatterCells();
480 
481  _mergeCR = shared_ptr< CRConnectivity > ( new CRConnectivity(*_site, *_site) );
482  //initCount
483  _mergeCR->initCount();
484 
485  //addcount
486  int indx = 0;
487  foreach ( set<int>::value_type proc, _group ){
488  const Array<int>& row = *_row[proc];
489  const Array<int>& col = *(_col[proc]);
490  const map<int,int>& gatherIDsLocalToGlobal = _gatherIDsLocalToGlobalMap[proc];
491 
492  int ghost_endID = row.getLength()-1;
493  int ghost_startID = ghost_endID - int( gatherIDsLocalToGlobal.size() );
494  int selfCount = (*_selfCounts)[proc];
495 
496  //loop over row
497  for ( int i = 0; i < selfCount; i++ ){
498  int count = row[i+1] - row[i];
499 // _mergeCR->addCount(indx++,count);
500  for ( int j = 0; j < count; j++){
501  int localID = col[ row[i]+j ]; //get surrounding local cellID
502  //excluding boundary conditions
503  if ( !(localID >= selfCount && localID < ghost_startID) )
504  _mergeCR->addCount( indx, 1 );
505  }
506  indx++;
507  }
508  }
509 
510  //finish count
511  _mergeCR->finishCount();
512 
513  //add
514  indx = 0;
515  foreach ( set<int>::value_type proc, _group ){
516  const Array<int>& row = *(_row[proc]);
517  const Array<int>& col = *(_col[proc]);
518  const Array<int>& localToGlobal = *_localToGlobal[proc];
519  const map<int,int>& gatherIDsLocalToGlobal = _gatherIDsLocalToGlobalMap[proc];
520 
521  int ghost_endID = row.getLength()-1;
522  int ghost_startID = ghost_endID - int( gatherIDsLocalToGlobal.size() );
523  int selfCount = (*_selfCounts)[proc];
524 
525  //loop over row
526  for ( int i = 0; i < selfCount; i++ ){
527  int count = row[i+1] - row[i];
528  //loop over surrounding cells
529  for ( int j = 0; j < count; j++ ){
530  int localID = col[ row[i]+j ]; //get surrounding local cellID
531  int globalID = -1;
532  //ghost cell check if inner cells or ghost cells
533  if ( localID < selfCount ){
534  globalID = localToGlobal[ localID ];
535  } else {
536  globalID = gatherIDsLocalToGlobal.find(localID)->second;
537  }
538 
539  //excluding boundary conditions
540  if ( !(localID >= selfCount && localID < ghost_startID) )
541  _mergeCR->add( indx, globalID );
542  }
543  indx++;
544  }
545  }
546  //finish add
547  _mergeCR->finishAdd();
548 
549  //update ghost cells as globalID
550  // update_col();
551 
552 // const Array<int>& col = _mergeCR->getCol();
553 // cout << "llllllllllllllllllllllllllllllllllllllllcol = " << col.getLength() << endl;
554 /* _mergeColPos = ArrayIntPtr( new Array<int> ( col.getLength() ) );
555  //store col position for given id
556  for ( int i = 0; i < col.getLength(); i++ ){
557  int id = col[i];
558  (*_mergeColPos)[id] = i;
559  }*/
560 }
561 
562 
563 void
564 LinearSystemMerger::update_gatherCells_from_scatterCells()
565 {
566  //get scatter cells from neighbouring mesh and update the current mesh gather cells
567  //loop over meshes
568 
569  foreach ( set<int>::value_type proc, _group ){
570  const Array<int>& gatherInterfaceIDs = *_gatherInterfaceIDs[proc];
571  //const Array<int>& scatterInterfaceIDs = *_scatterInterfaceIDs[proc];
572  //loop over interfaces on this mesh
573  for ( int n = 0; n < gatherInterfaceIDs.getLength(); n++ ){
574  int neighMeshID = gatherInterfaceIDs[n];
575  const Array<int>& gatherCells = *_gatherCells [proc][neighMeshID];
576  const Array<int>& scatterCells = *_scatterCells[neighMeshID][proc];
577  //update gatherCells
578  for ( int i = 0; i < gatherCells.getLength(); i++ ){
579  int cellID = (*_localToGlobal[neighMeshID])[ scatterCells[i] ]; //get global numbering of scatter cells on other mesh
580  int gatherID = gatherCells[i];
581  _gatherIDsLocalToGlobalMap[proc][ gatherID ] = cellID;
582  //gatherCells[i] = cellID;
583  }
584  }
585  }
586 
587 
588 
589 
590 }
591 
592 //update col
593 void
594 LinearSystemMerger::update_col()
595 {
596  //update _col for gather Cells
597  foreach( set<int>::value_type proc_id, _group ){
598  Array<int>& col = *_col[proc_id];
599  const Array<int>& row = *_row[proc_id];
600  const map<int,int>& gatherIDsLocalToGLobal = _gatherIDsLocalToGlobalMap[proc_id];
601 
602  int ghost_endID = row.getLength()-1;
603  int ghost_startID = ghost_endID - int( gatherIDsLocalToGLobal.size() );
604  int selfCount = (*_selfCounts)[proc_id];
605 
606  for ( int i = 0; i < col.getLength(); i++ ){
607  //check if it is ghost cells
608  if ( col[i] >= ghost_startID && col[i] <= ghost_endID )
609  col[i] = gatherIDsLocalToGLobal.find( col[i] )->second;
610 
611  //mark boundary as -1
612  if( col[i] >= selfCount && col[i] < ghost_startID ){
613  col[i] = -1;
614  }
615  }
616 
617 
618  }
619 
620 }
621 
622 //merging x, b, residual from coarse linear systems
623 void
624 LinearSystemMerger::set_ls_vectors()
625 {
626  _mergeLS->_b = shared_ptr<MultiField> ( new MultiField() );
627 
628  const MultiField& delta = _ls.getDelta();
629  const MultiField::ArrayIndexList& arrayIndices = delta.getArrayIndices();
630  foreach ( const MultiField::ArrayIndex& ai, arrayIndices){
631  const StorageSite& mergeSite = *_site;
632  MultiField::ArrayIndex mergeIndex( ai.first, &mergeSite );
633  //cout << " _procIDDDD= " << _procID << " mergeSite.getCount() = " << mergeSite.getCount() << endl;
634  _mergeLS->_b->addArray( mergeIndex, delta[ai].newSizedClone( mergeSite.getCount()) );
635 /*
636  const Array<double> & xarray = dynamic_cast< const Array<double> & > ( delta[ai] );
637  cout << " procid = " << _procID << " xarray.getLength() = " << xarray.getLength() << endl;
638  for ( int i = 0; i < xarray.getLength(); i++ )
639  cout << " xarray[" << i << "] = " << xarray[i] << endl;*/
640 
641  }
642 
643  _mergeLS->_b->zero();
644  _mergeLS->_delta = dynamic_pointer_cast<MultiField> ( _mergeLS->_b->newClone() );
645  _mergeLS->_delta->zero();
646  _mergeLS->_residual = dynamic_pointer_cast<MultiField> ( _mergeLS->_b->newClone() );
647  _mergeLS->_residual->zero();
648 
649  //_mergeLS->initAssembly();
650  //_mergeLS->getMatrix().initAssembly();
651 
652 }
653 
654 //constructing mergin matrix
655 void
656 LinearSystemMerger::gatherMatrix()
657 {
658 
659  //getting diag and off diag size (in BYTE )
660  Array<int> sizeDiag ( _totalProcs );
661  Array<int> sizeOffDiag( _totalProcs );
662  sizeDiag.zero();
663  sizeOffDiag.zero();
664  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
665  foreach( MultiField::ArrayIndex k, arrayIndices ){
666  int send_buffer = _ls.getMatrix().getMatrix(k,k).getDiagDataSize();
667  _comm.Gather( &send_buffer , 1, MPI::INT, sizeDiag.getData(), 1, MPI::INT, _targetID );
668  send_buffer = _ls.getMatrix().getMatrix(k,k).getOffDiagDataSize();
669  _comm.Gather( &send_buffer , 1, MPI::INT, sizeOffDiag.getData(), 1, MPI::INT, _targetID );
670  }
671 
672  //estimate size for diag and offdiag arrays for gathering
673  int size_diag = 0;
674  int size_offdiag = 0;
675  foreach ( set<int>::value_type proc, _group ){
676  sizeDiag[proc] = sizeDiag[proc] / sizeof( double );
677  sizeOffDiag[proc] = sizeOffDiag[proc] / sizeof( double );
678  size_diag += sizeDiag[proc];
679  size_offdiag += sizeOffDiag[proc];
680  }
681 
682  //
683  int displs_diag[ _totalProcs ];
684  int displs_offdiag[ _totalProcs ];
685  displs_diag[0] = 0;
686  displs_offdiag[0] = 0;
687  for ( int i = 1; i < _totalProcs; i++ ){
688  displs_diag[i] = displs_diag[i-1] + sizeDiag[i-1];
689  displs_offdiag[i] = displs_offdiag[i-1] + sizeOffDiag[i-1];
690  }
691 
692 
693  //allocating space for diag and offdiag
694  ArrayDblePtr diag ( new Array<double> ( size_diag ) );
695  ArrayDblePtr offdiag( new Array<double> ( size_offdiag ) );
696 // cout << " procIDdDDDDDDDDDDDDD = " << _procID << " size_diag = " << size_diag << " size_offdiag = " << size_offdiag << endl;
697 // if ( _procID == _targetID )
698 // for ( int n = 0; n < _totalProcs; n++ )
699 // cout << " sizeDiag[" << n << "] = " << sizeDiag[n] << " sizeOffDiag[" << n << "] = " << sizeOffDiag[n] << endl;
700 //
701 
702 
703  //gathering diag and offdiag
704  foreach( MultiField::ArrayIndex k, arrayIndices ){
705 
706 
707 // //assigning fake value before shipping
708 // double *diagPtr = reinterpret_cast < double* > (_ls.getMatrix().getMatrix(k,k).getDiagData() );
709 // int diag_cnt = _ls.getMatrix().getMatrix(k,k).getDiagDataSize() / sizeof( double );
710 // int off_cnt = _ls.getMatrix().getMatrix(k,k).getOffDiagDataSize() / sizeof( double );
711 // for ( int i = 0; i < diag_cnt; i++)
712 // *(diagPtr+i) = double(_procID * 100 + i);
713 //
714 // double *offDiagPtr = reinterpret_cast < double* > (_ls.getMatrix().getMatrix(k,k).getOffDiagData() );
715 // for ( int i = 0; i < off_cnt; i++)
716 // *(offDiagPtr+i) = double(_procID * 100 + i);
717 
718 
719  int send_cnts_diag = _ls.getMatrix().getMatrix(k,k).getDiagDataSize();
720  _comm.Gatherv( _ls.getMatrix().getMatrix(k,k).getDiagData(), send_cnts_diag, MPI::BYTE, diag->getData(), &sizeDiag[0], displs_diag, MPI::DOUBLE, _targetID );
721  int send_cnts_offdiag = _ls.getMatrix().getMatrix(k,k).getOffDiagDataSize();
722  _comm.Gatherv( _ls.getMatrix().getMatrix(k,k).getOffDiagData(), send_cnts_offdiag, MPI::BYTE, offdiag->getData(), &sizeOffDiag[0], displs_offdiag, MPI::DOUBLE, _targetID );
723  }
724 
725  //fill diag
726  int indx = 0;
727  foreach ( const set<int>::value_type proc_id, _group){
728  _diag[proc_id] = ArrayDblePtr( new Array<double> ( sizeDiag[proc_id] ) );
729  Array<double>& diagonal = *_diag[proc_id];
730  //fill data
731  for ( int i = 0; i < sizeDiag[proc_id]; i++ ){
732  diagonal[i] = (*diag)[indx];
733  indx++;
734  }
735  }
736  //fill off diaogonal
737  indx = 0;
738  foreach ( const set<int>::value_type proc_id, _group){
739  _offDiag[proc_id] = ArrayDblePtr( new Array<double> ( sizeOffDiag[proc_id] ) );
740  Array<double>& offDiagonal = *_offDiag[proc_id];
741  //fill data
742  for ( int i = 0; i < sizeOffDiag[proc_id]; i++ ){
743  offDiagonal[i] = (*offdiag)[indx];
744  indx++;
745  }
746  }
747 
748 
749 
750  int i = 0;
751  MultiField& mergeMultiField = _mergeLS->getDelta();
752  foreach( MultiField::ArrayIndex k, arrayIndices ){
753  const MultiField::ArrayIndex& mergeIndex = mergeMultiField.getArrayIndex(i++);
754  Matrix& mIJ = _ls.getMatrix().getMatrix( k, k );
755  _mergeLS->getMatrix().addMatrix( mergeIndex, mergeIndex , mIJ.createMergeMatrix( *this) );
756  }
757 
758 
759 }
760 
761 
762 
763 
764 
765 void
766 LinearSystemMerger::gatherB()
767 {
768 
769  int displs[ _totalProcs ];
770  displs[0] = 0;
771  for ( int i = 1; i < _totalProcs; i++ ){
772  displs[i] = displs[i-1] + (*_selfCounts)[i-1];
773  }
774 
775  //getting delta
776  int i = 0;
777  const MultiField::ArrayIndexList& arrayIndices = _ls.getB().getArrayIndices();
778  const MultiField& multiField = _ls.getB();
779  MultiField& mergeMultiField = _mergeLS->getB();
780  _mergeLS->getDelta().zero();
781  foreach( MultiField::ArrayIndex k, arrayIndices ){
782  const StorageSite& site = *k.second;
783  int send_cnts = site.getSelfCount();
784  const ArrayBase& B = multiField[k];
785 /* Array<double>& deltaDouble = dynamic_cast< Array<double>& > ( delta );
786  for ( int indx = 0; indx < deltaDouble.getLength(); indx++ ){
787  deltaDouble[indx] = double(_procID) * double(100) + double(indx) ;
788  cout << "proc_id = " << _procID << " delta(" << indx << ") = " << deltaDouble[indx] << endl;
789  }*/
790  const MultiField::ArrayIndex& mergerIndex = mergeMultiField.getArrayIndex(i++);
791  ArrayBase& mergeB = mergeMultiField[mergerIndex];
792  _comm.Gatherv( B.getData(), send_cnts, MPI::DOUBLE, mergeB.getData(), &(*_selfCounts)[0], displs, MPI::DOUBLE, _targetID );
793 
794  }
795 
796 
797 }
798 
799 void
800 LinearSystemMerger::scatterDelta()
801 {
802  MPI::COMM_WORLD.Barrier();
803  int displs[ _totalProcs ];
804  displs[0] = 0;
805  for ( int i = 1; i < _totalProcs; i++ )
806  displs[i] = displs[i-1] + (*_selfCounts)[i-1];
807 
808  int i = 0;
809  MultiField& multiField = _ls.getDelta();
810  const MultiField::ArrayIndexList& arrayIndices = _ls.getDelta().getArrayIndices();
811  foreach( MultiField::ArrayIndex k, arrayIndices ){
812  const StorageSite& site = *k.second;
813  int recv_cnts = site.getSelfCount();
814  ArrayBase& delta = multiField[k];
815 
816  const MultiField& mergeMultiField = _mergeLS->getDelta();
817  const MultiField::ArrayIndex& mergerIndex = mergeMultiField.getArrayIndex(i++);
818  const ArrayBase& mergeDelta = mergeMultiField[mergerIndex];
819  _comm.Scatterv( mergeDelta.getData(), &(*_selfCounts)[0], displs, MPI::DOUBLE, delta.getData(), recv_cnts, MPI::DOUBLE, _targetID );
820 
821  }
822 
823 
824 // MPI::COMM_WORLD.Barrier();
825 // cout << " _totalScatterCellss = " << _totalScatterCells << " procid = " << _procID << endl;
826 // MPI::COMM_WORLD.Barrier();
827 //
828 // debug_print();
829 
830 }
831 
832 
833 void
834 LinearSystemMerger::debug_print()
835 {
836 
837  if ( _procID == _targetID ){
838  stringstream ss;
839  ss << "proc" << MPI::COMM_WORLD.Get_rank() << "_linear_system_merger.dat";
840  ofstream debug_file( (ss.str()).c_str() );
841 
842 
843  //neighbourhd mesh counts
844  for ( int n = 0; n < _totalProcs; n++ )
845  debug_file << " _neighMeshCounts[" << n << "] = " << (*_neighMeshCounts)[n] << endl;
846  debug_file << endl;
847 
848  //scatter size for each mesh
849  for ( int n = 0; n < _totalProcs; n++ )
850  debug_file << " _scatterSize[" << n << "] = " << (*_scatterSize)[n] << endl;
851  debug_file << endl;
852 
853  //gather size for each mesh
854  for ( int n = 0; n < _totalProcs; n++ )
855  debug_file << " _gatherSize[" << n << "] = " << (*_gatherSize)[n] << endl;
856  debug_file << endl;
857 
858  //total interfaces
859  debug_file << " _totalInterfaces = " << _totalInterfaces << endl;
860  debug_file << endl;
861 
862  //total scatter cells
863  debug_file << " _totalScatterCells = " << _totalScatterCells << endl;
864  debug_file << endl;
865 
866  //total gather cells
867  debug_file << " _totalGatherCells = " << _totalGatherCells << endl;
868  debug_file << endl;
869 
870 
871  //scatter and gather counts for each process
872  foreach ( set<int>::value_type proc, _group ){
873  debug_file << "procID : " << proc << endl;
874  const Array<int>& scatter_counts = *_scatterInterfaceCounts[proc];
875  const Array<int>& gather_counts = *_gatherInterfaceCounts[proc];
876  for ( int n = 0; n < scatter_counts.getLength(); n++ )
877  debug_file << " scatter_counts[" << n << "] = " << scatter_counts[n] << endl;
878  debug_file << endl;
879 
880  for ( int n = 0; n < gather_counts.getLength(); n++ )
881  debug_file << " gather_counts[" << n << "] = " << gather_counts[n] << endl;
882  debug_file << endl;
883  }
884 
885 
886  //scatter interface ids (neightbourhood mesh ids )
887  int indx = 0;
888  foreach ( set<int>::value_type proc, _group ){
889  debug_file << "procID : " << proc << endl;
890  const Array<int>& scatterInterfaceIDs = *_scatterInterfaceIDs[proc];
891  for ( int n = 0; n < scatterInterfaceIDs.getLength(); n++ )
892  debug_file << " scatterInterfaceIDs[" << n << "] = " << scatterInterfaceIDs[n] << endl;
893  debug_file << endl;
894 
895  }
896 
897  //scatter cells
898  foreach ( set<int>::value_type proc, _group ){
899  debug_file << "procID : " << proc << endl;
900  //loop over scatter segments
901  const map<int, ArrayIntPtr>& cell_map = _scatterCells[proc];
902  foreach ( const ArrayIntPtrMap::value_type& pos, cell_map ){
903  debug_file << " scatterID = " << pos.first << endl;
904  for ( int n = 0; n < pos.second->getLength(); n++ )
905  debug_file << " " << (*pos.second)[n] << endl;
906  debug_file << endl;
907  }
908  debug_file << endl;
909  }
910 
911  //gather interface ids (neightbourhood mesh ids )
912  indx = 0;
913  foreach ( set<int>::value_type proc, _group ){
914  debug_file << "procID : " << proc << endl;
915  const Array<int>& gatherInterfaceIDs = *_gatherInterfaceIDs[proc];
916  for ( int n = 0; n < gatherInterfaceIDs.getLength(); n++ )
917  debug_file << " gatherInterfaceIDs[" << n << "] = " << gatherInterfaceIDs[n] << endl;
918  debug_file << endl;
919  }
920 
921  //gather cells
922  foreach ( set<int>::value_type proc, _group ){
923  debug_file << "procID : " << proc << endl;
924  //loop over scatter segments
925  const map<int, ArrayIntPtr>& cell_map = _gatherCells[proc];
926  foreach ( const ArrayIntPtrMap::value_type& pos, cell_map ){
927  debug_file << " gatherID = " << pos.first << endl;
928  for ( int n = 0; n < pos.second->getLength(); n++ )
929  debug_file << " " << (*pos.second)[n] << endl;
930  debug_file << endl;
931  }
932  debug_file << endl;
933  }
934 
935  //rowLength
936  debug_file << " _rowLength : " << endl;
937  for ( int n = 0; n < _rowLength->getLength(); n++ )
938  debug_file << " _rowLength[ " << n << "] = " << (*_rowLength)[n] << endl;
939  debug_file << endl;
940  //colLength
941  debug_file << " _colLength : " << endl;
942  for ( int n = 0; n < _colLength->getLength(); n++ )
943  debug_file << " _colLength[ " << n << "] = " << (*_colLength)[n] << endl;
944  debug_file << endl;
945  //selfCounts
946  debug_file << " _selfCounts : " << endl;
947  for ( int n = 0; n < _selfCounts->getLength(); n++ )
948  debug_file << " _selfCounts[ " << n << "] = " << (*_selfCounts)[n] << endl;
949  debug_file << endl;
950 
951  //local CRConnectivity
952  foreach ( set<int>::value_type proc, _group ){
953  debug_file << "procID : " << proc << endl;
954  const Array<int>& row = *(_row[proc]);
955  const Array<int>& col = *(_col[proc]);
956  for ( int i = 0; i < row.getLength()-1; i++ ){
957  int col_dim = row[i+1] - row[i];
958  for ( int j = 0; j < col_dim; j++ ){
959  debug_file << " coarseCR(" << i << "," << j << ") = " << col[ row[i]+j ] << endl;
960  }
961  }
962  }
963  debug_file << endl;
964 
965  //maps between local to Global, global to local
966  indx = 0;
967  foreach ( set<int>::value_type proc, _group ){
968  debug_file << "procID: " << proc << endl;
969  for ( int n = 0; n < (*_selfCounts)[indx]; n++ )
970  debug_file << "localToGlobal[" << n << "] = " << (*_localToGlobal[proc])[n] << endl;
971  indx++;
972  }
973  debug_file << endl;
974 
975  //_globalToProc, _globalToLocal
976  for ( int n = 0; n < _totalCells; n++ )
977  debug_file << "_globalToLocal[" << n << "] = " << (*_globalToLocal)[n] << " resides at procID = " << (*_globalToProc)[n] << endl;
978  debug_file << endl;
979 
980  //gather cells
981  foreach ( set<int>::value_type proc, _group ){
982  debug_file << "procID (global numbering) : " << proc << endl;
983  //loop over scatter segments
984  const map<int, ArrayIntPtr>& cell_map = _gatherCells[proc];
985  foreach ( const ArrayIntPtrMap::value_type& pos, cell_map ){
986  debug_file << " gatherID = " << pos.first << endl;
987  for ( int n = 0; n < pos.second->getLength(); n++ )
988  debug_file << " " << (*pos.second)[n] << endl;
989  debug_file << endl;
990  }
991  debug_file << endl;
992  }
993  debug_file << endl;
994  //merge CRconnectivity
995  int row_dim = _mergeCR->getRowDim();
996  for ( int i = 0; i < row_dim; i++ ){
997  int col_dim = _mergeCR->getCount(i);
998  for ( int j = 0; j < col_dim; j++ ){
999  debug_file << " mergeCR(" << i << "," << j << ") = " << (*_mergeCR)(i,j) << endl;
1000  }
1001  }
1002  debug_file << endl;
1003 
1004 
1005 
1006  //mergeCol
1007  const Array<int>& mergeCol = _mergeCR->getCol();
1008  for ( int i = 0; i < mergeCol.getLength(); i++ )
1009  debug_file << " mergeCol(" << i << ") = " << mergeCol[i] << endl;
1010  debug_file << endl;
1011 
1012 // //mergeColPos
1013 // for ( int i = 0; i < _mergeColPos->getLength(); i++ )
1014 // debug_file << " mergeColPos(" << i << ") = " << (*_mergeColPos)[i] << endl;
1015 // debug_file << endl;
1016 
1017  //delta
1018  const MultiField::ArrayIndexList& arrayIndices = _mergeLS->getDelta().getArrayIndices();
1019  foreach( MultiField::ArrayIndex k, arrayIndices ){
1020  const MultiField& multiField = _mergeLS->getDelta();
1021  const Array<double>& delta = dynamic_cast< const Array<double>& > ( multiField[k] );
1022  for ( int i = 0; i < delta.getLength(); i++ )
1023  debug_file << " delta(" << i << ") = " << delta[i] << endl;
1024 
1025  }
1026 
1027  //matrix (diag)
1028  foreach ( set<int>::value_type proc, _group ){
1029  debug_file << "procID : " << proc << endl;
1030  const Array<double>& diag = *_diag[proc];
1031  for ( int n = 0; n < diag.getLength(); n++ )
1032  debug_file << " diag[" << n << "] = " << diag[n] << endl;
1033  debug_file << endl;
1034  }
1035 
1036  debug_file << endl;
1037  //matrix (diag)
1038  foreach ( set<int>::value_type proc, _group ){
1039  debug_file << "procID : " << proc << endl;
1040  const Array<double>& offDiag = *_offDiag[proc];
1041  for ( int n = 0; n < offDiag.getLength(); n++ )
1042  debug_file << " offDiag[" << n << "] = " << offDiag[n] << endl;
1043  debug_file << endl;
1044  }
1045 
1046 
1047 
1048 
1049  debug_file.close();
1050  }
1051 
1052 
1053 }
1054 
1055 #endif
const Array< int > & getCol() const
const Array< int > & getRow() const
int getSelfCount() const
Definition: StorageSite.h:40
virtual void zero()
Definition: MultiField.cpp:115
virtual void * getData() const
Definition: Array.h:275
pair< const Field *, const StorageSite * > ArrayIndex
Definition: MultiField.h:21
int getGatherProcID() const
Definition: StorageSite.h:83
vector< ArrayIndex > ArrayIndexList
Definition: MultiField.h:24
Definition: Matrix.h:16
const ScatterMap & getScatterMap() const
Definition: StorageSite.h:58
map< const StorageSite *, shared_ptr< Array< int > > > ScatterMap
Definition: StorageSite.h:23
const GatherMap & getGatherMap() const
Definition: StorageSite.h:59
const ArrayIndexList & getArrayIndices() const
Definition: MultiField.h:68
virtual void * getData() const =0
int getCount() const
Definition: StorageSite.h:39
map< const StorageSite *, shared_ptr< Array< int > > > GatherMap
Definition: StorageSite.h:24
virtual shared_ptr< Matrix > createMergeMatrix(const LinearSystemMerger &mergeLS)
Definition: Matrix.h:57
const StorageSite & getRowSite() const
const ArrayIndex getArrayIndex(const int i) const
Definition: MultiField.h:55
int getLength() const
Definition: Array.h:87