CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Compilation fails under OF1806+ (https://www.cfd-online.com/Forums/openfoam-programming-development/210858-compilation-fails-under-of1806.html)

anon_q November 6, 2018 08:35

Compilation fails under OF1806+
 
Hello,
I have an OpenFOAM code that compiles and runs properly under OpenFOAM 6.
Now I switched to OpenFOAM V1806 but unfortunately the code doesn't compile. After reading the errors reported by the compiler, I understand that the problem is caused by hashtable, so I decided to isolate the problem and I created the sample code below that produces the same error:

The code:
Code:

#include "fvCFD.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

void fillHashTable(HashTable<List<label>, label>& hashTable, label maxN);
int main(int argc, char *argv[])
{

    HashTable<List<label>, label> table1;

    fillHashTable(table1, 5);

    Info << table1 << endl;
    Info<< "End\n" << endl;

    return 0;
}

void fillHashTable(HashTable<List<label>, label>& hashTable, label maxN)
{
    List<label> tmpList;
    for(int i=0; i < maxN; ++i)
    {
        tmpList.clear();
        tmpList = {2*i, i*i, i*i*i};
        hashTable.insert(i , tmpList);
    }
}

The error:
Code:

...
/home/evren/OpenFOAM/OpenFOAM-v1806/src/OpenFOAM/lnInclude/HashTableI.H:35: error: no match for call to ‘(Foam::string::hash) (const int&)’
    return Hash()(key) & (capacity_ - 1);
            ~~~~~~^~~~~
...

As I stated above, the code compiles and works perfectly when I use OpenFOAM 6.
Could you please help me debug this problem, is it a bug?
Update:
After changing the type of key to word it works, Could you please confirm that hashtables in OpenFOAM v1806 work only with string keys?

anon_q November 6, 2018 16:46

Problem solved!
using:
Code:


HashTable<List<label>, label, Hash<label>>


olesen November 11, 2018 20:49

Your posted solution is correct
Code:


HashTable<List<label>, label, Hash<label>>

Your first attempt using
Code:


HashTable<List<label>, label>

would have compiled and worked in older versions, but for all the wrong reasons. It is understandably annoying that it will not compile in 1806, but I think that is a good thing.



As you've discovered, the HashTable uses a 'word' as its default key, and hashes on that accordingly. If you change the type of the key used in the HashTable, you should be careful that the hashing method also matches.


With

Code:

HashTable<List<label>, label> myHash;

 myHash.insert(10, list1);
myHash.insert(200, list2);
 myHash.insert(3000, list3);
...

The error message actually provides some insight to how poorly this used to behave, and why it was changed for 1806.

Code:

/home/evren/OpenFOAM/OpenFOAM-v1806/src/OpenFOAM/lnInclude/HashTableI.H:35: error: no match for call to ‘(Foam::string::hash) (const int&)’

      return Hash()(key) & (capacity_ - 1);
            ~~~~~~^~~~~

Since the HashTable is using an int for the key, but the hasher requires a string, the compiler tries to find a way to convert the int to a string. This conversion is now explicit for 1806 and won't be considered (ie, the code won't compile). Previously an implicit conversion was permitted. This means that your int value (for example 3000) was converted to a string. Following the constructors, this means that the value of '3000' would be narrowed to a char value (0-255), from which a single character string would have been allocated. This stored data character would have been passed to the Hasher to generate a table value. Apart from the useless overhead of converting to a string etc. We have the obvious problem that all these int values are being narrowed to a char (0-255). This means many, many hash key collisions, which are resolved with chaining. This all would make things really slow.


Since using a 'label' as the key for a HashTable is fairly useful, you would expect that it must be easier than all of this (with much less typing). Indeed it is. The updated code that you should actually be using would be a Map:
Code:

Map<labelList> myHash;
myHash.insert(200, list2);

For 1812, there are additional hasher methods defined for lists of things. This can be useful for various things, one of which is a HashTable of faces.




/mark

olesen November 11, 2018 20:53

Quote:

Originally Posted by Evren Linda (Post 714329)
Hello,
Code:

void fillHashTable(HashTable<List<label>, label>& hashTable, label maxN)
{
    List<label> tmpList;
    for(int i=0; i < maxN; ++i)
    {
        tmpList.clear();
        tmpList = {2*i, i*i, i*i*i};
        hashTable.insert(i , tmpList);
    }
}



Could also use something this

Code:

void fillHashTable(Map<labelList>& hashTable, label maxN)
{
    for(int i=0; i < maxN; ++i)
    {
        hashTable.insert(i , labelList({2*i, i*i, i*i*i}));
    }
}

Unfortunately we don't yet have an emplace insertion method.

anon_q November 12, 2018 07:30

Thank you very much for the detailed answer


All times are GMT -4. The time now is 09:09.