Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
diffusion.cpp File Reference
#include <iostream>
#include <sstream>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include "moab/Core.hpp"
#include "moab/Interface.hpp"
#include "moab/IntxMesh/Intx2MeshOnSphere.hpp"
#include "moab/ProgOptions.hpp"
#include "MBTagConventions.hpp"
#include "moab/ParallelComm.hpp"
#include "moab/IntxMesh/IntxUtils.hpp"
#include "IntxUtilsCSLAM.hpp"
#include "TestUtil.hpp"
+ Include dependency graph for diffusion.cpp:

Go to the source code of this file.

Functions

ErrorCode add_field_value (Interface *mb, EntityHandle euler_set, int rank, Tag &tagTracer, Tag &tagElem, Tag &tagArea)
 
ErrorCode compute_velocity_case1 (Interface *mb, EntityHandle euler_set, Tag &tagh, int rank, int tStep)
 
ErrorCode compute_tracer_case1 (Interface *mb, Intx2MeshOnSphere &worker, EntityHandle euler_set, EntityHandle lagr_set, EntityHandle out_set, Tag &tagElem, Tag &tagArea, int rank, int tStep, Range &connecVerts)
 
int main (int argc, char **argv)
 

Variables

const char BRIEF_DESC [] = "Simulate a transport problem in a semi-Lagrangian formulation\n"
 
std::ostringstream LONG_DESC
 
double gtol = 1.e-9
 
double radius = 1.
 
int numSteps = 3
 
double T = 1
 
int case_number = 1
 
bool writeFiles = false
 
bool parallelWrite = false
 
bool velocity = false
 
int field_type = 1
 

Function Documentation

◆ add_field_value()

ErrorCode add_field_value ( Interface mb,
EntityHandle  euler_set,
int  rank,
Tag tagTracer,
Tag tagElem,
Tag tagArea 
)

Definition at line 61 of file diffusion.cpp.

62 {
63  /*
64  * get all plys first, then vertices, then move them on the surface of the sphere
65  * radius is 1., most of the time
66  *
67  */
68  Range polygons;
69  ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, polygons );
70  if( MB_SUCCESS != rval ) return rval;
71 
72  Range connecVerts;
73  rval = mb->get_connectivity( polygons, connecVerts );
74  if( MB_SUCCESS != rval ) return rval;
75 
76  void* data; // pointer to the LOC in memory, for each vertex
77  int count;
78 
79  rval = mb->tag_iterate( tagTracer, connecVerts.begin(), connecVerts.end(), count, data );MB_CHK_ERR( rval );
80  // here we are checking contiguity
81  assert( count == (int)connecVerts.size() );
82  double* ptr_DP = (double*)data;
83  // lambda is for longitude, theta for latitude
84  // param will be: (la1, te1), (la2, te2), b, c; hmax=1, r=1/2
85  // nondivergent flow, page 5, case 1, (la1, te1) = (M_PI, M_PI/3)
86  // (la2, te2) = (M_PI, -M_PI/3)
87  // la1, te1 la2 te2 b c hmax r
88  if( field_type == 1 ) // quasi smooth
89  {
90  double params[] = { M_PI, M_PI / 3, M_PI, -M_PI / 3, 0.1, 0.9, 1., 0.5 };
91  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
92  {
93  EntityHandle oldV = *vit;
94  CartVect posi;
95  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
96 
98 
99  ptr_DP[0] = IntxUtilsCSLAM::quasi_smooth_field( sphCoord.lon, sphCoord.lat, params );
100  ;
101 
102  ptr_DP++; // increment to the next node
103  }
104  }
105  else if( 2 == field_type ) // smooth
106  {
107  CartVect p1, p2;
109  spr.R = 1;
110  spr.lat = M_PI / 3;
111  spr.lon = M_PI;
113  spr.lat = -M_PI / 3;
115  // x1, y1, z1, x2, y2, z2, h_max, b0
116  double params[] = { p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], 1, 5. };
117  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
118  {
119  EntityHandle oldV = *vit;
120  CartVect posi;
121  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
122 
124 
125  ptr_DP[0] = IntxUtilsCSLAM::smooth_field( sphCoord.lon, sphCoord.lat, params );
126  ;
127 
128  ptr_DP++; // increment to the next node
129  }
130  }
131  else if( 3 == field_type ) // slotted
132  {
133  // la1, te1, la2, te2, b, c, r
134  double params[] = { M_PI, M_PI / 3, M_PI, -M_PI / 3, 0.1, 0.9, 0.5 }; // no h_max
135  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
136  {
137  EntityHandle oldV = *vit;
138  CartVect posi;
139  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
140 
142 
143  ptr_DP[0] = IntxUtilsCSLAM::slotted_cylinder_field( sphCoord.lon, sphCoord.lat, params );
144  ;
145 
146  ptr_DP++; // increment to the next node
147  }
148  }
149 
150  // add average value for quad/polygon (average corners)
151  // do some averages
152 
153  Range::iterator iter = polygons.begin();
154  double local_mass = 0.; // this is total mass on one proc
155  while( iter != polygons.end() )
156  {
157  rval = mb->tag_iterate( tagElem, iter, polygons.end(), count, data );MB_CHK_ERR( rval );
158  double* ptr = (double*)data;
159 
160  rval = mb->tag_iterate( tagArea, iter, polygons.end(), count, data );MB_CHK_ERR( rval );
161  double* ptrArea = (double*)data;
162  for( int i = 0; i < count; i++, ++iter, ptr++, ptrArea++ )
163  {
164  const moab::EntityHandle* conn = NULL;
165  int num_nodes = 0;
166  rval = mb->get_connectivity( *iter, conn, num_nodes );MB_CHK_ERR( rval );
167  if( num_nodes == 0 ) return MB_FAILURE;
168  std::vector< double > nodeVals( num_nodes );
169  double average = 0.;
170  rval = mb->tag_get_data( tagTracer, conn, num_nodes, &nodeVals[0] );MB_CHK_ERR( rval );
171  for( int j = 0; j < num_nodes; j++ )
172  average += nodeVals[j];
173  average /= num_nodes;
174  *ptr = average;
175 
176  // now get area
177  std::vector< double > coords;
178  coords.resize( 3 * num_nodes );
179  rval = mb->get_coords( conn, num_nodes, &coords[0] );MB_CHK_ERR( rval );
180 
181  moab::IntxAreaUtils sphAreaUtils;
182  *ptrArea = sphAreaUtils.area_spherical_polygon( &coords[0], num_nodes, radius );
183 
184  // we should have used some
185  // total mass:
186  local_mass += *ptrArea * average;
187  }
188  }
189  double total_mass = 0.;
190  int mpi_err = MPI_Reduce( &local_mass, &total_mass, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
191  if( MPI_SUCCESS != mpi_err ) return MB_FAILURE;
192 
193  if( rank == 0 ) std::cout << "initial total mass:" << total_mass << "\n";
194 
195  // now we can delete the tags? not yet
196  return MB_SUCCESS;
197 }

References moab::IntxAreaUtils::area_spherical_polygon(), moab::Range::begin(), moab::IntxUtils::cart_to_spherical(), moab::Range::end(), ErrorCode, field_type, moab::Core::get_connectivity(), moab::Core::get_coords(), moab::Core::get_entities_by_dimension(), moab::IntxUtils::SphereCoords::lat, moab::IntxUtils::SphereCoords::lon, mb, MB_CHK_ERR, MB_SUCCESS, IntxUtilsCSLAM::quasi_smooth_field(), moab::IntxUtils::SphereCoords::R, radius, moab::Range::size(), IntxUtilsCSLAM::slotted_cylinder_field(), IntxUtilsCSLAM::smooth_field(), moab::IntxUtils::spherical_to_cart(), moab::Core::tag_get_data(), and moab::Core::tag_iterate().

