MOAB: Mesh Oriented datABase  (version 5.3.0)
cslam_par_test.cpp
Go to the documentation of this file.
00001 /*
00002  * cslam_par_test.cpp
00003  *  test to trigger intersection on a sphere in parallel
00004  *  it will start from an eulerian mesh (mesh + velocity from Mark Taylor)
00005  *   file: VELO00.h5m; mesh + velo at 850 milibar, in an unstructured mesh refined from
00006  *   a cube sphere grid
00007  *  the mesh is read in parallel (euler mesh);
00008  *
00009  *   lagrangian mesh is obtained using
00010  *   pos (t-dt) = pos(t) -Velo(t)*dt
00011  *   then, project on the sphere with a given radius
00012  *
00013  *  Created on: Apr 22, 2013
00014  */
00015 
00016 #include <iostream>
00017 #include <sstream>
00018 #include <ctime>
00019 #include <cstdlib>
00020 #include <cstdio>
00021 #include <cstring>
00022 #include "moab/Core.hpp"
00023 #include "moab/Interface.hpp"
00024 #include "moab/IntxMesh/Intx2MeshOnSphere.hpp"
00025 #include <cmath>
00026 #include "TestUtil.hpp"
00027 #include "moab/ParallelComm.hpp"
00028 #include "moab/ProgOptions.hpp"
00029 #include "MBParallelConventions.h"
00030 #include "moab/ReadUtilIface.hpp"
00031 #include "MBTagConventions.hpp"
00032 
00033 #include "moab/IntxMesh/IntxUtils.hpp"
00034 #include "IntxUtilsCSLAM.hpp"
00035 
00036 // for M_PI
00037 #include <cmath>
00038 
00039 using namespace moab;
00040 // some input data
00041 double EPS1 = 0.2;                                // this is for box error
00042 std::string input_mesh_file( "VELO00_16p.h5m" );  // input file, partitioned correctly
00043 double Radius = 1.0;                              // change to radius
00044 double deltaT = 1.e-6;
00045 void test_intx_in_parallel_elem_based();
00046 
00047 int main( int argc, char** argv )
00048 {
00049     MPI_Init( &argc, &argv );
00050     EPS1       = 0.000002;
00051     int result = 0;
00052 
00053     if( argc > 1 )
00054     {
00055         int index = 1;
00056         while( index < argc )
00057         {
00058             if( !strcmp( argv[index], "-eps" ) )  // this is for box error
00059             {
00060                 EPS1 = atof( argv[++index] );
00061             }
00062             if( !strcmp( argv[index], "-input" ) ) { input_mesh_file = argv[++index]; }
00063             if( !strcmp( argv[index], "-radius" ) ) { Radius = atof( argv[++index] ); }
00064             if( !strcmp( argv[index], "-deltaT" ) ) { deltaT = atof( argv[++index] ); }
00065             index++;
00066         }
00067     }
00068     std::cout << " run: -input " << input_mesh_file << "  -eps " << EPS1 << " -radius " << Radius << " -deltaT "
00069               << deltaT << "\n";
00070 
00071     result += RUN_TEST( test_intx_in_parallel_elem_based );
00072 
00073     MPI_Finalize();
00074     return result;
00075 }
00076 // will save the LOC tag on the euler nodes
00077 ErrorCode compute_lagrange_mesh_on_sphere( Interface* mb, EntityHandle euler_set )
00078 {
00079     /*
00080      * get all quads first, then vertices, then move them on the surface of the sphere
00081      *  radius is 1, usually
00082      *  pos (t-dt) = pos(t) -Velo(t)*dt; this will be lagrange mesh, on each processor
00083      */
00084     Range quads;
00085     ErrorCode rval = mb->get_entities_by_type( euler_set, MBQUAD, quads );MB_CHK_ERR( rval );
00086 
00087     Range connecVerts;
00088     rval = mb->get_connectivity( quads, connecVerts );MB_CHK_ERR( rval );
00089 
00090     // the LOC tag, should be provided by the user?
00091     Tag tagh = 0;
00092     std::string tag_name( "DP" );
00093     rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
00094     void* data;  // pointer to the DP in memory, for each vertex
00095     int count;
00096 
00097     rval = mb->tag_iterate( tagh, connecVerts.begin(), connecVerts.end(), count, data );MB_CHK_ERR( rval );
00098     // here we are checking contiguity
00099     assert( count == (int)connecVerts.size() );
00100     double* ptr_DP = (double*)data;
00101     // get the coordinates of the old mesh, and move it around using velocity tag
00102 
00103     Tag tagv = 0;
00104     std::string velo_tag_name( "VELO" );
00105     rval = mb->tag_get_handle( velo_tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagv, MB_TAG_DENSE );MB_CHK_ERR( rval );
00106 
00107     /*void *datavelo; // pointer to the VELO in memory, for each vertex
00108 
00109     rval = mb->tag_iterate(tagv, connecVerts.begin(), connecVerts.end(), count, datavelo);MB_CHK_ERR(rval);*/
00110     // here we are checking contiguity
00111     assert( count == (int)connecVerts.size() );
00112     // now put the vertices in the right place....
00113     // int vix=0; // vertex index in new array
00114 
00115     for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
00116     {
00117         EntityHandle oldV = *vit;
00118         CartVect posi;
00119         rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
00120         CartVect velo;
00121         rval = mb->tag_get_data( tagv, &oldV, 1, (void*)&( velo[0] ) );MB_CHK_ERR( rval );
00122         // do some mumbo jumbo, as in python script
00123         CartVect newPos = posi - deltaT * velo;
00124         double len1     = newPos.length();
00125         newPos          = Radius * newPos / len1;
00126 
00127         ptr_DP[0] = newPos[0];
00128         ptr_DP[1] = newPos[1];
00129         ptr_DP[2] = newPos[2];
00130         ptr_DP += 3;  // increment to the next node
00131     }
00132 
00133     return rval;
00134 }
00135 
00136 void test_intx_in_parallel_elem_based()
00137 {
00138     std::string opts = std::string( "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION" ) +
00139                        std::string( ";PARALLEL_RESOLVE_SHARED_ENTS" );
00140     Core moab;
00141     Interface& mb = moab;
00142     EntityHandle euler_set;
00143     ErrorCode rval;
00144     rval = mb.create_meshset( MESHSET_SET, euler_set );MB_CHK_ERR_RET( rval );
00145     std::string example( TestDir + "/" + input_mesh_file );
00146 
00147     rval = mb.load_file( example.c_str(), &euler_set, opts.c_str() );
00148 
00149     ParallelComm* pcomm = ParallelComm::get_pcomm( &mb, 0 );MB_CHK_ERR_RET( rval );
00150 
00151     rval = pcomm->check_all_shared_handles();MB_CHK_ERR_RET( rval );
00152 
00153     // everybody will get a DP tag, including the non owned entities; so exchange tags is not
00154     // required for LOC (here)
00155     rval = compute_lagrange_mesh_on_sphere( &mb, euler_set );MB_CHK_ERR_RET( rval );
00156 
00157     int rank = pcomm->proc_config().proc_rank();
00158 
00159     std::stringstream ste;
00160     ste << "initial" << rank << ".vtk";
00161     mb.write_file( ste.str().c_str(), 0, 0, &euler_set, 1 );
00162 
00163     Intx2MeshOnSphere worker( &mb );
00164 
00165     worker.set_radius_source_mesh( Radius );
00166     worker.set_radius_destination_mesh( Radius );
00167     worker.set_box_error( EPS1 );  //
00168     // worker.SetEntityType(MBQUAD);
00169 
00170     worker.set_error_tolerance( Radius * 1.e-8 );
00171     std::cout << "error tolerance epsilon_1=" << Radius * 1.e-8 << "\n";
00172     //  worker.locate_departure_points(euler_set);
00173 
00174     rval = worker.FindMaxEdges( euler_set, euler_set );  // departure will be the same max_edges
00175     // we need to make sure the covering set is bigger than the euler mesh
00176     EntityHandle covering_lagr_set;
00177     rval = mb.create_meshset( MESHSET_SET, covering_lagr_set );MB_CHK_ERR_RET( rval );
00178 
00179     rval = worker.create_departure_mesh_2nd_alg( euler_set, covering_lagr_set );MB_CHK_ERR_RET( rval );
00180 
00181     std::stringstream ss;
00182     ss << "partial" << rank << ".vtk";
00183     mb.write_file( ss.str().c_str(), 0, 0, &covering_lagr_set, 1 );
00184     EntityHandle outputSet;
00185     rval = mb.create_meshset( MESHSET_SET, outputSet );MB_CHK_ERR_RET( rval );
00186     rval = worker.intersect_meshes( covering_lagr_set, euler_set, outputSet );MB_CHK_ERR_RET( rval );
00187 
00188     // std::string opts_write("PARALLEL=WRITE_PART");
00189     // rval = mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet, 1);
00190     // std::string opts_write("");
00191     std::stringstream outf;
00192     outf << "intersect" << rank << ".h5m";
00193     rval = mb.write_file( outf.str().c_str(), 0, 0, &outputSet, 1 );MB_CHK_ERR_RET( rval );
00194 
00195     moab::IntxAreaUtils sphAreaUtils;
00196     double intx_area    = sphAreaUtils.area_on_sphere( &mb, outputSet, Radius );
00197     double arrival_area = sphAreaUtils.area_on_sphere( &mb, euler_set, Radius );
00198     std::cout << "On rank : " << rank << " arrival area: " << arrival_area << "  intersection area:" << intx_area
00199               << " rel error: " << fabs( ( intx_area - arrival_area ) / arrival_area ) << "\n";
00200 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines