MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 <sstream> 00023 #include <mpi.h> 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<double *> 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