Referenced by main().

◆ compute_tracer_case1()

ErrorCode compute_tracer_case1 ( Interface mb,
Intx2MeshOnSphere worker,
EntityHandle  euler_set,
EntityHandle  lagr_set,
EntityHandle  out_set,
Tag tagElem,
Tag tagArea,
int  rank,
int  tStep,
Range connecVerts 
)

Definition at line 242 of file diffusion.cpp.

252 {
253  ErrorCode rval;
254  EntityHandle dum = 0;
255  Tag corrTag;
256  rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE, &dum );MB_CHK_ERR( rval );
257 
258  double t = tStep * T / numSteps; // numSteps is global; so is T
259  double delta_t = T / numSteps; // this is global too, actually
260  Range polys;
261  rval = mb->get_entities_by_dimension( euler_set, 2, polys );MB_CHK_ERR( rval );
262 
263  // change coordinates of lagr mesh vertices
264  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
265  {
266  EntityHandle oldV = *vit;
267  CartVect posi;
268  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
269  // Intx utils, case 1
270  CartVect newPos;
272  newPos = radius * newPos; // do we need this? the radius should be 1
273  EntityHandle new_vert;
274  rval = mb->tag_get_data( corrTag, &oldV, 1, &new_vert );MB_CHK_ERR( rval );
275  // set the new position for the new vertex
276  rval = mb->set_coords( &new_vert, 1, &( newPos[0] ) );MB_CHK_ERR( rval );
277  }
278 
279  // if in parallel, we have to move some elements to another proc, and receive other cells
280  // from other procs
281  // lagr and euler are preserved
282  EntityHandle covering_set;
283  rval = worker.create_departure_mesh_3rd_alg( lagr_set, covering_set );MB_CHK_ERR( rval );
284  if( writeFiles ) // so if write
285  {
286  std::stringstream departureMesh;
287  departureMesh << "Departure" << rank << "_" << tStep << ".vtk";
288  rval = mb->write_file( departureMesh.str().c_str(), 0, 0, &lagr_set, 1 );MB_CHK_ERR( rval );
289 
290  std::stringstream newTracer;
291  newTracer << "Tracer" << rank << "_" << tStep << ".vtk";
292  rval = mb->write_file( newTracer.str().c_str(), 0, 0, &euler_set, 1 );MB_CHK_ERR( rval );
293 
294  std::stringstream lagr_cover;
295  lagr_cover << "Cover" << rank << "_" << tStep << ".vtk";
296  rval = mb->write_file( lagr_cover.str().c_str(), 0, 0, &covering_set, 1 );MB_CHK_ERR( rval );
297  }
298  // so we have now the departure at the previous time
299  // intersect the 2 meshes (what about some checking of convexity?) for sufficient
300  // small dt, it is not an issue;
301 
302  rval = worker.intersect_meshes( covering_set, euler_set, out_set );MB_CHK_ERR( rval );
303  if( writeFiles ) // so if write
304  {
305  std::stringstream intx_mesh;
306  intx_mesh << "Intx" << rank << "_" << tStep << ".vtk";
307  rval = mb->write_file( intx_mesh.str().c_str(), 0, 0, &out_set, 1 );MB_CHK_ERR( rval );
308  }
309 
310  // serially: lagr is the same order as euler;
311  // we need to update now the tracer information on each element, based on
312  // initial value and areas of each resulting polygons
313  if( parallelWrite && tStep == 1 )
314  {
315  std::stringstream resTrace;
316  resTrace << "Tracer"
317  << "_" << tStep - 1 << ".h5m";
318  rval = mb->write_file( resTrace.str().c_str(), 0, "PARALLEL=WRITE_PART", &euler_set, 1, &tagElem, 1 );MB_CHK_ERR( rval );
319  }
320  rval = worker.update_tracer_data( out_set, tagElem, tagArea );MB_CHK_ERR( rval );
321 
322  if( parallelWrite )
323  {
324  std::stringstream resTrace;
325  resTrace << "Tracer"
326  << "_" << tStep << ".h5m";
327  rval = mb->write_file( resTrace.str().c_str(), 0, "PARALLEL=WRITE_PART", &euler_set, 1, &tagElem, 1 );
328  }
329 
330  if( writeFiles ) // so if write
331  {
332  std::stringstream newIntx;
333  newIntx << "newIntx" << rank << "_" << tStep << ".vtk";
334  rval = mb->write_file( newIntx.str().c_str(), 0, 0, &out_set, 1 );MB_CHK_ERR( rval );
335  }
336  // delete now the polygons and the elements of out_set
337  // also, all verts that are not in euler set or lagr_set
338  Range allVerts;
339  rval = mb->get_entities_by_dimension( 0, 0, allVerts );MB_CHK_ERR( rval );
340 
341  Range allElems;
342  rval = mb->get_entities_by_dimension( 0, 2, allElems );MB_CHK_ERR( rval );
343 
344  // add to polys range the lagr polys
345  // do not delete lagr set either, with its vertices
346  rval = mb->get_entities_by_dimension( lagr_set, 2, polys );MB_CHK_ERR( rval );
347  // add to the connecVerts range all verts, from all initial polys
348  Range vertsToStay;
349  rval = mb->get_connectivity( polys, vertsToStay );MB_CHK_ERR( rval );
350 
351  Range todeleteVerts = subtract( allVerts, vertsToStay );
352 
353  Range todeleteElem = subtract( allElems, polys );
354 
355  // empty the out mesh set
356  rval = mb->clear_meshset( &out_set, 1 );MB_CHK_ERR( rval );
357 
358  rval = mb->delete_entities( todeleteElem );MB_CHK_ERR( rval );
359  rval = mb->delete_entities( todeleteVerts );MB_CHK_ERR( rval );
360  if( rank == 0 ) std::cout << " step: " << tStep << "\n";
361  return rval;
362 }

