Compare commits

..

2 Commits

26 changed files with 163 additions and 993 deletions

View File

@ -204,6 +204,16 @@ int main(int argc, char *argv[])
Info<<" " << *iter;
}
Info<< nl;
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
Info<< "resize_unsafe(10)" << nl;
ident.resize_unsafe(10);
Info<< "data:" << Foam::name(ident.cdata())
<< " size:" << ident.size() << nl;
}
if (false)

View File

@ -132,11 +132,6 @@ projectDir="$HOME/OpenFOAM/OpenFOAM-$WM_PROJECT_VERSION"
# projectDir="@PROJECT_DIR@"
: # Safety statement (if the user removed all fallback values)
# [FOAM_MEMORY_POOL] - Optional memory management
# - overrides the 'memory_pool' etc/controlDict entry
# = "true | false | host [size=nn] [incr=nn]"
#export FOAM_MEMORY_POOL="host"
# [FOAM_SIGFPE] - Trap floating-point exceptions.
# - overrides the 'trapFpe' controlDict entry
# = true | false

View File

@ -221,9 +221,6 @@ OptimisationSwitches
// Other
// =====
// Optional memory management (sizing in MB)
// memory_pool "host; size=1024; incr=5"
// Trap floating point exception.
// Can override with FOAM_SIGFPE env variable (true|false)
trapFpe 1;

View File

