const MeshObjTopo *FlattenTopo(const MeshObjTopo &topo) {
  const std::string name = topo.name;

  if (name == "SHELL" || name == "SHELL4") {
    return GetTopo("QUAD");
  } else if (name == "SHELL9") {
    return GetTopo("QUAD9");
  } else if (name == "SHELL3" || name == "TRISHELL") {
    return GetTopo("TRI");
  }

  return &topo;
}
Esempio n. 2
0
MeshObjTopo *LowerTopo(const MeshObjTopo &topo) {
  const std::string name = topo.name;

  if (name == "HEX27") {
    return GetTopo("HEX8");
  } else if (name == "TETRA10") {
    return GetTopo("TETRA4");
  } else if (name == "QUAD9") {
    return GetTopo("QUAD4");
  } else if (name == "TRI6") {
    return GetTopo("TRI3");
  }

  return NULL;
}
Esempio n. 3
0
MeshObjTopo *GetTopo(UInt t) {

  // This is 1 based in topo, so zero is no topo (nodes)
  static const char *tmap[] = {
    "NULL",
    "HEX",
    "HEX27",
    "TETRA",
    "TETRA10",
    "TRI3",
    "TRI3_3D",
    "TRI6",
    "TRI6_3D",
    "QUAD",
    "QUAD_3D",
    "QUAD9",
    "QUAD9_3D",
    "SHELL",
    "SHELL9",
    "SHELL3",
    "BAR2",
    "BAR2_2D",
    "BAR2_3D",
    "BAR3",
    "BAR3_2D",
    "BAR3_3D"
};   

  return GetTopo(tmap[t]);
}
Esempio n. 4
0
// Add a homogeneous edge to a topo
void AddHomoEdge(MeshObjTopo *topo, std::string edge_name) {
  MeshObjTopo *etopo = GetTopo(edge_name);
  if (!etopo)
    Throw() << "'Topo:" << edge_name << " invalid";
  topo->side_topo_list.reserve(topo->num_edges);
  for (int i = 0; i < topo->num_edges; i++) {
    topo->edge_topo_list.push_back(etopo);
  }
}
Esempio n. 5
0
// Add a homogeneous side to a topo
void AddHomoSide(MeshObjTopo *topo, std::string side_name) {
  MeshObjTopo *stopo = GetTopo(side_name);
  if (!stopo)
    Throw() << "'Topo:" << side_name << " invalid";
  topo->side_topo_list.reserve(topo->num_sides);
  for (UInt i = 0; i < topo->num_sides; i++) {
    topo->side_topo_list.push_back(stopo);
  }
}
Esempio n. 6
0
MasterElement<METraits<> > *MEFamilyDG::getME(const std::string &toponame, METraits<>) const {
  // First get a suitable mapping
  const MeshObjTopo *topo = GetTopo(toponame);
  if (!topo) Throw() << "DG0 get Me, couldn't get topo";
  if (topo->parametric_dim == 2) {
    return MasterElementDG<METraits<> >::instance(ndof);
  } else if (topo->parametric_dim == 3) {
    return MasterElementDG<METraits<> >::instance(ndof);
  } else Throw() << "DG0 getME, unexpected pdim";
}
Esempio n. 7
0
const MeshObjTopo *FlattenTopo(const MeshObjTopo &topo) {
  const std::string name = topo.name;

  if (name == "SHELL" || name == "SHELL4" || name == "QUAD_3D") {
    return GetTopo("QUAD");
  } else if (name == "SHELL9") {
    return GetTopo("QUAD9");
  } else if (name == "SHELL3" || name == "TRISHELL") {
    return GetTopo("TRI");
  } else if (name == "BAR2_2D") {
    return GetTopo("BAR2");
  } else if (name == "BAR2_3D") {
    return GetTopo("BAR2");
  }

  if (topo.parametric_dim != topo.spatial_dim)
    Throw() << "Please define flatten topo for:" << topo.name;

  return &topo;
}
Esempio n. 8
0
// *** Convert a grid to a mesh.  The staggerLoc should describe
// whether the mesh is at the dual location or coincident with the
// grid itself.  I am not sure how this is going to work, though,
// since the dual of a nice multi-patch grid could be a very bad
// object, not representable by a mesh.
//
//   o------------o-------------o
//   |     :      |      :      |
//   |     :      |      :      |
//   |.....x......|......x......|
//   |     :      |      :      |
//   |     :      |      :      |
//   o------------o-------------o
//   |     :      |      :      |
//   |     :      |      :      |
//   |.....x......|......x......|
//   |     :      |      :      |
//   |     :      |      :      |
//   o------------o-------------o
//   
//   E.G. mesh o---o, dual mesh x....x
//
// I think there is work here.  
// For the moment, we should at least be able to represent the grid itself,
// and, maybe, for simple single patch grids with a periodic component,
// the dual, which is not so bad.  This will put us equivalent with
// SCRIP.  
void GridToMesh(const Grid &grid_, int staggerLoc, ESMCI::Mesh &mesh, const std::vector<ESMCI::Array*> &arrays) {
  Trace __trace("GridToMesh(const Grid &grid_, int staggerLoc, ESMCI::Mesh &mesh)");

  // Initialize the parallel environment for mesh (if not already done)
  ESMCI::Par::Init("MESHLOG", false /* use log */);

  Grid &grid = const_cast<Grid&>(grid_);


 bool is_sphere = grid.isSphere();

 try {

   // *** Grid error checking here ***


 
   // *** Set some meta-data ***
     // We set the topological dimension of the mesh (quad = 2, hex = 3, etc...)
   UInt pdim = grid.getDimCount();
   mesh.set_parametric_dimension(pdim);
  
     // In what dimension is the grid embedded?? (sphere = 3, simple rectangle = 2, etc...)
   // At this point the topological and spatial dim of the Grid is the same this should change soon
   UInt sdim = grid.getDimCount();


   if (is_sphere) {
     //std::cout << "g2m, is sphere=1" << std::endl;
     sdim = 3;
   }

   mesh.set_spatial_dimension(sdim);
  

   // We save the nodes in a linear list so that we can access then as such
   // for cell creation.
   //TODO: NEED MAX LID METHOD SOON ->Bob
   std::vector<MeshObj*> nodevect(100000);
   std::map<UInt,UInt> ngid2lid;

   UInt local_node_num = 0, local_elem_num = 0;


   // Set the id of this processor here (me)
   int localrc;
   int rc;
   int me = VM::getCurrent(&localrc)->getLocalPet();
//   if (ESMC_LogDefault.MsgFoundError(localrc, ESMF_ERR_PASSTHRU, &rc)) // How should I handle ESMF LogError?
//      return;

   // Keep track of locally owned, shared and shared, not-locally-owned
   std::vector<UInt> owned_shared;
   std::vector<UInt> notowned_shared;


   // *** Create the Nodes ***
     // Loop nodes of the grid.  Here we loop all nodes, both owned and not.
   ESMCI::GridIter *gni=new ESMCI::GridIter(&grid,staggerLoc,true);

   // Put Local in first, so we don't have to search for duplicates for every interation, 
   // after locals are in put in non-local

   // loop through all LOCAL nodes in the Grid owned by cells
   for(gni->toBeg(); !gni->isDone(); gni->adv()) {   

     // Only operate on Local Nodes
     if (gni->isLocal()) {
       MeshObj *node;
       
       // get the global id of this Grid node
       int gid=gni->getGlobalID(); 
       
       // get the local id of this Grid node
       int lid=gni->getLocalID(); 

#ifdef G2M_DBG
Par::Out() << "GID=" << gid << ", LID=" << lid << std::endl;
#endif

       // Create new node in mesh object       
       node = new MeshObj(MeshObj::NODE,     // node...
                                   gid,               // unique global id
                                   local_node_num
                                   );

       ngid2lid[gid] = lid;
       local_node_num++;
       
       
       node->set_owner(me);  // Set owner to this proc
       
       UInt nodeset = is_sphere ? gni->getPoleID() : 0;   // Do we need to partition the nodes in any sets?
       mesh.add_node(node, nodeset);
       
       // If Shared add to list to use DistDir on
       if (gni->isShared()) {
         
         // Put gid in list
         std::vector<UInt>::iterator lb =
           std::lower_bound(owned_shared.begin(), owned_shared.end(), gid);    
         
         if (lb == owned_shared.end() || *lb != gid)
           owned_shared.insert(lb, gid);
       }
       
       // Put node into vector
       nodevect[lid]=node;    
     }
     
   } // gni


   // loop through all NON-LOCAL nodes in the Grid owned by cells
   for(gni->toBeg(); !gni->isDone(); gni->adv()) {   

     // Only operate on non-local nodes
     if (!gni->isLocal()) {
       MeshObj *node;
       
       // get the global id of this Grid node
       int gid=gni->getGlobalID(); 
       
       // get the local id of this Grid node
       int lid=gni->getLocalID(); 
       
       // If Grid node is not already in the mesh then add 
       Mesh::MeshObjIDMap::iterator mi =  mesh.map_find(MeshObj::NODE, gid);
       if (mi == mesh.map_end(MeshObj::NODE)) {
         node = new MeshObj(MeshObj::NODE,    // node...
                            gid,              // unique global id
                            local_node_num   // local ID for boostrapping field data
                            );

         ngid2lid[gid] = lid;
         local_node_num++;
         
         node->set_owner(std::numeric_limits<UInt>::max());  // Set owner to unknown (will have to ghost later)
         
         UInt nodeset = is_sphere ? gni->getPoleID() : 0;   // Do we need to partition the nodes in any sets?
         mesh.add_node(node, nodeset);
         
         // Node must be shared
         std::vector<UInt>::iterator lb =
           std::lower_bound(notowned_shared.begin(), notowned_shared.end(), gid);    
         
         if (lb == notowned_shared.end() || *lb != gid)
           notowned_shared.insert(lb, gid);
         
       } else {
         node=&*mi; 
       }
       
       // Put node into vector
       nodevect[lid]=node;    
     }
   } // gni
  

   // Use DistDir to fill node owners for non-local nodes 
   // TODO: Use nodes which are gni->isLocal() && gni->isShared() to get owners of
   //       non-local nodes ->David


   // *** Create the Cells ***  

   // Presumably, for a structured grid there is only the
   // 'hypercube' topology, i.e. a quadrilateral for 2d
   // and a hexahedron for 3d
   const MeshObjTopo *ctopo = 0;
   if (pdim == 2) {
   
     ctopo = sdim == 2 ? GetTopo("QUAD") : GetTopo("QUAD_3D");
                                         
   } else if (pdim == 3) {

     ThrowRequire(sdim == 3);
     ctopo = GetTopo("HEX");

   } else Throw() << "Invalid parametric dim:" << pdim;

   if (!ctopo)
     Throw() << "Could not get topology for pdim=" << pdim;

   // Allocate vector to hold nodes for translation
   std::vector<MeshObj*> nodes(ctopo->num_nodes);


   // Loop Cells of the grid. 
   ESMCI::GridCellIter *gci=new ESMCI::GridCellIter(&grid,staggerLoc);

   for(gci->toBeg(); !gci->isDone(); gci->adv()) {   
     MeshObj *cell = new MeshObj(MeshObj::ELEMENT,     // Mesh equivalent of Cell
                                 gci->getGlobalID(),   // unique global id
                                 local_elem_num++
                                 );

#ifdef G2M_DBG
Par::Out() << "Cell:" << cell->get_id() << " uses nodes:";
#endif
  
     // Set Owner
     cell->set_owner(me);
   
     // Get Local Ids of Corners
     int cnrCount;
     int cnrList[16]; // ONLY WORKS FOR UP TO 4D
     gci->getCornersCellNodeLocalID(&cnrCount, cnrList);
     ThrowRequire(cnrCount == ctopo->num_nodes);

     // Get Nodes via Local IDs
     for (UInt n = 0; n < ctopo->num_nodes; ++n) {
       nodes[n] = nodevect[cnrList[n]];
#ifdef G2M_DBG
Par::Out() << nodes[n]->get_id() << " ";
#endif
     } // n
#ifdef G2M_DBG
Par::Out() << std::endl;
#endif


     UInt block_id = 1;  // Any reason to use different sets for cells?

     mesh.add_element(cell, nodes, block_id, ctopo);
     
   } // ci

    // Remove any superfluous nodes
    mesh.remove_unused_nodes();
    mesh.linearize_data_index();

     // Now set up the nodal coordinates
   IOField<NodalField> *node_coord = mesh.RegisterNodalField(mesh, "coordinates", sdim);

   // Create whatever fields the user wants
   std::vector<IOField<NodalField>*> nfields;
   for (UInt i = 0; i < arrays.size(); ++i) {
     char buf[512];
     std::sprintf(buf, "array_%03d", i);
     nfields.push_back(
             mesh.RegisterNodalField(mesh, buf, 1)
                      );
     nfields.back()->set_output_status(true);
   }

#ifdef G2M_DBG
   IOField<NodalField> *de_field = mesh.RegisterNodalField(mesh, "de", 1);
     de_field->set_output_status(true);
#endif

   // Loop through Mesh nodes setting up coordinates
   MeshDB::iterator ni = mesh.node_begin(), ne = mesh.node_end();

   for (; ni != ne; ++ni) {
     double *c = node_coord->data(*ni);

     double fdata;

     UInt lid = ngid2lid[ni->get_id()]; // we set this above when creating the node

//Par::Out() << "node:" << ni->get_id() << ", lid=" << lid;

     // Move to corresponding grid node
    gni->moveToLocalID(lid);      

    // If local fill in coords
    if (gni->isLocal()) {

     gni->getCoord(c);

     double DEG2RAD = M_PI/180.0;
     if (is_sphere) {

         double lon = c[0];
          double lat = c[1];
          double ninety = 90.0;
          double theta = DEG2RAD*lon, phi = DEG2RAD*(ninety-lat);
          c[0] = std::cos(theta)*std::sin(phi);
          c[1] = std::sin(theta)*std::sin(phi);
          c[2] = std::cos(phi);

 
     }

    } else { // set to Null value to be ghosted later
      for (int i=0; i<sdim; i++) {
   //     c[i]=std::numeric_limits<double>::max();
        c[i]=-10;
      }
    }

    // Other arrays
    for (UInt i = 0; i < arrays.size(); ++i) {
      gni->getArrayData(arrays[i], &fdata);
      double *data = nfields[i]->data(*ni);
      ThrowRequire(data);
      data[0] = fdata;
    }

#ifdef G2M_DBG
    // De field
    double *data = de_field->data(*ni);

    ThrowRequire(data);
    data[0] = gni->getDE();
#endif

    //printf("%d :: %f %f\n",gni->getGlobalID(),c[0],c[1]);

   } // ni


   // Now go back and resolve the ownership for shared nodes.  We create a distdir
   // from the owned, shared nodes, then look up the shared, not owned.
   {
     DDir<> dir;
   
     std::vector<UInt> lids(owned_shared.size(), 0);
     dir.Create(owned_shared.size(), &owned_shared[0], &lids[0]);
  
     std::vector<DDir<>::dentry> lookups;
     dir.RemoteGID(notowned_shared.size(), &notowned_shared[0], lookups);

     // Loop through the results.  Do a map lookup to find nodes--since the shared 
     // porition of the mesh is a hypersurface, this should be cheap enough to do.
     std::vector<DDir<>::dentry>::iterator ri = lookups.begin(), re = lookups.end();
     for (; ri != re; ++ri) {

       DDir<>::dentry &dent = *ri;

#ifdef G2M_DBG
Par::Out() << "Finding owner for gid" << dent.gid << " = " << dent.origin_proc << std::endl;
#endif

       Mesh::MeshObjIDMap::iterator mi =  mesh.map_find(MeshObj::NODE, dent.gid);
     //  ThrowRequire(mi != mesh.map_end(MeshObj::NODE));
       // May have been deleted as an unused node.  
       if (mi == mesh.map_end(MeshObj::NODE)) {
#ifdef G2M_DBG
Par::Out() << "\tnot in mesh!!" << std::endl;
#endif
         continue;
       }
 
       mi->set_owner(dent.origin_proc);

     } // ri

   } // ddir lookup


   // Can now build the communication pattern.
   mesh.build_sym_comm_rel(MeshObj::NODE);


   // ** That's it.  The mesh is now in the pre-commit phase, so other
   // fields can be registered, sides/faces can be turned on, etc, or one
   // can simply call mesh.Commit() and then proceed.
   char buf[512];
   //std::sprintf(buf, "g2m.%05d.txt", )
#ifdef G2M_DBG
   mesh.Print(Par::Out());
#endif

   mesh.Commit();

   {
     std::vector<MEField<>*> fds;

     Mesh::FieldReg::MEField_iterator fi = mesh.Field_begin(), fe = mesh.Field_end();

     for (; fi != fe; ++fi) fds.push_back(&*fi);

     mesh.HaloFields(fds.size(), &fds[0]);
 
/*
     MEField<> *cptr = mesh.GetCoordField();
     mesh.HaloFields(1, &cptr);
*/
   }

 } // try catch block
  catch (std::exception &x) {

  // Set any ESMF error codes/messages

 } // catch
  catch(...) {

  // Set any ESMF error codes/messages

 }

}