References moab::Range::begin(), moab::Core::clear_meshset(), CORRTAGNAME, moab::Intx2Mesh::create_departure_mesh_3rd_alg(), moab::Core::delete_entities(), delta_t, IntxUtilsCSLAM::departure_point_case1(), moab::dum, moab::Range::end(), ErrorCode, moab::Core::get_connectivity(), moab::Core::get_coords(), moab::Core::get_entities_by_dimension(), moab::Intx2Mesh::intersect_meshes(), mb, MB_CHK_ERR, MB_TAG_DENSE, MB_TYPE_HANDLE, numSteps, parallelWrite, radius, moab::Core::set_coords(), moab::subtract(), t, T, moab::Core::tag_get_data(), moab::Core::tag_get_handle(), moab::Intx2MeshOnSphere::update_tracer_data(), moab::Core::write_file(), and writeFiles.

Referenced by main().

◆ compute_velocity_case1()

ErrorCode compute_velocity_case1 ( Interface mb,
EntityHandle  euler_set,
Tag tagh,
int  rank,
int  tStep 
)

Definition at line 199 of file diffusion.cpp.

200 {
201  Range polygons;
202  ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, polygons );
203  if( MB_SUCCESS != rval ) return rval;
204 
205  Range connecVerts;
206  rval = mb->get_connectivity( polygons, connecVerts );
207  if( MB_SUCCESS != rval ) return rval;
208 
209  void* data; // pointer to the velo in memory, for each vertex
210  int count;
211 
212  rval = mb->tag_iterate( tagh, connecVerts.begin(), connecVerts.end(), count, data );MB_CHK_ERR( rval );
213  // here we are checking contiguity
214  assert( count == (int)connecVerts.size() );
215  double* ptr_velo = (double*)data;
216  // lambda is for longitude, theta for latitude
217 
218  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
219  {
220  EntityHandle oldV = *vit;
221  CartVect posi;
222  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
223  CartVect velo;
224  double t = T * tStep / numSteps; //
225  IntxUtilsCSLAM::velocity_case1( posi, t, velo );
226 
227  ptr_velo[0] = velo[0];
228  ptr_velo[1] = velo[1];
229  ptr_velo[2] = velo[2];
230 
231  // increment to the next node
232  ptr_velo += 3; // to next velocity
233  }
234 
235  std::stringstream velos;
236  velos << "Tracer" << rank << "_" << tStep << ".vtk";
237  rval = mb->write_file( velos.str().c_str(), 0, 0, &euler_set, 1, &tagh, 1 );MB_CHK_ERR( rval );
238 
239  return MB_SUCCESS;
240 }

References moab::Range::begin(), moab::Range::end(), ErrorCode, moab::Core::get_connectivity(), moab::Core::get_coords(), moab::Core::get_entities_by_dimension(), mb, MB_CHK_ERR, MB_SUCCESS, numSteps, moab::Range::size(), t, T, moab::Core::tag_iterate(), IntxUtilsCSLAM::velocity_case1(), and moab::Core::write_file().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 364 of file diffusion.cpp.

365 {
366  MPI_Init( &argc, &argv );
367  LONG_DESC << "This program simulates a transport problem on a sphere"
368  " according to a benchmark from a Nair & Lauritzen paper.\n"
369  << "It starts with a partitioned mesh on a sphere, add a tracer, and steps through.\n"
370  << "The flow reverses after half time, and it should return to original "
371  "configuration, if the integration was exact. ";
372  ProgOptions opts( LONG_DESC.str(), BRIEF_DESC );
373 
374  // read a homme file, partitioned in 16 so far
375  std::string fileN = TestDir + "unittest/mbcslam/fine4.h5m";
376  const char* filename_mesh1 = fileN.c_str();
377 
378  opts.addOpt< double >( "gtolerance,g", "geometric absolute tolerance (used for point concidence on the sphere)",
379  &gtol );
380 
381  std::string input_file;
382  opts.addOpt< std::string >( "input_file,i", "input mesh file, partitioned", &input_file );
383  std::string extra_read_opts;
384  opts.addOpt< std::string >( "extra_read_options,O", "extra read options ", &extra_read_opts );
385  // int field_type;
386  opts.addOpt< int >( "field_type,f", "field type-- 1: quasi-smooth; 2: smooth; 3: slotted cylinders (non-smooth)",
387  &field_type );
388 
389  opts.addOpt< int >( "num_steps,n", "number of steps ", &numSteps );
390 
391  // bool reorder = false;
392  opts.addOpt< void >( "write_debug_files,w", "write debugging files during simulation ", &writeFiles );
393 
394  opts.addOpt< void >( "write_velocity_files,v", "Reorder mesh to group entities by partition", &velocity );
395 
396  opts.addOpt< void >( "write_result_in_parallel,p", "write tracer result files", &parallelWrite );
397 
398  opts.parseCommandLine( argc, argv );
399 
400  if( !input_file.empty() ) filename_mesh1 = input_file.c_str();
401 
402  // read in parallel, in the "euler_set", the initial mesh
403  std::string optsRead = std::string( "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION" ) +
404  std::string( ";PARALLEL_RESOLVE_SHARED_ENTS" ) + extra_read_opts;
405  Core moab;
406  Interface& mb = moab;
407  EntityHandle euler_set;
408  ErrorCode rval;
409  rval = mb.create_meshset( MESHSET_SET, euler_set );MB_CHK_ERR( rval );
410 
411  rval = mb.load_file( filename_mesh1, &euler_set, optsRead.c_str() );MB_CHK_ERR( rval );
412 
413  ParallelComm* pcomm = ParallelComm::get_pcomm( &mb, 0 );
414 
415  rval = pcomm->check_all_shared_handles();MB_CHK_ERR( rval );
416 
417  int rank = pcomm->proc_config().proc_rank();
418 
419  if( 0 == rank )
420  {
421  std::cout << " case 1: use -gtol " << gtol << " -R " << radius << " -input " << filename_mesh1 << " -f "
422  << field_type << " numSteps: " << numSteps << "\n";
423  std::cout << " write debug results: " << ( writeFiles ? "yes" : "no" ) << "\n";
424  std::cout << " write tracer in parallel: " << ( parallelWrite ? "yes" : "no" ) << "\n";
425  std::cout << " output velocity: " << ( velocity ? "yes" : "no" ) << "\n";
426  }
427 
428  // tagTracer is the value at nodes
429  Tag tagTracer = 0;
430  std::string tag_name( "Tracer" );
431  rval = mb.tag_get_handle( tag_name.c_str(), 1, MB_TYPE_DOUBLE, tagTracer, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
432 
433  // tagElem is the average computed at each element, from nodal values
434  Tag tagElem = 0;
435  std::string tag_name2( "TracerAverage" );
436  rval = mb.tag_get_handle( tag_name2.c_str(), 1, MB_TYPE_DOUBLE, tagElem, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
437 
438  // area of the euler element is fixed, store it; it is used to recompute the averages at each
439  // time step
440  Tag tagArea = 0;
441  std::string tag_name4( "Area" );
442  rval = mb.tag_get_handle( tag_name4.c_str(), 1, MB_TYPE_DOUBLE, tagArea, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
443 
444  // add a field value, quasi smooth first
445  rval = add_field_value( &mb, euler_set, rank, tagTracer, tagElem, tagArea );MB_CHK_ERR( rval );
446 
447  // iniVals are used for 1-norm error computation
448  Range redEls;
449  rval = mb.get_entities_by_dimension( euler_set, 2, redEls );MB_CHK_ERR( rval );
450  std::vector< double > iniVals( redEls.size() );
451  rval = mb.tag_get_data( tagElem, redEls, &iniVals[0] );MB_CHK_ERR( rval );
452 
453  Tag tagh = 0;
454  std::string tag_name3( "Case1" );
455  rval = mb.tag_get_handle( tag_name3.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
456 
457  EntityHandle out_set, lagr_set;
458  rval = mb.create_meshset( MESHSET_SET, out_set );MB_CHK_ERR( rval );
459  rval = mb.create_meshset( MESHSET_SET, lagr_set );MB_CHK_ERR( rval );
460  // copy the initial mesh in the lagrangian set
461  // initial vertices will be at the same position as euler;
462 
463  rval = IntxUtilsCSLAM::deep_copy_set( &mb, euler_set, lagr_set );MB_CHK_ERR( rval );
464 
465  Intx2MeshOnSphere worker( &mb );
466  worker.set_radius_source_mesh( radius );
467  worker.set_radius_destination_mesh( radius );
468  worker.set_error_tolerance( gtol );
469  worker.set_parallel_comm( pcomm );
470 
471  rval = worker.FindMaxEdges( lagr_set, euler_set );MB_CHK_ERR( rval );
472  Range local_verts;
473  // output also the local_verts
474  rval = worker.build_processor_euler_boxes( euler_set, local_verts );MB_CHK_ERR( rval );
475  // these stay fixed for one run
476  // other things from intersection might need to change, like input blue set (departure set)
477  // so we need also a method to clean memory
478 
479  for( int i = 1; i < numSteps + 1; i++ )
480  {
481  // time depends on i; t = i*T/numSteps: ( 0, T/numSteps, 2*T/numSteps, ..., T )
482  // this is really just to create some plots; it is not really needed to proceed
483  // the compute_tracer_case1 method actually computes the departure point position
484  if( velocity )
485  {
486  rval = compute_velocity_case1( &mb, euler_set, tagh, rank, i );MB_CHK_ERR( rval );
487  }
488 
489  // this is to actually compute concentrations at time step i, using the
490  // current concentrations
491  rval =
492  compute_tracer_case1( &mb, worker, euler_set, lagr_set, out_set, tagElem, tagArea, rank, i, local_verts );MB_CHK_ERR( rval );
493  }
494 
495  // final vals and 1-norm
496  Range::iterator iter = redEls.begin();
497  double norm1 = 0.;
498  int count = 0;
499  void* data;
500  int j = 0; // index in iniVals
501  while( iter != redEls.end() )
502  {
503  rval = mb.tag_iterate( tagElem, iter, redEls.end(), count, data );MB_CHK_ERR( rval );
504  double* ptrTracer = (double*)data;
505 
506  rval = mb.tag_iterate( tagArea, iter, redEls.end(), count, data );MB_CHK_ERR( rval );
507  double* ptrArea = (double*)data;
508  for( int i = 0; i < count; i++, ++iter, ptrTracer++, ptrArea++, j++ )
509  {
510  // double area = *ptrArea;
511  norm1 += fabs( *ptrTracer - iniVals[j] ) * ( *ptrArea );
512  }
513  }
514 
515  double total_norm1 = 0;
516  int mpi_err = MPI_Reduce( &norm1, &total_norm1, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
517  if( MPI_SUCCESS != mpi_err ) return 1;
518  if( 0 == rank ) std::cout << " numSteps:" << numSteps << " 1-norm:" << total_norm1 << "\n";
519  MPI_Finalize();
520  return 0;
521 }

References add_field_value(), ProgOptions::addOpt(), moab::Range::begin(), BRIEF_DESC, moab::ParallelComm::check_all_shared_handles(), compute_tracer_case1(), compute_velocity_case1(), moab::Core::create_meshset(), IntxUtilsCSLAM::deep_copy_set(), moab::Range::end(), ErrorCode, field_type, moab::Intx2Mesh::FindMaxEdges(), moab::Core::get_entities_by_dimension(), moab::ParallelComm::get_pcomm(), gtol, input_file, moab::Core::load_file(), LONG_DESC, mb, MB_CHK_ERR, MB_TAG_CREAT, MB_TAG_DENSE, MB_TYPE_DOUBLE, MESHSET_SET, numSteps, parallelWrite, ProgOptions::parseCommandLine(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), radius, moab::Intx2Mesh::set_error_tolerance(), moab::Intx2MeshOnSphere::set_radius_destination_mesh(), moab::Intx2MeshOnSphere::set_radius_source_mesh(), moab::Range::size(), moab::Core::tag_get_data(), moab::Core::tag_get_handle(), moab::Core::tag_iterate(), velocity, and writeFiles.

Variable Documentation

◆ BRIEF_DESC

const char BRIEF_DESC[] = "Simulate a transport problem in a semi-Lagrangian formulation\n"

Definition at line 44 of file diffusion.cpp.

Referenced by main().

◆ case_number

int case_number = 1

Definition at line 54 of file diffusion.cpp.

◆ field_type

int field_type = 1

Definition at line 58 of file diffusion.cpp.

Referenced by add_field_value(), and main().

◆ gtol

double gtol = 1.e-9

Definition at line 49 of file diffusion.cpp.

Referenced by main().

◆ LONG_DESC

std::ostringstream LONG_DESC

Definition at line 45 of file diffusion.cpp.

Referenced by main().

◆ numSteps

int numSteps = 3

Definition at line 52 of file diffusion.cpp.

Referenced by compute_tracer_case1(), compute_velocity_case1(), and main().

◆ parallelWrite

bool parallelWrite = false

Definition at line 56 of file diffusion.cpp.

Referenced by compute_tracer_case1(), and main().

◆ radius

double radius = 1.

Definition at line 50 of file diffusion.cpp.

Referenced by add_field_value(), compute_tracer_case1(), and main().

◆ T

◆ velocity

bool velocity = false

Definition at line 57 of file diffusion.cpp.

Referenced by main().

◆ writeFiles

bool writeFiles = false

Definition at line 55 of file diffusion.cpp.

Referenced by compute_tracer_case1(), and main().