@ -134,11 +134,6 @@ set projectDir=`lsof +p $$ |& sed -ne 's#^[^/]*##;\@/'"$projectName"'[^/]*/etc/c
# Or optionally hard-coded (eg, with autoconfig)
# set projectDir="@PROJECT_DIR@"
# [FOAM_MEMORY_POOL] - Optional memory management
# - overrides the 'memory_pool' etc/controlDict entry
# = "true | false | host [size=nn] [incr=nn]"
#setenv FOAM_MEMORY_POOL "host"
# [FOAM_SIGFPE] - Trap floating-point exceptions.
# - overrides the 'trapFpe' controlDict entry
# = true | false

View File

@ -3,8 +3,6 @@ MSwindows.C
cpuInfo/cpuInfo.C
memInfo/memInfo.C
memory/MemoryPool.cxx
signals/sigFpe.cxx
signals/sigInt.cxx
signals/sigQuit.cxx

View File

@ -1,83 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 3 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, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "MemoryPool.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
// {
// return false;
// }
bool Foam::MemoryPool::create(bool verbose)
{
// No banner information since it is currently never an option
return false;
}
void Foam::MemoryPool::destroy(bool verbose)
{}
bool Foam::MemoryPool::active() noexcept
{
return false;
}
bool Foam::MemoryPool::suspend() noexcept
{
return false;
}
void Foam::MemoryPool::resume() noexcept
{}
bool Foam::MemoryPool::is_pool(void* ptr)
{
return false;
}
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
{
return nullptr;
}
bool Foam::MemoryPool::try_deallocate(void* ptr)
{
return (!ptr);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -2,7 +2,6 @@
cd "${0%/*}" || exit # Run from this directory
targetType=libo # Preferred library type
. ${WM_PROJECT_DIR:?}/wmake/scripts/AllwmakeParseArguments $*
. ${WM_PROJECT_DIR:?}/wmake/scripts/have_umpire
#------------------------------------------------------------------------------
# Hack for MacOS (with Gcc).
@ -60,47 +59,6 @@ then
export COMP_FLAGS="-DFOAM_USE_INOTIFY"
fi
#------------------------------------------------------------------------------
# Have -lumpire, but also -lcamp etc.
# Also need to follow the link order
get_umpire_libs()
{
if [ -d "${UMPIRE_LIB_DIR}" ]
then
set -- $(
# Expected link order
for name in umpire fmt camp
do
[ -f "$UMPIRE_LIB_DIR/lib${name}.a" ] && echo "-l$name"
done
)
echo "$@"
else
echo
fi
}
if have_umpire
then
libNames="$(get_umpire_libs)"
if [ -n "$libNames" ]
then
echo " found umpire -- enabling memory pool interface" 1>&2
echo " umpire libs: $libNames" 1>&2
COMP_FLAGS="$COMP_FLAGS -DFOAM_USE_UMPIRE -I${UMPIRE_INC_DIR}"
LINK_FLAGS="$LINK_FLAGS -L${UMPIRE_LIB_DIR} $libNames"
export COMP_FLAGS LINK_FLAGS
else
echo " expecting umpire, but did not resolve the libraries" 1>&2
fi
fi
#------------------------------------------------------------------------------
# Make object (non-shared by default)
# Never want/need openmp, especially for static objects
wmake -no-openmp $targetType

View File

@ -4,8 +4,6 @@ cpuInfo/cpuInfo.C
cpuTime/cpuTimePosix.C
memInfo/memInfo.C
memory/MemoryPool.cxx
signals/sigFpe.cxx
signals/sigSegv.cxx
signals/sigInt.cxx

View File

@ -1,4 +1 @@
/* umpire uses old-style cast etc */
EXE_INC = $(COMP_FLAGS) $(c++LESSWARN)
LIBO_LIBS = $(LINK_FLAGS)
EXE_INC = $(COMP_FLAGS)

View File

@ -1,510 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 3 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, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "MemoryPool.H"
#include "debug.H"
#include "dictionary.H"
#include "sigFpe.H"
#include "OSspecific.H" // For getEnv
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
#ifdef FOAM_USE_UMPIRE
// #include <cerrno>
#include <cinttypes>
#include <tuple>
#include "umpire/Allocator.hpp"
#include "umpire/ResourceManager.hpp"
#include "umpire/strategy/AlignedAllocator.hpp"
#include "umpire/strategy/DynamicPoolList.hpp"
static bool disabled_(false);
static umpire::Allocator aligned_allocator;
static umpire::Allocator pooled_allocator;
static umpire::ResourceManager* manager_(nullptr);
static umpire::ResourceManager* suspended_(nullptr);
#endif
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
#ifdef FOAM_USE_UMPIRE
namespace
{
// Different supported allocation types
enum class Types { undefined, none, host, device, managed };
typedef std::tuple<Types, std::size_t, std::size_t> ctrlTuple;
// Extract key=INT, the key includes the '='
int getIntParameter(const std::string& key, const std::string& ctrl)
{
int val(0);
const auto pos = ctrl.find(key);
if (pos == std::string::npos)
{
return val;
}
const char* buf = (ctrl.data() + pos + key.size());
char *endptr = nullptr;
errno = 0;
auto parsed = std::strtoimax(buf, &endptr, 10);
if (errno || endptr == buf)
{
// Some type of error OR no conversion
}
else
{
val = int(parsed);
}
return val;
}
ctrlTuple getControlValues(const std::string& ctrl)
{
ctrlTuple result(Types::undefined, 0, 0);
bool checkParam = false;
// Also find things that look like Switch constants.
// Unfortunately need to do this manually since Switch::find()
// itself would not manage to parse something like "true; size=10"
if (ctrl.empty())
{
// Nothing => undefined
}
else if
(
std::string::npos != ctrl.find("false") // ctrl.contains("false")
|| std::string::npos != ctrl.find("off") // ctrl.contains("off")
|| std::string::npos != ctrl.find("no") // ctrl.contains("no")
|| std::string::npos != ctrl.find("none") // ctrl.contains("none")
)
{
std::get<0>(result) = Types::none;
}
else if
(
std::string::npos != ctrl.find("true") // ctrl.contains("true")
|| std::string::npos != ctrl.find("on") // ctrl.contains("on")
|| std::string::npos != ctrl.find("yes") // ctrl.contains("yes")
|| std::string::npos != ctrl.find("host") // ctrl.contains("host")
|| std::string::npos != ctrl.find("system") // ctrl.contains("system")
)
{
std::get<0>(result) = Types::host;
checkParam = true;
}
// These need more testing
else if
(
std::string::npos != ctrl.find("device") // ctrl.contains("device")
)
{
std::get<0>(result) = Types::device;
checkParam = true;
}
else if
(
std::string::npos != ctrl.find("managed") // ctrl.contains("managed")
)
{
std::get<0>(result) = Types::managed;
checkParam = true;
}
if (checkParam)
{
std::get<1>(result) = getIntParameter("size=", ctrl);
std::get<2>(result) = getIntParameter("incr=", ctrl);
}
return result;
}
bool create_from(const ctrlTuple& controls, bool verbose)
{
using namespace Foam;
if (manager_ || suspended_)
{
// Already created
return true;
}
// Type, initial size, increment
auto [which, size, incr] = controls;
// std::cerr
// << "which=" << int(which)
// << ", size=" << int(size)
// << ", incr=" << int(incr) << '\n';
constexpr size_t MegaByte(1024*1024);
switch (which)
{
case Types::undefined :
{
if (verbose)
{
Info<< "memory pool : unused" << nl;
}
break;
}
case Types::none :
{
if (verbose)
{
Info<< "memory pool : disabled" << nl;
}
break;
}
case Types::host :
{
// Default sizing parameters
if (!size) size = 1024;
if (!incr) incr = 5;
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator =
rm.makeAllocator<umpire::strategy::AlignedAllocator>
(
"aligned_allocator",
rm.getAllocator("HOST"),
// alignment
256
);
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_HOST_pool",
aligned_allocator,
// initial block allocation size
(size*MegaByte),
// incremental block allocation size
(incr*MegaByte)
);
if (verbose)
{
Info<< "memory pool : host (size="
<< int(size) << "MB, incr="
<< int(incr) << "MB)\n";
}
break;
}
case Types::device :
{
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator = rm.getAllocator("DEVICE");
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_DEVICE_pool",
aligned_allocator
);
if (verbose)
{
Info<< "memory pool : device" << nl;
}
break;
}
case Types::managed :
{
// Default sizing parameters
if (!size) size = 10*1024;
if (!incr) incr = 10;
auto& rm = umpire::ResourceManager::getInstance();
manager_ = &rm;
aligned_allocator = rm.getAllocator("UM");
pooled_allocator =
rm.makeAllocator<umpire::strategy::DynamicPoolList>
(
"openfoam_UM_pool",
aligned_allocator,
// initial block allocation size
(size*MegaByte),
// incremental block allocation size
(incr*MegaByte)
);
if (verbose)
{
Info<< "memory pool : managed (size="
<< int(size) << "MB, incr="
<< int(incr) << "MB)\n";
}
break;
}
}
return (which != Types::undefined && which != Types::none);
}
} // End anonymous namespace
#endif // FOAM_USE_UMPIRE
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// bool Foam::MemoryPool::create(const std::string& ctrl, bool verbose)
// {
// #ifdef FOAM_USE_UMPIRE
// if (manager_ || suspended_)
// {
// // Already created
// return true;
// }
//
// auto controls = getControlValues(ctrl);
//
// return create_from(controls, verbose);
// #else
// return false;
// #endif
// }
bool Foam::MemoryPool::create(bool verbose)
{
#ifdef FOAM_USE_UMPIRE
if (disabled_)
{
// Disallowed
return false;
}
else if (manager_ || suspended_)
{
// Already created
return true;
}
// First check environment
auto controls = getControlValues(Foam::getEnv("FOAM_MEMORY_POOL"));
if (std::get<0>(controls) == Types::none)
{
// Disabled from environment - has highest priority
disabled_ = true;
}
// Currently no easy way to handle <system>/controlDict...
// Fallback from etc/controlDict
if (std::get<0>(controls) == Types::undefined)
{
// From central etc/controlDict
const auto& dict = Foam::debug::optimisationSwitches();
if (auto* eptr = dict.findStream("memory_pool", keyType::LITERAL))
{
const token& firstToken = eptr->front();
if (firstToken.isStringType())
{
controls = getControlValues(firstToken.stringToken());
}
}
}
return create_from(controls, verbose);
#else
if (verbose)
{
Info<< "memory pool : not available" << nl;
}
return false;
#endif
}
void Foam::MemoryPool::destroy(bool verbose)
{
// Nothing currently needed but could add in something like this:
// if (manager_ || suspended_)
// {
// pooled_allocator.release();
// }
// However, need to find the proper sequence within
// Foam::exit() or UPstream::exit() ...
}
bool Foam::MemoryPool::active() noexcept
{
#ifdef FOAM_USE_UMPIRE
return bool(manager_);
#else
return false;
#endif
}
bool Foam::MemoryPool::suspend() noexcept
{
#ifdef FOAM_USE_UMPIRE
bool status(suspended_);
if (manager_) // <- and (!suspended_)
{
std::swap(manager_, suspended_);
}
return status;
#else
return false;
#endif
}
void Foam::MemoryPool::resume() noexcept
{
#ifdef FOAM_USE_UMPIRE
if (suspended_) // <- and (!manager_)
{
std::swap(manager_, suspended_);
}
#endif
}
bool Foam::MemoryPool::is_pool(void* ptr)
{
#ifdef FOAM_USE_UMPIRE
if (ptr)
{
if (manager_)
{
return manager_->hasAllocator(ptr);
}
else if (suspended_)
{
return suspended_->hasAllocator(ptr);
}
}
#endif
return false;
}
void* Foam::MemoryPool::try_allocate(std::size_t nbytes)
{
void* ptr = nullptr;
#ifdef FOAM_USE_UMPIRE
if (manager_)
{
ptr = pooled_allocator.allocate(nbytes);
// std::cerr<< "allocate(" << int(nbytes) << ")\n";
// Optionally fill with NaN (depends on current flags)
Foam::sigFpe::fillNan_if(ptr, nbytes);
if (!ptr)
{
// Pout<< "umpire failed to allocate memory\n";
}
}
#endif
return ptr;
}
bool Foam::MemoryPool::try_deallocate(void* ptr)
{
#ifdef FOAM_USE_UMPIRE
if (ptr)
{
if (manager_)
{
if (manager_->hasAllocator(ptr)) // <- ie, is_pool()
{
// std::cerr<< "deallocate()\n";
manager_->deallocate(ptr);
return true;
}
}
else if (suspended_)
{
// Deallocate even if nominally suspended
if (suspended_->hasAllocator(ptr)) // <- ie, is_pool()
{
// std::cerr<< "deallocate()\n";
suspended_->deallocate(ptr);
return true;
}
}
}
#endif
return (!ptr);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -203,7 +203,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -251,6 +251,11 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -68,9 +68,7 @@ inline void Foam::DynamicList<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -97,9 +95,6 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -110,10 +105,8 @@ inline void Foam::DynamicList<T, SizeMin>::doReserve
}
else
{
List<T>::resize_copy(currLen, capacity_);
List<T>::resize(capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -278,7 +271,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // All contents moved
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
}
@ -292,7 +285,7 @@ inline Foam::DynamicList<T, SizeMin>::DynamicList
List<T>(std::move(static_cast<List<T>&>(list))),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // All contents moved
list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
}
@ -368,15 +361,8 @@ inline void Foam::DynamicList<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
List<T>::setAddressableSize(currLen);
}
}
@ -463,6 +449,18 @@ inline void Foam::DynamicList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicList<T, SizeMin>::swap(List<T>& list)

View File

@ -236,6 +236,13 @@ public:
// Otherwise the contents will be uninitialized.
inline void resize_nocopy(const label len);
//- Change the addressed list size directly without affecting
//- any memory management (advanced usage).
//
// It is left to the caller to avoid \em unsafe lengthening beyond
// the allocated memory region.
inline void resize_unsafe(const label len) noexcept;
//- Alias for resize()
void setSize(const label n) { this->resize(n); }

View File

@ -178,6 +178,13 @@ inline void Foam::List<T>::resize_nocopy(const label len)
}
template<class T>
inline void Foam::List<T>::resize_unsafe(const label len) noexcept
{
UList<T>::setAddressableSize(len);
}
template<class T>
inline T& Foam::List<T>::newElmt(const label i)
{

View File

@ -34,7 +34,6 @@ Description
#ifndef Foam_ListPolicy_H
#define Foam_ListPolicy_H
#include "MemoryPool.H" // Also includes <cstdint>
#include "contiguous.H" // Also includes <type_traits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -104,18 +103,6 @@ template<> struct no_linebreak<wordRe> : std::true_type {};
// - use_offload(n) :
// Lower threshold for switching to device offloading
//
//
// Use of the memory-pool is controlled by the 'is_aligned_type()' test
// and the minimum field size, controlled by the 'use_memory_pool()' test.
//
// If the memory-pool is not enabled or not required according to the two
// above tests, the allocation falls back to either an aligned or unaligned
// allocation.
//
// The decision about when to choose aligned vs unaligned allocation
// is still a compile-time option. Made by direct edit of the
// appropriate functions.
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Consider aligned allocation for the given type?
@ -159,104 +146,27 @@ inline constexpr bool use_offload(IntType n) noexcept
}
//- Default alignment for larger fields
inline constexpr std::align_val_t default_alignment() noexcept
{
return std::align_val_t(256);
}
//- Allocate from memory pool (if active), or aligned, or normal
template<class T, class IntType>
inline T* allocate(IntType n)
{
if constexpr (ListPolicy::is_aligned_type<T>())
{
// Note: threshold for use_memory_pool() >= use_alignment()
if (ListPolicy::use_alignment(n))
{
if
(
void *pool_ptr
(
// Consider memory pool for large amounts of data
ListPolicy::use_memory_pool(n)
? Foam::MemoryPool::try_allocate(sizeof(T)*n)
: nullptr
);
pool_ptr
)
{
// Placement new
return new (pool_ptr) T[n];
}
else
{
return new (ListPolicy::default_alignment()) T[n];
}
}
else
{
// Plain new
return new T[n];
}
}
else
{
// Plain new
return new T[n];
}
// Plain new
return new T[n];
}
//- Deallocate from memory pool, or normal
template<class T, class IntType>
inline void deallocate(T* ptr)
{
if constexpr (ListPolicy::is_aligned_type<T>())
{
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
{
// Plain new
delete[] ptr;
}
}
else
{
// Plain new
delete[] ptr;
}
// Plain new
delete[] ptr;
}
//- Deallocate from memory pool, or aligned, or normal
template<class T, class IntType>
inline void deallocate(T* ptr, [[maybe_unused]] IntType n)
{
if constexpr (ListPolicy::is_aligned_type<T>())
{
// Note: threshold for use_memory_pool() >= use_alignment()
if (ListPolicy::use_alignment(n))
{
if (ptr && !Foam::MemoryPool::try_deallocate(ptr))
{
// Alignment depends on the number of elements
::operator delete[](ptr, ListPolicy::default_alignment());
}
}
else
{
// Plain new
delete[] ptr;
}
}
else
{
// Plain new
delete[] ptr;
}
// Plain new
delete[] ptr;
}

View File

@ -112,26 +112,23 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size.
// New entries are initialized to nullptr.
inline void reserve(const label len);
//- Reserve allocation space for at least this size.
//- If allocation is required, uses the specified size
//- without any other resizing logic.
// New entries are initialized to nullptr.
inline void reserve_exact(const label len);
//- Alter the addressed list size.
// New entries are initialized to nullptr.
inline void resize(const label len);
inline void resize(const label newLen);
//- Set the addressed list to the given size,
//- deleting all existing entries.
//- Afterwards the list contains all \c nullptr entries.
inline void resize_null(const label len);
inline void resize_null(const label newLen);
//- Clear the addressed list, i.e. set the size to zero.
// Allocated size does not change
@ -143,6 +140,11 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
//- Alias for shrink_to_fit()
void shrink() { this->shrink_to_fit(); }

View File

@ -82,7 +82,10 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // All contents moved
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
}
@ -96,7 +99,10 @@ inline Foam::PtrDynList<T, SizeMin>::PtrDynList
PtrList<T>(std::move(list)),
capacity_(list.capacity())
{
list.setCapacity_unsafe(0); // All contents moved
// FUTURE:
// list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
list.clearStorage(); // capacity=0 etc.
}
@ -129,17 +135,11 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(capacity_);
capacity_ = PtrList<T>::size();
PtrList<T>::setAddressableSize(currLen);
}
}
@ -153,13 +153,8 @@ inline void Foam::PtrDynList<T, SizeMin>::reserve_exact(const label len)
// Preserve addressed size
const label currLen = PtrList<T>::size();
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// No PtrList<T>::resize_copy(...) -> copying nullptr is cheap
PtrList<T>::resize(len);
capacity_ = PtrList<T>::size();
capacity_ = len;
PtrList<T>::resize(capacity_);
PtrList<T>::setAddressableSize(currLen);
}
}
@ -169,12 +164,16 @@ template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
{
auto& ptrs = this->ptrs_;
const label oldLen = ptrs.size();
if (capacity_ < newLen)
{
// Extend list
this->reserve(newLen);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
PtrList<T>::resize(capacity_);
}
else if (newLen != oldLen)
{
@ -192,16 +191,13 @@ inline void Foam::PtrDynList<T, SizeMin>::resize(const label newLen)
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label len)
inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label newLen)
{
if (capacity_ < len)
if (capacity_ < newLen)
{
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
Foam::ListPolicy::reserve_size<SizeMin, 2>(newLen, capacity_);
PtrList<T>::resize_null(capacity_);
}
@ -211,7 +207,7 @@ inline void Foam::PtrDynList<T, SizeMin>::resize_null(const label len)
}
// Adjust addressed size
PtrList<T>::setAddressableSize(len);
PtrList<T>::setAddressableSize(newLen);
}
@ -244,6 +240,18 @@ inline void Foam::PtrDynList<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::shrink_unsafe()
{
if (PtrList<T>::empty())
{
// Delete empty list
PtrList<T>::clear();
}
capacity_ = PtrList<T>::size();
}
template<class T, int SizeMin>
inline Foam::label Foam::PtrDynList<T, SizeMin>::squeezeNull()
{

View File

@ -217,7 +217,7 @@ public:
//- Change the value for the list capacity directly (ADVANCED, UNSAFE)
//- Does not perform any memory management or resizing.
void setCapacity_unsafe(label len) noexcept { capacity_ = len; }
void setCapacity_unsafe(const label len) noexcept { capacity_ = len; }
//- Reserve allocation space for at least this size, allocating new
//- space if required and \em retaining old content.
@ -265,6 +265,11 @@ public:
//- Shrink the allocated space to the number of elements used.
inline void shrink_to_fit();
//- Shrink the internal bookkeeping of the allocated space to the
//- number of addressed elements without affecting allocation.
// \note when empty() it will delete any allocated memory.
inline void shrink_unsafe();
// Edit

View File

@ -66,9 +66,7 @@ inline void Foam::DynamicField<T, SizeMin>::doCapacity
// Addressable length, possibly truncated by new capacity
const label currLen = Foam::min(List<T>::size(), newCapacity);
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
if (nocopy)
{
List<T>::resize_nocopy(newCapacity);
@ -95,9 +93,6 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// Increase capacity (eg, doubling)
capacity_ =
Foam::ListPolicy::reserve_size<SizeMin, 2>(len, capacity_);
@ -108,10 +103,8 @@ inline void Foam::DynamicField<T, SizeMin>::doReserve
}
else
{
List<T>::resize_copy(currLen, capacity_);
List<T>::resize(capacity_);
}
capacity_ = List<T>::size();
List<T>::setAddressableSize(currLen);
}
}
@ -253,7 +246,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // All contents moved
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
}
@ -266,7 +259,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // All contents moved
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
}
@ -280,7 +273,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
Field<T>(std::move(static_cast<List<T>&>(content))),
capacity_(content.capacity())
{
content.setCapacity_unsafe(0); // All contents moved
content.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
}
@ -299,7 +292,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0); // All contents moved
content.setCapacity_unsafe(0);
}
else
{
@ -324,7 +317,7 @@ inline Foam::DynamicField<T, SizeMin>::DynamicField
{
Field<T>::transfer(static_cast<List<T>&>(content));
capacity_ = content.capacity();
content.setCapacity_unsafe(0); // All contents moved
content.setCapacity_unsafe(0);
}
else
{
@ -469,15 +462,8 @@ inline void Foam::DynamicField<T, SizeMin>::reserve_exact
// Preserve addressed size
const label currLen = List<T>::size();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
// if (!nocopy)
{
List<T>::resize_copy(currLen, len);
}
capacity_ = List<T>::size();
capacity_ = len;
List<T>::resize(capacity_);
List<T>::setAddressableSize(currLen);
}
}
@ -565,6 +551,18 @@ inline void Foam::DynamicField<T, SizeMin>::shrink_to_fit()
}
template<class T, int SizeMin>
inline void Foam::DynamicField<T, SizeMin>::shrink_unsafe()
{
if (List<T>::empty())
{
// Delete storage if empty
List<T>::clear();
}
capacity_ = List<T>::size();
}
template<class T, int SizeMin>
inline void
Foam::DynamicField<T, SizeMin>::swap(List<T>& list)

View File

@ -37,7 +37,6 @@ License
#include "IOobject.H"
#include "dynamicCode.H"
#include "simpleObjectRegistry.H"
#include "MemoryPool.H"
#include "sigFpe.H"
#include "sigInt.H"
#include "sigQuit.H"
@ -2183,9 +2182,6 @@ void Foam::argList::parse
sigQuit::set(bannerEnabled());
sigSegv::set(bannerEnabled());
// Create memory pool (if any) after MPI has been setup
MemoryPool::create(bannerEnabled());
if (UPstream::master() && bannerEnabled())
{
Info<< "fileModificationChecking : "

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2024 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -243,7 +243,15 @@ Foam::GAMGAgglomeration::GAMGAgglomeration
const dictionary& controlDict
)
:
MeshObject_type(mesh),
MeshObject_type
(
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
),
mesh
),
maxLevels_(50),
@ -308,10 +316,17 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const dictionary& controlDict
)
{
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
GAMGAgglomeration::typeName
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
);
if (agglomPtr)
@ -373,12 +388,16 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
GAMGAgglomeration::typeName
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
);
if (agglomPtr)
{
if (agglomPtr->requireUpdate_)
if (agglomPtr->requireUpdate_ || agglomPtr->requiresUpdate())
{
mesh.thisDb().checkOut(const_cast<GAMGAgglomeration*>(agglomPtr));
return GAMGAgglomeration::New(matrix, controlDict);
@ -431,12 +450,16 @@ const Foam::GAMGAgglomeration& Foam::GAMGAgglomeration::New
const GAMGAgglomeration* agglomPtr =
mesh.thisDb().cfindObject<GAMGAgglomeration>
(
GAMGAgglomeration::typeName
controlDict.getOrDefault<word>
(
"name",
GAMGAgglomeration::typeName
)
);
if (agglomPtr)
{
if (agglomPtr->requireUpdate_)
if (agglomPtr->requireUpdate_ || agglomPtr->requiresUpdate())
{
mesh.thisDb().checkOut(const_cast<GAMGAgglomeration*>(agglomPtr));
return GAMGAgglomeration::New(mesh, controlDict);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,8 +38,12 @@ Description
// Whether to cache the agglomeration
cacheAgglomeration yes;
// Optionally update every updateInterval mesh motion. Default is 1.
// Optionally update every updateInterval time steps. Default is 1.
// - only applies if cacheAgglomeration
// - applies also for static mesh cases
updateInterval 10;
// Optional name (default is GAMGAgglomeration)
//name pAgglomeration;
// Optionally agglomerate coarsest-level across processors
processorAgglomerator masterCoarsest;
@ -188,7 +192,7 @@ protected:
// Protected Member Functions
//- Does the agglomeration need to be fully updated?
bool requiresUpdate() const;
virtual bool requiresUpdate() const;
//- Assemble coarse mesh addressing
void agglomerateLduAddressing(const label fineLevelIndex);

View File

@ -1,116 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 3 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, see <http://www.gnu.org/licenses/>.
Class
Foam::MemoryPool
Description
Optional memory management using a memory pool such as Umpire
(https://github.com/LLNL/Umpire).
When compiled with Umpire, its use can be controlled by the
\c FOAM_MEMORY_POOL environment variable, or the
\c memory_pool Optimisation switch (etc/controlDict).
It currently looks for any of the following entries, in this order:
- true - same as \em "host"
- false/none - disabled.
- \em "host" - uses host memory pool
- \em "system" - same as \em "host"
- \em "device" - uses device memory pool
- \em "managed" - uses managed host/device memory pool
.
The parameters "size=nn" and "incr=nn" (in MegaBytes) can be used
to specify alternatives to the default sizing.
\*---------------------------------------------------------------------------*/
#ifndef Foam_MemoryPool_H
#define Foam_MemoryPool_H
#include <cstdint> // For size_t
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class MemoryPool Declaration
\*---------------------------------------------------------------------------*/
class MemoryPool
{
public:
// Constructors
//- Create a memory pool instance (if not already active).
// Uses environment or etc/controlDict entry
static bool create(bool verbose = false);
// Destructor
//- Remove the memory pool instance (currently does nothing)
static void destroy(bool verbose = false);
// Member Functions
//- True if pool is active (ie, created and not suspended)
static bool active() noexcept;
//- Suspend use of memory pool (for allocation).
// \return previous suspend status
static bool suspend() noexcept;
//- Resume use of memory pool (if previously active)
static void resume() noexcept;
//- Test if given pointer belongs to the pool
static bool is_pool(void *ptr);
//- Allocate from pool (if active).
// \returns nullptr if the pool is not active
static void* try_allocate(std::size_t nbytes);
//- Deallocate a pointer managed by the pool
// \returns True if a nullptr (no-op) or when the pointer was
// managed by the pool.
static bool try_deallocate(void *ptr);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -86,15 +86,7 @@ Foam::transformFaPatchField<Type>::valueInternalCoeffs
const tmp<scalarField>&
) const
{
// OR (!is_rotational_vectorspace_v<Type>)
if constexpr (std::is_arithmetic_v<Type>)
{
return tmp<Field<Type>>::New(this->size(), pTraits<Type>::one);
}
else
{
return pTraits<Type>::one - snGradTransformDiag();
}
return pTraits<Type>::one - snGradTransformDiag();
}
@ -119,15 +111,7 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::transformFaPatchField<Type>::gradientInternalCoeffs() const
{
// OR (!is_rotational_vectorspace_v<Type>)
if constexpr (std::is_arithmetic_v<Type>)
{
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
return -this->patch().deltaCoeffs()*snGradTransformDiag();
}
return -this->patch().deltaCoeffs()*snGradTransformDiag();
}

View File

@ -97,15 +97,7 @@ Foam::transformFvPatchField<Type>::valueInternalCoeffs
const tmp<scalarField>&
) const
{
// OR (!is_rotational_vectorspace_v<Type>)
if constexpr (std::is_arithmetic_v<Type>)
{
return tmp<Field<Type>>::New(this->size(), pTraits<Type>::one);
}
else
{
return pTraits<Type>::one - snGradTransformDiag();
}
return pTraits<Type>::one - snGradTransformDiag();
}
@ -130,15 +122,7 @@ template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::transformFvPatchField<Type>::gradientInternalCoeffs() const
{
// OR (!is_rotational_vectorspace_v<Type>)
if constexpr (std::is_arithmetic_v<Type>)
{
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
else
{
return -this->patch().deltaCoeffs()*snGradTransformDiag();
}
return -this->patch().deltaCoeffs()*snGradTransformDiag();
}

View File

@ -159,13 +159,13 @@ public:
// Coupled and adjust flux
//- Return neighbour field. Dummy value
//- Return neighbour field. Dummy (treat like zero-gradient)
virtual tmp<Field<Type>> patchNeighbourField() const
{
return tmp<Field<Type>>::New(this->size(), Foam::zero{});
}
//- Retrieve neighbour field. Dummy value
//- Retrieve neighbour field. Dummy (treat like zero-gradient)
virtual void patchNeighbourField(UList<Type>& pnf) const
{
pnf = Foam::zero{};