Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
cslam_par_test.cpp
Go to the documentation of this file.
1 /*
2  * cslam_par_test.cpp
3  * test to trigger intersection on a sphere in parallel
4  * it will start from an eulerian mesh (mesh + velocity from Mark Taylor)
5  * file: VELO00.h5m; mesh + velo at 850 milibar, in an unstructured mesh refined from
6  * a cube sphere grid
7  * the mesh is read in parallel (euler mesh);
8  *
9  * lagrangian mesh is obtained using
10  * pos (t-dt) = pos(t) -Velo(t)*dt
11  * then, project on the sphere with a given radius
12  *
13  * Created on: Apr 22, 2013
14  */
15 
16 #include <iostream>
17 #include <sstream>
18 #include <ctime>
19 #include <cstdlib>
20 #include <cstdio>
21 #include <cstring>
22 #include "moab/Core.hpp"
23 #include "moab/Interface.hpp"
25 #include <cmath>
26 #include "TestUtil.hpp"
27 #include "moab/ParallelComm.hpp"
28 #include "moab/ProgOptions.hpp"
29 #include "MBParallelConventions.h"
30 #include "moab/ReadUtilIface.hpp"
31 #include "MBTagConventions.hpp"
32 
34 #include "IntxUtilsCSLAM.hpp"
35 
36 // for M_PI
37 #include <cmath>
38 
39 using namespace moab;
40 // some input data
41 double EPS1 = 0.2; // this is for box error
42 std::string input_mesh_file( "VELO00_16p.h5m" ); // input file, partitioned correctly
43 double Radius = 1.0; // change to radius
44 double deltaT = 1.e-6;
46 
47 int main( int argc, char** argv )
48 {
49  MPI_Init( &argc, &argv );
50  EPS1 = 0.000002;
51  int result = 0;
52 
53  if( argc > 1 )
54  {
55  int index = 1;
56  while( index < argc )
57  {
58  if( !strcmp( argv[index], "-eps" ) ) // this is for box error
59  {
60  EPS1 = atof( argv[++index] );
61  }
62  if( !strcmp( argv[index], "-input" ) )
63  {
64  input_mesh_file = argv[++index];
65  }
66  if( !strcmp( argv[index], "-radius" ) )
67  {
68  Radius = atof( argv[++index] );
69  }
70  if( !strcmp( argv[index], "-deltaT" ) )
71  {
72  deltaT = atof( argv[++index] );
73  }
74  index++;
75  }
76  }
77  std::cout << " run: -input " << input_mesh_file << " -eps " << EPS1 << " -radius " << Radius << " -deltaT "
78  << deltaT << "\n";
79 
80  result += RUN_TEST( test_intx_in_parallel_elem_based );
81 
82  MPI_Finalize();
83  return result;
84 }
85 // will save the LOC tag on the euler nodes
87 {
88  /*
89  * get all quads first, then vertices, then move them on the surface of the sphere
90  * radius is 1, usually
91  * pos (t-dt) = pos(t) -Velo(t)*dt; this will be lagrange mesh, on each processor
92  */
93  Range quads;
94  ErrorCode rval = mb->get_entities_by_type( euler_set, MBQUAD, quads );MB_CHK_ERR( rval );
95 
96  Range connecVerts;
97  rval = mb->get_connectivity( quads, connecVerts );MB_CHK_ERR( rval );
98 
99  // the LOC tag, should be provided by the user?
100  Tag tagh = 0;
101  std::string tag_name( "DP" );
102  rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
103  void* data; // pointer to the DP in memory, for each vertex
104  int count;
105 
106  rval = mb->tag_iterate( tagh, connecVerts.begin(), connecVerts.end(), count, data );MB_CHK_ERR( rval );
107  // here we are checking contiguity
108  assert( count == (int)connecVerts.size() );
109  double* ptr_DP = (double*)data;
110  // get the coordinates of the old mesh, and move it around using velocity tag
111 
112  Tag tagv = 0;
113  std::string velo_tag_name( "VELO" );
114  rval = mb->tag_get_handle( velo_tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagv, MB_TAG_DENSE );MB_CHK_ERR( rval );
115 
116  /*void *datavelo; // pointer to the VELO in memory, for each vertex
117 
118  rval = mb->tag_iterate(tagv, connecVerts.begin(), connecVerts.end(), count, datavelo);MB_CHK_ERR(rval);*/
119  // here we are checking contiguity
120  assert( count == (int)connecVerts.size() );
121  // now put the vertices in the right place....
122  // int vix=0; // vertex index in new array
123 
124  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
125  {
126  EntityHandle oldV = *vit;
127  CartVect posi;
128  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
129  CartVect velo;
130  rval = mb->tag_get_data( tagv, &oldV, 1, (void*)&( velo[0] ) );MB_CHK_ERR( rval );
131  // do some mumbo jumbo, as in python script
132  CartVect newPos = posi - deltaT * velo;
133  double len1 = newPos.length();
134  newPos = Radius * newPos / len1;
135 
136  ptr_DP[0] = newPos[0];
137  ptr_DP[1] = newPos[1];
138  ptr_DP[2] = newPos[2];
139  ptr_DP += 3; // increment to the next node
140  }
141 
142  return rval;
143 }
144 
146 {
147  std::string opts = std::string( "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION" ) +
148  std::string( ";PARALLEL_RESOLVE_SHARED_ENTS" );
149  Core moab;
150  Interface& mb = moab;
151  EntityHandle euler_set;
152  ErrorCode rval;
153  rval = mb.create_meshset( MESHSET_SET, euler_set );MB_CHK_ERR_RET( rval );
154  std::string example( TestDir + "unittest/" + input_mesh_file );
155 
156  rval = mb.load_file( example.c_str(), &euler_set, opts.c_str() );
157 
158  ParallelComm* pcomm = ParallelComm::get_pcomm( &mb, 0 );MB_CHK_ERR_RET( rval );
159 
160  rval = pcomm->check_all_shared_handles();MB_CHK_ERR_RET( rval );
161 
162  // everybody will get a DP tag, including the non owned entities; so exchange tags is not
163  // required for LOC (here)
164  rval = compute_lagrange_mesh_on_sphere( &mb, euler_set );MB_CHK_ERR_RET( rval );
165 
166  int rank = pcomm->proc_config().proc_rank();
167 
168  std::stringstream ste;
169  ste << "initial" << rank << ".vtk";
170  mb.write_file( ste.str().c_str(), 0, 0, &euler_set, 1 );
171 
172  Intx2MeshOnSphere worker( &mb );
173 
174  worker.set_radius_source_mesh( Radius );
176  worker.set_box_error( EPS1 ); //
177  // worker.SetEntityType(MBQUAD);
178 
179  worker.set_error_tolerance( Radius * 1.e-8 );
180  std::cout << "error tolerance epsilon_1=" << Radius * 1.e-8 << "\n";
181  // worker.locate_departure_points(euler_set);
182 
183  rval = worker.FindMaxEdges( euler_set, euler_set ); // departure will be the same max_edges
184  // we need to make sure the covering set is bigger than the euler mesh
185  EntityHandle covering_lagr_set;
186  rval = mb.create_meshset( MESHSET_SET, covering_lagr_set );MB_CHK_ERR_RET( rval );
187 
188  rval = worker.create_departure_mesh_2nd_alg( euler_set, covering_lagr_set );MB_CHK_ERR_RET( rval );
189 
190  std::stringstream ss;
191  ss << "partial" << rank << ".vtk";
192  mb.write_file( ss.str().c_str(), 0, 0, &covering_lagr_set, 1 );
193  EntityHandle outputSet;
194  rval = mb.create_meshset( MESHSET_SET, outputSet );MB_CHK_ERR_RET( rval );
195  rval = worker.intersect_meshes( covering_lagr_set, euler_set, outputSet );MB_CHK_ERR_RET( rval );
196 
197  // std::string opts_write("PARALLEL=WRITE_PART");
198  // rval = mb.write_file("manuf.h5m", 0, opts_write.c_str(), &outputSet, 1);
199  // std::string opts_write("");
200  std::stringstream outf;
201  outf << "intersect" << rank << ".h5m";
202  rval = mb.write_file( outf.str().c_str(), 0, 0, &outputSet, 1 );MB_CHK_ERR_RET( rval );
203 
204  moab::IntxAreaUtils sphAreaUtils;
205  double intx_area = sphAreaUtils.area_on_sphere( &mb, outputSet, Radius );
206  double arrival_area = sphAreaUtils.area_on_sphere( &mb, euler_set, Radius );
207  std::cout << "On rank : " << rank << " arrival area: " << arrival_area << " intersection area:" << intx_area
208  << " rel error: " << fabs( ( intx_area - arrival_area ) / arrival_area ) << "\n";
209 }