ENH: improve hashing overloads of string-types and HashTable/HashSet

- additional dummy template parameter to assist with supporting
  derived classes. Currently just used for string types, but can be
  extended.

- provide hash specialization for various integer types.
  Removes the need for any forwarding.

- change default hasher for HashSet/HashTable from 'string::hash'
  to `Hash<Key>`. This avoids questionable hashing calls and/or
  avoids compiler resolution problems.

  For example,
  HashSet<label>::hasher and labelHashSet::hasher now both properly
  map to Hash<label> whereas previously HashSet<label> would have
  persistently mapped to string::hash, which was incorrect.

- standardize internal hashing functors.

  Functor name is 'hasher', as per STL set/map and the OpenFOAM
  HashSet/HashTable definitions.

  Older code had a local templated name, which added unnecessary
  clutter and the template parameter was always defaulted.
  For example,

      Old:  `FixedList<label, 3>::Hash<>()`
      New:  `FixedList<label, 3>::hasher()`
      Unchanged:  `labelHashSet::hasher()`

  Existing `Hash<>` functor namings are still supported,
  but deprecated.

- define hasher and Hash specialization for bitSet and PackedList

- add symmetric hasher for 'face'.
  Starts with lowest vertex value and walks in the direction
  of the next lowest value. This ensures that the hash code is
  independent of face orientation and face rotation.

NB:
  - some of keys for multiphase handling (eg, phasePairKey)
    still use yet another function naming: `hash` and `symmHash`.
    This will be targeted for alignment in the future.
