2 FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
3 Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
35 void GeomX::FreeBuffers ()
37 for (int n=0; n < (int) mBuf.size(); n++) {
38 free ( mBuf[n].data );
43 if ( mHeap != 0x0 ) free ( mHeap );
49 void GeomX::ResetHeap ()
57 int sum = mHeapNum * sizeof(hval) ;
58 for (int n=0; n < (int) mBuf.size(); n++)
60 sum += (int) mAttribute.size() * sizeof(GeomAttr);
64 void GeomX::ClearAttributes ()
69 int GeomX::CopyBuffer ( uchar bdest, uchar bsrc, GeomX& src )
71 if ( bsrc >= src.GetNumBuf() ) return -1;
73 if ( bdest >= GetNumBuf() ) {
74 for (int n=0; n <= bdest - GetNumBuf(); n++ )
75 AddBuffer ( 0, 0, 0 );
77 if ( mBuf[bdest].data != 0x0 ) {
78 free ( mBuf[bdest].data );
79 mBuf[bdest].data = 0x0;
82 GeomBuf* buf = src.GetBuffer( bsrc );
83 mBuf[bdest].dtype = buf->dtype;
84 mBuf[bdest].max = buf->max;
85 mBuf[bdest].num = buf->num;
86 mBuf[bdest].stride = buf->stride;
87 mBuf[bdest].size = buf->size;
88 mBuf[bdest].data = (char*) malloc ( mBuf[bdest].max * mBuf[bdest].stride );
89 memcpy ( mBuf[bdest].data, buf->data, mBuf[bdest].num * mBuf[bdest].stride );
95 void GeomX::CopyBuffers ( GeomX& src )
98 for (int n = 0; n < src.GetNumBuf(); n++)
99 CopyBuffer ( n, n, src );
103 void GeomX::CopyHeap ( GeomX& src )
105 hpos num, max, freepos;
106 hval* src_data = src.GetHeap ( num, max, freepos );
108 if ( mHeap != 0x0 ) {
113 mHeap = (hval*) malloc ( max * sizeof(hval) );
118 memcpy ( mHeap, src_data, mHeapNum * sizeof(hval) );
121 hval* GeomX::GetHeap ( hpos& num, hpos& max, hpos& free )
129 void GeomX::CopyAttributes ( GeomX& src )
134 for (int n = 0; n < src.GetNumAttr(); n++) {
135 attr = src.GetAttribute ( n );
136 a = AddAttribute ( (uchar) attr->buf, attr->name, attr->stride, false );
137 mAttribute[a].offset = attr->offset;
142 void GeomX::AddHeap ( int max )
144 mHeap = (hval*) malloc ( max * sizeof(hval ) );
150 int GeomX::AddAttribute ( uchar b, std::string name, ushort stride )
152 return AddAttribute ( b, name, stride, true );
155 int GeomX::AddAttribute ( uchar b, std::string name, ushort stride, bool bExtend )
157 GeomBuf* buf = &mBuf[b];
162 attr.offset = buf->stride;
163 attr.stride = stride;
166 int new_stride = buf->stride + attr.stride;
167 char* new_data = (char*) malloc ( buf->max * new_stride );
168 char* old_data = buf->data;
169 for (int n=0; n < buf->num; n++) {
170 memcpy ( new_data, old_data, buf->stride );
171 old_data += buf->stride;
172 new_data += new_stride;
175 buf->data = new_data;
176 buf->stride = new_stride;
178 mAttribute.push_back ( attr );
179 return (int) mAttribute.size()-1;
182 int GeomX::GetAttribute ( std::string name )
184 for (int n=0; n < (int) mAttribute.size(); n++) {
185 if ( mAttribute[n].name.compare ( name ) == 0 )
191 int GeomX::GetAttrOffset ( std::string name )
193 for (int n=0; n < (int) mAttribute.size(); n++) {
194 if ( mAttribute[n].name.compare ( name ) == 0 )
195 return mAttribute[n].offset;
200 int GeomX::AddBuffer ( uchar typ, ushort stride, int max )
208 buf.data = (char*) malloc ( buf.max * buf.stride );
209 mBuf.push_back ( buf );
210 return (int) mBuf.size()-1;
212 void GeomX::ResetBuffer ( uchar b, int n )
216 if ( mBuf[b].data != 0x0 ) free ( mBuf[b].data );
218 char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
220 mBuf[b].data = new_data;
223 mBuf[b].size = mBuf[b].num*mBuf[b].stride;
226 char* GeomX::AddElem ( uchar b, href& ndx )
228 if ( mBuf[b].num >= mBuf[b].max ) {
229 if ( long(mBuf[b].max) * 2 > ELEM_MAX ) {
230 error.PrintF ( "geom", "Maximum number of elements reached.\n" );
234 char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
235 memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride );
236 free ( mBuf[b].data );
237 mBuf[b].data = new_data;
240 mBuf[b].size += mBuf[b].stride;
242 return mBuf[b].data + ndx*mBuf[b].stride;
245 char* GeomX::RandomElem ( uchar b, href& ndx )
247 ndx = mBuf[b].num * rand() / RAND_MAX;
248 return mBuf[b].data + ndx*mBuf[b].stride;
251 int GeomX::AddElem ( uchar b, char* data )
253 if ( mBuf[b].num >= mBuf[b].max ) {
255 char* new_data = (char*) malloc ( mBuf[b].max * mBuf[b].stride );
256 memcpy ( new_data, mBuf[b].data, mBuf[b].num*mBuf[b].stride );
257 free ( mBuf[b].data );
258 mBuf[b].data = new_data;
260 memcpy ( mBuf[b].data + mBuf[b].num*mBuf[b].stride, data, mBuf[b].stride );
262 mBuf[b].size += mBuf[b].stride;
263 return mBuf[b].num-1;
266 bool GeomX::DelElem ( uchar b, int n )
268 if ( n >= 0 && n < mBuf[b].num ) {
269 memcpy ( mBuf[b].data + n*mBuf[b].stride, mBuf[b].data + (mBuf[b].num-1)*mBuf[b].stride, mBuf[b].stride );
271 mBuf[b].size -= mBuf[b].stride;
277 hpos GeomX::HeapExpand ( ushort size, ushort& ret )
280 if ( mHeapMax > HEAP_MAX ) {
281 error.PrintF ( "geom", "Geom heap size exceeds range of index.\n" );
284 hval* pNewHeap = (hval*) malloc ( mHeapMax * sizeof(hval) );
285 if ( pNewHeap == 0x0 ) {
286 error.PrintF ( "geom", "Geom heap out of memory.\n" );
289 memcpy ( pNewHeap, mHeap, mHeapNum*sizeof(hval) );
293 assert ( mHeapNum >= 0 && mHeapNum < mHeapMax );
299 hpos GeomX::HeapAlloc ( ushort size, ushort& ret )
302 hval* pCurr = mHeap + mHeapFree;
305 if ( mHeapNum + size < mHeapMax ) {
306 // Heap not yet full.
311 // Heap full, search free space
312 if ( mHeapFree == -1 ) {
313 pos = HeapExpand ( size, ret );
316 while ( *pCurr < size && pCurr != mHeap-1 ) {
318 pCurr = mHeap + * (hpos*) (pCurr + FPOS);
320 if ( pCurr != mHeap-1 ) {
322 if ( pPrev == 0x0 ) {
323 mHeapFree = * (hpos*) (pCurr + FPOS);
324 assert ( mHeapFree >= -1 );
326 * (hpos*) (pPrev+FPOS) = * (hpos*) (pCurr+FPOS);
331 // Heap full, no free space. Expand heap.
332 pos = HeapExpand ( size, ret );
338 assert ( pos >= 0 && pos <= mHeapNum );
339 memset ( mHeap+pos, 0, size*sizeof(hval) );
343 void GeomX::HeapAddFree ( hpos pos, int size )
345 // memset ( mHeap+pos, 0xFF, size*sizeof(hval) );
347 if ( pos < mHeapFree || mHeapFree == -1 ) {
348 // Lowest position. Insert at head of heap.
349 * (hpos*) (mHeap+pos) = size;
350 * (hpos*) (mHeap+pos + FPOS) = mHeapFree;
352 if ( mHeapFree != -1 && *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d\n", pos ); error.Exit (); }
354 assert ( mHeapFree >= -1 );
356 hval* pCurr = mHeap + pos;
358 hval* pNext = mHeap + mHeapFree;
360 if ( pCurr == pNext ) { // Freeing the first block
361 mHeapFree = * (hpos*) (pCurr + FPOS);
362 * (hpos*) (mHeap+mHeapFree + FPOS) = 0xFFFFFFFF;
363 * (hpos*) (pCurr + FPOS) = 0xFFFFFFFF;
364 * (hpos*) pCurr = 0xFFFFFFFF;
369 // Find first block greater than new free pos.
370 while ( pNext < pCurr && pNext != mHeap-1 ) {
372 pNext = mHeap + * (hpos*) (pNext + FPOS);
376 if ( pPrev + *(pPrev) == pCurr ) { // Prev block touches current one (expand previous)
377 * (hpos*) pPrev += size; // - prev.size = prev.size + curr.size
380 } else if ( pCurr + size == pNext && pNext != mHeap-1 ) { // Curr block touches next one (expand current block)
381 * (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr
382 * (hpos*) (pCurr + FPOS) = * (hpos*) (pNext + FPOS); // - curr.next = next.next
383 * (hpos*) pCurr = size + * (hpos*) pNext; // - curr.size = size + next.size
384 * (hpos*) (pNext) = 0xFFFFFFFF; // - curr = null
385 * (hpos*) (pNext + FPOS) = 0xFFFFFFFF; // - curr.next = null
388 } else { // Otherwise (linked list insert)
389 * (hpos*) (pPrev + FPOS) = pos; // - prev.next = curr
390 if ( pNext != mHeap-1 )
391 * (hpos*) (pCurr + FPOS) = pNext - mHeap; // - curr.next = next
393 * (hpos*) (pCurr + FPOS) = 0xFFFFFFFF; // - curr.next = null (no next node)
394 * (hpos*) pCurr = size; // - curr.size = size
397 if ( pCurr !=mHeap-1 && *(hpos*) (pCurr+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pCurr, %d, %d\n", x, pos ); error.Exit (); }
398 if ( pPrev !=mHeap-1 && *(hpos*) (pPrev+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pPrev, %d, %d\n", x, pos ); error.Exit (); }
399 if ( pNext !=mHeap-1 && *(hpos*) (pNext+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pNext, %d, %d\n", x, pos ); error.Exit (); }
400 if ( *(hpos*) (mHeap+mHeapFree+FPOS) == 0x0 ) { error.PrintF ( "geomx", "ERROR: Heap pointer 0. pHeapFree, %d, %d\n", x, pos ); error.Exit (); }
402 // -- check for bugs (remove eventually)
403 pNext = mHeap + mHeapFree;
404 while ( pNext != mHeap-1 ) {
406 pNext = mHeap + * (hpos*) (pNext + FPOS);
407 if ( pNext < pPrev && pNext != mHeap-1 ) {
408 error.PrintF ( "geomx", "ERROR: Heap free space out of order. %d, %d\n", x, pos );
416 void GeomX::ClearRefs ( hList& list )
423 hval GeomX::AddRef ( hval r, hList& list, hval delta )
425 if ( list.max == 0 ) {
427 list.pos = HeapAlloc ( LIST_INIT, list.max );
428 *(mHeap + list.pos) = r+delta;
430 if ( list.cnt >= list.max ) {
432 hpos new_pos = HeapAlloc ( siz+LIST_INIT, list.max ); // Alloc new location
433 //printf ( "MOVE %d -> %d\n", list.pos, new_pos );
434 memcpy ( mHeap+new_pos, mHeap+list.pos, list.cnt*sizeof(hval) ); // Copy data to new location
435 HeapAddFree ( list.pos, siz ); // Free old location
439 *(mHeap + list.pos + list.cnt) = r+delta;