Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
intx_mpas.cpp
Go to the documentation of this file.
1 /*
2  * mpas file test
3  *
4  * Created on: Feb 12, 2013
5  */
6 
7 // copy from case1 test
8 #include "moab/MOABConfig.h"
9 
10 #ifdef MOAB_HAVE_ZOLTAN
11 
12 #include <iostream>
13 #include <sstream>
14 #include <ctime>
15 #include <cstdlib>
16 #include <cstdio>
17 #include <cstring>
18 #include <cmath> // for M_PI
19 #include <ctime>
20 #include "moab/Core.hpp"
21 #include "moab/Interface.hpp"
23 #include "moab/ProgOptions.hpp"
24 #include "MBTagConventions.hpp"
25 #include "moab/ParallelComm.hpp"
27 #include "IntxUtilsCSLAM.hpp"
28 #include "TestUtil.hpp"
29 
30 using namespace moab;
31 // some input data
32 double gtol = 1.e-9; // this is for geometry tolerance
33 
34 double radius = 1.; // in m: 6371220.
35 
36 double t = 0.1, delta_t = 0.05; // check the script
37 bool Verbose = false;
38 double rot = M_PI / 10;
39 
41 {
42  ErrorCode rval = MB_SUCCESS;
43 
44  /*
45  * get all plys first, then vertices, then move them on the surface of the sphere
46  * radius is 1., most of the time
47  *
48  */
49  Range polygons;
50  rval = mb->get_entities_by_dimension( euler_set, 2, polygons );CHECK_ERR( rval );
51 
52  Range connecVerts;
53  rval = mb->get_connectivity( polygons, connecVerts );CHECK_ERR( rval );
54 
55  Tag tagh = 0;
56  std::string tag_name( "DP" );
57  rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT );CHECK_ERR( rval );
58  void* data; // pointer to the LOC in memory, for each vertex
59  int count;
60 
61  rval = mb->tag_iterate( tagh, connecVerts.begin(), connecVerts.end(), count, data );CHECK_ERR( rval );
62  // here we are checking contiguity
63  assert( count == (int)connecVerts.size() );
64  double* ptr_DP = (double*)data;
65  // get the coordinates of the old mesh, and move it around the sphere in the same way as in the
66  // python script
67 
68  // now put the vertices in the right place....
69  // int vix=0; // vertex index in new array
70  double T = 5; // check the script
71 
72  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
73  {
74  EntityHandle oldV = *vit;
75  CartVect posi;
76  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );CHECK_ERR( rval );
77  // do some mumbo jumbo, as in python script
79  double lat1 = sphCoord.lat - 2 * M_PI * t / T; // 0.1/5
80  double uu = 3 * radius / T * pow( sin( lat1 ), 2 ) * sin( 2 * sphCoord.lon ) * cos( M_PI * t / T );
81  uu += 2 * radius * M_PI * cos( sphCoord.lon ) / T;
82  double vv = 3 * radius / T * ( sin( 2 * lat1 ) ) * cos( sphCoord.lon ) * cos( M_PI * t / T );
83  double vx = -uu * sin( sphCoord.lon ) - vv * sin( sphCoord.lat ) * cos( sphCoord.lon );
84  double vy = -uu * cos( sphCoord.lon ) - vv * sin( sphCoord.lat ) * sin( sphCoord.lon );
85  double vz = vv * cos( sphCoord.lat );
86  posi = posi + delta_t * CartVect( vx, vy, vz );
87  double x2 = posi[0] * cos( rot ) - posi[1] * sin( rot );
88  double y2 = posi[0] * sin( rot ) + posi[1] * cos( rot );
89  CartVect newPos( x2, y2, posi[2] );
90  double len1 = newPos.length();
91  newPos = radius * newPos / len1;
92 
93  ptr_DP[0] = newPos[0];
94  ptr_DP[1] = newPos[1];
95  ptr_DP[2] = newPos[2];
96  ptr_DP += 3; // increment to the next node
97  }
98  return rval;
99 }
100 
101 int main( int argc, char** argv )
102 {
103 
104  MPI_Init( &argc, &argv );
105 
106  std::string extra_read_opts;
107  std::string fileN = TestDir + "unittest/io/mpasx1.642.t.2.nc";
108  const char* filename_mesh1 = fileN.c_str();
109  bool flux_form = false;
110  if( argc > 1 )
111  {
112  int index = 1;
113  while( index < argc )
114  {
115  if( !strcmp( argv[index], "-gtol" ) ) // this is for geometry tolerance
116  {
117  gtol = atof( argv[++index] );
118  }
119  if( !strcmp( argv[index], "-dt" ) )
120  {
121  delta_t = atof( argv[++index] );
122  }
123  if( !strcmp( argv[index], "-input" ) )
124  {
125  filename_mesh1 = argv[++index];
126  }
127  if( !strcmp( argv[index], "-R" ) )
128  {
129  radius = atof( argv[++index] );
130  }
131  if( !strcmp( argv[index], "-O" ) )
132  {
133  extra_read_opts = std::string( argv[++index] );
134  }
135  if( !strcmp( argv[index], "-FF" ) )
136  {
137  flux_form = true;
138  }
139  if( !strcmp( argv[index], "-v" ) )
140  {
141  Verbose = true;
142  }
143  if( !strcmp( argv[index], "-t" ) )
144  {
145  t = atof( argv[++index] );
146  }
147  if( !strcmp( argv[index], "-t" ) )
148  {
149  t = atof( argv[++index] );
150  }
151  if( !strcmp( argv[index], "-rot" ) )
152  {
153  rot = atof( argv[++index] );
154  rot = M_PI / rot; // so rot 50 means rotate with M_PI/50 radians
155  }
156 
157  index++;
158  }
159  }
160  // start copy
161  std::string opts = std::string( "PARALLEL=READ_PART;PARTITION_METHOD=RCBZOLTAN" ) +
162  std::string( ";PARALLEL_RESOLVE_SHARED_ENTS;VARIABLE=;NO_EDGES;" ) + extra_read_opts;
163  Core moab;
164  Interface& mb = moab;
165  EntityHandle euler_set;
166  ErrorCode rval;
167  rval = mb.create_meshset( MESHSET_SET, euler_set );CHECK_ERR( rval );
168 
169  clock_t tt = clock();
170 
171  rval = mb.load_file( filename_mesh1, &euler_set, opts.c_str() );CHECK_ERR( rval );
172 
173  ParallelComm* pcomm = ParallelComm::get_pcomm( &mb, 0 );CHECK_ERR( rval );
174 
175  /*rval = pcomm->check_all_shared_handles();CHECK_ERR(rval);*/
176  // end copy
177  int rank = pcomm->proc_config().proc_rank();
178  int procs = pcomm->proc_config().proc_size();
179 
180  if( 0 == rank )
181  std::cout << " case 1: use -gtol " << gtol << " -dt " << delta_t << " -R " << radius << " -input "
182  << filename_mesh1 << " -t " << t << " -rot " << rot << "\n";
183 
184  if( 0 == rank )
185  {
186  std::cout << "load mesh from " << filename_mesh1 << "\n on " << procs << " processors in "
187  << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl;
188  tt = clock();
189  }
190 
191  rval = manufacture_lagrange_mesh_on_sphere( &mb, euler_set );CHECK_ERR( rval );
192 
193  // create a set with quads corresponding to each initial edge spanned with the displacement
194  // field
195  if( flux_form )
196  {
197  rval = IntxUtilsCSLAM::create_span_quads( &mb, euler_set, rank );CHECK_ERR( rval );
198  }
199 
200  EntityHandle covering_lagr_set;
201  rval = mb.create_meshset( MESHSET_SET, covering_lagr_set );CHECK_ERR( rval );
202 
203  Intx2MeshOnSphere worker( &mb );
204  // double radius = 1.; // input
205  worker.set_radius_source_mesh( radius );
206  worker.set_radius_destination_mesh( radius );
207  worker.set_parallel_comm( pcomm );
208  if( 0 == rank )
209  {
210  std::cout << "manufacture departure mesh " << filename_mesh1 << "\n on " << procs << " processors in "
211  << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl;
212  tt = clock();
213  }
214  rval = worker.FindMaxEdges( euler_set, euler_set );CHECK_ERR( rval );
215  worker.set_error_tolerance( gtol );
216 
217  rval = worker.create_departure_mesh_2nd_alg( euler_set, covering_lagr_set );CHECK_ERR( rval );
218 
219  if( 0 == rank )
220  {
221  std::cout << "communicate covering mesh on " << procs << " processors in "
222  << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << std::endl;
223  tt = clock();
224  }
225 
226  if( Verbose )
227  {
228  std::stringstream lagrIni;
229  lagrIni << "lagr0" << rank << ".h5m";
230  rval = mb.write_file( lagrIni.str().c_str(), 0, 0, &covering_lagr_set, 1 );
231  }
232 
233  rval = IntxUtils::enforce_convexity( &mb, covering_lagr_set, rank );CHECK_ERR( rval );
234  if( Verbose )
235  {
236  std::stringstream ste;
237  ste << "euler0" << rank << ".h5m";
238  rval = mb.write_file( ste.str().c_str(), 0, 0, &euler_set, 1 );
239  }
240 
241  if( MB_SUCCESS != rval ) std::cout << "can't write lagr set\n";
242 
243  EntityHandle outputSet;
244  rval = mb.create_meshset( MESHSET_SET, outputSet );CHECK_ERR( rval );
245  rval = worker.intersect_meshes( covering_lagr_set, euler_set, outputSet );CHECK_ERR( rval );
246 
247  if( 0 == rank )
248  {
249  std::cout << "intersect meshes in " << procs << " processors in " << ( clock() - tt ) / (double)CLOCKS_PER_SEC
250  << " seconds" << std::endl;
251  tt = clock();
252  }
253  if( Verbose && rank <= 4 )
254  {
255  std::string opts_write( "" );
256  std::stringstream outf;
257  outf << "intersect0" << rank << ".h5m";
258  rval = mb.write_file( outf.str().c_str(), 0, 0, &outputSet, 1 );
259  if( MB_SUCCESS != rval ) std::cout << "can't write output\n";
260  }
261 
262  if( rank <= 4 )
263  {
264  moab::IntxAreaUtils areaAdaptor;
265  double intx_area = areaAdaptor.area_on_sphere( &mb, outputSet, radius );
266  double arrival_area = areaAdaptor.area_on_sphere( &mb, euler_set, radius );
267  std::cout << "On proc " << rank << " arrival area: " << arrival_area << " intersection area:" << intx_area
268  << " rel error: " << fabs( ( intx_area - arrival_area ) / arrival_area ) << "\n";
269  }
270 
271  MPI_Finalize();
272  if( MB_SUCCESS != rval ) return 1;
273 
274  return 0;
275 }
276 
277 #else
278 
279 int main( int /*argc*/, char** /*argv*/ )
280 {
281  return 0;
282 }
283 
284 #endif