00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _HOP_FUNC_H
00011 #define _HOP_FUNC_H
00012
00013 double* addToBuf(
00014 const Eref& e, HopIndex hopIndex, unsigned int size );
00015 void dispatchBuffers( const Eref& e, HopIndex hopIndex );
00016 double* remoteGet( const Eref& e , unsigned int bindIndex );
00017 void remoteGetVec( const Eref& e, unsigned int bindIndex,
00018 vector< vector< double > >& getRecvBuf,
00019 vector< unsigned int >& numOnNode );
00020 void remoteFieldGetVec( const Eref& e, unsigned int bindIndex,
00021 vector< double >& getRecvBuf );
00022 unsigned int mooseNumNodes();
00023 unsigned int mooseMyNode();
00024
00029 class HopFunc0: public OpFunc0Base
00030 {
00031 public:
00032 HopFunc0( HopIndex hopIndex )
00033 : hopIndex_( hopIndex )
00034 {;}
00035 void op( const Eref& e ) const
00036 {
00037 addToBuf( e, hopIndex_, 0 );
00038 dispatchBuffers( e, hopIndex_ );
00039 }
00040 private:
00041 HopIndex hopIndex_;
00042 };
00043
00044
00045 template < class A > class HopFunc1: public OpFunc1Base< A >
00046 {
00047 public:
00048 HopFunc1( HopIndex hopIndex )
00049 : hopIndex_( hopIndex )
00050 {;}
00051 void op( const Eref& e, A arg ) const
00052 {
00053 double* buf = addToBuf( e, hopIndex_, Conv< A >::size( arg ) );
00054 Conv< A >::val2buf( arg, &buf );
00055 dispatchBuffers( e, hopIndex_ );
00056 }
00057
00059 unsigned int localOpVec( Element* elm,
00060 const vector< A >& arg,
00061 const OpFunc1Base< A >* op,
00062 unsigned int k ) const
00063 {
00064 unsigned int numLocalData = elm->numLocalData();
00065 unsigned int start = elm->localDataStart();
00066 for ( unsigned int p = 0; p < numLocalData; ++p ) {
00067 unsigned int numField = elm->numField( p );
00068 for ( unsigned int q = 0; q < numField; ++q ) {
00069 Eref er( elm, p + start, q );
00070 op->op( er, arg[ k % arg.size() ] );
00071 k++;
00072 }
00073 }
00074 return k;
00075 }
00076
00078 unsigned int localFieldOpVec( const Eref& er,
00079 const vector< A >& arg,
00080 const OpFunc1Base< A >* op )
00081 const
00082 {
00083 assert( er.getNode() == mooseMyNode() );
00084 unsigned int di = er.dataIndex();
00085 Element* elm = er.element();
00086 unsigned int numField =
00087 elm->numField( di - er.element()->localDataStart() );
00088 for ( unsigned int q = 0; q < numField; ++q ) {
00089 Eref temp( elm, di, q );
00090 op->op( temp, arg[ q % arg.size() ] );
00091 }
00092 return numField;
00093 }
00094
00096 unsigned int remoteOpVec( const Eref& er,
00097 const vector< A >& arg,
00098 const OpFunc1Base< A >* op,
00099 unsigned int start, unsigned int end ) const
00100 {
00101 unsigned int k = start;
00102 unsigned int nn = end - start;
00103 if ( mooseNumNodes() > 1 && nn > 0 ) {
00104
00105
00106 vector< A > temp( nn );
00107
00108
00109 for ( unsigned int j = 0; j < nn; ++j ) {
00110 unsigned int x = k % arg.size();
00111 temp[j] = arg[x];
00112 k++;
00113 }
00114 double* buf = addToBuf( er, hopIndex_,
00115 Conv< vector< A > >::size( temp ) );
00116 Conv< vector< A > >::val2buf( temp, &buf );
00117 dispatchBuffers( er, hopIndex_ );
00118
00119 }
00120 return k;
00121 }
00122
00123 void dataOpVec( const Eref& e, const vector< A >& arg,
00124 const OpFunc1Base< A >* op ) const
00125 {
00126 Element* elm = e.element();
00127 vector< unsigned int > endOnNode( mooseNumNodes(), 0 );
00128 unsigned int lastEnd = 0;
00129 for ( unsigned int i = 0; i < mooseNumNodes(); ++i ) {
00130 endOnNode[i] = elm->getNumOnNode(i) + lastEnd;
00131 lastEnd = endOnNode[i];
00132 }
00133 unsigned int k = 0;
00134
00135 for ( unsigned int i = 0; i < mooseNumNodes(); ++i ) {
00136 if ( i == mooseMyNode() ) {
00137 k = localOpVec( elm, arg, op, k );
00138 assert( k == endOnNode[i] );
00139 } else {
00140 if ( !elm->isGlobal() ) {
00141 unsigned int start = elm->startDataIndex( i );
00142 if ( start < elm->numData() ) {
00143 Eref starter( elm, start );
00144 assert( elm->getNode( starter.dataIndex() ) == i );
00145 k = remoteOpVec( starter, arg, op, k, endOnNode[i]);
00146 }
00147 }
00148 }
00149 }
00150 if ( elm->isGlobal() ) {
00151 Eref starter( elm, 0 );
00152 remoteOpVec( starter, arg, op, 0, arg.size() );
00153 }
00154 }
00155
00156 void opVec( const Eref& er, const vector< A >& arg,
00157 const OpFunc1Base< A >* op ) const
00158 {
00159 Element* elm = er.element();
00160 if ( elm->hasFields() ) {
00161 if ( er.getNode() == mooseMyNode() ) {
00162
00163 localFieldOpVec( er, arg, op );
00164 }
00165 if ( elm->isGlobal() || er.getNode() != mooseMyNode() ) {
00166
00167
00168 remoteOpVec( er, arg, op, 0, arg.size() );
00169 }
00170 } else {
00171 dataOpVec( er, arg, op );
00172 }
00173 }
00174 private:
00175 HopIndex hopIndex_;
00176 };
00177
00182 template< class A >
00183 const OpFunc* OpFunc1Base< A >::makeHopFunc( HopIndex hopIndex ) const
00184 {
00185 return new HopFunc1< A >( hopIndex );
00186 }
00187
00188
00189 template < class A1, class A2 > class HopFunc2: public OpFunc2Base< A1, A2 >
00190 {
00191 using OpFunc2Base<A1, A2>::opVec;
00192
00193 public:
00194 HopFunc2( HopIndex hopIndex )
00195 : hopIndex_( hopIndex )
00196 {;}
00197 void op( const Eref& e, A1 arg1, A2 arg2 ) const
00198 {
00199 double* buf = addToBuf( e, hopIndex_,
00200 Conv< A1 >::size( arg1 ) + Conv< A2 >::size( arg2 ) );
00201
00202
00203
00204
00205
00206
00207
00208
00209 Conv< A1 >::val2buf( arg1, &buf );
00210 Conv< A2 >::val2buf( arg2, &buf );
00211 dispatchBuffers( e, hopIndex_ );
00212 }
00213
00214 void opVec( const Eref& e,
00215 const vector< A1 >& arg1,
00216 const vector< A1 >& arg2,
00217 const OpFunc2Base< A1, A2 >* op ) const
00218 {
00219 Element* elm = e.element();
00220 unsigned int k = 0;
00221 if ( elm->isGlobal() ) {
00222
00223
00224 }
00225 for ( unsigned int i = 0; i < mooseNumNodes(); ++i ) {
00226 if ( i == mooseMyNode() ) {
00227 unsigned int numData = elm->numLocalData();
00228 for ( unsigned int p = 0; p < numData; ++p ) {
00229 unsigned int numField = elm->numField( p );
00230 for ( unsigned int q = 0; q < numField; ++q ) {
00231 Eref er( elm, p, q );
00232 unsigned int x = k % arg1.size();
00233 unsigned int y = k % arg2.size();
00234 op->op( er, arg1[x], arg2[y] );
00235 k++;
00236 }
00237 }
00238 } else {
00239 unsigned int dataIndex = k;
00240
00241
00242 unsigned int nn = elm->getNumOnNode( i );
00243 vector< A1 > temp1( nn );
00244 vector< A2 > temp2( nn );
00245
00246
00247 for ( unsigned int j = 0; j < nn; ++j ) {
00248 unsigned int x = k % arg1.size();
00249 unsigned int y = k % arg2.size();
00250 temp1[j] = arg1[x];
00251 temp2[j] = arg2[y];
00252 k++;
00253 }
00254 double* buf = addToBuf( e, hopIndex_,
00255 Conv< vector< A1 > >::size( temp1 ) +
00256 Conv< vector< A2 > >::size( temp2 ) );
00257 Conv< vector< A1 > >::val2buf( temp1, &buf );
00258 Conv< vector< A2 > >::val2buf( temp2, &buf );
00259 dispatchBuffers( Eref( elm, dataIndex ), hopIndex_ );
00260
00261 }
00262 }
00263 }
00264 private:
00265 HopIndex hopIndex_;
00266 };
00267
00268 template< class A1, class A2 >
00269 const OpFunc* OpFunc2Base< A1, A2 >::makeHopFunc(
00270 HopIndex hopIndex) const
00271 {
00272 return new HopFunc2< A1, A2 >( hopIndex );
00273 }
00274
00275
00276 template < class A1, class A2, class A3 > class HopFunc3:
00277 public OpFunc3Base< A1, A2, A3 >
00278 {
00279 public:
00280 HopFunc3( HopIndex hopIndex )
00281 : hopIndex_( hopIndex )
00282 {;}
00283
00284 void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3 ) const
00285 {
00286 double* buf = addToBuf( e, hopIndex_,
00287 Conv< A1 >::size( arg1 ) + Conv< A2 >::size( arg2 ) +
00288 Conv< A3 >::size( arg3 ) );
00289 Conv< A1 >::val2buf( arg1, &buf );
00290 Conv< A2 >::val2buf( arg2, &buf );
00291 Conv< A3 >::val2buf( arg3, &buf );
00292 dispatchBuffers( e, hopIndex_ );
00293 }
00294 private:
00295 HopIndex hopIndex_;
00296 };
00297
00298 template< class A1, class A2, class A3 >
00299 const OpFunc* OpFunc3Base< A1, A2, A3 >::makeHopFunc(
00300 HopIndex hopIndex) const
00301 {
00302 return new HopFunc3< A1, A2, A3 >( hopIndex );
00303 }
00304
00305
00306 template < class A1, class A2, class A3, class A4 > class HopFunc4:
00307 public OpFunc4Base< A1, A2, A3, A4 >
00308 {
00309 public:
00310 HopFunc4( HopIndex hopIndex )
00311 : hopIndex_( hopIndex )
00312 {;}
00313
00314 void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3, A4 arg4 ) const
00315 {
00316 double* buf = addToBuf( e, hopIndex_,
00317 Conv< A1 >::size( arg1 ) + Conv< A2 >::size( arg2 ) +
00318 Conv< A3 >::size( arg3 ) + Conv< A4 >::size( arg4 ) );
00319 Conv< A1 >::val2buf( arg1, &buf );
00320 Conv< A2 >::val2buf( arg2, &buf );
00321 Conv< A3 >::val2buf( arg3, &buf );
00322 Conv< A4 >::val2buf( arg4, &buf );
00323 dispatchBuffers( e, hopIndex_ );
00324 }
00325 private:
00326 HopIndex hopIndex_;
00327 };
00328
00329 template< class A1, class A2, class A3, class A4 >
00330 const OpFunc* OpFunc4Base< A1, A2, A3, A4 >::makeHopFunc(
00331 HopIndex hopIndex) const
00332 {
00333 return new HopFunc4< A1, A2, A3, A4 >( hopIndex );
00334 }
00335
00336
00337 template < class A1, class A2, class A3, class A4, class A5 >
00338 class HopFunc5: public OpFunc5Base< A1, A2, A3, A4, A5 >
00339 {
00340 public:
00341 HopFunc5( HopIndex hopIndex )
00342 : hopIndex_( hopIndex )
00343 {;}
00344
00345 void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3,
00346 A4 arg4, A5 arg5 ) const
00347 {
00348 double* buf = addToBuf( e, hopIndex_,
00349 Conv< A1 >::size( arg1 ) + Conv< A2 >::size( arg2 ) +
00350 Conv< A3 >::size( arg3 ) + Conv< A4 >::size( arg4 ) +
00351 Conv< A5 >::size( arg5 ) );
00352 Conv< A1 >::val2buf( arg1, &buf );
00353 Conv< A2 >::val2buf( arg2, &buf );
00354 Conv< A3 >::val2buf( arg3, &buf );
00355 Conv< A4 >::val2buf( arg4, &buf );
00356 Conv< A5 >::val2buf( arg5, &buf );
00357 dispatchBuffers( e, hopIndex_ );
00358 }
00359 private:
00360 HopIndex hopIndex_;
00361 };
00362
00363 template< class A1, class A2, class A3, class A4, class A5 >
00364 const OpFunc* OpFunc5Base< A1, A2, A3, A4, A5 >::makeHopFunc(
00365 HopIndex hopIndex) const
00366 {
00367 return new HopFunc5< A1, A2, A3, A4, A5 >( hopIndex );
00368 }
00369
00370
00371 template < class A1, class A2, class A3, class A4, class A5, class A6 >
00372 class HopFunc6: public OpFunc6Base< A1, A2, A3, A4, A5, A6 >
00373 {
00374 public:
00375 HopFunc6( HopIndex hopIndex )
00376 : hopIndex_( hopIndex )
00377 {;}
00378
00379 void op( const Eref& e, A1 arg1, A2 arg2, A3 arg3,
00380 A4 arg4, A5 arg5, A6 arg6 ) const
00381 {
00382 double* buf = addToBuf( e, hopIndex_,
00383 Conv< A1 >::size( arg1 ) + Conv< A2 >::size( arg2 ) +
00384 Conv< A3 >::size( arg3 ) + Conv< A4 >::size( arg4 ) +
00385 Conv< A5 >::size( arg5 ) + Conv< A6 >::size( arg6 ) );
00386 Conv< A1 >::val2buf( arg1, &buf );
00387 Conv< A2 >::val2buf( arg2, &buf );
00388 Conv< A3 >::val2buf( arg3, &buf );
00389 Conv< A4 >::val2buf( arg4, &buf );
00390 Conv< A5 >::val2buf( arg5, &buf );
00391 Conv< A6 >::val2buf( arg6, &buf );
00392 dispatchBuffers( e, hopIndex_ );
00393 }
00394 private:
00395 HopIndex hopIndex_;
00396 };
00397
00398 template< class A1, class A2, class A3, class A4, class A5, class A6 >
00399 const OpFunc* OpFunc6Base< A1, A2, A3, A4, A5, A6 >::makeHopFunc(
00400 HopIndex hopIndex) const
00401 {
00402 return new HopFunc6< A1, A2, A3, A4, A5, A6 >( hopIndex );
00403 }
00404
00405
00406
00407 template < class A > class GetHopFunc: public OpFunc1Base< A* >
00408 {
00409 public:
00410 GetHopFunc( HopIndex hopIndex )
00411 : hopIndex_( hopIndex )
00412 {;}
00413
00414 void op( const Eref& e, A* ret ) const
00415 {
00416 double* buf = remoteGet( e, hopIndex_.bindIndex() );
00417 *ret = Conv< A >::buf2val( &buf );
00418 }
00419
00420 void getLocalFieldVec( const Eref& er, vector< A >& ret,
00421 const GetOpFuncBase< A >* op ) const
00422 {
00423 unsigned int p = er.dataIndex();
00424 Element* elm = er.element();
00425 unsigned int numField = elm->numField(
00426 p - elm->localDataStart() );
00427 for ( unsigned int q = 0; q < numField; ++q ) {
00428 Eref temp( elm, p, q );
00429 ret.push_back( op->returnOp( temp ) );
00430 }
00431 }
00432
00433 void getRemoteFieldVec( const Eref& e, vector< A >& ret,
00434 const GetOpFuncBase< A >* op ) const
00435 {
00436 vector< double > buf;
00437 remoteFieldGetVec( e, hopIndex_.bindIndex(), buf );
00438 assert( buf.size() > 0 );
00439 unsigned int numField = buf[0];
00440 double* val = &buf[1];
00441 for ( unsigned int j = 0; j < numField; ++j ) {
00442 ret.push_back( Conv< A >::buf2val( &val ) );
00443 }
00444 }
00445
00446 void getLocalVec( Element *elm, vector< A >& ret,
00447 const GetOpFuncBase< A >* op ) const
00448 {
00449 unsigned int start = elm->localDataStart();
00450 unsigned int end = start + elm->numLocalData();
00451 for ( unsigned int p = start; p < end; ++p ) {
00452 Eref er( elm, p, 0 );
00453 ret.push_back( op->returnOp( er ) );
00454 }
00455 }
00456
00457 void getMultiNodeVec( const Eref& e, vector< A >& ret,
00458 const GetOpFuncBase< A >* op ) const
00459 {
00460 Element* elm = e.element();
00461 vector< vector< double > > buf;
00462 vector< unsigned int > numOnNode;
00463 remoteGetVec( e, hopIndex_.bindIndex(), buf, numOnNode );
00464 assert( numOnNode.size() == mooseNumNodes() );
00465 assert( buf.size() == mooseNumNodes() );
00466 assert( buf.size() == numOnNode.size() );
00467 for ( unsigned int i = 0; i < mooseNumNodes(); ++i ) {
00468 if ( i == mooseMyNode() ) {
00469 getLocalVec( elm, ret, op );
00470 } else {
00471 vector< double >& temp = buf[i];
00472 assert( static_cast< unsigned int >( temp[0] ) ==
00473 numOnNode[i] );
00474 double* val = &temp[1];
00475 for ( unsigned int j = 0; j < numOnNode[i]; ++j ) {
00476
00477
00478 ret.push_back( Conv< A >::buf2val( &val ) );
00479 }
00480 }
00481 }
00482 }
00483
00484 void opGetVec( const Eref& e, vector< A >& ret,
00485 const GetOpFuncBase< A >* op ) const
00486 {
00487 Element* elm = e.element();
00488 ret.clear();
00489 ret.reserve( elm->numData() );
00490 if ( elm->hasFields() ) {
00491 if ( e.getNode() == mooseMyNode() ) {
00492 getLocalFieldVec( e, ret, op );
00493 } else {
00494 getRemoteFieldVec( e, ret, op );
00495 }
00496 } else {
00497 if ( mooseNumNodes() == 1 || elm->isGlobal() ) {
00498 getLocalVec( elm, ret, op );
00499 } else {
00500 getMultiNodeVec( e, ret, op );
00501 }
00502 }
00503 }
00504 private:
00505 HopIndex hopIndex_;
00506 };
00507
00512 template< class A >
00513 const OpFunc* GetOpFuncBase< A >::makeHopFunc( HopIndex hopIndex ) const
00514 {
00515 return new GetHopFunc< A >( hopIndex );
00516 }
00517
00518 #endif // _HOP_FUNC_H