Modifications to help move towards CUDA port
authorIsaac Dooley <idooley2@illinois.edu>
Mon, 5 Mar 2007 21:30:10 +0000 (21:30 +0000)
committerIsaac Dooley <idooley2@illinois.edu>
Mon, 5 Mar 2007 21:30:10 +0000 (21:30 +0000)
src/libs/ck-libs/ParFUM-Tops/ParFUM_TOPS.C
src/libs/ck-libs/ParFUM-Tops/ParFUM_TOPS.h
src/libs/ck-libs/ParFUM-Tops/ParFUM_TOPS_Iterators.C

index 938f577408cdcd439762181c1f7ec7ff5fe8a581..705edf4d4253fb852451287ec8fbdf684df4f2de 100644 (file)
@@ -2,14 +2,14 @@
 
    @file
    @brief Implementation of ParFUM-TOPS layer, except for Iterators
-   
+
    @author Isaac Dooley
 
    @todo add code to generate ghost layers
    @todo Support multiple models
 
    @note FEM_DATA+0 holds the elemAttr or nodeAtt data
-   @note FEM_DATA+1 holds the id 
+   @note FEM_DATA+1 holds the id
    @note FEM_CONN holds the element connectivity
    @note FEM_COORD holds the nodal coordinates
 
@@ -26,13 +26,14 @@ TopModel* topModel_Create_Init(int elem_attr_sz, int node_attr_sz){
   CkAssert(node_attr_sz > 0);
   elem_attr_size = elem_attr_sz;
   node_attr_size = node_attr_sz;
+  TopModel *model = new TopModel;
 
   // This only uses a single mesh, so better not create multiple ones of these
   int which_mesh=FEM_Mesh_default_write();
-  FEM_Mesh *mesh = FEM_Mesh_lookup(which_mesh,"TopModel::TopModel()");
+  model->mesh = FEM_Mesh_lookup(which_mesh,"TopModel::TopModel()");
 
   char* temp_array = new char[16]; // just some junk array to use below
-  
+
   // Allocate element connectivity
   FEM_Mesh_data(which_mesh,FEM_ELEM+0,FEM_CONN,temp_array, 0, 0, FEM_INDEX_0, 4);
   // Allocate element attributes
@@ -49,49 +50,88 @@ TopModel* topModel_Create_Init(int elem_attr_sz, int node_attr_sz){
 
   delete[] temp_array;
 
-  // Don't Allocate the Global Number attribute for the elements and nodes  
+  // Don't Allocate the Global Number attribute for the elements and nodes
   // It will be automatically created upon calls to void FEM_Entity::setGlobalno(int r,int g) {
 
   FEM_Mesh_allocate_valid_attr(which_mesh, FEM_NODE);
   FEM_Mesh_allocate_valid_attr(which_mesh, FEM_ELEM+0);
-  
+
 
   // Setup ghost layers, assume Tet4
   // const int tet4vertices[4] = {0,1,2,3};
   //  FEM_Add_ghost_layer(1,1);
   // FEM_Add_ghost_elem(0,4,tet4vertices);
 
-  return mesh;
+  return model;
 }
 
-TopModel* topModel_Create_Driver(int elem_attr_sz, int node_attr_sz){
-  // This only uses a single mesh, so don't create multiple TopModels of these
-  CkAssert(elem_attr_sz > 0);
-  CkAssert(node_attr_sz > 0);
-  elem_attr_size = elem_attr_sz;
-  node_attr_size = node_attr_sz;
-  int which_mesh=FEM_Mesh_default_read();
-  FEM_Mesh *mesh = FEM_Mesh_lookup(which_mesh,"TopModel::TopModel()");
-  return mesh;
+TopModel* topModel_Create_Driver(int elem_attr_sz, int node_attr_sz, int model_attr_sz, void *mAtt){
+    // This only uses a single mesh, so don't create multiple TopModels of these
+    CkAssert(elem_attr_sz > 0);
+    CkAssert(node_attr_sz > 0);
+    elem_attr_size = elem_attr_sz;
+    node_attr_size = node_attr_sz;
+    int which_mesh=FEM_Mesh_default_read();
+    TopModel *model = new TopModel;
+
+    model->mesh = FEM_Mesh_lookup(which_mesh,"TopModel::TopModel()");
+
+#if CUDA
+    /** Copy element Attribute array to device global memory */
+    {
+        FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->elem[0].lookup(FEM_DATA+0,"topModel_Create_Driver");
+        AllocTable2d<unsigned char> &dataTable  = at->getChar();
+        unsigned char *ElemData = dataTable.getData();
+        int size = at->size();
+        cudaMalloc(size, (void**)&(model->ElemDataDevice));
+        cudaMemcpy(ElemDataDevice,ElemData,size,cudaMemcpyHostToDevice);
+    }
+
+    /** Copy node Attribute array to device global memory */
+    {
+        FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+0,"topModel_Create_Driver");
+        AllocTable2d<unsigned char> &dataTable  = at->getChar();
+        unsigned char *NodeData = dataTable.getData();
+        int size = at->size();
+        cudaMalloc(size, (void**)&(model->NodeDataDevice));
+        cudaMemcpy(NodeDataDevice,NodeData,size,cudaMemcpyHostToDevice);
+    }
+
+    /** Copy model Attribute to device global memory */
+    {
+        cudaMalloc(sizeof(ModelAtt), (void**)&(model->mAttDevice));
+        cudaMemcpy(mAttDevice,mAtt,sizeof(ModelAtt),cudaMemcpyHostToDevice);
+    }
+#endif
+
+    return model;
 }
 
+
+/** Cleanup a model */
 void topModel_Destroy(TopModel* m){
+#if CUDA
+    cudaFree(m->mAttDevice);
+    cudaFree(m->NodeDataDevice);
+    cudaFree(m->ElemDataDevice);
+#endif
+    delete m;
 }
 
 
 TopNode topModel_InsertNode(TopModel* m, double x, double y, double z){
-  int newNode = FEM_add_node_local(m,false,false,false);
-  m->node.set_coord(newNode,x,y,z);
+  int newNode = FEM_add_node_local(m->mesh,false,false,false);
+  m->mesh->node.set_coord(newNode,x,y,z);
   return newNode;
 }
 
 
-/** Set id of a node 
+/** Set id of a node
 @todo Make this work with ghosts
 */
 void topNode_SetId(TopModel* m, TopNode n, TopID id){
   CkAssert(n>=0);
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->node.lookup(FEM_DATA+1,"topNode_SetId");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+1,"topNode_SetId");
   at->getInt()(n,0)=id;
 }
 
