Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
IntxUtilsCSLAM.cpp
Go to the documentation of this file.
1 #include <cmath>
2 #include "moab/ReadUtilIface.hpp"
3 #include "IntxUtilsCSLAM.hpp"
4 
5 using namespace moab;
6 
7 #ifndef CORRTAGNAME
8 #define CORRTAGNAME "__correspondent"
9 #endif
10 
11 // page 4 Nair Lauritzen paper
12 // param will be: (la1, te1), (la2, te2), b, c; hmax=1, r=1/2
13 double IntxUtilsCSLAM::quasi_smooth_field( double lam, double tet, double* params )
14 {
15  double la1 = params[0];
16  double te1 = params[1];
17  double la2 = params[2];
18  double te2 = params[3];
19  double b = params[4];
20  double c = params[5];
21  double hmax = params[6]; // 1;
22  double r = params[7]; // 0.5;
23  double r1 = moab::IntxUtils::distance_on_sphere( lam, tet, la1, te1 );
24  double r2 = moab::IntxUtils::distance_on_sphere( lam, tet, la2, te2 );
25  double value = b;
26  if( r1 < r )
27  {
28  value += c * hmax / 2 * ( 1 + cos( M_PI * r1 / r ) );
29  }
30  if( r2 < r )
31  {
32  value += c * hmax / 2 * ( 1 + cos( M_PI * r2 / r ) );
33  }
34  return value;
35 }
36 
37 // page 4
38 // params are now x1, y1, ..., y2, z2 (6 params)
39 // plus h max and b0 (total of 8 params); radius is 1
40 double IntxUtilsCSLAM::smooth_field( double lam, double tet, double* params )
41 {
43  sc.R = 1.;
44  sc.lat = tet;
45  sc.lon = lam;
46  double hmax = params[6];
47  double b0 = params[7];
49  CartVect c1( params );
50  CartVect c2( params + 3 );
51  double expo1 = -b0 * ( xyz - c1 ).length_squared();
52  double expo2 = -b0 * ( xyz - c2 ).length_squared();
53  return hmax * ( exp( expo1 ) + exp( expo2 ) );
54 }
55 
56 // page 5
57 double IntxUtilsCSLAM::slotted_cylinder_field( double lam, double tet, double* params )
58 {
59  double la1 = params[0];
60  double te1 = params[1];
61  double la2 = params[2];
62  double te2 = params[3];
63  double b = params[4];
64  double c = params[5];
65  // double hmax = params[6]; // 1;
66  double r = params[6]; // 0.5;
67  double r1 = moab::IntxUtils::distance_on_sphere( lam, tet, la1, te1 );
68  double r2 = moab::IntxUtils::distance_on_sphere( lam, tet, la2, te2 );
69  double value = b;
70  double d1 = fabs( lam - la1 );
71  double d2 = fabs( lam - la2 );
72  double rp6 = r / 6;
73  double rt5p12 = r * 5 / 12;
74 
75  if( r1 <= r && d1 >= rp6 ) value = c;
76  if( r2 <= r && d2 >= rp6 ) value = c;
77  if( r1 <= r && d1 < rp6 && tet - te1 < -rt5p12 ) value = c;
78  if( r2 <= r && d2 < rp6 && tet - te2 > rt5p12 ) value = c;
79 
80  return value;
81 }
82 
83 /*
84  * based on paper A class of deformational flow test cases for linear transport problems on the
85  * sphere longitude lambda [0.. 2*pi) and latitude theta (-pi/2, pi/2) lambda: -> lon (0, 2*pi)
86  * theta : -> lat (-pi/2, po/2)
87  * Radius of the sphere is 1 (if not, everything gets multiplied by 1)
88  *
89  * cosine bell: center lambda0, theta0:
90  */
92  double t,
93  double delta_t,
94  CartVect& departure_point )
95 {
96  // always assume radius is 1 here?
98  double T = 5; // duration of integration (5 units)
99  double k = 2.4; // flow parameter
100  /* radius needs to be within some range */
101  double sl2 = sin( sph.lon / 2 );
102  double pit = M_PI * t / T;
103  double omega = M_PI / T;
104  double costetha = cos( sph.lat );
105  // double u = k * sl2*sl2 * sin(2*sph.lat) * cos(pit);
106  double v = k * sin( sph.lon ) * costetha * cos( pit );
107  // double psi = k * sl2 * sl2 *costetha * costetha * cos(pit);
108  double u_tilda = 2 * k * sl2 * sl2 * sin( sph.lat ) * cos( pit );
109 
110  // formula 35, page 8
111  // this will approximate dep point using a Taylor series with up to second derivative
112  // this will be O(delta_t^3) exact.
113  double lon_dep =
114  sph.lon - delta_t * u_tilda -
115  delta_t * delta_t * k * sl2 *
116  ( sl2 * sin( sph.lat ) * sin( pit ) * omega - u_tilda * sin( sph.lat ) * cos( pit ) * cos( sph.lon / 2 ) -
117  v * sl2 * costetha * cos( pit ) );
118  // formula 36, page 8 again
119  double lat_dep = sph.lat - delta_t * v -
120  delta_t * delta_t / 4 * k *
121  ( sin( sph.lon ) * cos( sph.lat ) * sin( pit ) * omega -
122  u_tilda * cos( sph.lon ) * cos( sph.lat ) * cos( pit ) +
123  v * sin( sph.lon ) * sin( sph.lat ) * cos( pit ) );
124 
126  sph_dep.R = 1.; // radius
127  sph_dep.lat = lat_dep;
128  sph_dep.lon = lon_dep;
129 
130  departure_point = moab::IntxUtils::spherical_to_cart( sph_dep );
131  return;
132 }
133 
134 void IntxUtilsCSLAM::velocity_case1( CartVect& arrival_point, double t, CartVect& velo )
135 {
136  // always assume radius is 1 here?
138  double T = 5; // duration of integration (5 units)
139  double k = 2.4; // flow parameter
140  /* radius needs to be within some range */
141  double sl2 = sin( sph.lon / 2 );
142  double pit = M_PI * t / T;
143  // double omega = M_PI/T;
144  double coslat = cos( sph.lat );
145  double sinlat = sin( sph.lat );
146  double sinlon = sin( sph.lon );
147  double coslon = cos( sph.lon );
148  double u = k * sl2 * sl2 * sin( 2 * sph.lat ) * cos( pit );
149  double v = k / 2 * sinlon * coslat * cos( pit );
150  velo[0] = -u * sinlon - v * sinlat * coslon;
151  velo[1] = u * coslon - v * sinlat * sinlon;
152  velo[2] = v * coslat;
153 }
154 
156 {
157  // first get all edges adjacent to polygons
158  Tag dpTag = 0;
159  std::string tag_name( "DP" );
160  ErrorCode rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE );
161  // if the tag does not exist, get out early
162  if( rval != MB_SUCCESS ) return rval;
163  Range polygons;
164  rval = mb->get_entities_by_dimension( euler_set, 2, polygons );
165  if( MB_SUCCESS != rval ) return rval;
166  Range iniEdges;
167  rval = mb->get_adjacencies( polygons, 1, false, iniEdges, Interface::UNION );
168  if( MB_SUCCESS != rval ) return rval;
169  // now create some if missing
170  Range allEdges;
171  rval = mb->get_adjacencies( polygons, 1, true, allEdges, Interface::UNION );
172  if( MB_SUCCESS != rval ) return rval;
173  // create the vertices at the DP points, and the quads after that
174  Range verts;
175  rval = mb->get_connectivity( polygons, verts );
176  if( MB_SUCCESS != rval ) return rval;
177  int num_verts = (int)verts.size();
178  // now see the departure points; to what boxes should we send them?
179  std::vector< double > dep_points( 3 * num_verts );
180  rval = mb->tag_get_data( dpTag, verts, (void*)&dep_points[0] );
181  if( MB_SUCCESS != rval ) return rval;
182 
183  // create vertices corresponding to dp locations
184  ReadUtilIface* read_iface;
185  rval = mb->query_interface( read_iface );
186  if( MB_SUCCESS != rval ) return rval;
187  std::vector< double* > coords;
188  EntityHandle start_vert, start_elem, *connect;
189  // create verts, num is 2(nquads+1) because they're in a 1d row; will initialize coords in loop
190  // over quads later
191  rval = read_iface->get_node_coords( 3, num_verts, 0, start_vert, coords );
192  if( MB_SUCCESS != rval ) return rval;
193  // fill it up
194  // Cppcheck warning (false positive): variable coords is assigned a value that is never used
195  for( int i = 0; i < num_verts; i++ )
196  {
197  // block from interleaved
198  coords[0][i] = dep_points[3 * i];
199  coords[1][i] = dep_points[3 * i + 1];
200  coords[2][i] = dep_points[3 * i + 2];
201  }
202  // create quads; one quad for each edge
203  rval = read_iface->get_element_connect( allEdges.size(), 4, MBQUAD, 0, start_elem, connect );
204  if( MB_SUCCESS != rval ) return rval;
205 
206  const EntityHandle* edge_conn = NULL;
207  int quad_index = 0;
208  EntityHandle firstVertHandle = verts[0]; // assume vertices are contiguous...
209  for( Range::iterator eit = allEdges.begin(); eit != allEdges.end(); ++eit, quad_index++ )
210  {
211  EntityHandle edge = *eit;
212  int num_nodes;
213  rval = mb->get_connectivity( edge, edge_conn, num_nodes );
214  if( MB_SUCCESS != rval ) return rval;
215  connect[quad_index * 4] = edge_conn[0];
216  connect[quad_index * 4 + 1] = edge_conn[1];
217 
218  // maybe some indexing in range?
219  connect[quad_index * 4 + 2] = start_vert + edge_conn[1] - firstVertHandle;
220  connect[quad_index * 4 + 3] = start_vert + edge_conn[0] - firstVertHandle;
221  }
222 
223  Range quads( start_elem, start_elem + allEdges.size() - 1 );
224  EntityHandle outSet;
225  rval = mb->create_meshset( MESHSET_SET, outSet );
226  if( MB_SUCCESS != rval ) return rval;
227  mb->add_entities( outSet, quads );
228 
229  Tag colTag;
230  rval = mb->tag_get_handle( "COLOR_ID", 1, MB_TYPE_INTEGER, colTag, MB_TAG_DENSE | MB_TAG_CREAT );
231  if( MB_SUCCESS != rval ) return rval;
232  int j = 1;
233  for( Range::iterator itq = quads.begin(); itq != quads.end(); ++itq, j++ )
234  {
235  EntityHandle q = *itq;
236  rval = mb->tag_set_data( colTag, &q, 1, &j );
237  if( MB_SUCCESS != rval ) return rval;
238  }
239  std::stringstream outf;
240  outf << "SpanQuads" << rank << ".h5m";
241  rval = mb->write_file( outf.str().c_str(), 0, 0, &outSet, 1 );
242  if( MB_SUCCESS != rval ) return rval;
243  EntityHandle outSet2;
244  rval = mb->create_meshset( MESHSET_SET, outSet2 );
245  if( MB_SUCCESS != rval ) return rval;
246 
247  Range quadEdges;
248  rval = mb->get_adjacencies( quads, 1, true, quadEdges, Interface::UNION );
249  if( MB_SUCCESS != rval ) return rval;
250  mb->add_entities( outSet2, quadEdges );
251 
252  std::stringstream outf2;
253  outf2 << "SpanEdges" << rank << ".h5m";
254  rval = mb->write_file( outf2.str().c_str(), 0, 0, &outSet2, 1 );
255  if( MB_SUCCESS != rval ) return rval;
256 
257  // maybe some clean up
258  mb->delete_entities( &outSet, 1 );
259  mb->delete_entities( &outSet2, 1 );
260  mb->delete_entities( quads );
261  Range new_edges = subtract( allEdges, iniEdges );
262  mb->delete_entities( new_edges );
263  new_edges = subtract( quadEdges, iniEdges );
264  mb->delete_entities( new_edges );
265  Range new_verts( start_vert, start_vert + num_verts );
266  mb->delete_entities( new_verts );
267 
268  return MB_SUCCESS;
269 }
270 
271 // this simply copies the one mesh set into another, and sets some correlation tags
272 // for easy mapping back and forth
274 {
275  // create the handle tag for the corresponding element / vertex
276 
277  EntityHandle dum = 0;
278  Tag corrTag = 0; // it will be created here
280 
281  // give the same global id to new verts and cells created in the lagr(departure) mesh
282  Tag gid = mb->globalId_tag();
283 
284  Range polys;
285  rval = mb->get_entities_by_dimension( source_set, 2, polys );MB_CHK_ERR( rval );
286 
287  Range connecVerts;
288  rval = mb->get_connectivity( polys, connecVerts );MB_CHK_ERR( rval );
289 
290  std::map< EntityHandle, EntityHandle > newNodes;
291  for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
292  {
293  EntityHandle oldV = *vit;
294  CartVect posi;
295  rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
296  int global_id;
297  rval = mb->tag_get_data( gid, &oldV, 1, &global_id );MB_CHK_ERR( rval );
298 
299  EntityHandle new_vert;
300  // duplicate the position
301  rval = mb->create_vertex( &( posi[0] ), new_vert );MB_CHK_ERR( rval );
302  newNodes[oldV] = new_vert;
303 
304  // set also the correspondent tag :)
305  rval = mb->tag_set_data( corrTag, &oldV, 1, &new_vert );MB_CHK_ERR( rval );
306  // also the other side
307  // need to check if we really need this; the new vertex will never need the old vertex
308  // we have the global id which is the same
309  rval = mb->tag_set_data( corrTag, &new_vert, 1, &oldV );MB_CHK_ERR( rval );
310  // set the global id on the corresponding vertex the same as the initial vertex
311  rval = mb->tag_set_data( gid, &new_vert, 1, &global_id );MB_CHK_ERR( rval );
312  }
313 
314  for( Range::iterator it = polys.begin(); it != polys.end(); ++it )
315  {
316  EntityHandle q = *it;
317  int nnodes;
318  const EntityHandle* conn;
319  rval = mb->get_connectivity( q, conn, nnodes );MB_CHK_ERR( rval );
320 
321  int global_id;
322  rval = mb->tag_get_data( gid, &q, 1, &global_id );MB_CHK_ERR( rval );
323  EntityType typeElem = mb->type_from_handle( q );
324  std::vector< EntityHandle > new_conn( nnodes );
325  for( int i = 0; i < nnodes; i++ )
326  {
327  EntityHandle v1 = conn[i];
328  new_conn[i] = newNodes[v1];
329  }
330  EntityHandle newElement;
331  rval = mb->create_element( typeElem, &new_conn[0], nnodes, newElement );MB_CHK_ERR( rval );
332 
333  // set the corresponding tag; not sure we need this one, from old to new
334  rval = mb->tag_set_data( corrTag, &q, 1, &newElement );MB_CHK_ERR( rval );
335  rval = mb->tag_set_data( corrTag, &newElement, 1, &q );MB_CHK_ERR( rval );
336 
337  // set the global id
338  rval = mb->tag_set_data( gid, &newElement, 1, &global_id );MB_CHK_ERR( rval );
339  rval = mb->add_entities( dest_set, &newElement, 1 );MB_CHK_ERR( rval );
340  }
341 
342  return MB_SUCCESS;
343 }