![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /*
00002 * wrap_intx.cpp
00003 * Will implement the intersection method that will be callable from fortran too
00004 * will be added to the sub-library IntxMesh
00005 *
00006 *
00007 * Created on: Dec 14, 2013
00008 * Author: iulian
00009 */
00010 #include "iMesh.h"
00011 #include "iMeshP.h"
00012 #include "MBiMesh.hpp"
00013 #include "moab/Core.hpp"
00014 #include "moab/Range.hpp"
00015 #include "moab/Intx2MeshOnSphere.hpp"
00016 #include "moab/ReadUtilIface.hpp"
00017 #include "moab/ParallelComm.hpp"
00018 #include "MBTagConventions.hpp"
00019 #include "moab/ParallelMergeMesh.hpp"
00020 #include "moab/IntxUtils.hpp"
00021
00022 #include
00023 #include
00024
00025 using namespace moab;
00026 static double radius = 1.;
00027 static double gtol = 1.e-9;
00028 static bool debug = false;
00029
00030 // this mapping to coordinates will keep an index into the coords and dep_coords array
00031 // more exactly, the fine vertices are in a Range fineVerts;
00032 // then the vertex index i in fineVerts , fineVerts[i] will have 3 coordinates at
00033 // index mapping_to_coords[i] * 3
00034 // more exactly, x = coords[ mapping_to_coords[i] * 3 ]
00035 // y = coords[ mapping_to_coords[i] * 3 + 1]
00036 // z = coords[ mapping_to_coords[i] * 3 + 2]
00037
00038 // in the same way, departure position for vertex depVerts[i] will be at index
00039 // mapping_to_coords[i] * 2 in dep_coords array (it has just latitude and longitude)
00040 //
00041 static int* mapping_to_coords = NULL;
00042 static int numVertices = 0;
00043 // this will be instantiated at create mesh step
00044 // should be cleaned up at the end
00045 static Intx2MeshOnSphere* pworker = NULL;
00046
00047 // should get rid of this; instead of using array[NC+1][NC+1], use row based indexing (C-style):
00048 // parray = new int[ (NC+1)*(NC+1) ] , and instead of array[i][j], use parray[ i*(NC+1) + j ]
00049 #define NC 3
00050
00051 /*
00052 * methods defined here:
00053 * void update_tracer(iMesh_Instance instance,
00054 iBase_EntitySetHandle imesh_euler_set, int * ierr);
00055
00056 void create_mesh(iMesh_Instance instance,
00057 iBase_EntitySetHandle * imesh_euler_set, double * coords, int * corners,
00058 int nc, int nelem, MPI_Fint comm, int * ierr) ;
00059
00060 void intersection_at_level(iMesh_Instance instance,
00061 iBase_EntitySetHandle fine_set, iBase_EntitySetHandle * intx_set, double * dep_coords, double
00062 radius, int nc, int nelem, MPI_Fint comm, int * ierr)
00063
00064 */
00065 #ifdef __cplusplus
00066 extern "C" {
00067 #endif
00068
00069 void initialize_area_and_tracer( iMesh_Instance instance,
00070 iBase_EntitySetHandle imesh_euler_set,
00071 double* area_vals,
00072 int* ierr )
00073 {
00074
00075 EntityHandle eul_set = (EntityHandle)imesh_euler_set;
00076
00077 moab::Interface* mb = MOABI;
00078 *ierr = 1;
00079
00080 ErrorCode rval;
00081
00082 Range eulQuads;
00083 rval = mb->get_entities_by_type( eul_set, MBQUAD, eulQuads );
00084 ERRORV( rval, "can't get eulerian quads" );
00085
00086 // area of the euler element is fixed, store it; it is used to recompute the averages at each
00087 // time step
00088 Tag tagArea = 0;
00089 std::string tag_name4( "Area" );
00090 rval = mb->tag_get_handle( tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT );
00091 ERRORV( rval, "can't get area tag" );
00092
00093 std::cout << " num quads = " << eulQuads.size() << "\n";
00094 ERRORV( rval, "can't set area for each quad" );
00095
00096 rval = mb->tag_set_data( tagArea, eulQuads, &area_vals[0] );
00097
00098 *ierr = 0;
00099 return;
00100 }
00101
00102 void update_tracer_test( iMesh_Instance instance,
00103 iBase_EntitySetHandle imesh_euler_set,
00104 iBase_EntitySetHandle imesh_output_set,
00105 int numTracers,
00106 double* tracer_vals,
00107 int* ierr )
00108 {
00109
00110 EntityHandle eul_set = (EntityHandle)imesh_euler_set;
00111 EntityHandle output_set = (EntityHandle)imesh_output_set;
00112
00113 moab::Interface* mb = MOABI;
00114 *ierr = 1;
00115
00116 ErrorCode rval;
00117
00118 Range eulQuads;
00119 rval = mb->get_entities_by_type( eul_set, MBQUAD, eulQuads );
00120 ERRORV( rval, "can't get eulerian quads" );
00121
00122 // tagElem is the average computed at each element, from nodal values
00123 Tag tagElem = 0;
00124 std::string tag_name2( "TracerAverage" );
00125 rval = mb->tag_get_handle( tag_name2.c_str(), numTracers, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT );
00126 ERRORV( rval, "can't get tracer tag " );
00127
00128 // area of the euler element is fixed, store it; it is used to recompute the averages at each
00129 // time step
00130 Tag tagArea = 0;
00131 std::string tag_name4( "Area" );
00132 rval = mb->tag_get_handle( tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT );
00133 ERRORV( rval, "can't get area tag" );
00134
00135 std::cout << " num quads = " << eulQuads.size() << "\n";
00136
00137 rval = mb->tag_set_data( tagElem, eulQuads, &tracer_vals[0] );
00138 ERRORV( rval, "can't set tracer data" );
00139
00140 rval = pworker->update_tracer_data( output_set, tagElem, tagArea );
00141 ERRORV( rval, "can't update tracer " );
00142
00143 rval = mb->tag_get_data( tagElem, eulQuads, &tracer_vals[0] );
00144 ERRORV( rval, "can't get tracer data" );
00145
00146 *ierr = 0;
00147 return;
00148 }
00149
00150 void update_tracer( iMesh_Instance instance, iBase_EntitySetHandle imesh_euler_set, int* ierr )
00151 {
00152 using namespace moab;
00153 const double radius = 1.;
00154 const double gtol = 1.e-9;
00155 const bool debug = false;
00156
00157 Range ents;
00158 moab::Interface* mb = MOABI;
00159 *ierr = 1;
00160
00161 EntityHandle euler_set = (EntityHandle)imesh_euler_set;
00162
00163 Intx2MeshOnSphere worker( mb );
00164 worker.SetRadius( radius );
00165
00166 worker.SetErrorTolerance( gtol );
00167
00168 EntityHandle covering_lagr_set;
00169
00170 ErrorCode rval = mb->create_meshset( MESHSET_SET, covering_lagr_set );
00171 ERRORV( rval, "can't create covering set " );
00172
00173 // we need to update the correlation tag and remote tuples
00174 rval = worker.create_departure_mesh_2nd_alg( euler_set, covering_lagr_set );
00175 ERRORV( rval, "can't populate covering set " );
00176
00177 if( debug )
00178 {
00179 rval = mb->write_file( "lagr.h5m", 0, 0, &covering_lagr_set, 1 );
00180 ERRORV( rval, "can't write covering set " );
00181 }
00182
00183 //
00184 rval = enforce_convexity( mb, covering_lagr_set );
00185 ERRORV( rval, "can't write covering set " );
00186
00187 EntityHandle outputSet;
00188 rval = mb->create_meshset( MESHSET_SET, outputSet );
00189 ERRORV( rval, "can't create output set " );
00190
00191 rval = worker.intersect_meshes( covering_lagr_set, euler_set, outputSet );
00192 ERRORV( rval, "can't intersect " );
00193
00194 if( debug )
00195 {
00196 rval = mb->write_file( "output.vtk", 0, 0, &outputSet, 1 );
00197 ERRORV( rval, "can't write covering set " );
00198 }
00199
00200 // tagElem is the average computed at each element, from nodal values
00201 Tag tagElem = 0;
00202 std::string tag_name2( "TracerAverage" );
00203 rval = mb->tag_get_handle( tag_name2.c_str(), 1, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT );
00204 ERRORV( rval, "can't get tracer tag " );
00205
00206 // area of the euler element is fixed, store it; it is used to recompute the averages at each
00207 // time step
00208 Tag tagArea = 0;
00209 std::string tag_name4( "Area" );
00210 rval = mb->tag_get_handle( tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT );
00211 ERRORV( rval, "can't get area tag" );
00212
00213 rval = worker.update_tracer_data( outputSet, tagElem, tagArea );
00214 ERRORV( rval, "can't update tracer " );
00215
00216 // everything can be deleted now from intx data; polygons, etc.
00217
00218 *ierr = 0;
00219 return;
00220 }
00221
00222 ErrorCode create_coarse_mesh( Interface* mb,
00223 ParallelComm* pcomm,
00224 EntityHandle coarseSet,
00225 double* coords,
00226 int* corners,
00227 int nc,
00228 int nelem,
00229 EntityHandle& start_vert,
00230 int& totalNumVertices,
00231 int& numCornerVertices,
00232 std::vector< double* >& coordv )
00233 {
00234
00235 int rank = pcomm->proc_config().proc_rank();
00236
00237 Tag tagid; // global id at corners
00238 ErrorCode rval;
00239 tagid = mb->globalId_tag();
00240
00241 int dum_id = -1;
00242 Tag partitionTag;
00243 mb->tag_get_handle( PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, partitionTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00244 &dum_id );
00245
00246 // there are nelem*4 corners, and 3*(nc2+1)*(nc2+1)*nelem coordinates
00247 // create first a coarse mesh,
00248 int size_corners = 4 * nelem;
00249 // int size_coords=3*(nc+1)*(nc+1)*nelem;
00250 // order first the corners array, and eliminate duplicates
00251 std::vector< int > corn1( size_corners );
00252 std::copy( corners, corners + size_corners, corn1.begin() );
00253 std::sort( corn1.begin(), corn1.end() );
00254 corn1.erase( std::unique( corn1.begin(), corn1.end() ), corn1.end() );
00255
00256 numCornerVertices = (int)corn1.size();
00257
00258 // these corners are actually dofs in spectral mesh, so they will vary from 0 to
00259 // np*np*nel_global (at most) they are shared on edges, corners of spectral elements, so number
00260 // of dofs is lower than this estimate still, the number of coarse vertices is close to number
00261 // of cells + 2
00262
00263 std::map< int, int > index_map;
00264 for( size_t i = 0; i < corn1.size(); i++ )
00265 index_map[corn1[i]] = i;
00266
00267 // estimate for the vertices that will get created, from euler formula
00268 // v-e+f = 2 for whole sphere
00269 // for one task (distributed) v-e+f = 1, for one connected region
00270 // if multiple connex regions (out of HFSC distribution from homme), v-e+f = k, k is number of
00271 // connectivity regs so in any case, e = v+f -k, where k is at least 1 (1, 2, 3, etc) so in any
00272 // case number of coarse edges is at most e_max = v+f-1
00273
00274 // this will give an estimate for the number of "fine" vertices
00275 int e_max = nelem + numCornerVertices - 1;
00276 // total number of extra vertices will be
00277 int numVertsOnEdges = ( nc - 1 ) * e_max;
00278 int numExtraVerts = numVertsOnEdges + ( nc - 1 ) * ( nc - 1 ) * nelem; // internal fine vertices
00279
00280 totalNumVertices = numCornerVertices + numExtraVerts; // this could be overestimated, because we are not sure
00281 // about the number of edges
00282
00283 // used to determine the if the nodes are matching at corners of elements
00284 std::vector< int > index_used( numCornerVertices, 0 );
00285
00286 ReadUtilIface* read_iface;
00287 rval = mb->query_interface( read_iface );ERRORR( rval, "can't get query intf " );
00288
00289 EntityHandle start_elem, *connect;
00290 // create verts, num is 2(nquads+1) because they're in a 1d row; will initialize coords in loop
00291 // over quads later
00292 rval = read_iface->get_node_coords( 3, totalNumVertices, 0, start_vert, coordv );ERRORR( rval, "can't get node coords " );
00293 // fill it up
00294 int stride = ( nc + 1 ) * ( nc + 1 ); // 16, for nc ==3
00295 // int order_in_coord[] = {0, 3, 15, 12}; // for nc=3
00296 /*
00297
00298 * first j, then i, so this is the order of the points in coords array, now:
00299 *
00300 * nc(nc+1), ... (nc+1)*(nc+1)-1
00301 *
00302 * 2(nc+1),
00303 * nc+1, nc+2, 2*(nc+1)-1
00304 * 0, 1 , 2, ..........., nc
00305 */
00306 int order_in_coord[] = { 0, nc, ( nc + 1 ) * ( nc + 1 ) - 1, nc * ( nc + 1 ) };
00307 for( int i = 0; i < size_corners; i++ )
00308 {
00309 int id = corners[i];
00310 int index = index_map[id];
00311
00312 int j = i % 4;
00313 int ind_coord = i / 4;
00314 ind_coord = ( ind_coord * stride + order_in_coord[j] ) * 3;
00315 if( index_used[index] )
00316 {
00317 if( fabs( coordv[0][index] - coords[ind_coord] ) > 0.000001 )
00318 std::cout << " id:" << corners[i] << " i:" << i << " j:" << j << " " << coordv[0][index] << " "
00319 << coords[ind_coord] << "\n";
00320 continue;
00321 }
00322 coordv[0][index] = coords[ind_coord];
00323 coordv[1][index] = coords[ind_coord + 1];
00324 coordv[2][index] = coords[ind_coord + 2];
00325 index_used[index] = 1;
00326 EntityHandle vertexh = start_vert + index;
00327 rval = mb->tag_set_data( tagid, &vertexh, 1, (void*)&id );ERRORR( rval, "can't set tag id on vertex " );
00328 }
00329 // create quads; one quad for each spectral element; later, we will create fine quads
00330 rval = read_iface->get_element_connect( nelem, 4, MBQUAD, 0, start_elem, connect );ERRORR( rval, "can't create elements " );
00331
00332 for( int i = 0; i < nelem; i++ )
00333 {
00334 for( int j = 0; j < 4; j++ )
00335 {
00336 int index_v = index_map[corners[i * 4 + j]];
00337 connect[i * 4 + j] = start_vert + index_v;
00338 }
00339 }
00340
00341 Range quads( start_elem, start_elem + nelem - 1 );
00342
00343 mb->add_entities( coarseSet, quads );
00344
00345 // create all edges adjacent to quads
00346 Range coarseEdges;
00347 rval = mb->get_adjacencies( quads, 1, true, coarseEdges, Interface::UNION );ERRORR( rval, "can't create edges " );
00348
00349 mb->add_entities( coarseSet, coarseEdges );
00350
00351 // see how much we overestimated the number e_max
00352 std::cout << " on rank " << rank << " e_max is " << e_max << " actual number of edges: " << coarseEdges.size()
00353 << "\n";
00354 rval = pcomm->resolve_shared_ents( coarseSet, 2, 1 ); // resolve vertices and edges
00355 ERRORR( rval, "can't resolve shared vertices and edges " );
00356
00357 mb->tag_set_data( partitionTag, &coarseSet, 1, &rank );
00358
00359 /* // do we have any edges?
00360 Range edges;
00361 mb->get_entities_by_dimension(0, 1, edges);
00362 if (rank == 0)
00363 std::cout << " number of edges after resolve share ents:" << edges.size()
00364 << "\n";*/
00365
00366 rval = mb->write_file( "coarse.h5m", 0, "PARALLEL=WRITE_PART", &coarseSet, 1 );ERRORR( rval, "can't write in parallel coarse mesh" );
00367 // coarse mesh, from corners
00368
00369 return rval;
00370 }
00371
00372 // start_v and coordv refer to all vertices, including the coarse ones
00373 ErrorCode fill_coord_on_edges( Interface* mb,
00374 std::vector< double* >& coordv,
00375 double* coords,
00376 Range& edges,
00377 EntityHandle start_v,
00378 Range& coarseQuads,
00379 int nc,
00380 int numCornerVertices,
00381 Tag& fineVertOnEdgeTag )
00382 {
00383 ErrorCode rval = MB_SUCCESS;
00384
00385 double* coordv2[3];
00386 for( int k = 0; k < 3; k++ )
00387 coordv2[k] = coordv[k] + numCornerVertices; // they will start later
00388
00389 assert( NC == nc );
00390
00391 int edges_index[4][NC - 1]; // indices in the coords array for vertices, oriented positively
00392 /*
00393 * first j, then i, so this is the order of the points in coords array, now:
00394 *
00395 * nc(nc+1), ... (nc+1)*(nc+1)-1
00396 *
00397 * 2(nc+1),
00398 * nc+1, nc+2, 2*(nc+1)-1
00399 * 0, 1 , 2, ..........., nc
00400 */
00401 // for first edge, oriented positive, the coords indices (*3) are 1, 2, (nc-1)
00402 // second edge 2*(nc+1)-1, 3*(nc+1) -1, ...,
00403 // nc*(nc+1)-1 third edge: (nc+1) * (nc+1) -2,
00404 // ..., nc*(nc+1) +1 fourth edge: (nc-1)*(nc+1),
00405 // ..., (nc+1)
00406 for( int j = 1; j <= nc - 1; j++ )
00407 {
00408 edges_index[0][j - 1] = j; // for nc = 3: 1, 2
00409 edges_index[1][j - 1] = ( j + 1 ) * ( nc + 1 ) - 1; // 7, 11
00410 edges_index[2][j - 1] = ( nc + 1 ) * ( nc + 1 ) - j - 1; // 14, 13
00411 edges_index[3][j - 1] = ( nc - j ) * ( nc + 1 ); // 8, 4
00412 }
00413 // int num_quads=(int)coarseQuads.size();
00414 int stride = ( nc + 1 ) * ( nc + 1 );
00415 int indexv = 0;
00416 for( Range::iterator eit = edges.begin(); eit != edges.end(); ++eit )
00417 {
00418 EntityHandle edge = *eit;
00419 std::vector< EntityHandle > faces;
00420 rval = mb->get_adjacencies( &edge, 1, 2, false, faces );ERRORR( rval, "can't get adjacent faces." );
00421 if( faces.size() < 1 ) return MB_FAILURE;
00422 int sense = 0, side_number = -1, offset = -1;
00423 EntityHandle quad = faces[0]; // just consider first quad
00424 rval = mb->side_number( quad, edge, side_number, sense, offset );ERRORR( rval, "can't get side number" );
00425 int indexq = coarseQuads.index( quad );
00426
00427 if( indexq == -1 ) return MB_FAILURE;
00428
00429 EntityHandle firstRefinedV = start_v + numCornerVertices + indexv;
00430 rval = mb->tag_set_data( fineVertOnEdgeTag, &edge, 1, &firstRefinedV );ERRORR( rval, "can't set refined vertex tag" );
00431 // copy the right coordinates from the coords array to coordv2 array
00432
00433 double* start_quad = &coords[3 * stride * indexq];
00434 if( sense > 0 )
00435 {
00436 for( int k = 1; k <= nc - 1; k++ )
00437 {
00438 int index_in_quad = edges_index[side_number][k - 1] * 3;
00439 coordv2[0][indexv] = start_quad[index_in_quad];
00440 coordv2[1][indexv] = start_quad[index_in_quad + 1];
00441 coordv2[2][indexv] = start_quad[index_in_quad + 2];
00442 indexv++;
00443 }
00444 }
00445 else
00446 {
00447 // sense < 0, so we will traverse the edge in inverse sense
00448 for( int k = 1; k <= nc - 1; k++ )
00449 {
00450 int index_in_quad = edges_index[side_number][nc - 1 - k] * 3;
00451 coordv2[0][indexv] = start_quad[index_in_quad];
00452 coordv2[1][indexv] = start_quad[index_in_quad + 1];
00453 coordv2[2][indexv] = start_quad[index_in_quad + 2];
00454 indexv++;
00455 }
00456 }
00457 }
00458 return rval;
00459 }
00460 /*
00461 ErrorCode resolve_interior_verts_on_bound_edges(Interface * mb, ParallelComm * pcomm,
00462 Range & edges)
00463 {
00464 // edges are coarse edges;
00465 ErrorCode rval;
00466 int rank=pcomm->proc_config().proc_rank();
00467 Range sharedCoarseEdges=edges;// filter the non shared ones
00468 rval = pcomm->filter_pstatus(sharedCoarseEdges, PSTATUS_SHARED, PSTATUS_AND);ERRORR(rval, "can't filter coarse edges
00469 "); ParallelMergeMesh pmerge(pcomm, 0.0001); ErrorCode rval = pmerge.merge();
00470
00471 return rval;
00472 }*/
00473 ErrorCode create_fine_mesh( Interface* mb,
00474 ParallelComm* pcomm,
00475 EntityHandle coarseSet,
00476 EntityHandle fine_set,
00477 double* coords,
00478 int nc,
00479 int nelem,
00480 EntityHandle start_vert,
00481 int numCornerVertices,
00482 std::vector< double* >& coordv )
00483 {
00484 int rank = pcomm->proc_config().proc_rank();
00485 int stride = ( nc + 1 ) * ( nc + 1 ); // 16, for nc ==3
00486 // there are stride*3 coordinates for each coarse quad, representing the fine mesh
00487
00488 Tag fineVertTag;
00489 // will store the first refined vertex on an edge in a entity handle tag
00490 EntityHandle def = 0;
00491 ErrorCode rval =
00492 mb->tag_get_handle( "__firstvertex", 1, MB_TYPE_HANDLE, fineVertTag, MB_TAG_DENSE | MB_TAG_CREAT, &def );ERRORR( rval, "can't get tag on first vertex" );
00493
00494 Range coarseQuads;
00495 Range edges;
00496 rval = mb->get_entities_by_dimension( coarseSet, 2, coarseQuads );ERRORR( rval, "can't get coarse quads " );
00497
00498 rval = mb->get_entities_by_dimension( coarseSet, 1, edges );ERRORR( rval, "can't get coarse edges " );
00499
00500 Range verts;
00501 rval = mb->get_connectivity( coarseQuads, verts );ERRORR( rval, "can't get coarse vertices " );
00502
00503 /*std::cout <<" local coarse mesh on rank " << rank << " "<< coarseQuads.size() << " quads, "
00504 << edges.size() << " edges, " << verts.size() << " vertices.\n";*/
00505
00506 int dum_id = -1;
00507 Tag partitionTag;
00508 mb->tag_get_handle( PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, partitionTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00509 &dum_id );
00510 // fine mesh, with all coordinates
00511 // std::vector coordv2;
00512
00513 ReadUtilIface* read_iface;
00514 rval = mb->query_interface( read_iface );ERRORR( rval, "can't get query intf " );
00515
00516 ;
00517 // create verts, (nc+1)*(nc+1)*nelem - verts.size()
00518 //
00519 /* int numVertsOnEdges = (nc-1)*(int)edges.size();
00520 int numExtraVerts = numVertsOnEdges + (nc-1)*(nc-1)*nelem; // internal fine vertices
00521 rval = read_iface->get_node_coords(3, numExtraVerts, 0,
00522 start_vert, coordv2);*/
00523 // ERRORR(rval, "can't get coords fine mesh");
00524 // fill coordinates for vertices on the edges, then vertices in the interior of coarse quads
00525 // we know that all quads are in order, their index corresponds to index in coords array
00526 rval =
00527 fill_coord_on_edges( mb, coordv, coords, edges, start_vert, coarseQuads, nc, numCornerVertices, fineVertTag );ERRORR( rval, "can't fill edges vertex coords on fine mesh" );
00528
00529 EntityHandle start_elem, *connect;
00530 rval = read_iface->get_element_connect( nelem * nc * nc, 4, MBQUAD, 0, start_elem, connect );ERRORR( rval, "can't create elements fine mesh" );
00531
00532 int iv = ( nc - 1 ) * edges.size() + numCornerVertices; // iv is in the coordv array indices
00533 start_vert = start_vert + numCornerVertices + ( nc - 1 ) * edges.size();
00534
00535 /* // add a child to the mesh set, with the ordered vertices, as they come out in the list of
00536 coordinates EntityHandle vertSet; rval = mb->create_meshset(MESHSET_ORDERED, vertSet);ERRORR(rval, "can't create
00537 vertex set ");
00538
00539 rval = mb->add_parent_child(fine_set, vertSet);ERRORR(rval, "can't create parent child relation between fine set
00540 and vertSet ");*/
00541
00542 std::vector< EntityHandle > vertList;
00543 vertList.reserve( nelem * ( nc + 1 ) * ( nc + 1 ) ); // will have a list of vertices, in order
00544
00545 // now fill coordinates on interior nodes; also mark the start for each interior vertex
00546 // in a coarse quad
00547 for( int ie = 0; ie < nelem; ie++ )
00548 {
00549 // just fill coordinates for an array of (nc-1)*(nc-1) vertices
00550 EntityHandle firstVert = start_vert + ( nc - 1 ) * ( nc - 1 ) * ie;
00551 EntityHandle eh = coarseQuads[ie];
00552 rval = mb->tag_set_data( fineVertTag, &eh, 1, &firstVert );ERRORR( rval, "can't set refined vertex tag" );
00553
00554 int index_coords = stride * ie;
00555 for( int j = 1; j <= ( nc - 1 ); j++ )
00556 {
00557 for( int i = 1; i <= ( nc - 1 ); i++ )
00558 {
00559 int indx2 = 3 * ( index_coords + ( nc + 1 ) * j + i );
00560 coordv[0][iv] = coords[indx2];
00561 coordv[1][iv] = coords[indx2 + 1];
00562 coordv[2][iv] = coords[indx2 + 2];
00563 iv++;
00564 }
00565 }
00566 }
00567
00568 Range quads3( start_elem, start_elem + nelem * nc * nc - 1 );
00569
00570 int ic = 0;
00571 for( int ie = 0; ie < nelem; ie++ )
00572 {
00573 // just fill coordinates for an array of (nc-1)*(nc-1) vertices
00574 EntityHandle arr2[NC + 1][NC + 1]; //
00575 /*
00576 * (nc,0) (nc,nc)
00577 *
00578 *
00579 * (1,0) (1,nc)
00580 * (0,0) (0,1) (0,nc)
00581 */
00582 EntityHandle coarseQ = coarseQuads[ie];
00583 const EntityHandle* conn4 = NULL;
00584 int nnodes = 0;
00585 rval = mb->get_connectivity( coarseQ, conn4, nnodes );ERRORR( rval, "can't get conn of coarse quad" );
00586 if( nnodes != 4 ) return MB_FAILURE;
00587
00588 arr2[0][0] = conn4[0];
00589 arr2[nc][0] = conn4[1];
00590 arr2[nc][nc] = conn4[2];
00591 arr2[0][nc] = conn4[3];
00592
00593 // get the coarse edges
00594 std::vector< EntityHandle > aedges;
00595 rval = mb->get_adjacencies( &coarseQ, 1, 1, false, aedges );ERRORR( rval, "can't get adje edges of coarse quad" );
00596 assert( (int)aedges.size() == 4 );
00597
00598 for( int k = 0; k < 4; k++ )
00599 {
00600 EntityHandle edh = aedges[k];
00601 /*
00602 edges_index[0][j-1] = j; // for nc = 3: 1, 2
00603 edges_index[1][j-1] = (j+1)*(nc+1) - 1; // 7, 11
00604 edges_index[2][j-1] = (nc+1)*(nc+1) - j - 1; // 14, 13
00605 edges_index[3][j-1] = (nc-j) * (nc+1) ; // 8, 4
00606 */
00607 int sense = 0, side_number = -1, offset = -1;
00608 rval = mb->side_number( coarseQ, edh, side_number, sense, offset );ERRORR( rval, "can't get side number" );
00609 EntityHandle firstV; // first vertex on edge, if edge oriented positively
00610 rval = mb->tag_get_data( fineVertTag, &edh, 1, &firstV );ERRORR( rval, "can't get first vertex tag on edge" );
00611 if( sense > 0 )
00612 {
00613 if( 0 == side_number )
00614 {
00615 for( int i = 1; i <= nc - 1; i++ )
00616 arr2[i][0] = firstV + i - 1;
00617 }
00618 else if( 1 == side_number )
00619 {
00620 for( int j = 1; j <= nc - 1; j++ )
00621 arr2[nc][j] = firstV + j - 1;
00622 }
00623 else if( 2 == side_number )
00624 {
00625 for( int i = nc - 1; i >= 1; i-- )
00626 arr2[i][nc] = firstV + nc - 1 - i;
00627 }
00628 else if( 3 == side_number )
00629 {
00630 for( int j = nc - 1; j >= 1; j-- )
00631 arr2[0][j] = firstV + nc - 1 - j;
00632 }
00633 }
00634 else // if (sense<0)
00635 {
00636 if( 0 == side_number )
00637 {
00638 for( int i = 1; i <= nc - 1; i++ )
00639 arr2[i][0] = firstV + nc - 1 - i;
00640 }
00641 else if( 1 == side_number )
00642 {
00643 for( int j = 1; j <= nc - 1; j++ )
00644 arr2[nc][j] = firstV + nc - 1 - j;
00645 }
00646 else if( 2 == side_number )
00647 {
00648 for( int i = nc - 1; i >= 1; i-- )
00649 arr2[i][nc] = firstV + i - 1;
00650 }
00651 else if( 3 == side_number )
00652 {
00653 for( int j = nc - 1; j >= 1; j-- )
00654 arr2[0][j] = firstV + j - 1;
00655 }
00656 }
00657 }
00658 // fill the interior points matrix
00659 EntityHandle firstV; // first vertex on interior of coarse quad
00660 rval = mb->tag_get_data( fineVertTag, &coarseQ, 1, &firstV );ERRORR( rval, "can't get first vertex tag on coarse tag" );
00661 int inc = 0;
00662 for( int j = 1; j <= nc - 1; j++ )
00663 {
00664 for( int i = 1; i <= nc - 1; i++ )
00665 {
00666 arr2[i][j] = firstV + inc;
00667 inc++;
00668 }
00669 }
00670 // fill now the matrix of quads; vertices are from 0 to (nc+1)*(nc+1)-1
00671 for( int j1 = 0; j1 < nc; j1++ )
00672 {
00673 for( int i1 = 0; i1 < nc; i1++ )
00674 {
00675 connect[ic++] = arr2[i1][j1]; // first one
00676 connect[ic++] = arr2[i1 + 1][j1]; //
00677 connect[ic++] = arr2[i1 + 1][j1 + 1]; // opp diagonal
00678 connect[ic++] = arr2[i1][j1 + 1]; //
00679 }
00680 }
00681
00682 for( int j1 = 0; j1 <= nc; j1++ )
00683 {
00684 for( int i1 = 0; i1 <= nc; i1++ )
00685 {
00686 vertList.push_back( arr2[i1][j1] );
00687 }
00688 }
00689 }
00690 /*
00691 rval = mb->add_entities(vertSet, &vertList[0], (int)vertList.size());ERRORR(rval,"can't add to the vert set the
00692 list of ordered vertices");*/
00693
00694 mb->add_entities( fine_set, quads3 );
00695 // notify MOAB of the new elements
00696 rval = read_iface->update_adjacencies( start_elem, nelem * nc * nc, 4, connect );ERRORR( rval, "can't update adjacencies on fine quads" );
00697
00698 rval = mb->tag_set_data( partitionTag, &fine_set, 1, &rank );ERRORR( rval, "can't set partition tag on fine set" );
00699
00700 /*
00701 // delete the coarse mesh, except vertices
00702 mb->delete_entities(coarseQuads);
00703 mb->delete_entities(edges);
00704 */
00705
00706 // the vertices on the boundary edges of the partition need to be shared and resolved
00707 ParallelMergeMesh pmerge( pcomm, 0.0001 );
00708 rval = pmerge.merge();ERRORR( rval, "can't resolve vertices on interior of boundary edges " );
00709
00710 rval = mb->get_connectivity( quads3, verts );ERRORR( rval, "can't get vertices " );
00711
00712 Range owned_verts = verts;
00713 rval = pcomm->filter_pstatus( owned_verts, PSTATUS_NOT_OWNED, PSTATUS_NOT );ERRORR( rval, "can't filter for owned vertices only" );
00714
00715 Range entities[4];
00716 entities[0] = owned_verts;
00717 entities[2] = quads3;
00718 // assign new ids only for owned entities
00719 // will eliminate gaps in global id space for vertices
00720 rval = pcomm->assign_global_ids( entities, 2, 1, true, false );ERRORR( rval, "can't assign global ids for vertices " );
00721
00722 /*ErrorCode ParallelComm::assign_global_ids( Range entities[],
00723 const int dimension,
00724 const int start_id,
00725 const bool parallel,
00726 const bool owned_only) */
00727
00728 std::stringstream fff;
00729 fff << "fine0" << pcomm->proc_config().proc_rank() << ".h5m";
00730 mb->write_mesh( fff.str().c_str(), &fine_set, 1 );
00731
00732 rval = mb->write_file( "fine.h5m", 0, "PARALLEL=WRITE_PART", &fine_set, 1 );ERRORR( rval, "can't write set 3, fine " );
00733
00734 // we need to keep a mapping index, from the coords array to the vertex handles
00735 // so, for a given vertex entity handle, at what index in the coords array the vertex
00736 // coordinates are?
00737 // in the coords array, vertices are repeated 2 times if they are interior to a coarse edge, and
00738 // repeated 3 or 4 times if they are a corner vertex in a coarse quad
00739
00740 numVertices = (int)verts.size();
00741 mapping_to_coords = new int[numVertices];
00742 for( int k = 0; k < numVertices; k++ )
00743 mapping_to_coords[k] = -1; // it means it was not located yet in vertList
00744 // vertList is parallel to the coords and dep_coords array
00745
00746 // now loop over vertsList, and see where
00747 // vertList has nelem * (nc+1)*(nc+1) vertices; loop over them, and see where are they located
00748
00749 for( int kk = 0; kk < (int)vertList.size(); kk++ )
00750 {
00751 EntityHandle v = vertList[kk];
00752 int index = verts.index( v );
00753 if( -1 == index )
00754 {
00755 std::cout << " can't locate vertex " << v << " in vertex Range \n";
00756 return MB_FAILURE;
00757 }
00758 if( mapping_to_coords[index] == -1 ) // it means the vertex v was not yet encountered in the vertList
00759 {
00760 mapping_to_coords[index] = kk;
00761 }
00762 }
00763 // check that every mapping has an index different from -1
00764 for( int k = 0; k < numVertices; k++ )
00765 {
00766 if( mapping_to_coords[k] == -1 )
00767 {
00768 {
00769 std::cout << " vertex at index " << k << " in vertex Range " << verts[k] << " is not mapped \n";
00770 return MB_FAILURE; //
00771 }
00772 }
00773 }
00774
00775 return rval;
00776 }
00777
00778 // this is called from Fortran 90
00779 void create_mesh( iMesh_Instance instance,
00780 iBase_EntitySetHandle* imesh_euler_set,
00781 iBase_EntitySetHandle* imesh_departure_set,
00782 iBase_EntitySetHandle* imesh_intx_set,
00783 double* coords,
00784 int* corners,
00785 int nc,
00786 int nelem,
00787 MPI_Fint comm,
00788 int* ierr )
00789 {
00790 /* double * coords=(double*) icoords;
00791 int * corners = (int*) icorners;*/
00792 *ierr = 1;
00793 Interface* mb = MOABI;
00794 MPI_Comm mpicomm = MPI_Comm_f2c( comm );
00795 // instantiate parallel comm now or not?
00796 ParallelComm* pcomm = new ParallelComm( mb, mpicomm );
00797
00798 EntityHandle coarseSet;
00799 ErrorCode rval = mb->create_meshset( MESHSET_SET, coarseSet );
00800 ERRORV( rval, "can't create coarse set " );
00801
00802 EntityHandle start_vert;
00803 int totalNumVertices;
00804 int numCornerVertices;
00805 std::vector< double* > coordv;
00806 rval = create_coarse_mesh( mb, pcomm, coarseSet, coords, corners, nc, nelem, start_vert, totalNumVertices,
00807 numCornerVertices, coordv );
00808 ERRORV( rval, "can't create coarse set " );
00809
00810 EntityHandle fine_set;
00811 rval = mb->create_meshset( MESHSET_SET, fine_set );
00812 ERRORV( rval, "can't create fine set " );
00813
00814 rval = create_fine_mesh( mb, pcomm, coarseSet, fine_set, coords, nc, nelem, start_vert, numCornerVertices, coordv );
00815 ERRORV( rval, "can't create fine mesh set " );
00816
00817 *imesh_departure_set = (iBase_EntitySetHandle)fine_set;
00818
00819 EntityHandle euler_set;
00820 rval = mb->create_meshset( MESHSET_SET, euler_set );
00821 ERRORV( rval, "can't create moab euler set " );
00822 *imesh_euler_set = (iBase_EntitySetHandle)euler_set;
00823
00824 // call in Intx utils
00825 // it will copy the second set from the first set
00826 rval = deep_copy_set_with_quads( mb, fine_set, euler_set );
00827 ERRORV( rval, "can't populate lagrange set " );
00828
00829 EntityHandle intx_set;
00830 rval = mb->create_meshset( MESHSET_SET, intx_set );
00831 ERRORV( rval, "can't create output set " );
00832
00833 *imesh_intx_set = (iBase_EntitySetHandle)intx_set;
00834
00835 pworker = new Intx2MeshOnSphere( mb );
00836
00837 pworker->set_box_error( 100 * gtol );
00838 Range local_verts;
00839 rval = pworker->build_processor_euler_boxes( euler_set,
00840 local_verts ); // output also the local_verts
00841 ERRORV( rval, "can't compute euler boxes " );
00842 pworker->SetErrorTolerance( gtol );
00843
00844 *ierr = 0;
00845 return;
00846 }
00847 ErrorCode set_departure_points_position( Interface* mb, EntityHandle lagrSet, double* dep_coords, double radius2 )
00848 {
00849
00850 // the departure quads are created in the same order as the fine quads
00851 // for each coarse element, there are nc*nc fine quads
00852 // their vertices are in order
00853 Range lagr_quads;
00854 ErrorCode rval = mb->get_entities_by_type( lagrSet, MBQUAD, lagr_quads );ERRORR( rval, "can't get lagrange quads" );
00855
00856 // get all vertices from lagr_quads
00857 Range lVerts;
00858 rval = mb->get_connectivity( lagr_quads, lVerts );ERRORR( rval, "can't get lagrangian vertices (departure)" );
00859
00860 // they are parallel to the verts Array, they must have the same number of vertices
00861 assert( numVertices == (int)lVerts.size() );
00862
00863 for( int i = 0; i < numVertices; i++ )
00864 {
00865 EntityHandle v = lVerts[i];
00866 int index = mapping_to_coords[i];
00867 assert( -1 != index );
00868
00869 SphereCoords sph;
00870 sph.R = radius2;
00871 sph.lat = dep_coords[2 * index];
00872 sph.lon = dep_coords[2 * index + 1];
00873
00874 CartVect depPoint = spherical_to_cart( sph );
00875 rval = mb->set_coords( &v, 1, (double*)depPoint.array() );ERRORR( rval, "can't set position of vertex" );
00876 }
00877
00878 return MB_SUCCESS;
00879 }
00880 void intersection_at_level( iMesh_Instance instance,
00881 iBase_EntitySetHandle fine_set,
00882 iBase_EntitySetHandle lagr_set,
00883 iBase_EntitySetHandle intx_set,
00884 double* dep_coords,
00885 double radius2,
00886 int* ierr )
00887 {
00888 *ierr = 1;
00889 Interface* mb = MOABI;
00890 // MPI_Comm mpicomm = MPI_Comm_f2c(comm);
00891 // instantiate parallel comm now or not?
00892
00893 EntityHandle lagrMeshSet = (EntityHandle)lagr_set;
00894
00895 ParallelComm* pcomm = ParallelComm::get_pcomm( mb, 0 );
00896 if( NULL == pcomm ) return; // error is 1
00897
00898 // set the departure tag on the fine mesh vertices
00899 ErrorCode rval = set_departure_points_position( mb, lagrMeshSet, dep_coords, radius2 );
00900 ERRORV( rval, "can't set departure tag" );
00901 if( debug )
00902 {
00903 std::stringstream fff;
00904 fff << "lagr0" << pcomm->proc_config().proc_rank() << ".vtk";
00905 rval = mb->write_mesh( fff.str().c_str(), &lagrMeshSet, 1 );
00906 ERRORV( rval, "can't write covering set " );
00907 }
00908
00909 // it should be done earlier
00910 pworker->SetRadius( radius );
00911
00912 EntityHandle covering_set;
00913 rval = pworker->create_departure_mesh_3rd_alg( lagrMeshSet, covering_set );
00914 ERRORV( rval, "can't compute covering set " );
00915
00916 if( debug )
00917 {
00918 std::stringstream fff;
00919 fff << "cover" << pcomm->proc_config().proc_rank() << ".vtk";
00920 rval = mb->write_mesh( fff.str().c_str(), &covering_set, 1 );
00921
00922 ERRORV( rval, "can't write covering set " );
00923 }
00924 EntityHandle intxSet = (EntityHandle)intx_set;
00925 rval = pworker->intersect_meshes( covering_set, (EntityHandle)fine_set, intxSet );
00926 ERRORV( rval, "can't intersect " );
00927
00928 if( debug )
00929 {
00930 std::stringstream fff;
00931 fff << "intx0" << pcomm->proc_config().proc_rank() << ".vtk";
00932 rval = mb->write_mesh( fff.str().c_str(), &intxSet, 1 );
00933 ERRORV( rval, "can't write covering set " );
00934 }
00935
00936 return;
00937 }
00938 void cleanup_after_intersection( iMesh_Instance instance,
00939 iBase_EntitySetHandle fine_set,
00940 iBase_EntitySetHandle lagr_set,
00941 iBase_EntitySetHandle intx_set,
00942 int* ierr )
00943 {
00944 *ierr = 1;
00945 Interface* mb = MOABI;
00946 // delete elements
00947 // delete now the polygons and the elements of out_set
00948 // also, all verts that are not in euler set or lagr_set
00949 Range allVerts;
00950 ErrorCode rval = mb->get_entities_by_dimension( 0, 0, allVerts );
00951 ERRORV( rval, "can't get all vertices" );
00952
00953 Range allElems;
00954 rval = mb->get_entities_by_dimension( 0, 2, allElems );
00955 ERRORV( rval, "can't get all elems" );
00956
00957 Range polys; // first euler polys
00958 rval = mb->get_entities_by_dimension( (EntityHandle)fine_set, 2, polys );
00959 ERRORV( rval, "can't get all polys from fine set" );
00960
00961 // add to polys range the lagr polys
00962 rval = mb->get_entities_by_dimension( (EntityHandle)lagr_set, 2,
00963 polys ); // do not delete lagr set either, with its vertices
00964 ERRORV( rval, "can't get all polys from lagr set" );
00965 // add to the connecVerts range all verts, from all initial polys
00966 Range vertsToStay;
00967 rval = mb->get_connectivity( polys, vertsToStay );
00968 ERRORV( rval, "get verts that stay" );
00969
00970 Range todeleteVerts = subtract( allVerts, vertsToStay );
00971
00972 Range todeleteElem = subtract( allElems, polys ); // this is coarse mesh too (if still here)
00973
00974 // empty the out mesh set
00975 EntityHandle out_set = (EntityHandle)intx_set;
00976 rval = mb->clear_meshset( &out_set, 1 );
00977 ERRORV( rval, "clear mesh set" );
00978
00979 rval = mb->delete_entities( todeleteElem );
00980 ERRORV( rval, "delete intx elements" );
00981 rval = mb->delete_entities( todeleteVerts );
00982 ERRORV( rval, "failed to delete intx vertices" );
00983
00984 *ierr = 0;
00985 return;
00986 }
00987
00988 void cleanup_after_simulation( int* ierr )
00989 {
00990 delete[] mapping_to_coords;
00991 numVertices = 0;
00992 *ierr = 0;
00993 return;
00994 }
00995 #ifdef __cplusplus
00996 } // extern "C"
00997 #endif