@@ -103,72 +143,72 @@ TopElement topModel_InsertElem(TopModel*m, TopElemType type, TopNode* nodes){
   conn[1] = nodes[1];
   conn[2] = nodes[2];
   conn[3] = nodes[3];
-  int newEl = FEM_add_element_local(m, conn, 4, 0, 0, 0);
+  int newEl = FEM_add_element_local(m->mesh, conn, 4, 0, 0, 0);
   return newEl;
 }
 
-/** Set id of an element 
+/** Set id of an element
 @todo Make this work with ghosts
 */
 void topElement_SetId(TopModel* m, TopElement e, TopID id){
   CkAssert(e>=0);
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->elem[0].lookup(FEM_DATA+1,"topElement_SetId");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->elem[0].lookup(FEM_DATA+1,"topElement_SetId");
   at->getInt()(e,0)=id;
 }
 
 
 
-/** 
-       @brief Set attribute of a node 
-       
-       The attribute passed in must be a contiguous data structure with size equal to the value node_attr_sz passed into topModel_Create_Driver() and topModel_Create_Init() 
+/**
+       @brief Set attribute of a node
+
+       The attribute passed in must be a contiguous data structure with size equal to the value node_attr_sz passed into topModel_Create_Driver() and topModel_Create_Init()
 
-       The supplied attribute will be copied into the ParFUM attribute array "FEM_DATA+0". Then ParFUM will own this data. The function topNode_GetAttrib() will return a pointer to the copy owned by ParFUM. If a single material parameter attribute is used for multiple nodes, each node will get a separate copy of the array. Any subsequent modifications to the data will only be reflected at a single node. 
+       The supplied attribute will be copied into the ParFUM attribute array "FEM_DATA+0". Then ParFUM will own this data. The function topNode_GetAttrib() will return a pointer to the copy owned by ParFUM. If a single material parameter attribute is used for multiple nodes, each node will get a separate copy of the array. Any subsequent modifications to the data will only be reflected at a single node.
 
        The user is responsible for deallocating parameter d passed into this function.
 
 */
 void topNode_SetAttrib(TopModel* m, TopNode n, void* d){
   CkAssert(n>=0);
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->node.lookup(FEM_DATA+0,"topNode_SetAttrib");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+0,"topNode_SetAttrib");
   AllocTable2d<unsigned char> &dataTable  = at->getChar();
   unsigned char *data = dataTable.getData();
   memcpy(data + n*node_attr_size, d, node_attr_size);
 }
 