This commit is contained in:
Mark Olesen
2021-04-12 17:05:11 +02:00
committed by Andrew Heather
parent b060378dca
commit 95cd8ee75c
75 changed files with 1429 additions and 955 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2017 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -59,24 +59,23 @@ class multiphaseMixtureThermo
{
public:
//- Symmetric pair of interface names
class interfacePair
:
public Pair<word>
{
public:
struct hash
{
label operator()(const interfacePair& key) const
{
return word::hash()(key.first()) + word::hash()(key.second());
}
};
// Always use symmetric hashing
using hasher = Pair<word>::symmHasher;
// Always use symmetric hashing (alias)
using hash = Pair<word>::symmHasher;
// Constructors
interfacePair() {} // = default
interfacePair() = default;
interfacePair(const word& alpha1Name, const word& alpha2Name)
:
@ -97,11 +96,7 @@ public:
const interfacePair& b
)
{
return
(
((a.first() == b.first()) && (a.second() == b.second()))
|| ((a.first() == b.second()) && (a.second() == b.first()))
);
return (0 != Pair<word>::compare(a, b));
}
friend bool operator!=
@ -117,7 +112,7 @@ public:
private:
// Private data
// Private Data
//- Dictionary of phases
PtrDictionary<phaseModel> phases_;
@ -140,7 +135,7 @@ private:
const dimensionedScalar deltaN_;
// Private member functions
// Private Member Functions
void calcAlphas();

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -67,24 +68,23 @@ class multiphaseMixture
{
public:
//- Symmetric pair of interface names
class interfacePair
:
public Pair<word>
{
public:
struct hash
{
label operator()(const interfacePair& key) const
{
return word::hash()(key.first()) + word::hash()(key.second());
}
};
// Always use symmetric hashing
using hasher = Pair<word>::symmHasher;
// Always use symmetric hashing (alias)
using hash = Pair<word>::symmHasher;
// Constructors
interfacePair() {} // = default
interfacePair() = default;
interfacePair(const word& alpha1Name, const word& alpha2Name)
:
@ -105,11 +105,7 @@ public:
const interfacePair& b
)
{
return
(
((a.first() == b.first()) && (a.second() == b.second()))
|| ((a.first() == b.second()) && (a.second() == b.first()))
);
return (0 != Pair<word>::compare(a, b));
}
friend bool operator!=

View File

@ -186,14 +186,14 @@ int main(int argc, char *argv[])
FixedList<label, 4> list1{2, 3, 4, 5};
Info<< "list1:" << list1
<< " hash:" << FixedList<label, 4>::Hash<>()(list1) << nl
<< " hash:" << FixedList<label, 4>::hasher()(list1) << nl
<< " hash:" << Hash<FixedList<label, 4>>()(list1) << nl;
label a[4] = {0, 1, 2, 3};
FixedList<label, 4> list2(a);
Info<< "list2:" << list2
<< " hash:" << FixedList<label, 4>::Hash<>()(list2) << nl
<< " hash:" << FixedList<label, 4>::hasher()(list2) << nl
<< " hash:" << Hash<FixedList<label, 4>>()(list2) << nl;

View File

@ -127,13 +127,13 @@ int main()
myTable.insert("sqrt2", autoPtr<double>::New(1.414214));
myTable.insert("euler", autoPtr<double>::New(0.577216));
HashTable<std::unique_ptr<double>, word, string::hash> myTable1;
HashTable<std::unique_ptr<double>> myTable1;
myTable1.set("abc", std::unique_ptr<double>(new double(42.1)));
myTable1.set("pi", std::unique_ptr<double>(new double(3.14159)));
myTable1.set("natlog", std::unique_ptr<double>(new double(2.718282)));
HashTable<autoPtr<double>, word, string::hash> myTable2;
HashTable<autoPtr<double>> myTable2;
myTable2.set("abc", autoPtr<double>(new double(42.1)));
myTable2.set("pi", autoPtr<double>(new double(3.14159)));
@ -148,7 +148,7 @@ int main()
{
auto iter2 = myTable2.find("pi");
Info<< nl "Got pi=";
Info<< nl << "Got pi=";
if (iter2.good())
{
Info<< **iter2 << nl;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018 OpenCFD Ltd.
Copyright (C) 2018-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -80,6 +80,11 @@ void printMinMax(const HashSet<Key, Hash>& set)
int main(int argc, char *argv[])
{
Info<< "labelHashSet hasher: "
<< typeid(labelHashSet::hasher).name() << nl
<< "HashSet<label> hasher: "
<< typeid(HashSet<label>::hasher).name() << nl << nl;
hashedWordList words
{
"abc",

View File

@ -1,3 +0,0 @@
Test-Hashing.C
EXE = $(FOAM_USER_APPBIN)/Test-Hashing

View File

@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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::HashFunction
Description
Hash function class.
Verify that template overloads are properly resolved
Note
The second template parameter (bool) is used for SFINAE overloading,
\*---------------------------------------------------------------------------*/
#ifndef HashFunction_H
#define HashFunction_H
#include "Hash.H"
#ifdef FULLDEBUG
#define HashTypeInfo(Args) void info() { std::cerr<< "" Args << "\n"; }
#else
#define HashTypeInfo(Args) void info() {}
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class Hash Declaration
\*---------------------------------------------------------------------------*/
template<class T, class SFINAEType=bool>
struct HashFun
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "default"; }
#endif
HashTypeInfo("plain hash")
unsigned operator()(const T& obj, unsigned seed=0) const
{
return Foam::Hasher(&obj, sizeof(obj), seed);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Hashing for label
template<> struct HashFun<Foam::label> : Hash<label>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "label"; }
#endif
HashTypeInfo("hash label")
};
//- Hashing for pointers, interpret pointer as a integer type
template<> struct HashFun<void*> : Hash<void *>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "pointer"; }
#endif
HashTypeInfo("hash ptr")
};
//- Hashing for string types
template<class StringType>
struct HashFun
<
StringType,
typename std::enable_if
<
std::is_base_of<std::string, StringType>::value, bool
>::type
>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "string"; }
#endif
HashTypeInfo("hash string")
unsigned operator()(const std::string& obj, unsigned seed=0) const
{
return Foam::Hasher(obj.data(), obj.size(), seed);
}
};
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Various
#include "edge.H"
#include "face.H"
#include "triFace.H"
#include "Pair.H"
#include "Tuple2.H"
#include "DynamicList.H"
#include "FixedList.H"
namespace Foam
{
template<> struct HashFun<edge> : Hash<edge>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "edge"; }
#endif
HashTypeInfo("hash edge")
};
template<> struct HashFun<face> : Hash<face>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "face"; }
#endif
HashTypeInfo("hash face")
};
template<> struct HashFun<triFace> : Hash<triFace>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "triFace"; }
#endif
HashTypeInfo("hash triFace")
};
template<class T>
struct HashFun<Pair<T>> : Hash<Pair<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "Pair"; }
#endif
HashTypeInfo("hash Pair")
};
template<class T1, class T2>
struct HashFun<Tuple2<T1, T2>> : Hash<Tuple2<T1, T2>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "Tuple2"; }
#endif
HashTypeInfo("hash Tuple2")
};
template<class T>
struct HashFun<List<T>> : Hash<List<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "List"; }
#endif
HashTypeInfo("hash List")
};
template<class T> struct HashFun<UList<T>> : Hash<UList<T>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "UList"; }
#endif
HashTypeInfo("hash UList")
};
template<class T, int SizeMin>
struct HashFun<DynamicList<T, SizeMin>> : Hash<DynamicList<T, SizeMin>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "DynamicList"; }
#endif
HashTypeInfo("hash DynamicList")
};
template<class T, unsigned N>
struct HashFun<FixedList<T, N>> : Hash<FixedList<T, N>>
{
#ifdef FULLDEBUG
static constexpr const char* name() noexcept { return "FixedList"; }
#endif
HashTypeInfo("hash FixedList")
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
Test-Hashing1.C
EXE = $(FOAM_USER_APPBIN)/Test-Hashing1

View File

@ -0,0 +1,163 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
Application
Test-Hashing1
Description
Test/verify overloads of Hash function
\*---------------------------------------------------------------------------*/
#include "IOstreams.H"
#include "IOobject.H"
#include "IFstream.H"
#include "stringList.H"
#include "labelList.H"
#include "labelPair.H"
#include "wordPair.H"
#include "edgeList.H"
#include "faceList.H"
#include "triFaceList.H"
#define FULLDEBUG
#include "HashFunction.H"
using namespace Foam;
template<class T>
unsigned rawHasher(const T& obj)
{
return Foam::Hasher(&obj, sizeof(T), 0u);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
{
typedef unsigned Type;
Type value = 100;
Info<< "hash " << typeid(value).name() << " of " << value << nl;
Info<< " Hasher: " << rawHasher(value) << nl;
Info<< " Hash<>: " << Hash<Type>()(value) << nl;
}
{
typedef int32_t Type;
Type value = 100;
Info<< "hash " << typeid(value).name() << " of " << value << nl;
Info<< " Hasher: " << rawHasher(value) << nl;
Info<< " Hash<>: " << Hash<Type>()(value) << nl;
}
{
typedef int64_t Type;
Type value = 100;
Info<< "hash " << typeid(value).name() << " of " << value << nl;
Info<< " Hasher: " << rawHasher(value) << nl;
Info<< " Hash<>: " << Hash<Type>()(value) << nl;
}
HashFun<std::string>().info();
HashFun<string>().info();
HashFun<Foam::word>().info();
HashFun<Foam::keyType>().info();
HashFun<int>().info();
HashFun<label>().info();
HashFun<float>().info();
HashFun<double>().info();
{
float value = 15.f;
Info<< "hash of " << Foam::name(&value)
<< " = " << HashFun<void*>()(&value) << nl;
}
HashFun<labelList>().info();
HashFun<wordUList>().info();
HashFun<edge>().info();
HashFun<Pair<label>>().info();
HashFun<labelPair>().info();
HashFun<labelPairPair>().info();
HashFun<Tuple2<label, word>>().info();
{
typedef Tuple2<label, word> Type;
Type obj(10, "test");
Info<< obj << " hash=" << Hash<Type>()(obj) << nl;
}
{
typedef Tuple2<label, label> Type;
Type obj(10, 12);
Info<< obj << " hash=" << Hash<Type>()(obj) << nl;
}
{
typedef Pair<label> Type;
Type obj(10, 12);
Info<< obj << " hash=" << Hash<Type>()(obj) << nl;
}
{
typedef std::pair<label, label> Type;
Type obj(10, 12);
Info<< obj << " hash=" << Hash<Type>()(obj) << nl;
HashSet<Type> hs;
hs.insert(obj);
hs.erase(obj);
}
{
Pair<label>::hasher op;
Info<< "hasher: " << op(Pair<label>(10, 12)) << nl;
}
// Not supported
#if 0
{
Tuple2<label, label>::hasher op;
Info<< "hasher: " << op(Tuple2<label>(10, 12)) << nl;
}
#endif
Info<< "\nEnd\n" << nl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
Test-Hashing2.C
EXE = $(FOAM_USER_APPBIN)/Test-Hashing2

View File

@ -0,0 +1,3 @@
EXE_INC = ${c++LESSWARN}
/* EXE_LIBS = */

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd.
Copyright (C) 2018-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -25,7 +25,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
testHashing
Test-Hashing2
Description
@ -44,6 +44,7 @@ Description
#include "triFaceList.H"
#include "Hash.H"
#include "HashSet.H"
using namespace Foam;
@ -84,7 +85,7 @@ void reportHashList(const UList<string>& list)
for (const string& val : list)
{
unsigned hash1 = string::hash()(val);
unsigned hash1 = string::hasher()(val);
Info<< hex << hash1 << ": " << val << nl;
}
@ -117,11 +118,11 @@ void reportHashList(const UList<face>& list)
for (const face& f : list)
{
// Direct value
unsigned hash1 = face::Hash<>()(f);
unsigned hash1 = face::hasher()(f);
unsigned hash2 = Hash<face>()(f);
Info<< hex << "face::Hash<> " << hash1
Info<< hex << "face hash " << hash1
<< " Hash<face> " << hash2
<< ": " << dec << flatOutput(f) << nl;
}
@ -132,14 +133,10 @@ void reportHashList(const UList<labelList>& list)
{
for (const labelList& val : list)
{
unsigned hash1 = Hasher
(
val.cdata(),
val.size() * sizeof(label)
);
unsigned hash1 = Foam::Hasher(val.cdata(), val.size_bytes());
unsigned hash2 = Hash<labelList>()(val);
unsigned hash2b = labelList::Hash<>()(val);
unsigned hash2b = labelList::hasher()(val);
Info<< hex << hash1 << " or " << hash2
<< "(" << hash2b << ") "
@ -147,7 +144,7 @@ void reportHashList(const UList<labelList>& list)
}
unsigned hash2 = Hash<labelListList>()(list);
unsigned hash2bad = HasherT(list);
unsigned hash2bad = Foam::Hasher(&list, sizeof(list));
Info<< hex << hash2 << " : " << dec << flatOutput(list) << nl
<< hex << hash2bad << " as direct hash would be wrong"
@ -164,10 +161,10 @@ void reportHashList(const UList<wordPair>& list)
unsigned hash1 = Hash<wordPair>()(pr);
// as FixedList
unsigned hash2 = wordPair::Hash<>()(pr);
unsigned hash2 = wordPair::hasher()(pr);
// as FixedList
unsigned hash2sym = wordPair::SymmHash<>()(pr);
unsigned hash2sym = wordPair::symmHasher()(pr);
// as FixedList
unsigned hash3 = Hash<FixedList<word,2>>()(pr);
@ -189,7 +186,7 @@ void reportHashList(const UList<labelPair>& list)
unsigned hash1 = Hash<labelPair>()(pr);
// as FixedList
unsigned hash2 = labelPair::Hash<>()(pr);
unsigned hash2 = labelPair::hasher()(pr);
// as FixedList
unsigned hash3 = Hash<labelPair>()(pr);
@ -210,7 +207,7 @@ void reportHashList(const UList<labelPairPair>& list)
unsigned hash1 = Hash<labelPairPair>()(pr);
// as FixedList
unsigned hash2 = labelPairPair::Hash<>()(pr);
unsigned hash2 = labelPairPair::hasher()(pr);
// as FixedList
unsigned hash3 = Hash<labelPairPair>()(pr);
@ -231,7 +228,7 @@ void reportHashList(const UList<edge>& list)
unsigned hash1 = Hash<edge>()(e);
// as FixedList
unsigned hash2 = labelPair::Hash<>()(e);
unsigned hash2 = labelPair::hasher()(e);
// as FixedList
unsigned hash3 = Hash<labelPair>()(e);
@ -251,7 +248,7 @@ void reportHashList(const UList<triFace>& list)
{
// direct value
unsigned hash1 = Hash<triFace>()(f);
unsigned hash2 = FixedList<label, 3>::Hash<>()(f);
unsigned hash2 = FixedList<label, 3>::hasher()(f);
Info<< hex << hash1 << " (as FixedList: " << hash2
<< "): " << dec << f << nl;

View File

@ -3,8 +3,8 @@
#include "Hasher.H"
#include "int.H"
#include <stdio.h>
#include <time.h>
#include <cstdio>
#include <ctime>
#ifndef CLOCKS_PER_SEC
#ifdef CLK_TCK
@ -1048,7 +1048,7 @@ int32_t i;
struct tagtest {
double res;
char * name;
const char * name;
hashFn hash;
} tests[] = {
// { 0.0, "CRC32\t\t", GetCRC32 },

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -658,11 +658,11 @@ int main(int argc, char *argv[])
Info<<"hash of " << flatOutput(list1)
<< " = " << Hash<labelList>()(list1) << " or "
<< labelList::Hash<>()(list1) << nl;
<< labelList::hasher()(list1) << nl;
Info<<"hash of " << flatOutput(list2) << " = "
<< Hash<labelList>()(list2) << " or "
<< labelList::Hash<>()(list2) << nl;
<< labelList::hasher()(list2) << nl;
}
return 0;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenCFD Ltd.
Copyright (C) 2017-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -57,7 +57,7 @@ Ostream& operator<<
);
template<class T, class Key, class Hash>
template<class T, class Key, class Hash=Foam::Hash<Key>>
class HashSorter
{
const HashTable<T, Key, Hash>& table;
@ -219,8 +219,8 @@ int main(int argc, char *argv[])
Info<< nl << "Test inplaceMapValue" << nl << nl;
HashTable<label> input;
typedef HashSorter<label, label, Hash<label>> Mapper;
typedef HashSorter<label, word, string::hash> Sorter;
typedef HashSorter<label, label> Mapper;
typedef HashSorter<label, word> Sorter;
for (label i=0; i < 10; ++i)
{

View File

@ -0,0 +1,3 @@
Test-faceHashing.C
EXE = $(FOAM_USER_APPBIN)/Test-faceHashing

View File

@ -0,0 +1,3 @@
EXE_INC = ${c++LESSWARN}
/* EXE_LIBS = */

View File

@ -0,0 +1,153 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 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/>.
Application
Test-faceHashing
Description
Basic tests of face/triFace hashing
\*---------------------------------------------------------------------------*/
#include "IOstreams.H"
#include "IOobject.H"
#include "IFstream.H"
#include "faceList.H"
#include "triFaceList.H"
#include "HashSet.H"
#include "HashTable.H"
using namespace Foam;
template<class HashSetType, class FaceListType>
void checkHashSet(const HashSetType& hs, const FaceListType& faces)
{
Info<< hs << nl;
for (const auto& f : faces)
{
Info<< " " << f << " found=" << hs.found(f) << nl;
}
Info<< nl;
}
void checkHashes(const faceList& faces)
{
face::hasher op1;
face::symmHasher op2;
Info<< "face hasher/symmHasher: " << faces.size() << " faces" << nl;
for (const face& f : faces)
{
Info<< " " << f << " symmhash=" << op2(f)
<< " hash=" << op1(f) << nl;
}
Info<< nl;
}
void checkHashes(const triFaceList& faces)
{
triFace::hasher op1;
Info<< "triFace hasher: " << faces.size() << " faces" << nl;
for (const triFace& f : faces)
{
Info<< " " << f << " hash=" << op1(f) << nl;
}
Info<< nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
{
faceList faces
({
face{0, 1, 2, 3}, // regular
face{0, 3, 2, 1}, // flip
face{2, 3, 0, 1}, // rotate
face{2, 1, 0, 3}, // rotate (flip)
face{2, 0, 1, 3}, // permute
face{2, 1, 0, 3}, // permute
});
checkHashes(faces);
HashSet<face, face::hasher> hs1;
HashSet<face, face::symmHasher> hs2;
hs1.insert(faces);
hs2.insert(faces);
Info<< "hashset (hasher)" << nl;
checkHashSet(hs1, faces);
Info<< nl;
hs1.erase(faces[0]);
Info<< "remove " << faces[0] << nl;
Info<< "hashset (hasher)" << nl;
checkHashSet(hs1, faces);
Info<< nl;
Info<< "hashset (symmHasher)" << nl;
checkHashSet(hs2, faces);
Info<< nl;
hs2.erase(faces[0]);
Info<< "remove " << faces[0] << nl;
Info<< "hashset (symmHasher)" << nl;
checkHashSet(hs2, faces);
Info<< nl;
}
{
triFaceList faces
({
triFace{0, 1, 2}, // regular
triFace{0, 2, 1}, // flip
triFace{2, 0, 1}, // rotate
});
checkHashes(faces);
HashSet<triFace> hs1;
hs1.insert(faces);
Info<< "hashset (symmHasher)" << nl;
checkHashSet(hs1, faces);
Info<< nl;
}
Info<< "\nEnd\n" << nl;
return 0;
}
// ************************************************************************* //

View File

@ -167,7 +167,7 @@ int main(int argc, char *argv[])
Info<< "string:" << test << nl << "hash:"
<< unsigned(string::hash()(test)) << endl;
<< unsigned(string::hasher()(test)) << endl;
Info<<"trimLeft: " << stringOps::trimLeft(test) << endl;
Info<<"trimRight: " << stringOps::trimRight(test) << endl;
@ -333,11 +333,11 @@ int main(int argc, char *argv[])
cout<< "output string with " << s2.length() << " characters\n";
cout<< "ostream<< >" << s2 << "<\n";
Info<< "Ostream<< >" << s2 << "<\n";
Info<< "hash:" << hex << string::hash()(s2) << dec << endl;
Info<< "hash:" << hex << string::hasher()(s2) << dec << endl;
cout<< "\ntest Foam::name()\n";
Info<< "hash: = " << word::printf("0x%012X", string::hash()(s2)) << endl;
Info<< "hash: = " << word::printf("0x%012X", string::hasher()(s2)) << endl;
// Test formatting on int
{

View File

@ -850,35 +850,39 @@ int main(int argc, char *argv[])
Map<label> faceToCell[2];
{
HashTable<label, face, face::Hash<>> faceToFaceID(boundaryFaces.size());
forAll(boundaryFaces, facei)
// Can use face::symmHasher or use sorted indices instead
// - choose the latter in case UNV has anything odd
HashTable<label, face> faceToFaceID(2*boundaryFaces.size());
forAll(boundaryFaces, bfacei)
{
SortableList<label> sortedVerts(boundaryFaces[facei]);
faceToFaceID.insert(face(sortedVerts), facei);
face sortedVerts(boundaryFaces[bfacei]);
Foam::sort(sortedVerts);
faceToFaceID.insert(sortedVerts, bfacei);
}
forAll(cellVerts, celli)
{
faceList faces = cellVerts[celli].faces();
forAll(faces, i)
const cellShape& shape = cellVerts[celli];
for (const face& f : shape.faces())
{
SortableList<label> sortedVerts(faces[i]);
const auto fnd = faceToFaceID.find(face(sortedVerts));
if (fnd.found())
face sortedVerts(f);
Foam::sort(sortedVerts);
const label bfacei = faceToFaceID.lookup(sortedVerts, -1);
if (bfacei != -1)
{
label facei = *fnd;
int stat = face::compare(faces[i], boundaryFaces[facei]);
const int cmp = face::compare(f, boundaryFaces[bfacei]);
if (stat == 1)
if (cmp == 1)
{
// Same orientation. Cell is owner.
own[facei] = celli;
own[bfacei] = celli;
}
else if (stat == -1)
else if (cmp == -1)
{
// Opposite orientation. Cell is neighbour.
nei[facei] = celli;
nei[bfacei] = celli;
}
}
}
@ -958,15 +962,13 @@ int main(int argc, char *argv[])
{
const cellShape& shape = cellVerts[celli];
const faceList shapeFaces(shape.faces());
forAll(shapeFaces, i)
for (const face& f : shape.faces())
{
label patchi = findPatch(dofGroups, shapeFaces[i]);
label patchi = findPatch(dofGroups, f);
if (patchi != -1)
{
dynPatchFaces[patchi].append(shapeFaces[i]);
dynPatchFaces[patchi].append(f);
}
}
}

View File

@ -173,7 +173,7 @@ int main(int argc, char *argv[])
label maxPatch = 0;
// Boundary faces as three vertices
HashTable<label, triFace, triFace::Hash<>> vertsToBoundary(nFaces);
HashTable<label, triFace> vertsToBoundary(nFaces);
forAll(boundaryFaces, facei)
{

View File

@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2015 OpenFOAM Foundation
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -55,15 +56,15 @@ namespace Foam
template<class Triangulation>
class pointPairs
:
public HashSet<labelPairPair, labelPairPair::Hash<>>
public HashSet<labelPairPair>
{
// Private typedefs
// Private Typedefs
typedef HashSet<labelPairPair, labelPairPair::Hash<>> StorageContainer;
typedef HashSet<labelPairPair> StorageContainer;
typedef typename Triangulation::Vertex_handle Vertex_handle;
// Private data
// Private Data
const Triangulation& triangulation_;