CFD Online Discussion Forums

CFD Online Discussion Forums (http://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (http://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Append scalar to scalarField (http://www.cfd-online.com/Forums/openfoam-programming-development/93821-append-scalar-scalarfield.html)

Hisham October 27, 2011 07:34

Append scalar to scalarField
 
Dear Foamers,

I need to expand a scalarField size by one for each time step. How can I append a scalar to a scalarField?

Regards
Hisham

deepsterblue October 27, 2011 08:36

You can use the setSize(const label, const T&) member function in the List class (where Field is derived from) to increment its size (by 1 or any other number). This automatically copies values from the old field, and fills the remaining space with a value that you specify.

Take a look at List.C / List.H.

Hisham October 27, 2011 09:08

Thanks a lot! There is also an append function for the list class

Regards
Hisham

tomislav_maric October 27, 2011 10:31

Quote:

Originally Posted by Hisham (Post 329702)
Dear Foamers,

I need to expand a scalarField size by one for each time step. How can I append a scalar to a scalarField?

Regards
Hisham


Will this not be expensive because of the memory copying taking place?

Code:

T* nv = new T[label(newSize)];
From List.C:setSize... append will do the same becaues it is a wrapper for setSize. There is some memcpy option inside, which does the following:

Code:

void * memcpy ( void * destination, const void * source, size_t num );
  Copy block of memory
 Copies the values of num bytes from the location pointed by source directly to the memory block pointed by destination.

If you have a large set of data that doesn't require direct access, you can use DynamicList<T>...

Hisham October 27, 2011 10:54

Thanks Tomislav,

This feels more professional :D

Regards
Hisham

tomislav_maric October 28, 2011 10:02

Quote:

Originally Posted by Hisham (Post 329749)
Thanks Tomislav,

This feels more professional :D

Regards
Hisham

Hi Hisham:

that feeling was wrong for the both of us. It seems that the DynamicList is nothing more than a wrapper for List<T> when it comes to expanding the storage.

If you take a look at DynamicListI.H and inspect the append method:

Code:

00309 inline void Foam::DynamicList<T, SizeInc, SizeMult, SizeDiv>::append
00310 (
00311    const T& t
00312 )
00313 {
00314    label elemI = List<T>::size();
00315    setSize(elemI + 1);
00316
00317    this->operator[](elemI) = t;
00318 }
00319

The "setSize" seemed suspicious to me because I have already seen it in List<T>, and,
guess what the DynamicList::setSize does:


Code:

00173    if (nElem > capacity_)
00174    {
00175 // TODO: convince the compiler that division by zero does not occur
00176 //        if (SizeInc && (!SizeMult || !SizeDiv))
00177 //        {
00178 //            // resize with SizeInc as the granularity
00179 //            capacity_ = nElem;
00180 //            unsigned pad = SizeInc - (capacity_ % SizeInc);
00181 //            if (pad != SizeInc)
00182 //            {
00183 //                capacity_ += pad;
00184 //            }
00185 //        }
00186 //        else
00187        {
00188            capacity_ = max
00189            (
00190                nElem,
00191                label(SizeInc + capacity_ * SizeMult / SizeDiv)
00192            );
00193        }
00194
00195        List<T>::setSize(capacity_);
00196    }
00197

It calls the List<T>::setSize. And this function copies the entire list using memcpy.

What I don't get is why would one wrap a List<T> into something called "DynamicList"
if the underlying engine is based on something like (from UList<T>):

Code:

this->v_ = new T[this->size_];
and not a pointer... well, I have some work to do over the weekend, I think the actual pointer based
list that allows for appending without memcopy would be LList (Linked List),
but I need to check that out...

Of course it was wrong, why would it be right? :D

T.

deepsterblue October 28, 2011 10:26

Quote:

Originally Posted by tomislav_maric (Post 329887)

What I don't get is why would one wrap a List<T> into something called "DynamicList"
if the underlying engine is based on something like (from UList<T>):

It's not a simple wrap around List<T>. It's true that the underlying memory-handling is done by List<T>, but allocations/deallocations and memcpy's are rare. The idea is to pre-allocate a region of memory (larger than the current list), and use that by operating DynamicList with the append() / remove() methods - which, if you look at sources, merely sets the UList::size_ value to change addressed memory.

If and when increased capacity is required, additional memory is allocated (typically twice current capacity), so appends / removes can continue happily.

tomislav_maric October 28, 2011 15:38

Quote:

Originally Posted by deepsterblue (Post 329894)
It's not a simple wrap around List<T>. It's true that the underlying memory-handling is done by List<T>, but allocations/deallocations and memcpy's are rare. The idea is to pre-allocate a region of memory (larger than the current list), and use that by operating DynamicList with the append() / remove() methods - which, if you look at sources, merely sets the UList::size_ value to change addressed memory.

If and when increased capacity is required, additional memory is allocated (typically twice current capacity), so appends / removes can continue happily.

Hi Sandeep,

I didn't say it was "just a simple wrapper around List", I said:

"
DynamicList is nothing more than a wrapper for List<T> when it comes to expanding the storage."

and that's, well, true. :D

memcpy or not, it uses simple arrays on the low level. This means that it has to create a completely new list in one way or the other (for the sake of this argument, it makes absolutely no difference in which way the copying is taking place), in order to append something to the existing one, in a logical sense. From List::setSize:

Code:

00327    if (newSize != this->size_)
00328    {
00329        if (newSize > 0)
00330        {
00331            T* nv = new T[label(newSize)];

And then it goes either into memcpy or copies the data via pointer...

That's what's in the code anyway.... or am I reading it wrong?

T.

deepsterblue October 28, 2011 15:45

The new list is created only when the underlying storage is filled to capacity. Anyhow, I can't think of a better way to do this, so I consider this optimal.

tomislav_maric October 28, 2011 15:58

Quote:

Originally Posted by deepsterblue (Post 329924)
The new list is created only when the underlying storage is filled to capacity. Anyhow, I can't think of a better way to do this, so I consider this optimal.

If there is no way for me to guess the size of the list, which is happening actually in what I'm trying to code around every corner, then it will always re-create the list. If I do this for 10-20% of all the cells in the mesh, 10 times in average per time step, that will be a lot of copying.

If I want to use a linked list, it may save more time, but may not, because there will be a price to pay if I need to acces n-th element directly in the fact that it will take (textbook quote) "linear time" to get to it by using an iterator.

Now the real question is, for small lists that span from 10 to 100 elements, say hundred thousand of them within a time-step scope, do I use "dynamic" storage of DynamicList, or dynamic storage provided by a Linked List.

The only thing that comes to my mind is to benchmark this somehow, but what I read about benchmarking makes it seem evil. :D

The question I had was because I'm used to thinking about dynamical storage in the sense of lists that actually create memory space for an element, and use pointers to access that. This is why the name DynamicList threw me off.

I have no idea for the motivation behind this (I'm not the developer, nor had any of the guys/girls that wrote this explained the background to me), and I'm not saying its wrong or something, it's just that I find the name confusing (especially with the coment that says something about automatically resizing... ). :D

deepsterblue October 28, 2011 16:07

Choosing a particular container depends on how you would like to use it. If you want random access into a linked list, then a hash table would be a good choice, but you'll take a hit with performance due to cache misses. If linear traversal is of priority, then nothing beats a regular array.

I've used the DynamicList / DynamicField functionality quite extensively, and I find that it strikes an optimal balance with speed and flexibility of storage. But again, something that works for me doesn't necessarily translate to general applicability.

tomislav_maric October 28, 2011 16:17

Well, right now I've coded everything with DynamicList, and it seems to be working with O.K. speed. I don't think I'll touch this untill the coupling with the CFD solution... that's something that just came to my mind.... heaven knows how will all this compare to the governing system solution. If the total computational time is in order of few % of the governing system solution, it will make no sense to change it.

That is if I ever get to the point of solving the system. Wish me luck.. I'll need it. :D

Hisham October 28, 2011 19:42

Hi Tomislav and Sandeep,

Thanks a lot for your posts. Much food for thought :)

My problem is about a dynamic container that is unique for the domain (actually they are two). Its size is a user input and after a little thought I need to trim the first element and append a new element at the end and renumber the elements for each time step (so the defined size is constant). Luckily, this is not for each cell. I started using a dynamic allocation of an array. I will look to your suggestions in more details.

Nevertheless, considering the new infos, how can one does this in the optimum Foam way?

Regards,
Hisham


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