-/** @brief Set attribute of an element 
+/** @brief Set attribute of an element
 See topNode_SetAttrib() for description
 */
 void topElement_SetAttrib(TopModel* m, TopElement e, void* d){
   CkAssert(e>=0);
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->elem[0].lookup(FEM_DATA+0,"topElem_SetAttrib");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->elem[0].lookup(FEM_DATA+0,"topElem_SetAttrib");
   AllocTable2d<unsigned char> &dataTable  = at->getChar();
   unsigned char *data = dataTable.getData();
   memcpy(data + e*elem_attr_size, d, elem_attr_size);
 }
 
 
-/** @brief Get elem attribute 
+/** @brief Get elem attribute
 See topNode_SetAttrib() for description
 */
 void* topElement_GetAttrib(TopModel* m, TopElement e){
-  if(! m->elem[0].is_valid_any_idx(e))
+  if(! m->mesh->elem[0].is_valid_any_idx(e))
        return NULL;
 
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->elem[0].lookup(FEM_DATA+0,"topElem_GetAttrib");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->elem[0].lookup(FEM_DATA+0,"topElem_GetAttrib");
   AllocTable2d<unsigned char> &dataTable  = at->getChar();
   unsigned char *data = dataTable.getData();
   return (data + e*elem_attr_size);
 }
 
-/** @brief Get nodal attribute 
+/** @brief Get nodal attribute
 See topNode_SetAttrib() for description
 */
 void* topNode_GetAttrib(TopModel* m, TopNode n){
-  if(! m->node.is_valid_any_idx(n))
+  if(! m->mesh->node.is_valid_any_idx(n))
        return NULL;
 
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->node.lookup(FEM_DATA+0,"topNode_GetAttrib");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+0,"topNode_GetAttrib");
   AllocTable2d<unsigned char> &dataTable  = at->getChar();
   unsigned char *data = dataTable.getData();
   return (data + n*node_attr_size);
