Example #1
0
void ParallelMesher::add_parallel_mesh_op(PARALLEL_OP_TYPE type, bool after)
{
  bool inserted = false;
  MeshOp *mesher = NULL;
  std::vector<MeshOp*> meshops;
  MEntSet::iterator iter = m_sEntity[type].begin();
  MEntSet::iterator end_iter = m_sEntity[type].end();

  for (; iter != end_iter; iter++) {
    bool found = false;
    if (!mesher) mesher = get_mesher(type); // get a mesher if we haven't already
    meshops.clear();
    (*iter)->get_meshops(meshops);
    int n_meshops = meshops.size();

    if (n_meshops > 0) {
      for (int i = 0; i < n_meshops; i++) {
        if (meshops[i] == mesher) {
          found = true;
          break;
        }
      }
    }
    
    if (!found) { // if no specified meshop
      // add this entity to it, and if first, make sure it's added upstream
      mesher->add_modelent(*iter);
      if (!inserted) {
        if (after) mk_core()->insert_node(mesher, mk_core()->leaf_node(), this);
        else mk_core()->insert_node(mesher, this);
        inserted = true;
      }
    }
  }
}
Example #2
0
ParallelMesher::ParallelMesher(MKCore *mkcore, const MEntVector &me_vec)
  : MeshScheme(mkcore, me_vec)
{
  // get information related to MOAB parallel communication
  m_mpcomm = moab::ParallelComm::get_pcomm(mk_core()->moab_instance(), 0);
  if (NULL == m_mpcomm) m_mpcomm = new moab::ParallelComm(mk_core()->moab_instance(), MPI_COMM_WORLD);
  m_rank = m_mpcomm->proc_config().proc_rank();

  // create tag
  iMesh::Error err = mk_core()->imesh_instance()->createTag("PARALLEL_UNIQUE_ID", 1, iBase_INTEGER, m_mPuniqueIDTag);
  IBERRCHK(err, "Trouble create a parallel unique id tag handle.");

  m_sEntity.resize(10);

  if (debug_parallelmesher) m_mpcomm->set_debug_verbosity(5);
}
Example #3
0
void mk_simplified_app::operator()(func_decl * decl, unsigned num, expr * const * args, expr_ref & result) {
    result = 0;
    mk_core(decl, num, args, result);
    if (!result) 
        result = m_imp->m.mk_app(decl, num, args);
    // TODO: if the result of mk_core is different from BR_FAILED, then the
    // result is not really simplified.
}
Example #4
0
//---------------------------------------------IBERRCHK(g_err, "Trouble get the adjacent geometric nodes on a surface.");------------------------------//
// measure function: compute the distance between the parametric coordinate 
// ustart and the parametric coordinate uend
double EdgeMesher::measure(iGeom::EntityHandle ent, double ustart, double uend) const
{
	double umin, umax;

	//get the minimal and maximal parametrical coordinates of the edge
	iGeom::Error err = mk_core()->igeom_instance()->getEntURange(ent, umin, umax);
	IBERRCHK(err, "Trouble getting parameter range for edge.");

	if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to same parameter umax and umin.");

	//compute the distance for edges
	double measure;
	err = mk_core()->igeom_instance()->measure(&ent, 1, &measure);

	IBERRCHK(err, "Trouble getting edge measure.");

	return measure * (uend - ustart) / (umax - umin);
}
Example #5
0
void ParallelMesher::check_partition(TDParallel* td_par, ModelEnt* me, int dim)
{
  bool b_partitioned = false;
  unsigned int charge_p = td_par->get_charge_proc();
  if (m_rank == charge_p) { // charge processor
    if (dim == 2) {
      m_sEntity[MESH_INTER_SURF].insert(me);
      m_sEntity[SEND_POST_SURF_MESH].insert(me);
      m_sEntity[RECV_SURF_MESH].insert(me);
    }
    else if (dim == 1) {
      m_sEntity[MESH_EDGE].insert(me);
      m_sEntity[EXCHANGE_EDGE].insert(me);
    }
    else if (dim == 0) {
      m_sEntity[MESH_VERTEX].insert(me);
      m_sEntity[EXCHANGE_VERTEX].insert(me);
    }
    b_partitioned = true;
  }
  else {
    DLIList<int>* shared_procs = td_par->get_shared_proc_list();
    int n_shared = shared_procs->size();
    for (int i = 0; i < n_shared; i++) {
      if (m_rank == (unsigned int)shared_procs->get_and_step()) { // shared processor
        if (dim == 2) {
          m_sEntity[SEND_POST_SURF_MESH].insert(me);
          m_sEntity[RECV_SURF_MESH].insert(me);
        }
        else if (dim == 1) {
          m_sEntity[EXCHANGE_EDGE].insert(me);
        }
        else if (dim == 0) {
          m_sEntity[EXCHANGE_VERTEX].insert(me);
        }
        b_partitioned = true;
        break;
      }
    }
  }

  // set geometry unique id to corresponding surface entityset
  if (b_partitioned) {
    unsigned int unique_id = td_par->get_unique_id();
    iBase_EntitySetHandle entityset = reinterpret_cast<iBase_EntitySetHandle> ((me)->mesh_handle());
    iMesh::Error err = mk_core()->imesh_instance()->setEntSetIntData(entityset, m_mPuniqueIDTag, unique_id);
    IBERRCHK(err, "Couldn't set geometry unique id to corresponding mesh entityset.");
  }
}
Example #6
0
MeshOp *ParallelMesher::get_mesher(PARALLEL_OP_TYPE type)
{
  MeshOpProxy* proxy = NULL;
  std::vector<MeshOpProxy *> proxies;
  if (type == MESH_VERTEX) {
    mk_core()->meshop_by_mesh_type(moab::MBVERTEX, proxies);
    proxy = *proxies.begin();  }
  else if (type == MESH_EDGE) {
    mk_core()->meshop_by_mesh_type(moab::MBEDGE, proxies);
    proxy = *proxies.begin();
  }
  else if (type == MESH_INTER_SURF || type == MESH_NINTER_SURF) {
    //mk_core()->meshop_by_mesh_type(moab::MBTRI, proxies);
    proxy = MKCore::meshop_proxy("CAMALTriAdvance");
  }
  else if (type == MESH_VOLUME) {
    //mk_core()->meshop_by_mesh_type(moab::MBTET, proxies);
    proxy = MKCore::meshop_proxy("CAMALTetMesher");
  }
  else if (type == EXCHANGE_VERTEX || type == EXCHANGE_EDGE) {
    proxy = MKCore::meshop_proxy("ParExchangeMesh");
  }
  else if (type == POST_RECV) {
    proxy = MKCore::meshop_proxy("ParPostRecv");
  }
  else if (type == SEND_POST_SURF_MESH) {
    proxy = MKCore::meshop_proxy("ParSendPostSurfMesh");
  }
  else if (type == RECV_SURF_MESH) {
    proxy = MKCore::meshop_proxy("ParRecvSurfMesh");
  }

  if (proxy == NULL) throw Error(MK_FAILURE, "Couldn't find a MeshOp capable of producing the given mesh type.");
  
  return mk_core()->construct_meshop(proxy);
}
Example #7
0
void ParallelMesher::print_mesh()
{
  moab::ErrorCode rval;
  int tmp_procs[MAX_SHARING_PROCS];
  moab::EntityHandle tmp_hs[MAX_SHARING_PROCS];
  unsigned char pstat;
  int num_ps;
  moab::Range entities;

  for (moab::EntityType type = MBVERTEX; type != MBMAXTYPE; type++) {
    entities.clear();
    rval = mk_core()->moab_instance()->get_entities_by_type(0, type, entities);
    MBERRCHK(rval, mk_core()->moab_instance());

    for (moab::Range::iterator rit = entities.begin(); rit != entities.end(); rit++) {
      rval = m_mpcomm->get_sharing_data(*rit, tmp_procs, tmp_hs, pstat, num_ps);
      MBERRCHK(rval, mk_core()->moab_instance());

      if (type != MBENTITYSET) {
        std::cout << "ParallelMesher::entity=" << *rit << ", type=" << type;
        if (type == MBVERTEX) {
          double coord[3];
          rval = mk_core()->moab_instance()->get_coords(&(*rit), 1, coord);
          MBERRCHK(rval, mk_core()->moab_instance());
          std::cout << ", coords=" << coord[0] << " " << coord[1] << " " << coord[2];
        }
        else {
          std::vector<moab::EntityHandle> connect;
          rval = mk_core()->moab_instance()->get_connectivity(&(*rit), 1, connect);
          MBERRCHK(rval, mk_core()->moab_instance());
          int n_conn = connect.size();
          std::cout << ", connect=";
          for (int j = 0; j < n_conn; j++) {
            std::cout << connect[j] << " ";
          }
        }
        
        std::cout << ", shared_info=";
        for (int ii = 0; ii < num_ps; ii++) {
          std::cout << tmp_procs[ii] << ":" << tmp_hs[ii] << ", ";
        }
        std::cout << std::endl;
      }
    }
  }    
}
Example #8
0
//create the mesh for edges based on variable size from SizingFunction (var)
void EdgeMesher::VariableMeshing(ModelEnt *ent, int &num_edges, std::vector<double> &coords)
{
  double umin, umax, measure;
  (void) measure;
  // because of that, keep track of the first node position and last node position
  // first node position does not change, but the last node position do change
  // coords will contain all nodes, including umax in Urecord!

  SizingFunction *sf = mk_core()->sizing_function(ent->sizing_function_index());
  //get the u range for the edge
  iGeom::EntityHandle edge = ent->geom_handle();
  iGeom::Error gerr = ent->igeom_instance() ->getEntURange(edge, umin, umax);
  IBERRCHK(gerr, "Trouble get parameter range for edge.");

  if (umin == umax) throw Error(MK_BAD_GEOMETRIC_EVALUATION, "Edge evaluated to some parameter umax and umin.");

  //get the arc length
  measure = ent -> measure();

  // start advancing for each edge mesh, from the first point position
  double currentPar = umin;
  double currentPosition[3];
  gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umin, currentPosition[0],
      currentPosition[1], currentPosition[2] );

  double endPoint[3];
  gerr = ent->igeom_instance() ->getEntUtoXYZ(edge, umax, endPoint[0],
      endPoint[1], endPoint[2] );
  Vector<3> endpt(endPoint);

  double targetSize = sf->size(currentPosition);
  double startSize = targetSize;

  double endSize = sf->size(endPoint);
  // advance u such that the next point is at "currentSize" distance
  // or close to it
  // try first with a u that is coming from the (umax-umin)/number of edges
  double deltaU = (umax-umin)/num_edges;
  //coords.clear(); we do not want to clear, as the first node is still fine
  std::vector<double> URecord;    //record the values for u; we may have to adjust all
  // of them accordingly, and even add one more if we have some evenify problems.
  // keep in mind that size is just a suggestion, number of intervals is more important for
  // paver mesher
  Vector<3> pt(currentPosition);

  //bool notDone = true;
  double prevU = umin;
  while (currentPar + 1.1*deltaU < umax)
  {
    // do some binary search; actually, better, do Newton-Raphson, which should converge
    // faster
    //
    prevU = currentPar;
    currentPar += deltaU;
    // adjust current par, such that
    double point[3];
    gerr=ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2] );
    IBERRCHK(gerr, "Trouble getting position at parameter u.");
    Vector<3> ptCandidate(point);
    double compSize = length(ptCandidate-pt);
    int nit = 0;

    while ( (fabs(1.-compSize/targetSize)> 0.02 ) && (nit < 5))// 2% of the target size
    {
      // do Newton iteration
      double tangent[3];
      gerr=ent->igeom_instance() ->getEntTgntU(edge, currentPar, tangent[0], tangent[1], tangent[2] );
      IBERRCHK(gerr, "Trouble getting tangent at parameter u.");
      Vector<3> tang(tangent);
      double dldu = 1./compSize * ((ptCandidate-pt )%tang);
      nit++;// increase iteration count
      if (dldu!=0.)
      {
        double deu= (targetSize-compSize)/dldu;
        currentPar+=deu;
        if (prevU>currentPar)
        {
          break; // something is wrong
        }
        if (umax < currentPar)
        {
          currentPar = umax;
          break;
        }
        ent->igeom_instance()->getEntUtoXYZ(edge, currentPar, point[0], point[1], point[2]);
        Vector<3> newPt(point);
        compSize = length(newPt-pt);
        ptCandidate = newPt;
      }

    }
    // we have found an acceptable point/param
    URecord.push_back(currentPar);
    deltaU = currentPar-prevU;// should be greater than 0
    pt = ptCandidate;
    targetSize = sf->size(pt.data());// a new target size, at the current point



  }
  // when we are out of here, we need to adjust the URecords, to be more nicely
  // distributed; also, look at the evenify again
  int sizeU = (int)URecord.size();
  if ((sizeU%2==0) && ent->constrain_even() )
  {
    // add one more
    if (sizeU==0)
    {
      // just add one in the middle, and call it done
      URecord.push_back( (umin+umax)/2);
    }
    else
    {
      //at least 2 (maybe 4)
      double lastDelta = URecord[sizeU-1]-URecord[sizeU-2];
      URecord.push_back(URecord[sizeU-1]+lastDelta );
    }
  }
  // now, we have to redistribute, such as the last 2 deltas are about the same
  // so, we should have after a little work,
  // umin, umin+c*(URecord[0]-umin), ... umin+c*(URecord[size-1]-umin), umax
  // what we have now is
  // umin, URecord[0], ... ,URecord[size-1], and umax could be even outside or inside
  // keep the last sizes equal
  //  umin+c(UR[size-2]-umin) + umax = 2*( umin+c*(UR[size-1]-umin))
  //  c ( 2*(UR[size-1]-umin) -(UR[size-2]-umin) ) = umax - umin
  // c ( 2*UR[size-1] - UR[size-2] - umin ) = umax - umin
  // c = (umax-umin)/( 2*UR[size-1] - UR[size-2] - umin)
  sizeU = (int)URecord.size();// it may be bigger by one than the last time
  if (sizeU == 0)
  {
    // nothing to do, only one edge to generate
  }
  else if (sizeU == 1)
  {
    // put it according to the sizes at ends, and assume a nice variation for u
    // (u-umin) / (umax-u) = startSize / endSize
    // (u-umin)*endSize = (umax-u) * startSize
    // u(endSize+startSize)=(umax*startSize+umin*endSize)
    URecord[0] = (umax*startSize+umin*endSize)/(startSize+endSize);

  }
  else // sizeU>=2, so we can spread the param a little more, assuming nice
    // uniform mapping
  {
    double c =  (umax-umin)/( 2*URecord[sizeU-1] - URecord[sizeU-2] - umin);
    for (int i=0; i<sizeU; i++)
      URecord[i] = umin + c*(URecord[i] -umin);// some spreading out
  }
  // now, we can finally get the points for each U, U's should be spread out nicely
  URecord.push_back(umax); // just add the last u, for the end point
  //
  sizeU = (int) URecord.size(); // new size, after pushing the last u, umax
  num_edges = sizeU;// this is the new number of edges; the last one will be the end point
  // of the edge, corresponding to umax
  coords.resize(3*sizeU+3);
  // we already know that at i=0 is the first node, start vertex of edge
  // the rest will be computed from u
  // even the last one, which is an overkill
  for (int i = 1; i <= num_edges; i++)
  {
    double u = URecord[i-1];
    gerr = ent->igeom_instance()->getEntUtoXYZ(edge, u, coords[3*i], coords[3*i+1], coords[3*i+2]);
    IBERRCHK(gerr, "Trouble getting U from XYZ along the edge.");
  }
  return;

}
Example #9
0
//---------------------------------------------------------------------------//
// setup function: set up the number of intervals for edge meshing through the 
// sizing function
void EdgeMesher::setup_this()
{
    //compute the number of intervals for the associated ModelEnts, from the size set on them
    //the sizing function they point to, or a default sizing function
  for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
  {
    ModelEnt *me = mit->first;

      //first check to see whether entity is meshed
    if (me->get_meshed_state() >= COMPLETE_MESH || me->mesh_intervals() > 0)
      continue;
    
    SizingFunction *sf = mk_core()->sizing_function(me->sizing_function_index());
    if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT &&
        mk_core()->sizing_function(0))
      sf = mk_core()->sizing_function(0);
    
    if (!sf && me -> mesh_intervals() < 0 && me -> interval_firmness() == DEFAULT)
    {
        //no sizing set, just assume default #intervals as 4
      me->mesh_intervals(4);
      me->interval_firmness(DEFAULT);
    }
    else
    {
        //check # intervals first, then size, and just choose for now
      if (sf->intervals() > 0)
      {
        if (me->constrain_even() && sf->intervals()%2)
          me -> mesh_intervals(sf->intervals()+1);
        else
          me -> mesh_intervals(sf->intervals());
        me -> interval_firmness(HARD);
      }
      else if (sf->size()>0)
      {
        int intervals = me->measure()/sf->size();
        if (!intervals) intervals++;
        if (me->constrain_even() && intervals%2) intervals++;
        me->mesh_intervals(intervals);
        me->interval_firmness(SOFT);
      }
      else
        throw Error(MK_INCOMPLETE_MESH_SPECIFICATION,  "Sizing function for edge had neither positive size nor positive intervals.");
    }
  }

  // now call setup_boundary to treat vertices
   // Wrong!!!!!!!!!
  // setup_boundary();
  /* this is not enough to ensure that vertex mesher will be called before
    "this" edge mesher
    the case that fell through the cracks was if the end nodes were already setup
   then the this_op[0] would not be retrieved, and not inserted "before" the edge mesher MeshOp
  */
  int dim=0;
  MeshOp * vm = (MeshOp*) mk_core()->construct_meshop(dim);

  for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
  {
    ModelEnt *me = mit->first;
    MEntVector children;
    me->get_adjacencies(0, children);
    for (unsigned int i=0; i<children.size(); i++)
      if (children[i]->is_meshops_list_empty())
      {
        vm->add_modelent(children[i]);
      }
  }
  // in any case, make sure that the vertex mesher is inserted before this edge mesher
  mk_core()->insert_node(vm, this, mk_core()->root_node());


}
Example #10
0
//---------------------------------------------------------------------------//
// execute function: Generate the mesh for edges
void EdgeMesher::execute_this()
{
  std::vector<double> coords;
  std::vector<moab::EntityHandle> nodes;

  for (MEntSelection::iterator mit = mentSelection.begin(); mit != mentSelection.end(); mit++)
  {
    ModelEnt *me = mit -> first;
    if (me->get_meshed_state() >= COMPLETE_MESH)
	continue;
    //resize the coords based on the interval setting
    int num_edges = me->mesh_intervals();
    coords.resize(3*(num_edges+1));
    nodes.clear();
    nodes.reserve(num_edges + 1);

    //get bounding mesh entities, use 1st 2 entries of nodes list temporarily
    //pick up the boundary end nodes
    me->boundary(0, nodes);

    bool periodic = (nodes.size() == 1);
    
    //get coords in list, then move one tuple to the last position
    moab::ErrorCode rval = mk_core()->moab_instance()->get_coords(&nodes[0], nodes.size(), &coords[0]);
    MBERRCHK(rval, mk_core()->moab_instance());

    //move the second node to the endmost position in the node list
    // if periodic, the last node coordinates are also at index 0 in coords array
    // there is only one node, coords[3+i] are not even initialized
    int index2 = (periodic) ? 0 : 3;
    for (int i = 0; i < 3; i++)
      coords[3*num_edges+i] = coords[index2+i];

    EdgeSchemeType scheme = schemeType;
    SizingFunction *sz = mk_core()->sizing_function(me->sizing_function_index());
    if (sz->variable())
      scheme = VARIABLE;

    //choose the scheme for edge mesher
    switch(scheme)
    {
      case EQUAL://equal meshing for edges
          EqualMeshing(me, num_edges, coords);
          break;
      case BIAS://bias meshing for edges
          BiasMeshing(me, num_edges, coords);
          break;
      case DUAL://dual bias meshing for edges
          DualBiasMeshing(me, num_edges, coords);
          break;
      case CURVATURE://curvature-based meshing for edges
          CurvatureMeshing(me, num_edges, coords);
          break;
      case VARIABLE: // use a var size from sizing function
          VariableMeshing(me, num_edges, coords);
          break;
      case EQUIGNOMONIC: // used to generate HOMME type meshes on a sphere
          EquiAngleGnomonic(me, num_edges, coords);
          break;
      default:
          break;			
    }
    //the variable nodes should be resized, node size may be changed in the different scheme for edge meshing
    me->mesh_intervals(num_edges);
    nodes.resize(num_edges+1);
    
    //move the other nodes to the end of nodes' list
    if (periodic) nodes[num_edges] = nodes[0];
    else nodes[num_edges] = nodes[1];

    //create the vertices' entities on the edge
    if (num_edges > 1) {
      rval = mk_core()->moab_instance()->create_vertices(&coords[3], num_edges - 1, mit -> second);
      MBERRCHK(rval, mk_core()->moab_instance());
    }
    
    //distribute the nodes into vector
    int j = 1;
    for (moab::Range::iterator rit = mit -> second.begin(); rit != mit -> second.end(); rit++)
      nodes[j++] = *rit;

      //get the query interface, which we will use to create the edges directly 
    moab::ReadUtilIface *iface;
    rval = mk_core() -> moab_instance() -> query_interface(iface);
    MBERRCHK(rval, mk_core()->moab_instance());		

      //create the edges, get a direct ptr to connectivity
    moab::EntityHandle starth, *connect, *tmp_connect;
    rval = iface -> get_element_connect(num_edges, 2, moab::MBEDGE, 1, starth, connect);
    MBERRCHK(rval, mk_core()->moab_instance());

      //add edges to range for the MESelection
    mit -> second.insert(starth, starth + num_edges - 1);

      //now set the connectivity array from the nodes
    tmp_connect = &nodes[0];
    for (int i = 0; i < num_edges; i++)
    {
      connect[0] = tmp_connect[0];
      connect[1] = tmp_connect[1];

        //increment connectivity ptr by 2 to go to next edge
      connect += 2;
			
        //increment tmp_connect by 1, to go to next node
      tmp_connect++;
    }

      //   ok, we are done, commit to ME
    me->commit_mesh(mit->second, COMPLETE_MESH);
   
	
  }

	
}