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; } } } }
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); }
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. }
//---------------------------------------------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); }
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."); } }
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); }
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; } } } }
//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; }
//---------------------------------------------------------------------------// // 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()); }
//---------------------------------------------------------------------------// // 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); } }