@@ -176,15 +216,15 @@ void* topNode_GetAttrib(TopModel* m, TopNode n){
 
 
 
-/** 
-       Get node via id 
-       @todo Re-implement this function with some hash to make it fast. 
+/**
+       Get node via id
+       @todo Re-implement this function with some hash to make it fast.
        @note In the explicit FEA example, this is just used during initialization, so speed is not too important.
        @todo Does not work with ghosts yet.
 */
 TopNode topModel_GetNodeAtId(TopModel* m, TopID id){
   // lookup node via global ID
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->node.lookup(FEM_DATA+1,"topModel_GetNodeAtId");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+1,"topModel_GetNodeAtId");
   for(int i=0;i<at->getInt().size();++i){
        if(at->getInt()(i,0)==id){
          return i;
@@ -193,7 +233,7 @@ TopNode topModel_GetNodeAtId(TopModel* m, TopID id){
   return -1;
 }
 
-/** 
+/**
        Get elem via id
        @todo Implement this function
        @note Is this function even supposed to exist?
@@ -207,7 +247,7 @@ TopElement topModel_GetElemAtId(TopModel*m,TopID id){
 
 TopNode topElement_GetNode(TopModel* m,TopElement e,int idx){
   CkAssert(e>=0);
-  const AllocTable2d<int> &conn = m->elem[0].getConn();
+  const AllocTable2d<int> &conn = m->mesh->elem[0].getConn();
   CkAssert(idx>=0 && idx<conn.width());
   CkAssert(idx<conn.size());
 
@@ -218,14 +258,14 @@ TopNode topElement_GetNode(TopModel* m,TopElement e,int idx){
 
 int topNode_GetId(TopModel* m, TopNode n){
   CkAssert(n>=0);
-  FEM_DataAttribute * at = (FEM_DataAttribute*) m->node.lookup(FEM_DATA+1,"topNode_SetId");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) m->mesh->node.lookup(FEM_DATA+1,"topNode_SetId");
   return at->getInt()(n,0);
 }
 
 
 /** @todo handle ghost nodes as appropriate */
 int topModel_GetNNodes(TopModel *model){
-  return model->node.count_valid();
+  return model->mesh->node.count_valid();
 }
 
 /** @todo Fix to return the width of the conn array */
@@ -239,7 +279,7 @@ void topNode_GetPosition(TopModel*model, TopNode node,double*x,double*y,double*z
   double coord[3]={7.01,7.01,7.01};
 
   // lookup node via global ID
-  FEM_DataAttribute * at = (FEM_DataAttribute*) model->node.lookup(FEM_COORD,"topModel_GetNodeAtId");
+  FEM_DataAttribute * at = (FEM_DataAttribute*) model->mesh->node.lookup(FEM_COORD,"topModel_GetNodeAtId");
   CkAssert(at->getDouble().width()==3);
   //  CkPrintf("node=%d, size=%d\n",node,at->getDouble().size() );
   CkAssert(node<at->getDouble().size());
@@ -251,20 +291,20 @@ void topNode_GetPosition(TopModel*model, TopNode node,double*x,double*y,double*z
 void topModel_Sync(TopModel*m){
   MPI_Barrier(MPI_COMM_WORLD);
 
-  //  CkPrintf("%d: %d local, %d ghost elements\n", FEM_My_partition(), m->elem[0].size(),m->elem[0].ghost->size() );
-  //  CkPrintf("%d: %d local, %d ghost valid elements\n", FEM_My_partition(), m->elem[0].count_valid(),m->elem[0].ghost->count_valid() );
+
+  //  CkPrintf("%d: %d local, %d ghost elements\n", FEM_My_partition(), m->mesh->elem[0].size(),m->mesh->elem[0].ghost->size() );
+  //  CkPrintf("%d: %d local, %d ghost valid elements\n", FEM_My_partition(), m->mesh->elem[0].count_valid(),m->mesh->elem[0].ghost->count_valid() );
 
 }
 
 void topModel_TestIterators(TopModel*m){
-  CkAssert(m->elem[0].ghost!=NULL);
-  CkAssert(m->node.ghost!=NULL);
+  CkAssert(m->mesh->elem[0].ghost!=NULL);
+  CkAssert(m->mesh->node.ghost!=NULL);
 
-  int expected_elem_count = m->elem[0].count_valid() + m->elem[0].ghost->count_valid(); 
+  int expected_elem_count = m->mesh->elem[0].count_valid() + m->mesh->elem[0].ghost->count_valid();
   int iterated_elem_count = 0;
 
-  int expected_node_count = m->node.count_valid() + m->node.ghost->count_valid(); 
+  int expected_node_count = m->mesh->node.count_valid() + m->mesh->node.ghost->count_valid();
   int iterated_node_count = 0;
 
   int myId = FEM_My_partition();
@@ -277,7 +317,7 @@ void topModel_TestIterators(TopModel*m){
        void* na = topNode_GetAttrib(m,node);
        CkAssert(na != NULL);
   }
-    
+
   TopElemItr* e_itr = topModel_CreateElemItr(m);
   for(topElemItr_Begin(e_itr);topElemItr_IsValid(e_itr);topElemItr_Next(e_itr)){
        iterated_elem_count++;
@@ -285,10 +325,10 @@ void topModel_TestIterators(TopModel*m){
        void* ea = topElement_GetAttrib(m,elem);
        CkAssert(ea != NULL);
   }
-  
+
   CkAssert(iterated_node_count == expected_node_count);
   CkAssert(iterated_elem_count==expected_elem_count);
-  
+
 }
 
 
index d2cec40105217d6ad504543f18ce2dc5e1422074..fac7d72a9115bc1d59fa0cf29e73962596cbc29d 100644 (file)
@@ -1,7 +1,7 @@
 /**
    @file
    @brief A ParFUM "Tops" compatibility layer API Definition
-   
+
    @author Isaac Dooley
 
    ParFUM-TOPS provides a Tops-like API for ParFUM.
@@ -58,7 +58,17 @@ Sample usage:
 
 
 /** A tops model is roughly equivalent to a ParFUM FEM_Mesh object */
-typedef FEM_Mesh TopModel;
+typedef struct{
+    FEM_Mesh *mesh;
+
+#ifdef CUDA
+    unsigned char *mAttDevice; /** Device pointers to the goods */
+    unsigned char *ElemDataDevice;
+    unsigned char *NodeDataDevice;
+#endif
+
+} TopModel;
+
 
 /** Tops uses some bit patterns for these, but we just use TopNode as a signed value to represent the corresponding ParFUM node. A non-negative value is a local node, while a negative value is a ghost. */
 typedef long TopNode;
@@ -91,7 +101,7 @@ enum {
 /** Node Iterator */
 class TopNodeItr{
 public:
-  /** The signed index used to refer to a ParFUM Element. Non-negatives are ghosts*/ 
+  /** The signed index used to refer to a ParFUM Element. Non-negatives are ghosts*/
   int parfum_index;
   /** The associated model */
   TopModel *model;
@@ -111,14 +121,14 @@ typedef int TopID;
 typedef int TopElemType;
 
 
-/** 
-Create and access a Tops model. Only call from Init 
+/**
+Create and access a Tops model. Only call from Init
 Currently only one model can be created. To extend, each model must just reference a different FEM_Mesh object
 */
 TopModel* topModel_Create_Init(int elem_attr_sz, int node_attr_sz);
 
 /** Create and access a Tops model. Only call from Driver */
-TopModel* topModel_Create_Driver(int elem_attr_sz, int node_attr_sz);
+TopModel* topModel_Create_Driver(int elem_attr_sz, int node_attr_sz, int model_attr_sz, void* mAtt);
 
 /** Cleanup a model. Currently does nothing */
 void topModel_Destroy(TopModel* m);
@@ -205,4 +215,11 @@ TopElement topElemItr_GetCurr(TopElemItr*);
 void topModel_TestIterators(TopModel*m);
 
 
+#if CUDA
+void* topElement_D_GetAttrib(TopModel* m, TopElement e);
+void* topNode_D_GetAttrib(TopModel* m, TopNode n);
+TopNode topElement_D_GetNode(TopModel* m,TopElement e,int idx);
+#endif
+
+
 #endif
index 05d2628059e52799a007df803a8b76337bc88390..97bd17563ff633e92b4a124a359ee6af7cf72502 100644 (file)
@@ -4,7 +4,7 @@
 
 
 /**************************************************************************
- *     Iterator for nodes 
+ *     Iterator for nodes
  */
 
 TopNodeItr*  topModel_CreateNodeItr(TopModel* model){
@@ -18,21 +18,21 @@ void topNodeItr_Destroy(TopNodeItr* itr){
 }
 
 void topNodeItr_Begin(TopNodeItr* itr){
-  if(itr->model->node.ghost != NULL){
-       itr->parfum_index =  FEM_To_ghost_index(itr->model->node.ghost->size());
+  if(itr->model->mesh->node.ghost != NULL){
+       itr->parfum_index =  FEM_To_ghost_index(itr->model->mesh->node.ghost->size());
   }
   else{
        itr->parfum_index =  0;
-  }  
+  }
 
   // Make sure we start with a valid one:
-  while((!itr->model->node.is_valid_any_idx(itr->parfum_index)) &&
-               (itr->parfum_index < itr->model->node.size()))
+  while((!itr->model->mesh->node.is_valid_any_idx(itr->parfum_index)) &&
+               (itr->parfum_index < itr->model->mesh->node.size()))
        itr->parfum_index++;
-  
-  if(itr->parfum_index==itr->model->node.size()){
-       itr->parfum_index = itr->model->node.size()+1000; // way past the end
-  }  
+
+  if(itr->parfum_index==itr->model->mesh->node.size()){
+       itr->parfum_index = itr->model->mesh->node.size()+1000; // way past the end
+  }
 
 #ifdef PTOPS_ITERATOR_PRINT
   CkPrintf("Initializing Node Iterator to %d\n", itr->parfum_index);
@@ -40,22 +40,22 @@ void topNodeItr_Begin(TopNodeItr* itr){
 }
 
 bool topNodeItr_IsValid(TopNodeItr*itr){
-       return itr->model->node.is_valid_any_idx(itr->parfum_index);
+       return itr->model->mesh->node.is_valid_any_idx(itr->parfum_index);
 }
 
 void topNodeItr_Next(TopNodeItr* itr){
   CkAssert(topNodeItr_IsValid(itr));
-  
+
   // advance index until we hit a valid index
   itr->parfum_index++;
 
-  while((!itr->model->node.is_valid_any_idx(itr->parfum_index)) &&
-               (itr->parfum_index < itr->model->node.size()))
+  while((!itr->model->mesh->node.is_valid_any_idx(itr->parfum_index)) &&
+               (itr->parfum_index < itr->model->mesh->node.size()))
        itr->parfum_index++;
-  
-  if(itr->parfum_index==itr->model->node.size()){
-       itr->parfum_index = itr->model->node.size()+1000; // way past the end
-  }  
+
+  if(itr->parfum_index==itr->model->mesh->node.size()){
+       itr->parfum_index = itr->model->mesh->node.size()+1000; // way past the end
+  }
 
 #ifdef PTOPS_ITERATOR_PRINT
   CkPrintf("Advancing Node Iterator to %d\n", itr->parfum_index);
@@ -83,21 +83,21 @@ void topElemItr_Destroy(TopElemItr* itr){
 }
 
 void topElemItr_Begin(TopElemItr* itr){
-  if(itr->model->elem[0].ghost != NULL){
-       itr->parfum_index =  FEM_To_ghost_index(itr->model->elem[0].ghost->size());
+  if(itr->model->mesh->elem[0].ghost != NULL){
+       itr->parfum_index =  FEM_To_ghost_index(itr->model->mesh->elem[0].ghost->size());
   }
   else{
        itr->parfum_index =  0;
-  }  
+  }
 
   // Make sure we start with a valid one:
-  while((!itr->model->elem[0].is_valid_any_idx(itr->parfum_index)) &&
-               (itr->parfum_index < itr->model->elem[0].size()))
+  while((!itr->model->mesh->elem[0].is_valid_any_idx(itr->parfum_index)) &&
+               (itr->parfum_index < itr->model->mesh->elem[0].size()))
        itr->parfum_index++;
-  
-  if(itr->parfum_index==itr->model->elem[0].size()){
-       itr->parfum_index = itr->model->elem[0].size()+1000; // way past the end
-  }  
+
+  if(itr->parfum_index==itr->model->mesh->elem[0].size()){
+       itr->parfum_index = itr->model->mesh->elem[0].size()+1000; // way past the end
+  }
 
 #ifdef PTOPS_ITERATOR_PRINT
   CkPrintf("Initializing Elem[0] Iterator to %d\n", itr->parfum_index);
@@ -106,23 +106,23 @@ void topElemItr_Begin(TopElemItr* itr){
 }
 
 bool topElemItr_IsValid(TopElemItr*itr){
-  return itr->model->elem[0].is_valid_any_idx(itr->parfum_index);
+  return itr->model->mesh->elem[0].is_valid_any_idx(itr->parfum_index);
 }
 
 void topElemItr_Next(TopElemItr* itr){
   CkAssert(topElemItr_IsValid(itr));
-  
+
   // advance index until we hit a valid index
   itr->parfum_index++;
 
-  while((!itr->model->elem[0].is_valid_any_idx(itr->parfum_index)) &&
-               (itr->parfum_index < itr->model->elem[0].size()))
+  while((!itr->model->mesh->elem[0].is_valid_any_idx(itr->parfum_index)) &&
+               (itr->parfum_index < itr->model->mesh->elem[0].size()))
        itr->parfum_index++;
 
-  
-  if(itr->parfum_index==itr->model->elem[0].size()){
-       itr->parfum_index = itr->model->elem[0].size()+1000; // way past the end
-  }  
+
+  if(itr->parfum_index==itr->model->mesh->elem[0].size()){
+       itr->parfum_index = itr->model->mesh->elem[0].size()+1000; // way past the end
+  }
 
 #ifdef PTOPS_ITERATOR_PRINT
   CkPrintf("Advancing Elem Iterator to %d\n", itr->parfum_index);