moab
Intx2MeshOnSphere.cpp
Go to the documentation of this file.
00001 /*
00002  * Intx2MeshOnSphere.cpp
00003  *
00004  *  Created on: Oct 3, 2012
00005  */
00006 
00007 #include "Intx2MeshOnSphere.hpp"
00008 #include "moab/GeomUtil.hpp"
00009 #include "MBTagConventions.hpp"
00010 #include <queue>
00011 #ifdef USE_MPI
00012 #include "moab/ParallelComm.hpp"
00013 #endif
00014 
00015 namespace moab {
00016 
00017 
00018 Intx2MeshOnSphere::Intx2MeshOnSphere(Interface * mbimpl):Intx2Mesh(mbimpl)
00019 {
00020   // TODO Auto-generated constructor stub
00021 
00022 }
00023 
00024 Intx2MeshOnSphere::~Intx2MeshOnSphere()
00025 {
00026   // TODO Auto-generated destructor stub
00027 }
00028 
00029 /* the elements are convex for sure, then do a gnomonic projection of both,
00030  *  compute intersection in the plane, then go back to the sphere for the points
00031  *  */
00032 int Intx2MeshOnSphere::computeIntersectionBetweenRedAndBlue(EntityHandle red, EntityHandle blue,
00033     double * P, int & nP, double & area, int markb[MAXEDGES], int markr[MAXEDGES],
00034     int & nsBlue, int & nsRed, bool check_boxes_first)
00035 {
00036   // the points will be at most 40; they will describe a convex patch, after the points will be ordered and
00037   // collapsed (eliminate doubles)
00038   // the area is not really required, except to see if it is greater than 0
00039 
00040   // gnomonic projection
00041   // int plane = 0;
00042   // get coordinates of the red quad, to decide the gnomonic plane
00043 
00044   int num_nodes;
00045   ErrorCode rval = mb->get_connectivity(red, redConn, num_nodes);
00046 
00047   if (MB_SUCCESS != rval )
00048     return 1;
00049   nsRed = num_nodes;
00050   // account for possible padded polygons
00051   while (redConn[nsRed-2]==redConn[nsRed-1] && nsRed>3)
00052     nsRed--;
00053 
00054   //CartVect coords[4];
00055   rval = mb->get_coords(redConn, nsRed, &(redCoords[0][0]));
00056   if (MB_SUCCESS != rval)
00057     return 1;
00058   CartVect middle = redCoords[0];
00059   for (int i=1; i<nsRed; i++)
00060     middle += redCoords[i];
00061   middle = 1./nsRed * middle;
00062 
00063   decide_gnomonic_plane(middle, plane);// output the plane
00064   //CartVect bluecoords[4];
00065   rval = mb->get_connectivity(blue, blueConn, num_nodes);
00066   if (MB_SUCCESS != rval )
00067     return 1;
00068   nsBlue = num_nodes;
00069   // account for possible padded polygons
00070   while (blueConn[nsBlue-2]==blueConn[nsBlue-1] && nsBlue>3)
00071     nsBlue--;
00072   rval = mb->get_coords(blueConn, nsBlue, &(blueCoords[0][0]));
00073   if (MB_SUCCESS != rval)
00074     return 1;
00075 
00076   if (dbg_1)
00077   {
00078     std::cout << "red " << mb->id_from_handle(red) << "\n";
00079     for (int j = 0; j < nsRed; j++)
00080     {
00081       std::cout << redCoords[j] << "\n";
00082     }
00083     std::cout << "blue " << mb->id_from_handle(blue) << "\n";
00084     for (int j = 0; j < nsBlue; j++)
00085     {
00086       std::cout << blueCoords[j] << "\n";
00087     }
00088     mb->list_entities(&red, 1);
00089     mb->list_entities(&blue, 1);
00090     std::cout << "middle " << middle << "  plane:" << plane << "\n";
00091   }
00092   area = 0.;
00093   nP = 0; // number of intersection points we are marking the boundary of blue!
00094   if (check_boxes_first)
00095   {
00096     // look at the boxes formed with vertices; if they are far away, return false early
00097     if (!GeomUtil::bounding_boxes_overlap(redCoords, nsRed, blueCoords, nsBlue, box_error))
00098       return 0; // no error, but no intersection, decide early to get out
00099   }
00100   for (int j = 0; j < nsRed; j++)
00101   {
00102     // populate coords in the plane for intersection
00103     // they should be oriented correctly, positively
00104     int rc = gnomonic_projection(redCoords[j],  R, plane, redCoords2D[2 * j],
00105         redCoords2D[2 * j + 1]);
00106     if (rc != 0)
00107       return 1;
00108   }
00109   for (int j=0; j<nsBlue; j++)
00110   {
00111     int rc = gnomonic_projection(blueCoords[j], R, plane, blueCoords2D[2 * j],
00112         blueCoords2D[2 * j + 1]);
00113     if (rc != 0)
00114       return 1;
00115   }
00116   if (dbg_1)
00117   {
00118     std::cout << "gnomonic plane: " << plane << "\n";
00119     std::cout << " red                                blue\n";
00120     for (int j = 0; j < nsRed; j++)
00121     {
00122       std::cout << redCoords2D[2 * j] << " " << redCoords2D[2 * j + 1] << "\n";
00123     }
00124     for (int j = 0; j < nsBlue; j++)
00125     {
00126       std::cout << blueCoords2D[2 * j] << " " << blueCoords2D[2 * j + 1] << "\n";
00127     }
00128   }
00129 
00130   int ret = EdgeIntersections2(blueCoords2D, nsBlue, redCoords2D, nsRed, markb, markr, P, nP);
00131   if (ret != 0)
00132     return 1; // some unforeseen error
00133 
00134   int side[MAXEDGES] = { 0 };// this refers to what side? blue or red?
00135   int extraPoints = borderPointsOfXinY2(blueCoords2D, nsBlue, redCoords2D, nsRed, &(P[2 * nP]), side, epsilon_area);
00136   if (extraPoints >= 1)
00137   {
00138     for (int k = 0; k < nsBlue; k++)
00139     {
00140       if (side[k])
00141       {
00142         // this means that vertex k of blue is inside convex red; mark edges k-1 and k in blue,
00143         //   as being "intersected" by red; (even though they might not be intersected by other edges,
00144         //   the fact that their apex is inside, is good enough)
00145         markb[k] = 1;
00146         markb[(k + nsBlue-1) % nsBlue] = 1; // it is the previous edge, actually, but instead of doing -1, it is
00147         // better to do modulo +3 (modulo 4)
00148         // null side b for next call
00149         side[k]=0;
00150       }
00151     }
00152   }
00153   nP += extraPoints;
00154 
00155   extraPoints = borderPointsOfXinY2(redCoords2D, nsRed, blueCoords2D, nsBlue, &(P[2 * nP]), side, epsilon_area);
00156   if (extraPoints >= 1)
00157   {
00158     for (int k = 0; k < nsRed; k++)
00159     {
00160       if (side[k])
00161       {
00162         // this is to mark that red edges k-1 and k are intersecting blue
00163         markr[k] = 1;
00164         markr[(k + nsRed-1) % nsRed] = 1; // it is the previous edge, actually, but instead of doing -1, it is
00165         // better to do modulo +3 (modulo 4)
00166         // null side b for next call
00167       }
00168     }
00169   }
00170   nP += extraPoints;
00171 
00172   // now sort and orient the points in P, such that they are forming a convex polygon
00173   // this will be the foundation of our new mesh
00174   // this works if the polygons are convex
00175   SortAndRemoveDoubles2(P, nP, epsilon_1); // nP should be at most 8 in the end ?
00176   // if there are more than 3 points, some area will be positive
00177 
00178   if (nP >= 3)
00179   {
00180     for (int k = 1; k < nP - 1; k++)
00181       area += area2D(P, &P[2 * k], &P[2 * k + 2]);
00182   }
00183 
00184   return 0; // no error
00185 }
00186 
00187 
00188 // this method will also construct the triangles/polygons in the new mesh
00189 // if we accept planar polygons, we just save them
00190 // also, we could just create new vertices every time, and merge only in the end;
00191 // could be too expensive, and the tolerance for merging could be an
00192 // interesting topic
00193 int Intx2MeshOnSphere::findNodes(EntityHandle red, int nsRed, EntityHandle blue, int nsBlue,
00194     double * iP, int nP)
00195 {
00196   // first of all, check against red and blue vertices
00197   //
00198   if (dbg_1)
00199   {
00200     std::cout << "red, blue, nP, P " << mb->id_from_handle(red) << " "
00201         << mb->id_from_handle(blue) << " " << nP << "\n";
00202     for (int n = 0; n < nP; n++)
00203       std::cout << " \t" << iP[2 * n] << "\t" << iP[2 * n + 1] << "\n";
00204 
00205   }
00206 
00207   // get the edges for the red triangle; the extra points will be on those edges, saved as
00208   // lists (unordered)
00209   std::vector<EntityHandle> redEdges(nsRed);//
00210   int i = 0;
00211   for (i = 0; i < nsRed; i++)
00212   {
00213     EntityHandle v[2] = { redConn[i], redConn[(i + 1) % nsRed] };// this is fine even for padded polygons
00214     std::vector<EntityHandle> adj_entities;
00215     ErrorCode rval = mb->get_adjacencies(v, 2, 1, false, adj_entities,
00216         Interface::INTERSECT);
00217     if (rval != MB_SUCCESS || adj_entities.size() < 1)
00218       return 0; // get out , big error
00219     redEdges[i] = adj_entities[0]; // should be only one edge between 2 nodes
00220   }
00221   // these will be in the new mesh, mbOut
00222   // some of them will be handles to the initial vertices from blue or red meshes (lagr or euler)
00223 
00224   EntityHandle * foundIds = new EntityHandle[nP];
00225   for (i = 0; i < nP; i++)
00226   {
00227     double * pp = &iP[2 * i]; // iP+2*i
00228     // project the point back on the sphere
00229     CartVect pos;
00230     reverse_gnomonic_projection(pp[0], pp[1], R, plane, pos);
00231     int found = 0;
00232     // first, are they on vertices from red or blue?
00233     // priority is the red mesh (mb2?)
00234     int j = 0;
00235     EntityHandle outNode = (EntityHandle) 0;
00236     for (j = 0; j < nsRed && !found; j++)
00237     {
00238       //int node = redTri.v[j];
00239       double d2 = dist2(pp, &redCoords2D[2 * j]);
00240       if (d2 < epsilon_1)
00241       {
00242 
00243         foundIds[i] = redConn[j]; // no new node
00244         found = 1;
00245         if (dbg_1)
00246           std::cout << "  red node j:" << j << " id:"
00247               << mb->id_from_handle(redConn[j]) << " 2d coords:" << redCoords2D[2 * j] << "  "
00248               << redCoords2D[2 * j + 1] << " d2: " << d2 << " \n";
00249       }
00250     }
00251 
00252     for (j = 0; j < nsBlue && !found; j++)
00253     {
00254       //int node = blueTri.v[j];
00255       double d2 = dist2(pp, &blueCoords2D[2 * j]);
00256       if (d2 < epsilon_1)
00257       {
00258         // suspect is blueConn[j] corresponding in mbOut
00259 
00260         foundIds[i] = blueConn[j]; // no new node
00261         found = 1;
00262         if (dbg_1)
00263           std::cout << "  blue node " << j << " "
00264               << mb->id_from_handle(blueConn[j]) << " d2:" << d2 << " \n";
00265       }
00266 
00267     }
00268     if (!found)
00269     {
00270       // find the edge it belongs, first, on the red element
00271       //
00272       for (j = 0; j < nsRed; j++)
00273       {
00274         int j1 = (j + 1) % nsRed;
00275         double area = area2D(&redCoords2D[2 * j], &redCoords2D[2 * j1], pp);
00276         if (dbg_1)
00277           std::cout << "   edge " << j << ": "
00278               << mb->id_from_handle(redEdges[j]) << " " << redConn[j] << " "
00279               << redConn[j1] << "  area : " << area << "\n";
00280         if (fabs(area) < epsilon_1/2)
00281         {
00282           // found the edge; now find if there is a point in the list here
00283           //std::vector<EntityHandle> * expts = extraNodesMap[redEdges[j]];
00284           int indx = -1;
00285           indx = RedEdges.index(redEdges[j]);
00286           std::vector<EntityHandle> * expts = extraNodesVec[indx];
00287           // if the points pp is between extra points, then just give that id
00288           // if not, create a new point, (check the id)
00289           // get the coordinates of the extra points so far
00290           int nbExtraNodesSoFar = expts->size();
00291           CartVect * coords1 = new CartVect[nbExtraNodesSoFar];
00292           mb->get_coords(&(*expts)[0], nbExtraNodesSoFar, &(coords1[0][0]));
00293           //std::list<int>::iterator it;
00294           for (int k = 0; k < nbExtraNodesSoFar && !found; k++)
00295           {
00296             //int pnt = *it;
00297             double d2 = (pos - coords1[k]).length_squared();
00298             if (d2 < epsilon_1)
00299             {
00300               found = 1;
00301               foundIds[i] = (*expts)[k];
00302               if (dbg_1)
00303                 std::cout << " found node:" << foundIds[i] << std::endl;
00304             }
00305           }
00306           if (!found)
00307           {
00308             // create a new point in 2d (at the intersection)
00309             //foundIds[i] = m_num2dPoints;
00310             //expts.push_back(m_num2dPoints);
00311             // need to create a new node in mbOut
00312             // this will be on the edge, and it will be added to the local list
00313             mb->create_vertex(pos.array(), outNode);
00314             (*expts).push_back(outNode);
00315             foundIds[i] = outNode;
00316             found = 1;
00317             if (dbg_1)
00318               std::cout << " new node: " << outNode << std::endl;
00319           }
00320           delete[] coords1;
00321         }
00322       }
00323     }
00324     if (!found)
00325     {
00326       std::cout << " red quad: ";
00327       for (int j1 = 0; j1 < nsRed; j1++)
00328       {
00329         std::cout << redCoords2D[2 * j1] << " " << redCoords2D[2 * j1 + 1] << "\n";
00330       }
00331       std::cout << " a point pp is not on a red quad " << *pp << " " << pp[1]
00332           << " red quad " << mb->id_from_handle(red) << " \n";
00333       delete[] foundIds;
00334       return 1;
00335     }
00336   }
00337   if (dbg_1)
00338   {
00339     std::cout << " candidate polygon: nP" << nP <<  " plane: " << plane << "\n";
00340     for (int i1 = 0; i1 < nP; i1++)
00341             std::cout << iP[2 * i1] << " " << iP[2 * i1 + 1] << " " << foundIds[i1] << "\n";
00342   }
00343   // first, find out if we have nodes collapsed; shrink them
00344   // we may have to reduce nP
00345   // it is possible that some nodes are collapsed after intersection only
00346   // nodes will always be in order (convex intersection)
00347   correct_polygon(foundIds, nP);
00348   // now we can build the triangles, from P array, with foundIds
00349   // we will put them in the out set
00350   if (nP >= 3)
00351   {
00352     EntityHandle polyNew;
00353     mb->create_element(MBPOLYGON, foundIds, nP, polyNew);
00354     mb->add_entities(outSet, &polyNew, 1);
00355 
00356     // tag it with the index ids from red and blue sets
00357     int id = rs1.index(blue); // index starts from 0
00358     mb->tag_set_data(blueParentTag, &polyNew, 1, &id);
00359     id = rs2.index(red);
00360     mb->tag_set_data(redParentTag, &polyNew, 1, &id);
00361 
00362     static int count=0;
00363     count++;
00364     mb->tag_set_data(countTag, &polyNew, 1, &count);
00365 
00366     if (dbg_1)
00367     {
00368 
00369       std::cout << "Count: " << count << "\n";
00370       std::cout << " polygon " << mb->id_from_handle(polyNew) << "  nodes: " << nP << " :";
00371       for (int i1 = 0; i1 < nP; i1++)
00372         std::cout << " " << mb->id_from_handle(foundIds[i1]);
00373       std::cout << " plane: " << plane << "\n";
00374       std::vector<CartVect> posi(nP);
00375       mb->get_coords(foundIds, nP, &(posi[0][0]));
00376       for (int i1 = 0; i1 < nP; i1++)
00377         std::cout << foundIds[i1]<< " " << posi[i1] << "\n";
00378 
00379       std::stringstream fff;
00380       fff << "file0" <<  count<< ".vtk";
00381          mb->write_mesh(fff.str().c_str(), &outSet, 1);
00382     }
00383 
00384   }
00385   disable_debug();
00386   delete[] foundIds;
00387   foundIds = NULL;
00388   return 0;
00389 }
00390 bool Intx2MeshOnSphere::is_inside_element(double xyz[3], EntityHandle eh)
00391 {
00392   int num_nodes;
00393   ErrorCode rval = mb->get_connectivity(eh, redConn, num_nodes);
00394 
00395   if (MB_SUCCESS != rval)
00396     return false;
00397   int nsRed = num_nodes;
00398 
00399   //CartVect coords[4];
00400   rval = mb->get_coords(redConn, num_nodes, &(redCoords[0][0]));
00401   if (MB_SUCCESS != rval)
00402     return 1;
00403   CartVect center(0.,0.,0.);
00404   for (int k=0; k<num_nodes; k++)
00405       center += redCoords[k];
00406   center = 1./num_nodes*center;
00407   decide_gnomonic_plane(center, plane);// output the plane
00408   for (int j = 0; j < nsRed; j++)
00409   {
00410     // populate coords in the plane for decision making
00411     // they should be oriented correctly, positively
00412     int rc = gnomonic_projection(redCoords[j],  R, plane, redCoords2D[2 * j],
00413         redCoords2D[2 * j + 1]);
00414     if (rc != 0)
00415       return false;
00416   }
00417   double pt[2];
00418   CartVect pos(xyz);
00419   int rc=gnomonic_projection(pos, R, plane, pt[0], pt[1]);
00420   if (rc != 0)
00421     return false;
00422 
00423   // now, is the projected point inside the red quad?
00424   // cslam utils
00425   if (point_in_interior_of_convex_polygon (redCoords2D, nsRed, pt))
00426     return true;
00427   return false;
00428 }
00429 
00430 ErrorCode Intx2MeshOnSphere::update_tracer_data(EntityHandle out_set, Tag & tagElem, Tag & tagArea)
00431 {
00432   EntityHandle dum = 0;
00433 
00434   Tag corrTag;
00435   ErrorCode rval = mb->tag_get_handle(CORRTAGNAME,
00436                                            1, MB_TYPE_HANDLE, corrTag,
00437                                            MB_TAG_DENSE, &dum); // it should have been created
00438   ERRORR(rval, "can't get correlation tag");
00439 
00440   Tag gid;
00441   rval = mb->tag_get_handle(GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, gid, MB_TAG_DENSE);
00442   ERRORR(rval,"can't get global ID tag" );
00443 
00444   // get all polygons out of out_set; then see where are they coming from
00445   Range polys;
00446   rval = mb->get_entities_by_dimension(out_set, 2, polys);
00447   ERRORR(rval, "can't get polygons out");
00448 
00449   // rs2 is the red range, arrival; rs1 is blue, departure;
00450   // there is a connection between rs1 and rs2, through the corrTag
00451   // corrTag is __correlation
00452   // basically, mb->tag_get_data(corrTag, &(redPoly), 1, &bluePoly);
00453   // also,  mb->tag_get_data(corrTag, &(bluePoly), 1, &redPoly);
00454   // we start from rs2 existing, then we have to update something
00455   std::vector<double>  currentVals(rs2.size());
00456   rval = mb->tag_get_data(tagElem, rs2, &currentVals[0]);
00457   ERRORR(rval, "can't get existing tag values");
00458 
00459   // for each polygon, we have 2 indices: red and blue parents
00460   // we need index blue to update index red?
00461   std::vector<double> newValues(rs2.size(), 0.);// initialize with 0 all of them
00462   // area of the polygon * conc on red (old) current quantity
00463   // finaly, divide by the area of the red
00464   double check_intx_area=0.;
00465   for (Range::iterator it= polys.begin(); it!=polys.end(); it++)
00466   {
00467     EntityHandle poly=*it;
00468     int blueIndex, redIndex;
00469     rval =  mb->tag_get_data(blueParentTag, &poly, 1, &blueIndex);
00470     ERRORR(rval, "can't get blue tag");
00471     EntityHandle blue = rs1[blueIndex];
00472     rval =  mb->tag_get_data(redParentTag, &poly, 1, &redIndex);
00473     ERRORR(rval, "can't get red tag");
00474     //EntityHandle red = rs2[redIndex];
00475     // big assumption here, red and blue are "parallel" ;we should have an index from
00476     // blue to red (so a deformed blue corresponds to an arrival red)
00477     double areap = area_spherical_element(mb, poly, R);
00478     check_intx_area+=areap;
00479     // so the departure cell at time t (blueIndex) covers a portion of a redCell
00480     // that quantity will be transported to the redCell at time t+dt
00481     // the blue corresponds to a red arrival
00482     EntityHandle redArr;
00483     rval = mb->tag_get_data(corrTag, &blue, 1, &redArr);
00484     if (0==redArr || MB_TAG_NOT_FOUND==rval)
00485     {
00486 #ifdef USE_MPI
00487       if (!remote_cells)
00488         ERRORR( MB_FAILURE, "no remote cells, failure\n");
00489       // maybe the element is remote, from another processor
00490       int global_id_blue;
00491       rval = mb->tag_get_data(gid, &blue, 1, &global_id_blue);
00492       ERRORR(rval, "can't get arrival red for corresponding blue gid");
00493       // find the
00494       int index_in_remote = remote_cells->find(1, global_id_blue);
00495       if (index_in_remote==-1)
00496         ERRORR( MB_FAILURE, "can't find the global id element in remote cells\n");
00497       remote_cells->vr_wr[index_in_remote] += currentVals[redIndex]*areap;
00498 #endif
00499     }
00500     else if (MB_SUCCESS==rval)
00501     {
00502       int arrRedIndex = rs2.index(redArr);
00503       if (-1 == arrRedIndex)
00504         ERRORR(MB_FAILURE, "can't find the red arrival index");
00505       newValues[arrRedIndex] += currentVals[redIndex]*areap;
00506     }
00507 
00508     else
00509       ERRORR(rval, "can't get arrival red for corresponding ");
00510   }
00511   // now, send back the remote_cells to the processors they came from, with the updated values for
00512   // the tracer mass in a cell
00513 #ifdef USE_MPI
00514   if (remote_cells)
00515   {
00516     // so this means that some cells will be sent back with tracer info to the procs they were sent from
00517     (parcomm->proc_config().crystal_router())->gs_transfer(1, *remote_cells, 0);
00518     // now, look at the global id, find the proper "red" cell with that index and update its mass
00519     //remote_cells->print("remote cells after routing");
00520     int n = remote_cells->get_n();
00521     for (int j=0; j<n; j++)
00522     {
00523       EntityHandle redCell = remote_cells->vul_rd[j];// entity handle sent back
00524       int arrRedIndex = rs2.index(redCell);
00525       if (-1 == arrRedIndex)
00526         ERRORR(MB_FAILURE, "can't find the red arrival index");
00527       newValues[arrRedIndex] += remote_cells->vr_rd[j];
00528     }
00529   }
00530 #endif /* USE_MPI */
00531   // now divide by red area (current)
00532   int j=0;
00533   Range::iterator iter = rs2.begin();
00534   void * data=NULL; //used for stored area
00535   int count =0;
00536   double total_mass_local=0.;
00537   while (iter != rs2.end())
00538   {
00539     rval = mb->tag_iterate(tagArea, iter, rs2.end(), count, data);
00540     ERRORR(rval, "can't tag iterate");
00541     double * ptrArea=(double*)data;
00542     for (int i=0; i<count; i++, iter++, j++, ptrArea++)
00543     {
00544       total_mass_local+=newValues[j];
00545       newValues[j]/= (*ptrArea);
00546     }
00547   }
00548   rval = mb->tag_set_data(tagElem, rs2, &newValues[0]);
00549   ERRORR(rval, "can't set new values tag");
00550 
00551 
00552 #ifdef USE_MPI
00553   double total_mass=0.;
00554   double total_intx_area =0;
00555   int mpi_err = MPI_Reduce(&total_mass_local, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
00556   if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
00557   // now reduce total area
00558   mpi_err = MPI_Reduce(&check_intx_area, &total_intx_area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
00559   if (MPI_SUCCESS != mpi_err) return MB_FAILURE;
00560   if (my_rank==0)
00561   {
00562     std::cout <<"total mass now:" << total_mass << "\n";
00563     std::cout <<"check: total intersection area: (4 * M_PI * R^2): " << 4 * M_PI * R*R << " " << total_intx_area << "\n";
00564   }
00565 
00566   if (remote_cells)
00567   {
00568     delete remote_cells;
00569     remote_cells=NULL;
00570   }
00571 #else
00572   std::cout <<"total mass now:" << total_mass_local << "\n";
00573   std::cout <<"check: total intersection area: (4 * M_PI * R^2): "  << 4 * M_PI * R*R << " " << check_intx_area << "\n";
00574 #endif
00575   return MB_SUCCESS;
00576 }
00577 } /* namespace moab */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines