1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 cfMesh is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "VRWGraphSMPModifier.H"
27 #include "labelPair.H"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 template<class ListType>
41 void VRWGraphSMPModifier::setSizeAndRowSize(const ListType& s)
43 graph_.rows_.setSize(s.size());
46 label nThreads = 3 * omp_get_num_procs();
50 const label nThreads(1);
54 DynList<label> procEntries;
55 procEntries.setSize(nThreads);
58 # pragma omp parallel num_threads(nThreads)
62 label& nLocalEntries = procEntries[omp_get_thread_num()];
64 label& nLocalEntries = procEntries[0];
69 # pragma omp for schedule(static)
72 nLocalEntries += s[i];
77 nEntries += nLocalEntries;
85 graph_.data_.setSize(nEntries);
94 for(label i=0;i<omp_get_thread_num();++i)
95 start += procEntries[i];
99 # pragma omp for schedule(static)
103 graph_.rows_[i].start() = start;
104 graph_.rows_[i].size() = s[i];
110 template<class GraphType>
111 void VRWGraphSMPModifier::reverseAddressing(const GraphType& origGraph)
114 labelLongList nAppearances;
117 label nThreads = 3 * omp_get_num_procs();
118 if( origGraph.size() < 1000 )
121 const label nThreads(1);
124 label minRow(INT_MAX), maxRow(-1);
125 List<List<LongList<labelPair> > > dataForOtherThreads(nThreads);
128 # pragma omp parallel num_threads(nThreads)
132 const label threadI = omp_get_thread_num();
134 const label threadI(0);
137 List<LongList<labelPair> >& dot = dataForOtherThreads[threadI];
138 dot.setSize(nThreads);
140 //- find min and max entry in the graph
141 //- they are used for assigning ranges of values local for each process
142 label localMinRow(INT_MAX), localMaxRow(-1);
144 # pragma omp for schedule(static)
146 forAll(origGraph, rowI)
148 forAll(origGraph[rowI], i)
150 const label entryI = origGraph[rowI][i];
151 localMaxRow = Foam::max(localMaxRow, entryI);
152 localMinRow = Foam::min(localMinRow, entryI);
159 # pragma omp critical
162 minRow = Foam::min(minRow, localMinRow);
163 maxRow = Foam::max(maxRow, localMaxRow);
165 nAppearances.setSize(maxRow);
171 //- initialise appearances
172 # pragma omp for schedule(static)
174 for(label i=0;i<maxRow;++i)
181 const label range = (maxRow - minRow) / nThreads + 1;
182 const label localMin = minRow + threadI * range;
183 const label localMax = Foam::min(localMin + range, maxRow);
185 //- find the number of appearances of each element in the original graph
187 # pragma omp for schedule(static)
189 forAll(origGraph, rowI)
191 forAll(origGraph[rowI], j)
193 const label entryI = origGraph[rowI][j];
195 const label threadNo = (entryI - minRow) / range;
197 if( threadNo == threadI )
199 ++nAppearances[entryI];
203 dot[threadNo].append(labelPair(entryI, rowI));
212 //- count the appearances which are not local to the processor
213 for(label i=0;i<nThreads;++i)
215 const LongList<labelPair>& data =
216 dataForOtherThreads[i][threadI];
219 ++nAppearances[data[j].first()];
228 setSizeAndRowSize(nAppearances);
234 for(label i=localMin;i<localMax;++i)
239 //- start filling reverse addressing graph
240 //- update data from processors with smaller labels
241 for(label i=0;i<threadI;++i)
243 const LongList<labelPair>& data =
244 dataForOtherThreads[i][threadI];
248 const label entryI = data[j].first();
249 graph_(entryI, nAppearances[entryI]++) = data[j].second();
253 //- update data local to the processor
255 # pragma omp for schedule(static)
257 forAll(origGraph, rowI)
259 forAll(origGraph[rowI], j)
261 const label entryI = origGraph[rowI][j];
263 if( (entryI >= localMin) && (entryI < localMax) )
264 graph_(entryI, nAppearances[entryI]++) = rowI;
268 //- update data from the processors with higher labels
269 for(label i=threadI+1;i<nThreads;++i)
271 const LongList<labelPair>& data =
272 dataForOtherThreads[i][threadI];
276 const label entryI = data[j].first();
277 graph_(entryI, nAppearances[entryI]++) = data[j].second();
283 template<class ListType, class GraphType>
284 void VRWGraphSMPModifier::reverseAddressing
286 const ListType& mapper,
287 const GraphType& origGraph
290 ListType nAppearances;
293 label nThreads = 3 * omp_get_num_procs();
294 if( origGraph.size() < 1000 )
297 const label nThreads(1);
300 label minRow(INT_MAX), maxRow(-1);
301 List<List<LongList<labelPair> > > dataForOtherThreads(nThreads);
304 # pragma omp parallel num_threads(nThreads)
308 const label threadI = omp_get_thread_num();
310 const label threadI(0);
313 List<LongList<labelPair> >& dot = dataForOtherThreads[threadI];
314 dot.setSize(nThreads);
316 //- find min and max entry in the graph
317 //- they are used for assigning ranges of values local for each process
318 label localMinRow(INT_MAX), localMaxRow(-1);
320 # pragma omp for schedule(static)
322 forAll(origGraph, rowI)
324 forAll(origGraph[rowI], i)
326 const label entryI = mapper[origGraph[rowI][i]];
327 localMaxRow = Foam::max(localMaxRow, entryI);
328 localMinRow = Foam::min(localMinRow, entryI);
335 # pragma omp critical
338 minRow = Foam::min(minRow, localMinRow);
339 maxRow = Foam::max(maxRow, localMaxRow);
340 nAppearances.setSize(maxRow);
346 //- initialise appearances
347 # pragma omp for schedule(static)
349 for(label i=0;i<maxRow;++i)
356 const label range = (maxRow - minRow) / nThreads + 1;
357 const label localMin = minRow + threadI * range;
358 const label localMax = Foam::min(localMin + range, maxRow);
360 //- find the number of appearances of each element in the original graph
362 # pragma omp for schedule(static)
364 forAll(origGraph, rowI)
366 forAll(origGraph[rowI], i)
368 const label entryI = mapper[origGraph[rowI][i]];
370 const label threadNo = (entryI - minRow) / range;
372 if( threadNo == threadI )
374 ++nAppearances[entryI];
378 dot[threadNo].append(labelPair(entryI, rowI));
387 //- count the appearances which are not local to the processor
388 for(label i=0;i<nThreads;++i)
390 const LongList<labelPair>& data =
391 dataForOtherThreads[i][threadI];
394 ++nAppearances[data[j].first()];
404 setSizeAndRowSize(nAppearances);
411 for(label i=localMin;i<localMax;++i)
416 //- start filling reverse addressing graph
417 //- update data from processors with smaller labels
418 for(label i=0;i<threadI;++i)
420 const LongList<labelPair>& data =
421 dataForOtherThreads[i][threadI];
425 const label entryI = data[j].first();
426 graph_(entryI, nAppearances[entryI]++) = data[j].second();
430 //- update data local to the processor
432 # pragma omp for schedule(static)
434 forAll(origGraph, rowI)
436 forAll(origGraph[rowI], j)
438 const label entryI = mapper[origGraph[rowI][j]];
440 if( (entryI >= localMin) && (entryI < localMax) )
441 graph_(entryI, nAppearances[entryI]++) = rowI;
445 //- update data from the processors with higher labels
446 for(label i=threadI+1;i<nThreads;++i)
448 const LongList<labelPair>& data =
449 dataForOtherThreads[i][threadI];
453 const label entryI = data[j].first();
454 graph_(entryI, nAppearances[entryI]++) = data[j].second();
460 template<class ListType>
461 void VRWGraphSMPModifier::reverseAddressing
463 const ListType& mapper,
464 const VRWGraph& origGraph
467 ListType nAppearances;
470 label nThreads = 3 * omp_get_num_procs();
471 if( origGraph.size() < 1000 )
474 const label nThreads(1);
477 label minRow(INT_MAX), maxRow(-1);
478 List<List<LongList<labelPair> > > dataForOtherThreads(nThreads);
481 # pragma omp parallel num_threads(nThreads)
485 const label threadI = omp_get_thread_num();
487 const label threadI(0);
490 List<LongList<labelPair> >& dot = dataForOtherThreads[threadI];
491 dot.setSize(nThreads);
493 //- find min and max entry in the graph
494 //- they are used for assigning ranges of values local for each process
495 label localMinRow(INT_MAX), localMaxRow(-1);
497 # pragma omp for schedule(static)
499 forAll(origGraph, rowI)
501 forAllRow(origGraph, rowI, i)
503 const label entryI = mapper[origGraph(rowI, i)];
504 localMaxRow = Foam::max(localMaxRow, entryI);
505 localMinRow = Foam::min(localMinRow, entryI);
512 # pragma omp critical
515 minRow = Foam::min(minRow, localMinRow);
516 maxRow = Foam::max(maxRow, localMaxRow);
517 nAppearances.setSize(maxRow);
523 //- initialise appearances
524 # pragma omp for schedule(static)
526 for(label i=0;i<maxRow;++i)
533 const label range = (maxRow - minRow) / nThreads + 1;
534 const label localMin = minRow + threadI * range;
535 const label localMax = Foam::min(localMin + range, maxRow);
537 //- find the number of appearances of each element in the original graph
539 # pragma omp for schedule(static)
541 forAll(origGraph, rowI)
543 forAllRow(origGraph, rowI, i)
545 const label entryI = mapper[origGraph(rowI, i)];
547 const label threadNo = (entryI - minRow) / range;
549 if( threadNo == threadI )
551 ++nAppearances[entryI];
555 dot[threadNo].append(labelPair(entryI, rowI));
564 //- count the appearances which are not local to the processor
565 for(label i=0;i<nThreads;++i)
567 const LongList<labelPair>& data =
568 dataForOtherThreads[i][threadI];
571 ++nAppearances[data[j].first()];
581 setSizeAndRowSize(nAppearances);
587 for(label i=localMin;i<localMax;++i)
590 //- start filling reverse addressing graph
591 //- update data from processors with smaller labels
592 for(label i=0;i<threadI;++i)
594 const LongList<labelPair>& data =
595 dataForOtherThreads[i][threadI];
599 const label entryI = data[j].first();
600 graph_(entryI, nAppearances[entryI]++) = data[j].second();
604 //- update data local to the processor
606 # pragma omp for schedule(static)
608 forAll(origGraph, rowI)
610 forAllRow(origGraph, rowI, j)
612 const label entryI = mapper[origGraph(rowI, j)];
614 if( (entryI >= localMin) && (entryI < localMax) )
615 graph_(entryI, nAppearances[entryI]++) = rowI;
619 //- update data from the processors with higher labels
620 for(label i=threadI+1;i<nThreads;++i)
622 const LongList<labelPair>& data =
623 dataForOtherThreads[i][threadI];
627 const label entryI = data[j].first();
628 graph_(entryI, nAppearances[entryI]++) = data[j].second();
634 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
636 } // End namespace Foam
638 // ************************************************************************* //