ErrorCode ScdInterface::assign_global_ids(ScdBox *box) { // Get a ptr to global id memory void* data; int count = 0; Tag gid_tag; ErrorCode rval = mbImpl->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid_tag, MB_TAG_CREAT & MB_TAG_DENSE, &count); ERRORR(rval, "Trouble getting global id tag handle."); Range tmp_range(box->start_vertex(), box->start_vertex() + box->num_vertices()); rval = mbImpl->tag_iterate(gid_tag, tmp_range.begin(), tmp_range.end(), count, data); ERRORR(rval, "Failed to get tag iterator."); assert(count == box->num_vertices()); int* gid_data = (int*) data; int di = box->par_data().gDims[3] - box->par_data().gDims[0] + 1; int dj = box->par_data().gDims[4] - box->par_data().gDims[1] + 1; for (int kl = box->box_dims()[2]; kl <= box->box_dims()[5]; kl++) { for (int jl = box->box_dims()[1]; jl <= box->box_dims()[4]; jl++) { for (int il = box->box_dims()[0]; il <= box->box_dims()[3]; il++) { int itmp = (!box->locally_periodic()[0] && box->par_data().gPeriodic[0] && il == box->par_data().gDims[3] ? box->par_data().gDims[0] : il); *gid_data = (-1 != kl ? kl * di * dj : 0) + jl * di + itmp + 1; gid_data++; } } } return MB_SUCCESS; }
int AssocPair::set_relation(iBase_EntitySetHandle set1, iBase_EntityHandle ent2) { if (entOrSet[0] == iRel_ENTITY || entOrSet[1] == iRel_SET) ERRORR(iBase_FAILURE, "Invalid relation type"); // check that if we're passing in an ent for a 'both'-type // assoc, there's already a set associated to the other ent iBase_EntityHandle tmp_ent; if (entOrSet[1] == iRel_BOTH && relSides[0]->get_relation_side(&set1, 1, &tmp_ent) != iBase_SUCCESS) ERRORR(iBase_FAILURE, "Couldn't find associated set on right side"); // set set1 => ent2 if (relStatus[0] == iRel_ACTIVE) CHK_ERRORR( relSides[0]->set_relation_side(&set1, 1, &ent2) ); // set ent1 <= set2 if (relStatus[1] == iRel_ACTIVE) CHK_ERRORR( relSides[1]->set_relation_side(&ent2, 1, &set1) ); // if the left side is a 'both'-type association, set the contents of set1 // to point to ent2 as well if (entOrSet[0] == iRel_BOTH) CHK_ERRORR( populate_recursive(0, set1, ent2) ); RETURNR(iBase_SUCCESS); }
int AssocPair::set_relation(iBase_EntityHandle ent1, iBase_EntityHandle ent2) { if (entOrSet[0] == iRel_SET || entOrSet[1] == iRel_SET) ERRORR(iBase_FAILURE, "Invalid relation type"); // check that if we're passing in an ent for a 'both'-type // assoc, there's already a set associated to the other ent iBase_EntityHandle tmp_ent; if (entOrSet[0] == iRel_BOTH && relSides[1]->get_relation_side(&ent2, 1, &tmp_ent) != iBase_SUCCESS) ERRORR(iBase_FAILURE, "Couldn't find associated set on left side"); if (entOrSet[1] == iRel_BOTH && relSides[0]->get_relation_side(&ent1, 1, &tmp_ent) != iBase_SUCCESS) ERRORR(iBase_FAILURE, "Couldn't find associated set on right side"); // set ent1 => ent2 if (relStatus[0] == iRel_ACTIVE) CHK_ERRORR( relSides[0]->set_relation_side(&ent1, 1, &ent2) ); // set ent1 <= ent2 if (relStatus[1] == iRel_ACTIVE) CHK_ERRORR( relSides[1]->set_relation_side(&ent2, 1, &ent1) ); RETURNR(iBase_SUCCESS); }
int AssocPair::get_relation(int iface_no, iBase_EntitySetHandle *sets, int num_sets, iBase_EntitySetHandle *tag_values) { if (relStatus[iface_no] == iRel_NOTEXIST) ERRORR(iBase_FAILURE, "Relation does not exist on this side"); if (entOrSet[!iface_no] == iRel_ENTITY) // other iface is not sets ERRORR(iBase_INVALID_ENTITY_HANDLE, "Expected Entity, got EntitySet"); return relSides[iface_no]->get_relation_side(sets, num_sets, tag_values); }
int AssocPair::rmv_relation(int iface_no, iBase_EntitySetHandle *sets, int num_sets) { if (relStatus[iface_no] == iRel_NOTEXIST) ERRORR(iBase_FAILURE, "Relation does not exist on this side"); // TODO: handle "both" case // Remove the opposite side first if (relStatus[!iface_no] == iRel_ACTIVE) { if (entOrSet[!iface_no] == iRel_ENTITY) { std::vector<iBase_EntityHandle> other_entities(num_sets); CHK_ERRORR( get_relation(iface_no, sets, num_sets, &other_entities[0]) ); CHK_ERRORR( relSides[!iface_no]->rmv_relation_side(&other_entities[0], num_sets) ); } else { std::vector<iBase_EntitySetHandle> other_sets(num_sets); CHK_ERRORR( get_relation(iface_no, sets, num_sets, &other_sets[0]) ); CHK_ERRORR( relSides[!iface_no]->rmv_relation_side(&other_sets[0], num_sets) ); } } return relSides[iface_no]->rmv_relation_side(sets, num_sets); }
int AssocPair::change_type(int iface_no, iRel_RelationType type) { if (entOrSet[iface_no] == type) RETURNR(iBase_SUCCESS); if (entOrSet[iface_no] == iRel_ENTITY || type == iRel_ENTITY) ERRORR(iBase_FAILURE, "Can only change type from \"set\" to \"both\", or " "vice-versa"); entOrSet[iface_no] = type; if (relStatus[iface_no] != iRel_ACTIVE) RETURNR(iBase_SUCCESS); iBase_EntitySetHandle *sets = NULL; int set_alloc = 0, set_size; CHK_ERRORR( relSides[iface_no]->get_related_sets(&sets, &set_alloc, &set_size) ); if (type == iRel_BOTH) { if (entOrSet[!iface_no] == iRel_ENTITY) { std::vector<iBase_EntityHandle> related_ents(set_size); CHK_ERRORR( relSides[iface_no]->get_relation_side(sets, set_size, &related_ents[0]) ); for (int i = 0; i < set_size; i++) CHK_ERRORR( populate_recursive(iface_no, sets[i], related_ents[i]) ); } else { std::vector<iBase_EntitySetHandle> related_sets(set_size); CHK_ERRORR( relSides[iface_no]->get_relation_side(sets, set_size, &related_sets[0]) ); for (int i = 0; i < set_size; i++) CHK_ERRORR( populate_recursive(iface_no, sets[i], related_sets[i]) ); } } else if (type == iRel_SET) { for (int i = 0; i < set_size; i++) CHK_ERRORR( unpopulate_recursive(iface_no, sets[i]) ); } free(sets); RETURNR(iBase_SUCCESS); }
int AssocPair::set_relation(iBase_EntitySetHandle set1, iBase_EntitySetHandle set2) { if (entOrSet[0] == iRel_ENTITY || entOrSet[1] == iRel_ENTITY) ERRORR(iBase_FAILURE, "Invalid relation type"); // set set1 => set2 if (relStatus[0] == iRel_ACTIVE) CHK_ERRORR( relSides[0]->set_relation_side(&set1, 1, &set2) ); // set set1 <= set2 if (relStatus[1] == iRel_ACTIVE) CHK_ERRORR( relSides[1]->set_relation_side(&set2, 1, &set1) ); // if either side is a 'both'-type association, set the contents of set1 // to point to set2 as well (and/or vice-versa) if (entOrSet[0] == iRel_BOTH) CHK_ERRORR( populate_recursive(0, set1, set2) ); if (entOrSet[1] == iRel_BOTH) CHK_ERRORR( populate_recursive(1, set2, set1) ); RETURNR(iBase_SUCCESS); }
ErrorCode ScdInterface::construct_box(HomCoord low, HomCoord high, const double * const coords, unsigned int num_coords, ScdBox *& new_box, int * const lperiodic, ScdParData *par_data, bool assign_gids, int tag_shared_ents) { // create a rectangular structured mesh block ErrorCode rval; int tmp_lper[3] = {0, 0, 0}; if (lperiodic) std::copy(lperiodic, lperiodic+3, tmp_lper); #ifndef MOAB_HAVE_MPI if (-1 != tag_shared_ents) ERRORR(MB_FAILURE, "Parallel capability requested but MOAB not compiled parallel."); if (-1 == tag_shared_ents && !assign_gids) assign_gids = true; // need to assign gids in order to tag shared verts #else if (par_data && low == high && ScdParData::NOPART != par_data->partMethod) { // requesting creation of parallel mesh, so need to compute partition if (!par_data->pComm) { // this is a really boneheaded way to have to create a PC par_data->pComm = ParallelComm::get_pcomm(mbImpl, 0); if (NULL == par_data->pComm) par_data->pComm = new ParallelComm(mbImpl, MPI_COMM_WORLD); } int ldims[6]; rval = compute_partition(par_data->pComm->size(), par_data->pComm->rank(), *par_data, ldims, tmp_lper, par_data->pDims); ERRORR(rval, "Error returned from compute_partition."); low.set(ldims[0],ldims[1],ldims[2]); high.set(ldims[3],ldims[4],ldims[5]); if (par_data->pComm->get_debug_verbosity() > 0) { std::cout << "Proc " << par_data->pComm->rank() << ": " << *par_data; std::cout << "Proc " << par_data->pComm->rank() << " local dims: " << low << "-" << high << std::endl; } } #endif HomCoord tmp_size = high - low + HomCoord(1, 1, 1, 0); if ((tmp_size[1] && num_coords && (int)num_coords < tmp_size[0]) || (tmp_size[2] && num_coords && (int)num_coords < tmp_size[0]*tmp_size[1])) return MB_FAILURE; rval = create_scd_sequence(low, high, MBVERTEX, 0, new_box); ERRORR(rval, "Trouble creating scd vertex sequence."); // set the vertex coordinates double *xc, *yc, *zc; rval = new_box->get_coordinate_arrays(xc, yc, zc); ERRORR(rval, "Couldn't get vertex coordinate arrays."); if (coords && num_coords) { unsigned int i = 0; for (int kl = low[2]; kl <= high[2]; kl++) { for (int jl = low[1]; jl <= high[1]; jl++) { for (int il = low[0]; il <= high[0]; il++) { xc[i] = coords[3*i]; if (new_box->box_size()[1]) yc[i] = coords[3*i+1]; if (new_box->box_size()[2]) zc[i] = coords[3*i+2]; i++; } } } } else { unsigned int i = 0; for (int kl = low[2]; kl <= high[2]; kl++) { for (int jl = low[1]; jl <= high[1]; jl++) { for (int il = low[0]; il <= high[0]; il++) { xc[i] = (double) il; if (new_box->box_size()[1]) yc[i] = (double) jl; else yc[i] = 0.0; if (new_box->box_size()[2]) zc[i] = (double) kl; else zc[i] = 0.0; i++; } } } } // create element sequence Core *mbcore = dynamic_cast<Core*>(mbImpl); SequenceManager *seq_mgr = mbcore->sequence_manager(); EntitySequence *tmp_seq; EntityHandle start_ent; // construct the sequence EntityType this_tp = MBHEX; if (1 >= tmp_size[2]) this_tp = MBQUAD; if (1 >= tmp_size[2] && 1 >= tmp_size[1]) this_tp = MBEDGE; rval = seq_mgr->create_scd_sequence(low, high, this_tp, 0, start_ent, tmp_seq, tmp_lper); ERRORR(rval, "Trouble creating scd element sequence."); new_box->elem_seq(tmp_seq); new_box->start_element(start_ent); // add vertex seq to element seq, forward orientation, unity transform rval = new_box->add_vbox(new_box, // p1: imin,jmin low, low, // p2: imax,jmin low + HomCoord(1, 0, 0), low + HomCoord(1, 0, 0), // p3: imin,jmax low + HomCoord(0, 1, 0), low + HomCoord(0, 1, 0)); ERRORR(rval, "Error constructing structured element sequence."); // add the new hexes to the scd box set; vertices were added in call to create_scd_sequence Range tmp_range(new_box->start_element(), new_box->start_element() + new_box->num_elements() - 1); rval = mbImpl->add_entities(new_box->box_set(), tmp_range); ERRORR(rval, "Couldn't add new hexes to box set."); if (par_data) new_box->par_data(*par_data); if (assign_gids) { rval = assign_global_ids(new_box); ERRORR(rval, "Trouble assigning global ids"); } #ifdef MOAB_HAVE_MPI if (par_data && -1 != tag_shared_ents) { rval = tag_shared_vertices(par_data->pComm, new_box); } #endif return MB_SUCCESS; }
ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagElem, Tag & tagArea) { EntityHandle dum = 0; Tag corrTag; ErrorCode rval = mb->tag_get_handle(CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE, &dum); // it should have been created ERRORR(rval, "can't get correlation tag"); Tag gid; rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE); ERRORR(rval,"can't get global ID tag" ); // get all polygons out of out_set; then see where are they coming from Range polys; rval = mb->get_entities_by_dimension(out_set, 2, polys); ERRORR(rval, "can't get polygons out"); // rs2 is the red range, arrival; rs1 is blue, departure; // there is a connection between rs1 and rs2, through the corrTag // corrTag is __correlation // basically, mb->tag_get_data(corrTag, &(redPoly), 1, &bluePoly); // also, mb->tag_get_data(corrTag, &(bluePoly), 1, &redPoly); // we start from rs2 existing, then we have to update something std::vector<double> currentVals(rs2.size()); rval = mb->tag_get_data(tagElem, rs2, ¤tVals[0]); ERRORR(rval, "can't get existing tag values"); // for each polygon, we have 2 indices: red and blue parents // we need index blue to update index red? std::vector<double> newValues(rs2.size(), 0.);// initialize with 0 all of them // area of the polygon * conc on red (old) current quantity // finaly, divide by the area of the red double check_intx_area=0.; for (Range::iterator it= polys.begin(); it!=polys.end(); it++) { EntityHandle poly=*it; int blueIndex, redIndex; rval = mb->tag_get_data(blueParentTag, &poly, 1, &blueIndex); ERRORR(rval, "can't get blue tag"); EntityHandle blue = rs1[blueIndex]; rval = mb->tag_get_data(redParentTag, &poly, 1, &redIndex); ERRORR(rval, "can't get red tag"); //EntityHandle red = rs2[redIndex]; // big assumption here, red and blue are "parallel" ;we should have an index from // blue to red (so a deformed blue corresponds to an arrival red) double areap = area_spherical_element(mb, poly, R); check_intx_area+=areap; // so the departure cell at time t (blueIndex) covers a portion of a redCell // that quantity will be transported to the redCell at time t+dt // the blue corresponds to a red arrival EntityHandle redArr; rval = mb->tag_get_data(corrTag, &blue, 1, &redArr); if (0==redArr || MB_TAG_NOT_FOUND==rval) { if (!remote_cells) ERRORR( MB_FAILURE, "no remote cells, failure\n"); // maybe the element is remote, from another processor int global_id_blue; rval = mb->tag_get_data(gid, &blue, 1, &global_id_blue); ERRORR(rval, "can't get arrival red for corresponding blue gid"); // find the int index_in_remote = remote_cells->find(1, global_id_blue); if (index_in_remote==-1) ERRORR( MB_FAILURE, "can't find the global id element in remote cells\n"); remote_cells->vr_wr[index_in_remote] += currentVals[redIndex]*areap; } else if (MB_SUCCESS==rval) { int arrRedIndex = rs2.index(redArr); if (-1 == arrRedIndex) ERRORR(MB_FAILURE, "can't find the red arrival index"); newValues[arrRedIndex] += currentVals[redIndex]*areap; } else ERRORR(rval, "can't get arrival red for corresponding "); } // now, send back the remote_cells to the processors they came from, with the updated values for // the tracer mass in a cell if (remote_cells) { // so this means that some cells will be sent back with tracer info to the procs they were sent from (parcomm->proc_config().crystal_router())->gs_transfer(1, *remote_cells, 0); // now, look at the global id, find the proper "red" cell with that index and update its mass //remote_cells->print("remote cells after routing"); int n = remote_cells->get_n(); for (int j=0; j<n; j++) { EntityHandle redCell = remote_cells->vul_rd[j];// entity handle sent back int arrRedIndex = rs2.index(redCell); if (-1 == arrRedIndex) ERRORR(MB_FAILURE, "can't find the red arrival index"); newValues[arrRedIndex] += remote_cells->vr_rd[j]; } } // now divide by red area (current) int j=0; Range::iterator iter = rs2.begin(); void * data=NULL; //used for stored area int count =0; double total_mass_local=0.; while (iter != rs2.end()) { rval = mb->tag_iterate(tagArea, iter, rs2.end(), count, data); ERRORR(rval, "can't tag iterate"); double * ptrArea=(double*)data; for (int i=0; i<count; i++, iter++, j++, ptrArea++) { total_mass_local+=newValues[j]; newValues[j]/= (*ptrArea); } } rval = mb->tag_set_data(tagElem, rs2, &newValues[0]); ERRORR(rval, "can't set new values tag"); double total_mass=0.; double total_intx_area =0; int mpi_err = MPI_Reduce(&total_mass_local, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (MPI_SUCCESS != mpi_err) return MB_FAILURE; // now reduce total area mpi_err = MPI_Reduce(&check_intx_area, &total_intx_area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (MPI_SUCCESS != mpi_err) return MB_FAILURE; if (my_rank==0) { std::cout <<"total mass now:" << total_mass << "\n"; std::cout <<"check: total intersection area: (4 * M_PI * R^2): " << total_intx_area << "\n"; } if (remote_cells) { delete remote_cells; remote_cells=NULL; } return MB_SUCCESS; }
int AssocPair::change_status(int iface_no, iRel_RelationStatus status) { if (relStatus[iface_no] == status) RETURNR(iBase_SUCCESS); relStatus[iface_no] = status; if (status == iRel_NOTEXIST) { // Destroy the assoc tag CHK_ERRORR( relSides[iface_no]->destroy_relation_side() ); } else if (status == iRel_INACTIVE) { // Create the assoc tag CHK_ERRORR( relSides[iface_no]->create_relation_side() ); } // Update the assoc tag else if (status == iRel_ACTIVE) { CHK_ERRORR( relSides[iface_no]->destroy_relation_side() ); CHK_ERRORR( relSides[iface_no]->create_relation_side() ); if (entOrSet[!iface_no] == iRel_ENTITY) { iBase_EntityHandle *entities = NULL; int ent_alloc = 0, ent_size; CHK_ERRORR( relSides[!iface_no]->get_related_ents(&entities, &ent_alloc, &ent_size) ); if (entOrSet[iface_no] == iRel_ENTITY) { std::vector<iBase_EntityHandle> related_ents(ent_size); int result = relSides[!iface_no]->get_relation_side( entities, ent_size, &related_ents[0]); if (result == iBase_SUCCESS) { if (iface_no == 0) for (int i = 0; i < ent_size; i++) CHK_ERRORR( set_relation(related_ents[i], entities[i]) ); else for (int i = 0; i < ent_size; i++) CHK_ERRORR( set_relation(entities[i], related_ents[i]) ); } } else { std::vector<iBase_EntitySetHandle> related_sets(ent_size); int result = relSides[!iface_no]->get_relation_side( entities, ent_size, &related_sets[0]); if (result == iBase_SUCCESS) { if (iface_no == 0) for (int i = 0; i < ent_size; i++) CHK_ERRORR( set_relation(related_sets[i], entities[i]) ); else for (int i = 0; i < ent_size; i++) CHK_ERRORR( set_relation(entities[i], related_sets[i]) ); } } free(entities); } else { iBase_EntitySetHandle *sets = NULL; int set_alloc = 0, set_size; CHK_ERRORR( relSides[!iface_no]->get_related_sets(&sets, &set_alloc, &set_size) ); if (entOrSet[iface_no] == iRel_ENTITY) { std::vector<iBase_EntityHandle> related_ents(set_size); int result = relSides[!iface_no]->get_relation_side( sets, set_size, &related_ents[0]); if (result == iBase_SUCCESS) { if (iface_no == 0) for (int i = 0; i < set_size; i++) CHK_ERRORR( set_relation(related_ents[i], sets[i]) ); else for (int i = 0; i < set_size; i++) CHK_ERRORR( set_relation(sets[i], related_ents[i]) ); } } else { std::vector<iBase_EntitySetHandle> related_sets(set_size); int result = relSides[!iface_no]->get_relation_side( sets, set_size, &related_sets[0]); if (result == iBase_SUCCESS) { if (iface_no == 0) for (int i = 0; i < set_size; i++) CHK_ERRORR( set_relation(related_sets[i], sets[i]) ); else for (int i = 0; i < set_size; i++) CHK_ERRORR( set_relation(sets[i], related_sets[i]) ); } } free(sets); } } else { ERRORR(iBase_INVALID_ARGUMENT, "Invalid argument for relation status"); } RETURNR(iBase_SUCCESS); }