MOAB: Mesh Oriented datABase
(version 5.4.1)
|
00001 /*This unit test is for the convergence study of high order reconstruction under uniform 00002 * refinement*/ 00003 #include <iostream> 00004 #include <string> 00005 #include <sstream> 00006 #if defined( __MINGW32__ ) 00007 #include <sys/time.h> 00008 #else 00009 #include <ctime> 00010 #endif 00011 00012 #include <vector> 00013 #include <algorithm> 00014 #include "moab/Core.hpp" 00015 #include "moab/Range.hpp" 00016 #include "moab/MeshTopoUtil.hpp" 00017 #include "moab/NestedRefine.hpp" 00018 #include "moab/DiscreteGeometry/DGMSolver.hpp" 00019 #include "moab/DiscreteGeometry/HiReconstruction.hpp" 00020 #include "TestUtil.hpp" 00021 #include "geomObject.cpp" 00022 #include <cmath> 00023 #include <cstdlib> 00024 00025 #ifdef MOAB_HAVE_MPI 00026 #include "moab/ParallelComm.hpp" 00027 #include "MBParallelConventions.h" 00028 #include "ReadParallel.hpp" 00029 #include "moab/FileOptions.hpp" 00030 #include "MBTagConventions.hpp" 00031 #include "moab_mpi.h" 00032 #endif 00033 00034 using namespace moab; 00035 00036 #define nsamples 10 00037 00038 #ifdef MOAB_HAVE_MPI 00039 std::string read_options; 00040 #endif 00041 00042 ErrorCode test_closedsurface_mesh( const char* filename, 00043 int* level_degrees, 00044 int num_levels, 00045 int degree, 00046 bool interp, 00047 int dim, 00048 geomObject* obj ) 00049 { 00050 Core moab; 00051 Interface* mbImpl = &moab; 00052 ParallelComm* pc = NULL; 00053 EntityHandle fileset; 00054 ErrorCode error; 00055 error = mbImpl->create_meshset( moab::MESHSET_SET, fileset );MB_CHK_ERR( error ); 00056 // load mesh from file 00057 #ifdef MOAB_HAVE_MPI 00058 MPI_Comm comm = MPI_COMM_WORLD; 00059 EntityHandle partnset; 00060 error = mbImpl->create_meshset( moab::MESHSET_SET, partnset );MB_CHK_ERR( error ); 00061 pc = moab::ParallelComm::get_pcomm( mbImpl, partnset, &comm ); 00062 int procs = 1; 00063 MPI_Comm_size( comm, &procs ); 00064 00065 if( procs > 1 ) 00066 { 00067 read_options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;"; 00068 error = mbImpl->load_file( filename, &fileset, read_options.c_str() );MB_CHK_ERR( error ); 00069 } 00070 else 00071 { 00072 error = mbImpl->load_file( filename, &fileset );MB_CHK_ERR( error ); 00073 } 00074 00075 #else 00076 error = mbImpl->load_file( filename, &fileset );MB_CHK_ERR( error ); 00077 #endif 00078 00079 // Generate hierarchy 00080 // error = refine_entities(&moab, pc, fileset, level_degrees, num_levels, true); 00081 // CHECK_ERR(error); 00082 NestedRefine uref( &moab, pc, fileset ); 00083 std::vector< EntityHandle > meshes; 00084 error = uref.generate_mesh_hierarchy( num_levels, level_degrees, meshes );MB_CHK_ERR( error ); 00085 00086 // Perform high order reconstruction on level 0 mesh 00087 HiReconstruction hirec( &moab, pc, fileset ); 00088 assert( dim == 2 ); 00089 error = hirec.reconstruct3D_surf_geom( degree, interp, false );MB_CHK_ERR( error ); 00090 00091 // High order projection 00092 Range verts, vorig; 00093 error = mbImpl->get_entities_by_dimension( meshes.back(), 0, verts );MB_CHK_ERR( error ); 00094 error = mbImpl->get_entities_by_dimension( meshes.front(), 0, vorig );MB_CHK_ERR( error ); 00095 int nvorig = vorig.size(); 00096 double l1err = 0, l2err = 0, linferr = 0; 00097 00098 for( Range::iterator ivert = verts.begin() + nvorig; ivert != verts.end(); ++ivert ) 00099 { 00100 // locate the element in level 0 mesh, on which *ivert is lying 00101 EntityHandle currvert = *ivert; 00102 00103 std::vector< EntityHandle > parentEntities; 00104 error = uref.get_adjacencies( *ivert, 2, parentEntities );MB_CHK_ERR( error ); 00105 assert( parentEntities.size() ); 00106 00107 EntityHandle rootelem; 00108 error = uref.child_to_parent( parentEntities[0], num_levels, 0, &rootelem );MB_CHK_ERR( error ); 00109 00110 // compute the natural coordinates of *ivert in this element 00111 assert( TYPE_FROM_HANDLE( rootelem ) == MBTRI ); 00112 00113 const EntityHandle* conn; 00114 int nvpe = 3; 00115 error = mbImpl->get_connectivity( rootelem, conn, nvpe );MB_CHK_ERR( error ); 00116 00117 std::vector< double > cornercoords( 3 * nvpe ), currcoords( 3 ); 00118 error = mbImpl->get_coords( conn, nvpe, &( cornercoords[0] ) );MB_CHK_ERR( error ); 00119 error = mbImpl->get_coords( &currvert, 1, &( currcoords[0] ) );MB_CHK_ERR( error ); 00120 00121 std::vector< double > naturalcoords2fit( 3 ); 00122 DGMSolver::get_tri_natural_coords( 3, &( cornercoords[0] ), 1, &( currcoords[0] ), &( naturalcoords2fit[0] ) ); 00123 00124 // project onto the estimated geometry 00125 double hicoords[3]; 00126 error = hirec.hiproj_walf_in_element( rootelem, nvpe, 1, &( naturalcoords2fit[0] ), hicoords );MB_CHK_ERR( error ); 00127 00128 // estimate error 00129 double err = obj->compute_projecterror( 3, hicoords ); 00130 l1err += err; 00131 l2err += err * err; 00132 linferr = std::max( linferr, err ); 00133 } 00134 00135 l1err /= verts.size() - nvorig; 00136 l2err = sqrt( l2err / ( verts.size() - nvorig ) ); 00137 std::cout << "L1 error " << l1err << " L2 error " << l2err << " Linf error " << linferr << std::endl; 00138 return error; 00139 } 00140 00141 ErrorCode closedsurface_uref_hirec_convergence_study( const char* filename, 00142 int* level_degrees, 00143 int num_levels, 00144 std::vector< int >& degs2fit, 00145 bool interp, 00146 geomObject* obj ) 00147 { 00148 Core moab; 00149 Interface* mbImpl = &moab; 00150 ParallelComm* pc = NULL; 00151 EntityHandle fileset; 00152 ErrorCode error; 00153 error = mbImpl->create_meshset( moab::MESHSET_SET, fileset );MB_CHK_ERR( error ); 00154 // load mesh from file 00155 #ifdef MOAB_HAVE_MPI 00156 MPI_Comm comm = MPI_COMM_WORLD; 00157 EntityHandle partnset; 00158 error = mbImpl->create_meshset( moab::MESHSET_SET, partnset );MB_CHK_ERR( error ); 00159 pc = moab::ParallelComm::get_pcomm( mbImpl, partnset, &comm ); 00160 int procs = 1; 00161 MPI_Comm_size( comm, &procs ); 00162 00163 if( procs > 1 ) 00164 { 00165 read_options = "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;PARALLEL_RESOLVE_SHARED_ENTS;"; 00166 error = mbImpl->load_file( filename, &fileset, read_options.c_str() );MB_CHK_ERR( error ); 00167 } 00168 else 00169 { 00170 error = mbImpl->load_file( filename, &fileset );MB_CHK_ERR( error ); 00171 } 00172 00173 #else 00174 error = mbImpl->load_file( filename, &fileset );MB_CHK_ERR( error ); 00175 #endif 00176 // Generate hierarchy 00177 NestedRefine uref( &moab, pc, fileset ); 00178 std::vector< EntityHandle > meshes; 00179 std::vector< int > meshsizes; 00180 error = uref.generate_mesh_hierarchy( num_levels, level_degrees, meshes );MB_CHK_ERR( error ); 00181 std::vector< std::vector< double > > geoml1errs( 1 + degs2fit.size() ), geoml2errs( 1 + degs2fit.size() ), 00182 geomlinferrs( 1 + degs2fit.size() ); 00183 00184 // Perform high order reconstruction on each level of mesh (projected onto exact geometry) and 00185 // estimate geometric error with various degrees of fitting 00186 for( size_t i = 0; i < meshes.size(); ++i ) 00187 { 00188 EntityHandle& mesh = meshes[i]; 00189 // project onto exact geometry since each level with uref has only linear coordinates 00190 Range verts; 00191 error = mbImpl->get_entities_by_dimension( mesh, 0, verts );MB_CHK_ERR( error ); 00192 00193 for( Range::iterator ivert = verts.begin(); ivert != verts.end(); ++ivert ) 00194 { 00195 EntityHandle currvert = *ivert; 00196 double currcoords[3], exactcoords[3]; 00197 error = mbImpl->get_coords( &currvert, 1, currcoords ); 00198 obj->project_points2geom( 3, currcoords, exactcoords, NULL ); 00199 error = mbImpl->set_coords( &currvert, 1, exactcoords ); 00200 } 00201 00202 // generate random points on each elements, assument 3D coordinates 00203 Range elems; 00204 error = mbImpl->get_entities_by_dimension( mesh, 2, elems );MB_CHK_ERR( error ); 00205 meshsizes.push_back( elems.size() ); 00206 int nvpe = TYPE_FROM_HANDLE( *elems.begin() ) == MBTRI ? 3 : 4; 00207 std::vector< double > testpnts, testnaturalcoords; 00208 testpnts.reserve( 3 * elems.size() * nsamples ); 00209 testnaturalcoords.reserve( nvpe * elems.size() * nsamples ); 00210 00211 for( Range::iterator ielem = elems.begin(); ielem != elems.end(); ++ielem ) 00212 { 00213 EntityHandle currelem = *ielem; 00214 std::vector< EntityHandle > conn; 00215 error = mbImpl->get_connectivity( &currelem, 1, conn );MB_CHK_ERR( error ); 00216 nvpe = conn.size(); 00217 std::vector< double > elemcoords( 3 * conn.size() ); 00218 error = mbImpl->get_coords( &( conn[0] ), conn.size(), &( elemcoords[0] ) );MB_CHK_ERR( error ); 00219 EntityType type = TYPE_FROM_HANDLE( currelem ); 00220 00221 for( int s = 0; s < nsamples; ++s ) 00222 { 00223 if( type == MBTRI ) 00224 { 00225 double a = (double)rand() / RAND_MAX, b = (double)rand() / RAND_MAX, c = (double)rand() / RAND_MAX, 00226 sum; 00227 sum = a + b + c; 00228 00229 if( sum < 1e-12 ) 00230 { 00231 --s; 00232 continue; 00233 } 00234 else 00235 { 00236 a /= sum, b /= sum, c /= sum; 00237 } 00238 00239 testpnts.push_back( a * elemcoords[0] + b * elemcoords[3] + c * elemcoords[6] ); 00240 testpnts.push_back( a * elemcoords[1] + b * elemcoords[4] + c * elemcoords[7] ); 00241 testpnts.push_back( a * elemcoords[2] + b * elemcoords[5] + c * elemcoords[8] ); 00242 testnaturalcoords.push_back( a ); 00243 testnaturalcoords.push_back( b ); 00244 testnaturalcoords.push_back( c ); 00245 } 00246 else if( type == MBQUAD ) 00247 { 00248 double xi = (double)rand() / RAND_MAX, eta = (double)rand() / RAND_MAX, N[4]; 00249 xi = 2 * xi - 1; 00250 eta = 2 * eta - 1; 00251 N[0] = ( 1 - xi ) * ( 1 - eta ) / 4, N[1] = ( 1 + xi ) * ( 1 - eta ) / 4, 00252 N[2] = ( 1 + xi ) * ( 1 + eta ) / 4, N[3] = ( 1 - xi ) * ( 1 + eta ) / 4; 00253 testpnts.push_back( N[0] * elemcoords[0] + N[1] * elemcoords[3] + N[2] * elemcoords[6] + 00254 N[3] * elemcoords[9] ); 00255 testpnts.push_back( N[0] * elemcoords[1] + N[1] * elemcoords[4] + N[2] * elemcoords[7] + 00256 N[3] * elemcoords[10] ); 00257 testpnts.push_back( N[0] * elemcoords[2] + N[1] * elemcoords[5] + N[2] * elemcoords[8] + 00258 N[3] * elemcoords[11] ); 00259 testnaturalcoords.push_back( N[0] ); 00260 testnaturalcoords.push_back( N[1] ); 00261 testnaturalcoords.push_back( N[2] ); 00262 testnaturalcoords.push_back( N[3] ); 00263 } 00264 else 00265 { 00266 throw std::invalid_argument( "NOT SUPPORTED ELEMENT TYPE" ); 00267 } 00268 } 00269 } 00270 00271 // Compute error of linear interpolation 00272 double l1err, l2err, linferr; 00273 obj->compute_projecterror( 3, elems.size() * nsamples, &( testpnts[0] ), l1err, l2err, linferr ); 00274 geoml1errs[0].push_back( l1err ); 00275 geoml2errs[0].push_back( l2err ); 00276 geomlinferrs[0].push_back( linferr ); 00277 // Perform high order projection and compute error 00278 HiReconstruction hirec( &moab, pc, mesh ); 00279 00280 for( size_t ideg = 0; ideg < degs2fit.size(); ++ideg ) 00281 { 00282 // High order reconstruction 00283 error = hirec.reconstruct3D_surf_geom( degs2fit[ideg], interp, false, true );MB_CHK_ERR( error ); 00284 int index = 0; 00285 00286 for( Range::iterator ielem = elems.begin(); ielem != elems.end(); ++ielem, ++index ) 00287 { 00288 // Projection 00289 error = hirec.hiproj_walf_in_element( *ielem, nvpe, nsamples, 00290 &( testnaturalcoords[nvpe * nsamples * index] ), 00291 &( testpnts[3 * nsamples * index] ) );MB_CHK_ERR( error ); 00292 } 00293 00294 // Estimate error 00295 obj->compute_projecterror( 3, elems.size() * nsamples, &( testpnts[0] ), l1err, l2err, linferr ); 00296 geoml1errs[ideg + 1].push_back( l1err ); 00297 geoml2errs[ideg + 1].push_back( l2err ); 00298 geomlinferrs[ideg + 1].push_back( linferr ); 00299 } 00300 } 00301 00302 std::cout << "Mesh Size: "; 00303 00304 for( size_t i = 0; i < meshsizes.size(); ++i ) 00305 { 00306 std::cout << meshsizes[i] << " "; 00307 } 00308 00309 std::cout << std::endl; 00310 std::cout << "Degrees: 0 "; 00311 00312 for( size_t ideg = 0; ideg < degs2fit.size(); ++ideg ) 00313 { 00314 std::cout << degs2fit[ideg] << " "; 00315 } 00316 00317 std::cout << std::endl; 00318 std::cout << "L1-norm error: \n"; 00319 00320 for( size_t i = 0; i < geoml1errs.size(); ++i ) 00321 { 00322 for( size_t j = 0; j < geoml1errs[i].size(); ++j ) 00323 { 00324 std::cout << geoml1errs[i][j] << " "; 00325 } 00326 00327 std::cout << std::endl; 00328 } 00329 00330 std::cout << "L2-norm error: \n"; 00331 00332 for( size_t i = 0; i < geoml2errs.size(); ++i ) 00333 { 00334 for( size_t j = 0; j < geoml2errs[i].size(); ++j ) 00335 { 00336 std::cout << geoml2errs[i][j] << " "; 00337 } 00338 00339 std::cout << std::endl; 00340 } 00341 00342 std::cout << "Linf-norm error: \n"; 00343 00344 for( size_t i = 0; i < geomlinferrs.size(); ++i ) 00345 { 00346 for( size_t j = 0; j < geomlinferrs[i].size(); ++j ) 00347 { 00348 std::cout << geomlinferrs[i][j] << " "; 00349 } 00350 00351 std::cout << std::endl; 00352 } 00353 00354 return error; 00355 } 00356 00357 void usage() 00358 { 00359 std::cout << "usage: ./uref_hirec_test <mesh file> -degree <degree> -interp <0=least square, " 00360 "1=interpolation> -dim <mesh dimension> -geom <s=sphere,t=torus>" 00361 << std::endl; 00362 std::cout << "Example: ./uref_hirec_test $MOAB_SOURCE_DIR/MeshFiles/unittest/sphere_tris_5.vtk " 00363 "-degree 2 -interp 0 -dim 2 -geom s" 00364 << std::endl; 00365 } 00366 00367 int main( int argc, char* argv[] ) 00368 { 00369 #ifdef MOAB_HAVE_MPI 00370 MPI_Init( &argc, &argv ); 00371 int nprocs, rank; 00372 MPI_Comm_size( MPI_COMM_WORLD, &nprocs ); 00373 MPI_Comm_rank( MPI_COMM_WORLD, &rank ); 00374 #endif 00375 00376 std::string infile = TestDir + "unittest/sphere_tris_5.vtk"; 00377 00378 int degree = 2, dim = 2, geom = 0; 00379 bool interp = false; 00380 ErrorCode error; 00381 00382 if( argc == 10 ) 00383 { 00384 infile = std::string( argv[1] ); 00385 bool hasdim = false; 00386 00387 for( int i = 2; i < argc; ++i ) 00388 { 00389 if( i + 1 != argc ) 00390 { 00391 if( std::string( argv[i] ) == "-degree" ) 00392 { 00393 degree = atoi( argv[++i] ); 00394 } 00395 else if( std::string( argv[i] ) == "-interp" ) 00396 { 00397 interp = atoi( argv[++i] ); 00398 } 00399 else if( std::string( argv[i] ) == "-dim" ) 00400 { 00401 dim = atoi( argv[++i] ); 00402 hasdim = true; 00403 } 00404 else if( std::string( argv[i] ) == "-geom" ) 00405 { 00406 geom = std::string( argv[++i] ) == "s" ? 0 : 1; 00407 } 00408 else 00409 { 00410 #ifdef MOAB_HAVE_MPI 00411 00412 if( 0 == rank ) 00413 { 00414 usage(); 00415 } 00416 MPI_Finalize(); 00417 00418 #else 00419 usage(); 00420 #endif 00421 return -1; 00422 } 00423 } 00424 } 00425 00426 if( !hasdim ) 00427 { 00428 #ifdef MOAB_HAVE_MPI 00429 00430 if( 0 == rank ) 00431 { 00432 std::cout << "Dimension of input mesh should be provided, positive and less than 3" << std::endl; 00433 } 00434 00435 #else 00436 std::cout << "Dimension of input mesh should be provided, positive and less than 3" << std::endl; 00437 #endif 00438 return -1; 00439 } 00440 00441 if( degree <= 0 || dim > 2 || dim <= 0 ) 00442 { 00443 #ifdef MOAB_HAVE_MPI 00444 00445 if( 0 == rank ) 00446 { 00447 std::cout << "Input degree should be positive number;\n"; 00448 std::cout << "Input dimesion should be positive and less than 3;" << std::endl; 00449 } 00450 00451 #else 00452 std::cout << "Input degree should be positive number;\n"; 00453 std::cout << "Input dimesion should be positive and less than 3;" << std::endl; 00454 #endif 00455 return -1; 00456 } 00457 00458 #ifdef MOAB_HAVE_MPI 00459 00460 if( 0 == rank ) 00461 { 00462 std::cout << "Testing on " << infile << " with dimension " << dim << "\n"; 00463 std::string opts = interp ? "interpolation" : "least square fitting"; 00464 std::cout << "High order reconstruction with degree " << degree << " " << opts << std::endl; 00465 } 00466 00467 #else 00468 std::cout << "Testing on " << infile << " with dimension " << dim << "\n"; 00469 std::string opts = interp ? "interpolation" : "least square fitting"; 00470 std::cout << "High order reconstruction with degree " << degree << " " << opts << std::endl; 00471 #endif 00472 } 00473 else 00474 { 00475 if( argc > 1 ) 00476 { 00477 usage(); 00478 return -1; 00479 } 00480 } 00481 00482 { 00483 int level_degrees[3] = { 2, 2, 2 }; 00484 int num_levels = 3; 00485 00486 // create the geometry object 00487 geomObject* obj; 00488 if( geom ) 00489 obj = new torus(); 00490 else 00491 obj = new sphere(); 00492 00493 error = test_closedsurface_mesh( infile.c_str(), level_degrees, num_levels, degree, interp, dim, obj );MB_CHK_ERR( error ); 00494 00495 std::vector< int > degs2fit( 6 ); 00496 for( int d = 1; d <= 6; ++d ) 00497 { 00498 degs2fit[d - 1] = d; 00499 } 00500 00501 // Call the higher order reconstruction routines and compute error convergence 00502 error = closedsurface_uref_hirec_convergence_study( infile.c_str(), level_degrees, num_levels, degs2fit, interp, 00503 obj );MB_CHK_ERR( error ); 00504 // cleanup memory 00505 delete obj; 00506 } 00507 00508 #ifdef MOAB_HAVE_MPI 00509 MPI_Finalize(); 00510 #endif 00511 return 0; 00512 }