diff --git a/applications/solvers/multiphase/lesInterFoam/lesInterFoam.C b/applications/solvers/multiphase/lesInterFoam/lesInterFoam.C index 264eb28dea..8d109f03b3 100644 --- a/applications/solvers/multiphase/lesInterFoam/lesInterFoam.C +++ b/applications/solvers/multiphase/lesInterFoam/lesInterFoam.C @@ -85,6 +85,8 @@ int main(int argc, char *argv[]) #include "continuityErrs.H" + p = pd + rho*gh; + runTime.write(); Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" diff --git a/applications/utilities/mesh/advanced/refineWallLayer/refineWallLayer.C b/applications/utilities/mesh/advanced/refineWallLayer/refineWallLayer.C index 61a2f4d854..f4336bce92 100644 --- a/applications/utilities/mesh/advanced/refineWallLayer/refineWallLayer.C +++ b/applications/utilities/mesh/advanced/refineWallLayer/refineWallLayer.C @@ -184,10 +184,6 @@ int main(int argc, char *argv[]) << endl; // Transfer DynamicLists to straight ones. - labelList cutEdges; - cutEdges.transfer(allCutEdges); - allCutEdges.clear(); - scalarField cutEdgeWeights; cutEdgeWeights.transfer(allCutEdgeWeights); allCutEdgeWeights.clear(); @@ -199,7 +195,7 @@ int main(int argc, char *argv[]) mesh, cutCells.toc(), // cells candidate for cutting labelList(0), // cut vertices - cutEdges, // cut edges + allCutEdges, // cut edges cutEdgeWeights // weight on cut edges ); diff --git a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C index 4737f38e53..edcfbf2aee 100644 --- a/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C +++ b/applications/utilities/mesh/generation/snappyHexMesh/snappyHexMesh.C @@ -433,7 +433,7 @@ int main(int argc, char *argv[]) Info<< "Finished meshing in = " << runTime.elapsedCpuTime() << " s." << endl; - Pout<< "End\n" << endl; + Info<< "End\n" << endl; return(0); } diff --git a/applications/utilities/parallelProcessing/decomposePar/decomposeMesh.C b/applications/utilities/parallelProcessing/decomposePar/decomposeMesh.C index 0d81b1aedd..55f5c96579 100644 --- a/applications/utilities/parallelProcessing/decomposePar/decomposeMesh.C +++ b/applications/utilities/parallelProcessing/decomposePar/decomposeMesh.C @@ -35,11 +35,8 @@ Description #include "IOstreams.H" #include "SLPtrList.H" #include "boolList.H" -#include "cellList.H" #include "primitiveMesh.H" -#include "cyclicFvPatch.H" -#include "fvPatchList.H" -#include "DynamicList.H" +#include "cyclicPolyPatch.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // diff --git a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C index bee2d17b25..dd107c2f2f 100644 --- a/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C +++ b/applications/utilities/parallelProcessing/decomposePar/domainDecomposition.C @@ -33,7 +33,7 @@ License #include "OSspecific.H" #include "Map.H" #include "globalMeshData.H" - +#include "DynamicList.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // diff --git a/applications/utilities/postProcessing/dataConversion/foamToFieldview9/foamToFieldview9.C b/applications/utilities/postProcessing/dataConversion/foamToFieldview9/foamToFieldview9.C index 3030a30316..7cf137cd0e 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToFieldview9/foamToFieldview9.C +++ b/applications/utilities/postProcessing/dataConversion/foamToFieldview9/foamToFieldview9.C @@ -45,7 +45,6 @@ Description #include "IOobjectList.H" #include "boolList.H" #include "stringList.H" -#include "DynamicList.H" #include "cellModeller.H" #include "floatScalar.H" diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/internalWriter.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/internalWriter.C index bf1fb3b775..1ac0d8b729 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/internalWriter.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/internalWriter.C @@ -27,9 +27,6 @@ License #include "internalWriter.H" #include "writeFuns.H" -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Construct from components diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/lagrangianWriter.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/lagrangianWriter.C index bbf24b1b17..ea7da50a40 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/lagrangianWriter.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/lagrangianWriter.C @@ -29,9 +29,6 @@ License #include "Cloud.H" #include "passiveParticle.H" -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Construct from components diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/writePatchGeom.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/writePatchGeom.C index 62b8661810..6ad993e0aa 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/writePatchGeom.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/writePatchGeom.C @@ -78,6 +78,7 @@ void writePatchGeom writeFuns::write(pStream, binary, vertLabels); } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/writePointSet.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/writePointSet.C index ea7dbf4301..9e495e073d 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/writePointSet.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/writePointSet.C @@ -103,6 +103,7 @@ void writePointSet writeFuns::write(pStream, binary, pointIDs); } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.C b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.C index 8297002b82..24d1edea53 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.C +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.C @@ -33,7 +33,7 @@ template Foam::DynamicList::DynamicList(Istream& is) : List(is), - nextFree_(List::size()) + allocSize_(List::size()) {} @@ -44,9 +44,6 @@ Foam::Ostream& Foam::operator<< const Foam::DynamicList& DL ) { - const_cast&>(DL) - .setSize(DL.nextFree_); - os << static_cast&>(DL); return os; } @@ -60,7 +57,7 @@ Foam::Istream& Foam::operator>> ) { is >> static_cast&>(DL); - DL.nextFree_ = DL.List::size(); + DL.allocSize_ = DL.List::size(); return is; } diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H index a98be44fef..684d393745 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicList.H @@ -81,24 +81,29 @@ class DynamicList { // Private data - //- Number of next free element - label nextFree_; + //- Allocated size for underlying List. + label allocSize_; public: + // Related types + + //- Declare friendship with the List class + friend class List; + // Constructors //- Construct null inline DynamicList(); - //- Construct given size + //- Construct given size. explicit inline DynamicList(const label); - //- Construct from UList. nextFree_ set to size(). + //- Construct from UList. Size set to UList size. explicit inline DynamicList(const UList&); - //- Construct from Istream. nextFree_ set to size(). + //- Construct from Istream. Size set to size of read list. explicit DynamicList(Istream&); @@ -106,22 +111,24 @@ public: // Access - //- Size of the active part of the list. - // Direct over-ride of list size member function - inline label size() const; + //- Size of the underlying storage. + inline label allocSize() const; // Edit //- Reset size of List. - void setSize(const label); + inline void setSize(const label); //- Reset size of List and value for new elements. - void setSize(const label, const T&); + inline void setSize(const label, const T&); - //- Clear the list, i.e. set next free to zero. + //- Clear the list, i.e. set the size to zero. // Allocated size does not change - void clear(); + inline void clear(); + + //- Clear the list and delete storage. + inline void clearStorage(); //- Shrink the List to the number of elements used inline DynamicList& shrink(); @@ -130,11 +137,11 @@ public: // and annull the argument list. Is same as List::transfer except // checks that you're not changing the underlying list to something // smaller than nextFree_. - void transfer(List&); + inline void transfer(List&); //- Transfer the contents of the argument DynamicList into this // DynamicList and annull the argument list. - void transfer(DynamicList&); + inline void transfer(DynamicList&); // Member Operators @@ -152,9 +159,15 @@ public: //- Assignment of all entries to the given value inline void operator=(const T&); - //- Assignment to List + //- Assignment from List inline void operator=(const List&); + //- Assignment from DynamicList + inline void operator= + ( + const DynamicList& + ); + // IOstream operators diff --git a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H index 8d451ccd7a..d9a14a1111 100644 --- a/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H +++ b/src/OpenFOAM/containers/Lists/DynamicList/DynamicListI.H @@ -31,8 +31,10 @@ template inline Foam::DynamicList::DynamicList() : List(SizeInc), - nextFree_(0) -{} + allocSize_(SizeInc) +{ + List::size() = 0; +} //- Construct given size @@ -43,8 +45,10 @@ inline Foam::DynamicList::DynamicList ) : List(s), - nextFree_(0) -{} + allocSize_(s) +{ + List::size() = 0; +} //- Construct given size @@ -55,17 +59,17 @@ inline Foam::DynamicList::DynamicList ) : List(s), - nextFree_(s.size()) + allocSize_(s.size()) {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template -inline Foam::label Foam::DynamicList::size() +inline Foam::label Foam::DynamicList::allocSize() const { - return nextFree_; + return allocSize_; } @@ -75,13 +79,14 @@ inline void Foam::DynamicList::setSize const label s ) { - if (s < nextFree_) + if (s < List::size()) { - nextFree_ = s; + List::size() = s; } else { - List::setSize(s); + allocSize_ = s; + List::setSize(allocSize_); } } @@ -93,14 +98,14 @@ inline void Foam::DynamicList::setSize const T& t ) { - if (s < nextFree_) + if (s < List::size()) { - nextFree_ = s; + List::size() = s; } else { - List::setSize(s, t); - nextFree_ = s; + allocSize_ = s; + List::setSize(allocSize_, t); } } @@ -108,7 +113,16 @@ inline void Foam::DynamicList::setSize template inline void Foam::DynamicList::clear() { - nextFree_ = 0; + List::size() = 0; +} + + +template +inline void Foam::DynamicList::clearStorage() +{ + List::size() = allocSize_; // make List consistent + List::clear(); + allocSize_ = 0; } @@ -116,7 +130,8 @@ template inline Foam::DynamicList& Foam::DynamicList::shrink() { - List::setSize(nextFree_); + allocSize_ = List::size(); + List::setSize(allocSize_); return *this; } @@ -125,20 +140,20 @@ template inline void Foam::DynamicList::transfer(List& l) { - if (l.size() < nextFree_) + if (l.size() < List::size()) { FatalErrorIn ( "void DynamicList::transfer(List&)" ) << "Cannot replace the underlying storage of this DynamicList" - << " of which " << nextFree_ << " elements are used" << nl + << " of which " << List::size() << " elements are used" << nl << "with a List of size " << l.size() << abort(FatalError); } else { + allocSize_ = l.size(); List::transfer(l); // take over storage - l.clear(); // set nextFree of l to 0 } } @@ -150,40 +165,40 @@ Foam::DynamicList::transfer DynamicList& l ) { + allocSize_ = l.allocSize(); List::transfer(l); // take over storage - nextFree_ = l.size(); // take over used size - l.clear(); // set nextFree of l to 0 + l.allocSize_ = 0; } template -inline void Foam::DynamicList::append -( - const T& e -) +inline void Foam::DynamicList::append(const T& e) { - nextFree_++; + // Work on copy free index since gets overwritten by setSize + label nextFree = List::size(); - if (nextFree_ > List::size()) + nextFree++; + + if (nextFree > allocSize_) { - List::setSize + allocSize_ = max ( - max - ( - nextFree_, - label(SizeMult*List::size()/SizeDiv + SizeInc) - ) + nextFree, + label(SizeMult*allocSize_/SizeDiv + SizeInc) ); + List::setSize(allocSize_); } - this->operator[](nextFree_ - 1) = e; + this->operator[](nextFree - 1) = e; + + List::size() = nextFree; } template inline T Foam::DynamicList::remove() { - if (nextFree_ == 0) + if (List::size() == 0) { FatalErrorIn ( @@ -191,7 +206,7 @@ inline T Foam::DynamicList::remove() ) << "List is empty" << abort(FatalError); } - return List::operator[](--nextFree_); + return List::operator[](--List::size()); } @@ -203,20 +218,22 @@ inline T& Foam::DynamicList::operator() const label i ) { - nextFree_ = max(nextFree_, i + 1); + label nextFree = List::size(); - if (nextFree_ > List::size()) + nextFree = max(nextFree, i + 1); + + if (nextFree > allocSize_) { - List::setSize + allocSize_ = max ( - max - ( - nextFree_, - label(SizeMult*List::size()/SizeDiv + SizeInc) - ) + nextFree, + label(SizeMult*allocSize_/SizeDiv + SizeInc) ); + List::setSize(allocSize_); } + List::size() = nextFree; + return this->operator[](i); } @@ -228,7 +245,7 @@ inline void Foam::DynamicList::operator= ) { List::operator=(t); - nextFree_ = List::size(); + allocSize_ = List::size(); } @@ -239,7 +256,18 @@ inline void Foam::DynamicList::operator= ) { List::operator=(l); - nextFree_ = l.size(); + allocSize_ = List::size(); +} + + +template +inline void Foam::DynamicList::operator= +( + const DynamicList& l +) +{ + List::operator=(l); + allocSize_ = l.allocSize(); } diff --git a/src/OpenFOAM/containers/Lists/List/List.C b/src/OpenFOAM/containers/Lists/List/List.C index 249d1fcf2b..21cc042050 100644 --- a/src/OpenFOAM/containers/Lists/List/List.C +++ b/src/OpenFOAM/containers/Lists/List/List.C @@ -420,6 +420,23 @@ void List::transfer(List& a) } +// Transfer the contents of the argument DynamicList into this List +// and anull the argument list +template +template +void List::transfer(DynamicList& a) +{ + if (this->v_) delete[] this->v_; + + this->size_ = a.size_; + this->v_ = a.v_; + + a.size_ = 0; + a.allocSize_ = 0; + a.v_ = 0; +} + + template void sort(List& a) { diff --git a/src/OpenFOAM/containers/Lists/List/List.H b/src/OpenFOAM/containers/Lists/List/List.H index 3ee814a0f6..7269159ef7 100644 --- a/src/OpenFOAM/containers/Lists/List/List.H +++ b/src/OpenFOAM/containers/Lists/List/List.H @@ -61,6 +61,8 @@ template Istream& operator>>(Istream&, List&); template class FixedList; template class PtrList; template class SLList; +template + class DynamicList; template class IndirectList; template class BiIndirectList; @@ -156,6 +158,11 @@ public: // and annull the argument list. void transfer(List&); + //- Transfer the contents of the argument List into this List + // and annull the argument list. + template + void transfer(DynamicList&); + //- Return subscript-checked element of UList. inline T& newElmt(const label); diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C index ab98111778..7c20b200b3 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.C +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.C @@ -40,10 +40,7 @@ PackedList::PackedList(const label size, const unsigned int val) List(intSize(size)), size_(size) { - for (label i = 0; i < size; i++) - { - set(i, val); - } + operator=(val); } diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H index 8eb84b9749..5a966c6e68 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedList.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedList.H @@ -160,13 +160,15 @@ public: //- Number of packed elements inline label size() const; - //- Get value at index I inline unsigned int get(const label i) const; //- Set value at index I. Return true if value changed. inline bool set(const label i, const unsigned int val); + //- Underlying storage + inline List& storage(); + // Member operators @@ -179,7 +181,8 @@ public: //- Assignment operator. Takes linear time. void operator=(const PackedList&); - //- Assignment of all entries to the given value + //- Assignment of all entries to the given value. Does set on all + // elements. inline void operator=(const unsigned int val); //- Return as labelList diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H index 42b7afb81a..8e24a291bc 100644 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H +++ b/src/OpenFOAM/containers/Lists/PackedList/PackedListI.H @@ -83,7 +83,7 @@ inline void PackedList::checkValue(const unsigned int val) const { if (val>=(1u << nBits)) { - FatalErrorIn("PackedList::set(const unsigned int)") + FatalErrorIn("PackedList::checkValue(const unsigned int)") << "value " << label(val) << " out of range 0 ... " << label((1u << nBits)-1) << " representable by " << nBits << " bits" @@ -183,6 +183,13 @@ inline bool PackedList::set(const label i, const unsigned int val) } +template +inline List& PackedList::storage() +{ + return static_cast&>(*this); +} + + template inline ::Foam::reference PackedList::operator[](const label i) { @@ -213,9 +220,21 @@ inline void PackedList::operator=(const unsigned int val) # ifdef DEBUGList checkValue(val); # endif - List::operator=(val); + + if (val == 0) + { + List::operator=(val); + } + else + { + for (label i = 0; i < size_; i++) + { + set(i, val); + } + } } + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // } // End namespace Foam diff --git a/src/OpenFOAM/containers/Lists/PackedList/PackedListIO.C b/src/OpenFOAM/containers/Lists/PackedList/PackedListIO.C deleted file mode 100644 index dfa961a873..0000000000 --- a/src/OpenFOAM/containers/Lists/PackedList/PackedListIO.C +++ /dev/null @@ -1,152 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd. - \\/ M anipulation | -------------------------------------------------------------------------------- -License - This file is part of OpenFOAM. - - OpenFOAM 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. - - OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation, - Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -\*---------------------------------------------------------------------------*/ - -#include "PackedList.H" -#include "Ostream.H" -#include "token.H" -#include "contiguous.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ - -// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // - -template -void PackedList::writeEntry(Ostream& os) const -{ - if - ( - size() - && token::compound::isCompound - ( - "List<" + word(pTraits::typeName) + '>' - ) - ) - { - os << word("List<" + word(pTraits::typeName) + '>') << " "; - } - - os << *this; -} - - -template -void PackedList::writeEntry(const word& keyword, Ostream& os) const -{ - os.writeKeyword(keyword); - writeEntry(os); - os << token::END_STATEMENT << endl; -} - - -template -Ostream& operator<<(Ostream& os, const PackedList& L) -{ - // Write list contents depending on data format - if (os.format() == IOstream::ASCII || !contiguous()) - { - bool uniform = false; - - if (L.size() > 1 && contiguous()) - { - uniform = true; - - unsigned int L0 = L.get(0); - - forAll(L, i) - { - if (L.get(i) != L0) - { - uniform = false; - break; - } - } - } - - if (uniform) - { - // Write size of list and start contents delimiter - os << L.size() << token::BEGIN_BLOCK; - - // Write list contents - os << L.get(0); - - // Write end of contents delimiter - os << token::END_BLOCK; - } - else if (L.size() < 11 && contiguous()) - { - // Write size of list and start contents delimiter - os << L.size() << token::BEGIN_LIST; - - // Write list contents - forAll(L, i) - { - if (i > 0) os << token::SPACE; - os << L.get(i); - } - - // Write end of contents delimiter - os << token::END_LIST; - } - else - { - // Write size of list and start contents delimiter - os << nl << L.size() << nl << token::BEGIN_LIST; - - // Write list contents - forAll(L, i) - { - os << nl << L.get(i); - } - - // Write end of contents delimiter - os << nl << token::END_LIST << nl; - } - } - else - { - os << nl << L.size() << nl; - if (L.size()) - { - os.write((const char*)L.v_, L.size()*sizeof(T)); - } - } - - // Check state of IOstream - os.check("Ostream& operator<<(Ostream&, const PackedList&)"); - - return os; -} - - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - -// ************************************************************************* // diff --git a/src/OpenFOAM/meshes/boundBox/boundBox.C b/src/OpenFOAM/meshes/boundBox/boundBox.C index c87e552c85..a4b82f9dc4 100644 --- a/src/OpenFOAM/meshes/boundBox/boundBox.C +++ b/src/OpenFOAM/meshes/boundBox/boundBox.C @@ -79,10 +79,9 @@ boundBox::boundBox(const pointField& points, const bool doReduce) boundBox::boundBox(Istream& is) -: - min_(is), - max_(is) -{} +{ + operator>>(is, *this); +} // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // @@ -113,7 +112,7 @@ Istream& operator>>(Istream& is, boundBox& bb) { if (is.format() == IOstream::ASCII) { - return is >> bb.min_ >> bb.max_; + return is >> bb.min_ >> bb.max_; } else { diff --git a/src/OpenFOAM/meshes/meshShapes/edge/edge.H b/src/OpenFOAM/meshes/meshShapes/edge/edge.H index 4e481c24f1..8b37a9f3be 100644 --- a/src/OpenFOAM/meshes/meshShapes/edge/edge.H +++ b/src/OpenFOAM/meshes/meshShapes/edge/edge.H @@ -141,6 +141,9 @@ inline label Hash::operator()(const edge& e) const return e[0]*e[1] + e[0]+e[1]; } +template<> +inline bool contiguous() {return true;} + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H b/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H index 38301fec58..48b79eebe4 100644 --- a/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H +++ b/src/OpenFOAM/meshes/meshShapes/triFace/triFace.H @@ -166,6 +166,9 @@ inline label Hash::operator()(const triFace& t) const return (t[0]*t[1]*t[2] + t[0]+t[1]+t[2]); } +template<> +inline bool contiguous() {return true;} + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C index 2760104238..eda9946856 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalIndex.C @@ -26,12 +26,6 @@ License #include "globalIndex.H" -// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // - - // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::globalIndex::globalIndex(const label localSize) @@ -68,15 +62,6 @@ Foam::globalIndex::globalIndex(Istream& is) } -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - - -// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * // - - // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // Foam::Istream& Foam::operator>>(Istream& is, globalIndex& gi) diff --git a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C index df8d61fa21..8fdee370a0 100644 --- a/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C +++ b/src/OpenFOAM/meshes/polyMesh/globalMeshData/globalMeshData.C @@ -397,13 +397,11 @@ void Foam::globalMeshData::calcSharedEdges() const sharedEdgeLabelsPtr_ = new labelList(); labelList& sharedEdgeLabels = *sharedEdgeLabelsPtr_; sharedEdgeLabels.transfer(dynSharedEdgeLabels); - dynSharedEdgeLabels.clear(); dynSharedEdgeAddr.shrink(); sharedEdgeAddrPtr_ = new labelList(); labelList& sharedEdgeAddr = *sharedEdgeAddrPtr_; sharedEdgeAddr.transfer(dynSharedEdgeAddr); - dynSharedEdgeAddr.clear(); if (debug) { diff --git a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C index 6ad85c7971..86a0a618c1 100644 --- a/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/mapPolyMesh/mapDistribute/mapDistributeTemplates.C @@ -84,16 +84,32 @@ void Foam::mapDistribute::distribute // Receive sub field from neighbour for (label domain = 0; domain < Pstream::nProcs(); domain++) { - if - ( - domain != Pstream::myProcNo() - && constructMap[domain].size() > 0 - ) + const labelList& map = constructMap[domain]; + + if (domain != Pstream::myProcNo() && map.size() > 0) { IPstream fromNbr(Pstream::blocking, domain); List subField(fromNbr); - const labelList& map = constructMap[domain]; + if (subField.size() != map.size()) + { + FatalErrorIn + ( + "template\n" + "void mapDistribute::distribute\n" + "(\n" + " const Pstream::commsTypes commsType,\n" + " const List& schedule,\n" + " const label constructSize,\n" + " const labelListList& subMap,\n" + " const labelListList& constructMap,\n" + " List& field\n" + ")\n" + ) << "Expected from processor " << domain + << " " << map.size() << " but received " + << subField.size() << " elements." + << abort(FatalError); + } forAll(map, i) { @@ -126,6 +142,7 @@ void Foam::mapDistribute::distribute newField[map[i]] = subField[i]; } + // Schedule will already have pruned 0-sized comms forAll(schedule, i) { const labelPair& twoProcs = schedule[i]; @@ -154,6 +171,26 @@ void Foam::mapDistribute::distribute const labelList& map = constructMap[sendProc]; + if (subField.size() != map.size()) + { + FatalErrorIn + ( + "template\n" + "void mapDistribute::distribute\n" + "(\n" + " const Pstream::commsTypes commsType,\n" + " const List& schedule,\n" + " const label constructSize,\n" + " const labelListList& subMap,\n" + " const labelListList& constructMap,\n" + " List& field\n" + ")\n" + ) << "Expected from processor " << sendProc + << " " << map.size() << " but received " + << subField.size() << " elements." + << abort(FatalError); + } + forAll(map, i) { newField[map[i]] = subField[i]; @@ -164,7 +201,74 @@ void Foam::mapDistribute::distribute } else if (commsType == Pstream::nonBlocking) { - List newField(constructSize); + if (!contiguous()) + { + FatalErrorIn + ( + "template\n" + "void mapDistribute::distribute\n" + "(\n" + " const Pstream::commsTypes commsType,\n" + " const List& schedule,\n" + " const label constructSize,\n" + " const labelListList& subMap,\n" + " const labelListList& constructMap,\n" + " List& field\n" + ")\n" + ) << "Non-blocking only supported for contiguous data." + << exit(FatalError); + } + + // Set up sends to neighbours + + List > sendFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = subMap[domain]; + + if (domain != Pstream::myProcNo() && map.size() > 0) + { + List& subField = sendFields[domain]; + subField.setSize(map.size()); + forAll(map, i) + { + subField[i] = field[map[i]]; + } + + OPstream::write + ( + Pstream::nonBlocking, + domain, + reinterpret_cast(subField.begin()), + subField.size() + ); + } + } + + // Set up receives from neighbours + + List > recvFields(Pstream::nProcs()); + + for (label domain = 0; domain < Pstream::nProcs(); domain++) + { + const labelList& map = constructMap[domain]; + + if (domain != Pstream::myProcNo() && map.size() > 0) + { + recvFields[domain].setSize(map.size()); + IPstream::read + ( + Pstream::nonBlocking, + domain, + reinterpret_cast(recvFields[domain].begin()), + recvFields[domain].size() + ); + } + } + + + // Combine bits. Note that can reuse field storage // Subset myself const labelList& mySubMap = subMap[Pstream::myProcNo()]; @@ -175,54 +279,56 @@ void Foam::mapDistribute::distribute subField[i] = field[mySubMap[i]]; } + field.setSize(constructSize); + // Receive sub field from myself (subField) const labelList& map = constructMap[Pstream::myProcNo()]; forAll(map, i) { - newField[map[i]] = subField[i]; - } - - // Send sub field to neighbour - for (label domain = 0; domain < Pstream::nProcs(); domain++) - { - const labelList& map = subMap[domain]; - - if (domain != Pstream::myProcNo() && map.size() > 0) - { - - List subField(map.size()); - forAll(map, i) - { - subField[i] = field[map[i]]; - } - - OPstream toNbr(Pstream::nonBlocking, domain); - toNbr << subField; - } + field[map[i]] = subField[i]; } - // Receive sub field from neighbour + // Wait for all to finish + + OPstream::waitRequests(); + IPstream::waitRequests(); + + // Collect neighbour fields + for (label domain = 0; domain < Pstream::nProcs(); domain++) { const labelList& map = constructMap[domain]; if (domain != Pstream::myProcNo() && map.size() > 0) { - IPstream fromNbr(Pstream::nonBlocking, domain); - List subField(fromNbr); + if (recvFields[domain].size() != map.size()) + { + FatalErrorIn + ( + "template\n" + "void mapDistribute::distribute\n" + "(\n" + " const Pstream::commsTypes commsType,\n" + " const List& schedule,\n" + " const label constructSize,\n" + " const labelListList& subMap,\n" + " const labelListList& constructMap,\n" + " List& field\n" + ")\n" + ) << "Expected from processor " << domain + << " " << map.size() << " but received " + << recvFields[domain].size() << " elements." + << abort(FatalError); + } forAll(map, i) { - newField[map[i]] = subField[i]; + field[map[i]] = recvFields[domain][i]; } } } - OPstream::waitRequests(); - IPstream::waitRequests(); - - field.transfer(newField); } else { diff --git a/src/OpenFOAM/meshes/polyMesh/syncTools/syncTools.H b/src/OpenFOAM/meshes/polyMesh/syncTools/syncTools.H index 7312e08e55..48c0c566fc 100644 --- a/src/OpenFOAM/meshes/polyMesh/syncTools/syncTools.H +++ b/src/OpenFOAM/meshes/polyMesh/syncTools/syncTools.H @@ -221,6 +221,41 @@ public: const bool applySeparation ); + // PackedList versions + + template + static void syncFaceList + ( + const polyMesh& mesh, + PackedList& faceValues, + const CombineOp& cop + ); + + template + static void swapFaceList + ( + const polyMesh& mesh, + PackedList& faceValues + ); + + template + static void syncPointList + ( + const polyMesh& mesh, + PackedList& pointValues, + const CombineOp& cop, + const unsigned int nullValue + ); + + template + static void syncEdgeList + ( + const polyMesh& mesh, + PackedList& edgeValues, + const CombineOp& cop, + const unsigned int nullValue + ); + // Other //- Get per point whether is it master (of a coupled set of points) diff --git a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C index 9715ba65b2..3ee897d97d 100644 --- a/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C +++ b/src/OpenFOAM/meshes/polyMesh/syncTools/syncToolsTemplates.C @@ -940,17 +940,7 @@ void Foam::syncTools::syncPointList fromNbr >> nbrPatchInfo; } // Null any value which is not on neighbouring processor - label nbrSize = nbrPatchInfo.size(); - nbrPatchInfo.setSize(procPatch.nPoints()); - for - ( - label i = nbrSize; - i < procPatch.nPoints(); - i++ - ) - { - nbrPatchInfo[i] = nullValue; - } + nbrPatchInfo.setSize(procPatch.nPoints(), nullValue); if (!procPatch.parallel()) { @@ -1225,18 +1215,7 @@ void Foam::syncTools::syncEdgeList fromNeighb >> nbrPatchInfo; } // Null any value which is not on neighbouring processor - label nbrSize = nbrPatchInfo.size(); - nbrPatchInfo.setSize(procPatch.nEdges()); - for - ( - label i = nbrSize; - i < procPatch.nEdges(); - i++ - ) - { - nbrPatchInfo[i] = nullValue; - } - + nbrPatchInfo.setSize(procPatch.nEdges(), nullValue); if (!procPatch.parallel()) { @@ -1591,4 +1570,469 @@ void Foam::syncTools::swapFaceList } +template +void Foam::syncTools::syncFaceList +( + const polyMesh& mesh, + PackedList& faceValues, + const CombineOp& cop +) +{ + if (faceValues.size() != mesh.nFaces()) + { + FatalErrorIn + ( + "syncTools::syncFaceList" + "(const polyMesh&, PackedList&, const CombineOp&)" + ) << "Number of values " << faceValues.size() + << " is not equal to the number of faces in the mesh " + << mesh.nFaces() << abort(FatalError); + } + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + if (!hasCouples(patches)) + { + return; + } + + // Patch data (proc patches only). + List > patchValues(patches.size()); + + if (Pstream::parRun()) + { + // Send + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].size() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + patchValues[patchI].setSize(procPatch.size()); + forAll(procPatch, i) + { + patchValues[patchI][i] = + faceValues.get(procPatch.start()+i); + } + + OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo()); + toNbr << patchValues[patchI]; + } + } + + + // Receive and combine. + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].size() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + { + IPstream fromNbr + ( + Pstream::blocking, + procPatch.neighbProcNo() + ); + fromNbr >> patchValues[patchI]; + } + + // Combine (bitwise) + forAll(procPatch, i) + { + unsigned int patchVal = patchValues[patchI][i]; + label meshFaceI = procPatch.start()+i; + unsigned int faceVal = faceValues.get(meshFaceI); + cop(faceVal, patchVal); + faceValues.set(meshFaceI, faceVal); + } + } + } + } + + // Do the cyclics. + forAll(patches, patchI) + { + if (isA(patches[patchI])) + { + const cyclicPolyPatch& cycPatch = + refCast(patches[patchI]); + + label half = cycPatch.size()/2; + + for (label i = 0; i < half; i++) + { + label meshFace0 = cycPatch.start()+i; + unsigned int val0 = faceValues.get(meshFace0); + label meshFace1 = meshFace0 + half; + unsigned int val1 = faceValues.get(meshFace1); + + unsigned int t = val0; + cop(t, val1); + faceValues.set(meshFace0, t); + + cop(val1, val0); + faceValues.set(meshFace1, val1); + } + } + } +} + + +template +void Foam::syncTools::swapFaceList +( + const polyMesh& mesh, + PackedList& faceValues +) +{ + syncFaceList(mesh, faceValues, eqOp()); +} + + +template +void Foam::syncTools::syncPointList +( + const polyMesh& mesh, + PackedList& pointValues, + const CombineOp& cop, + const unsigned int nullValue +) +{ + if (pointValues.size() != mesh.nPoints()) + { + FatalErrorIn + ( + "syncTools::syncPointList" + "(const polyMesh&, PackedList&, const CombineOp&" + ", const unsigned int&)" + ) << "Number of values " << pointValues.size() + << " is not equal to the number of points in the mesh " + << mesh.nPoints() << abort(FatalError); + } + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + if (!hasCouples(patches)) + { + return; + } + + // Patch data (proc patches only). + List > patchValues(patches.size()); + + if (Pstream::parRun()) + { + // Send + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].nPoints() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + patchValues[patchI].setSize(procPatch.nPoints()); + patchValues[patchI] = nullValue; + + const labelList& meshPts = procPatch.meshPoints(); + const labelList& nbrPts = procPatch.neighbPoints(); + + forAll(nbrPts, pointI) + { + label nbrPointI = nbrPts[pointI]; + if (nbrPointI >= 0 && nbrPointI < procPatch.nPoints()) + { + patchValues[patchI][nbrPointI] = + pointValues.get(meshPts[pointI]); + } + } + + OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo()); + toNbr << patchValues[patchI]; + } + } + + + // Receive and combine. + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].nPoints() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + { + // We do not know the number of points on the other side + // so cannot use Pstream::read. + IPstream fromNbr + ( + Pstream::blocking, + procPatch.neighbProcNo() + ); + fromNbr >> patchValues[patchI]; + } + + // Null any value which is not on neighbouring processor + patchValues[patchI].setSize(procPatch.nPoints(), nullValue); + + const labelList& meshPts = procPatch.meshPoints(); + + forAll(meshPts, pointI) + { + label meshPointI = meshPts[pointI]; + unsigned int pointVal = pointValues.get(meshPointI); + cop(pointVal, patchValues[patchI][pointI]); + pointValues.set(meshPointI, pointVal); + } + } + } + } + + // Do the cyclics. + forAll(patches, patchI) + { + if (isA(patches[patchI])) + { + const cyclicPolyPatch& cycPatch = + refCast(patches[patchI]); + + const edgeList& coupledPoints = cycPatch.coupledPoints(); + const labelList& meshPts = cycPatch.meshPoints(); + + forAll(coupledPoints, i) + { + const edge& e = coupledPoints[i]; + + label point0 = meshPts[e[0]]; + label point1 = meshPts[e[1]]; + + unsigned int val0 = pointValues.get(point0); + unsigned int t = val0; + unsigned int val1 = pointValues.get(point1); + + cop(t, val1); + pointValues.set(point0, t); + cop(val1, val0); + pointValues.set(point1, val1); + } + } + } + + // Synchronize multiple shared points. + const globalMeshData& pd = mesh.globalData(); + + if (pd.nGlobalPoints() > 0) + { + // Values on shared points. Use unpacked storage for ease! + List sharedPts(pd.nGlobalPoints(), nullValue); + + forAll(pd.sharedPointLabels(), i) + { + label meshPointI = pd.sharedPointLabels()[i]; + // Fill my entries in the shared points + sharedPts[pd.sharedPointAddr()[i]] = pointValues.get(meshPointI); + } + + // Combine on master. + Pstream::listCombineGather(sharedPts, cop); + Pstream::listCombineScatter(sharedPts); + + // Now we will all have the same information. Merge it back with + // my local information. + forAll(pd.sharedPointLabels(), i) + { + label meshPointI = pd.sharedPointLabels()[i]; + pointValues.set(meshPointI, sharedPts[pd.sharedPointAddr()[i]]); + } + } +} + + +template +void Foam::syncTools::syncEdgeList +( + const polyMesh& mesh, + PackedList& edgeValues, + const CombineOp& cop, + const unsigned int nullValue +) +{ + if (edgeValues.size() != mesh.nEdges()) + { + FatalErrorIn + ( + "syncTools::syncEdgeList" + "(const polyMesh&, PackedList&, const CombineOp&" + ", const unsigned int&)" + ) << "Number of values " << edgeValues.size() + << " is not equal to the number of edges in the mesh " + << mesh.nEdges() << abort(FatalError); + } + + const polyBoundaryMesh& patches = mesh.boundaryMesh(); + + if (!hasCouples(patches)) + { + return; + } + + // Patch data (proc patches only). + List > patchValues(patches.size()); + + if (Pstream::parRun()) + { + // Send + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].nEdges() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + patchValues[patchI].setSize(procPatch.nEdges(), nullValue); + + const labelList& meshEdges = procPatch.meshEdges(); + const labelList& neighbEdges = procPatch.neighbEdges(); + + forAll(neighbEdges, edgeI) + { + label nbrEdgeI = neighbEdges[edgeI]; + if (nbrEdgeI >= 0 && nbrEdgeI < procPatch.nEdges()) + { + patchValues[patchI][nbrEdgeI] = + edgeValues.get(meshEdges[edgeI]); + } + } + + OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo()); + toNbr << patchValues[patchI]; + } + } + + + // Receive and combine. + + forAll(patches, patchI) + { + if + ( + isA(patches[patchI]) + && patches[patchI].nEdges() > 0 + ) + { + const processorPolyPatch& procPatch = + refCast(patches[patchI]); + + { + IPstream fromNeighb + ( + Pstream::blocking, + procPatch.neighbProcNo() + ); + fromNeighb >> patchValues[patchI]; + } + + patchValues[patchI].setSize(procPatch.nEdges(), nullValue); + + const labelList& meshEdges = procPatch.meshEdges(); + + forAll(meshEdges, edgeI) + { + unsigned int patchVal = patchValues[patchI][edgeI]; + label meshEdgeI = meshEdges[edgeI]; + unsigned int edgeVal = edgeValues.get(meshEdgeI); + cop(edgeVal, patchVal); + edgeValues.set(meshEdgeI, edgeVal); + } + } + } + } + + // Do the cyclics. + forAll(patches, patchI) + { + if (isA(patches[patchI])) + { + const cyclicPolyPatch& cycPatch = + refCast(patches[patchI]); + + const edgeList& coupledEdges = cycPatch.coupledEdges(); + const labelList& meshEdges = cycPatch.meshEdges(); + + forAll(coupledEdges, i) + { + const edge& e = coupledEdges[i]; + + label edge0 = meshEdges[e[0]]; + label edge1 = meshEdges[e[1]]; + + unsigned int val0 = edgeValues.get(edge0); + unsigned int t = val0; + unsigned int val1 = edgeValues.get(edge1); + + cop(t, val1); + edgeValues.set(edge0, t); + cop(val1, val0); + edgeValues.set(edge1, val1); + } + } + } + + // Synchronize multiple shared edges. + const globalMeshData& pd = mesh.globalData(); + + if (pd.nGlobalEdges() > 0) + { + // Values on shared edges. Use unpacked storage for ease! + List sharedPts(pd.nGlobalEdges(), nullValue); + + forAll(pd.sharedEdgeLabels(), i) + { + label meshEdgeI = pd.sharedEdgeLabels()[i]; + // Fill my entries in the shared edges + sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues.get(meshEdgeI); + } + + // Combine on master. + Pstream::listCombineGather(sharedPts, cop); + Pstream::listCombineScatter(sharedPts); + + // Now we will all have the same information. Merge it back with + // my local information. + forAll(pd.sharedEdgeLabels(), i) + { + label meshEdgeI = pd.sharedEdgeLabels()[i]; + edgeValues.set(meshEdgeI, sharedPts[pd.sharedEdgeAddr()[i]]); + } + } +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatchExtra/PrimitivePatchExtraSearch.C b/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatchExtra/PrimitivePatchExtraSearch.C index 453cdd63c9..ffad4f005f 100644 --- a/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatchExtra/PrimitivePatchExtraSearch.C +++ b/src/OpenFOAM/meshes/primitiveMesh/PrimitivePatchExtra/PrimitivePatchExtraSearch.C @@ -102,8 +102,9 @@ void Foam::PrimitivePatchExtra::markZone break; } - changedFaces.transfer(newChangedFaces.shrink()); - newChangedFaces.clear(); + // New dynamiclist: can leave dynamicList unshrunk + //changedFaces.transfer(newChangedFaces.shrink()); + changedFaces.transfer(newChangedFaces); } } diff --git a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshEdges.C b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshEdges.C index b60b366079..b64eda7266 100644 --- a/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshEdges.C +++ b/src/OpenFOAM/meshes/primitiveMesh/primitiveMeshEdges.C @@ -441,11 +441,10 @@ void primitiveMesh::calcEdges(const bool doFaceEdges) const forAll(pe, pointI) { DynamicList