![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include
00002 #include "moab/ReadUtilIface.hpp"
00003 #include "IntxUtilsCSLAM.hpp"
00004
00005 using namespace moab;
00006
00007 #ifndef CORRTAGNAME
00008 #define CORRTAGNAME "__correspondent"
00009 #endif
00010
00011 // page 4 Nair Lauritzen paper
00012 // param will be: (la1, te1), (la2, te2), b, c; hmax=1, r=1/2
00013 double IntxUtilsCSLAM::quasi_smooth_field( double lam, double tet, double* params )
00014 {
00015 double la1 = params[0];
00016 double te1 = params[1];
00017 double la2 = params[2];
00018 double te2 = params[3];
00019 double b = params[4];
00020 double c = params[5];
00021 double hmax = params[6]; // 1;
00022 double r = params[7]; // 0.5;
00023 double r1 = moab::IntxUtils::distance_on_sphere( lam, tet, la1, te1 );
00024 double r2 = moab::IntxUtils::distance_on_sphere( lam, tet, la2, te2 );
00025 double value = b;
00026 if( r1 < r )
00027 {
00028 value += c * hmax / 2 * ( 1 + cos( M_PI * r1 / r ) );
00029 }
00030 if( r2 < r )
00031 {
00032 value += c * hmax / 2 * ( 1 + cos( M_PI * r2 / r ) );
00033 }
00034 return value;
00035 }
00036
00037 // page 4
00038 // params are now x1, y1, ..., y2, z2 (6 params)
00039 // plus h max and b0 (total of 8 params); radius is 1
00040 double IntxUtilsCSLAM::smooth_field( double lam, double tet, double* params )
00041 {
00042 moab::IntxUtils::SphereCoords sc;
00043 sc.R = 1.;
00044 sc.lat = tet;
00045 sc.lon = lam;
00046 double hmax = params[6];
00047 double b0 = params[7];
00048 CartVect xyz = moab::IntxUtils::spherical_to_cart( sc );
00049 CartVect c1( params );
00050 CartVect c2( params + 3 );
00051 double expo1 = -b0 * ( xyz - c1 ).length_squared();
00052 double expo2 = -b0 * ( xyz - c2 ).length_squared();
00053 return hmax * ( exp( expo1 ) + exp( expo2 ) );
00054 }
00055
00056 // page 5
00057 double IntxUtilsCSLAM::slotted_cylinder_field( double lam, double tet, double* params )
00058 {
00059 double la1 = params[0];
00060 double te1 = params[1];
00061 double la2 = params[2];
00062 double te2 = params[3];
00063 double b = params[4];
00064 double c = params[5];
00065 // double hmax = params[6]; // 1;
00066 double r = params[6]; // 0.5;
00067 double r1 = moab::IntxUtils::distance_on_sphere( lam, tet, la1, te1 );
00068 double r2 = moab::IntxUtils::distance_on_sphere( lam, tet, la2, te2 );
00069 double value = b;
00070 double d1 = fabs( lam - la1 );
00071 double d2 = fabs( lam - la2 );
00072 double rp6 = r / 6;
00073 double rt5p12 = r * 5 / 12;
00074
00075 if( r1 <= r && d1 >= rp6 ) value = c;
00076 if( r2 <= r && d2 >= rp6 ) value = c;
00077 if( r1 <= r && d1 < rp6 && tet - te1 < -rt5p12 ) value = c;
00078 if( r2 <= r && d2 < rp6 && tet - te2 > rt5p12 ) value = c;
00079
00080 return value;
00081 }
00082
00083 /*
00084 * based on paper A class of deformational flow test cases for linear transport problems on the
00085 * sphere longitude lambda [0.. 2*pi) and latitude theta (-pi/2, pi/2) lambda: -> lon (0, 2*pi)
00086 * theta : -> lat (-pi/2, po/2)
00087 * Radius of the sphere is 1 (if not, everything gets multiplied by 1)
00088 *
00089 * cosine bell: center lambda0, theta0:
00090 */
00091 void IntxUtilsCSLAM::departure_point_case1( CartVect& arrival_point,
00092 double t,
00093 double delta_t,
00094 CartVect& departure_point )
00095 {
00096 // always assume radius is 1 here?
00097 moab::IntxUtils::SphereCoords sph = moab::IntxUtils::cart_to_spherical( arrival_point );
00098 double T = 5; // duration of integration (5 units)
00099 double k = 2.4; // flow parameter
00100 /* radius needs to be within some range */
00101 double sl2 = sin( sph.lon / 2 );
00102 double pit = M_PI * t / T;
00103 double omega = M_PI / T;
00104 double costetha = cos( sph.lat );
00105 // double u = k * sl2*sl2 * sin(2*sph.lat) * cos(pit);
00106 double v = k * sin( sph.lon ) * costetha * cos( pit );
00107 // double psi = k * sl2 * sl2 *costetha * costetha * cos(pit);
00108 double u_tilda = 2 * k * sl2 * sl2 * sin( sph.lat ) * cos( pit );
00109
00110 // formula 35, page 8
00111 // this will approximate dep point using a Taylor series with up to second derivative
00112 // this will be O(delta_t^3) exact.
00113 double lon_dep =
00114 sph.lon - delta_t * u_tilda -
00115 delta_t * delta_t * k * sl2 *
00116 ( sl2 * sin( sph.lat ) * sin( pit ) * omega - u_tilda * sin( sph.lat ) * cos( pit ) * cos( sph.lon / 2 ) -
00117 v * sl2 * costetha * cos( pit ) );
00118 // formula 36, page 8 again
00119 double lat_dep = sph.lat - delta_t * v -
00120 delta_t * delta_t / 4 * k *
00121 ( sin( sph.lon ) * cos( sph.lat ) * sin( pit ) * omega -
00122 u_tilda * cos( sph.lon ) * cos( sph.lat ) * cos( pit ) +
00123 v * sin( sph.lon ) * sin( sph.lat ) * cos( pit ) );
00124
00125 moab::IntxUtils::SphereCoords sph_dep;
00126 sph_dep.R = 1.; // radius
00127 sph_dep.lat = lat_dep;
00128 sph_dep.lon = lon_dep;
00129
00130 departure_point = moab::IntxUtils::spherical_to_cart( sph_dep );
00131 return;
00132 }
00133
00134 void IntxUtilsCSLAM::velocity_case1( CartVect& arrival_point, double t, CartVect& velo )
00135 {
00136 // always assume radius is 1 here?
00137 moab::IntxUtils::SphereCoords sph = moab::IntxUtils::cart_to_spherical( arrival_point );
00138 double T = 5; // duration of integration (5 units)
00139 double k = 2.4; // flow parameter
00140 /* radius needs to be within some range */
00141 double sl2 = sin( sph.lon / 2 );
00142 double pit = M_PI * t / T;
00143 // double omega = M_PI/T;
00144 double coslat = cos( sph.lat );
00145 double sinlat = sin( sph.lat );
00146 double sinlon = sin( sph.lon );
00147 double coslon = cos( sph.lon );
00148 double u = k * sl2 * sl2 * sin( 2 * sph.lat ) * cos( pit );
00149 double v = k / 2 * sinlon * coslat * cos( pit );
00150 velo[0] = -u * sinlon - v * sinlat * coslon;
00151 velo[1] = u * coslon - v * sinlat * sinlon;
00152 velo[2] = v * coslat;
00153 }
00154
00155 ErrorCode IntxUtilsCSLAM::create_span_quads( Interface* mb, EntityHandle euler_set, int rank )
00156 {
00157 // first get all edges adjacent to polygons
00158 Tag dpTag = 0;
00159 std::string tag_name( "DP" );
00160 ErrorCode rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE );
00161 // if the tag does not exist, get out early
00162 if( rval != MB_SUCCESS ) return rval;
00163 Range polygons;
00164 rval = mb->get_entities_by_dimension( euler_set, 2, polygons );
00165 if( MB_SUCCESS != rval ) return rval;
00166 Range iniEdges;
00167 rval = mb->get_adjacencies( polygons, 1, false, iniEdges, Interface::UNION );
00168 if( MB_SUCCESS != rval ) return rval;
00169 // now create some if missing
00170 Range allEdges;
00171 rval = mb->get_adjacencies( polygons, 1, true, allEdges, Interface::UNION );
00172 if( MB_SUCCESS != rval ) return rval;
00173 // create the vertices at the DP points, and the quads after that
00174 Range verts;
00175 rval = mb->get_connectivity( polygons, verts );
00176 if( MB_SUCCESS != rval ) return rval;
00177 int num_verts = (int)verts.size();
00178 // now see the departure points; to what boxes should we send them?
00179 std::vector< double > dep_points( 3 * num_verts );
00180 rval = mb->tag_get_data( dpTag, verts, (void*)&dep_points[0] );
00181 if( MB_SUCCESS != rval ) return rval;
00182
00183 // create vertices corresponding to dp locations
00184 ReadUtilIface* read_iface;
00185 rval = mb->query_interface( read_iface );
00186 if( MB_SUCCESS != rval ) return rval;
00187 std::vector< double* > coords;
00188 EntityHandle start_vert, start_elem, *connect;
00189 // create verts, num is 2(nquads+1) because they're in a 1d row; will initialize coords in loop
00190 // over quads later
00191 rval = read_iface->get_node_coords( 3, num_verts, 0, start_vert, coords );
00192 if( MB_SUCCESS != rval ) return rval;
00193 // fill it up
00194 // Cppcheck warning (false positive): variable coords is assigned a value that is never used
00195 for( int i = 0; i < num_verts; i++ )
00196 {
00197 // block from interleaved
00198 coords[0][i] = dep_points[3 * i];
00199 coords[1][i] = dep_points[3 * i + 1];
00200 coords[2][i] = dep_points[3 * i + 2];
00201 }
00202 // create quads; one quad for each edge
00203 rval = read_iface->get_element_connect( allEdges.size(), 4, MBQUAD, 0, start_elem, connect );
00204 if( MB_SUCCESS != rval ) return rval;
00205
00206 const EntityHandle* edge_conn = NULL;
00207 int quad_index = 0;
00208 EntityHandle firstVertHandle = verts[0]; // assume vertices are contiguous...
00209 for( Range::iterator eit = allEdges.begin(); eit != allEdges.end(); ++eit, quad_index++ )
00210 {
00211 EntityHandle edge = *eit;
00212 int num_nodes;
00213 rval = mb->get_connectivity( edge, edge_conn, num_nodes );
00214 if( MB_SUCCESS != rval ) return rval;
00215 connect[quad_index * 4] = edge_conn[0];
00216 connect[quad_index * 4 + 1] = edge_conn[1];
00217
00218 // maybe some indexing in range?
00219 connect[quad_index * 4 + 2] = start_vert + edge_conn[1] - firstVertHandle;
00220 connect[quad_index * 4 + 3] = start_vert + edge_conn[0] - firstVertHandle;
00221 }
00222
00223 Range quads( start_elem, start_elem + allEdges.size() - 1 );
00224 EntityHandle outSet;
00225 rval = mb->create_meshset( MESHSET_SET, outSet );
00226 if( MB_SUCCESS != rval ) return rval;
00227 mb->add_entities( outSet, quads );
00228
00229 Tag colTag;
00230 rval = mb->tag_get_handle( "COLOR_ID", 1, MB_TYPE_INTEGER, colTag, MB_TAG_DENSE | MB_TAG_CREAT );
00231 if( MB_SUCCESS != rval ) return rval;
00232 int j = 1;
00233 for( Range::iterator itq = quads.begin(); itq != quads.end(); ++itq, j++ )
00234 {
00235 EntityHandle q = *itq;
00236 rval = mb->tag_set_data( colTag, &q, 1, &j );
00237 if( MB_SUCCESS != rval ) return rval;
00238 }
00239 std::stringstream outf;
00240 outf << "SpanQuads" << rank << ".h5m";
00241 rval = mb->write_file( outf.str().c_str(), 0, 0, &outSet, 1 );
00242 if( MB_SUCCESS != rval ) return rval;
00243 EntityHandle outSet2;
00244 rval = mb->create_meshset( MESHSET_SET, outSet2 );
00245 if( MB_SUCCESS != rval ) return rval;
00246
00247 Range quadEdges;
00248 rval = mb->get_adjacencies( quads, 1, true, quadEdges, Interface::UNION );
00249 if( MB_SUCCESS != rval ) return rval;
00250 mb->add_entities( outSet2, quadEdges );
00251
00252 std::stringstream outf2;
00253 outf2 << "SpanEdges" << rank << ".h5m";
00254 rval = mb->write_file( outf2.str().c_str(), 0, 0, &outSet2, 1 );
00255 if( MB_SUCCESS != rval ) return rval;
00256
00257 // maybe some clean up
00258 mb->delete_entities( &outSet, 1 );
00259 mb->delete_entities( &outSet2, 1 );
00260 mb->delete_entities( quads );
00261 Range new_edges = subtract( allEdges, iniEdges );
00262 mb->delete_entities( new_edges );
00263 new_edges = subtract( quadEdges, iniEdges );
00264 mb->delete_entities( new_edges );
00265 Range new_verts( start_vert, start_vert + num_verts );
00266 mb->delete_entities( new_verts );
00267
00268 return MB_SUCCESS;
00269 }
00270
00271 // this simply copies the one mesh set into another, and sets some correlation tags
00272 // for easy mapping back and forth
00273 ErrorCode IntxUtilsCSLAM::deep_copy_set( Interface* mb, EntityHandle source_set, EntityHandle dest_set )
00274 {
00275 // create the handle tag for the corresponding element / vertex
00276
00277 EntityHandle dum = 0;
00278 Tag corrTag = 0; // it will be created here
00279 ErrorCode rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum );MB_CHK_ERR( rval );
00280
00281 // give the same global id to new verts and cells created in the lagr(departure) mesh
00282 Tag gid = mb->globalId_tag();
00283
00284 Range polys;
00285 rval = mb->get_entities_by_dimension( source_set, 2, polys );MB_CHK_ERR( rval );
00286
00287 Range connecVerts;
00288 rval = mb->get_connectivity( polys, connecVerts );MB_CHK_ERR( rval );
00289
00290 std::map< EntityHandle, EntityHandle > newNodes;
00291 for( Range::iterator vit = connecVerts.begin(); vit != connecVerts.end(); ++vit )
00292 {
00293 EntityHandle oldV = *vit;
00294 CartVect posi;
00295 rval = mb->get_coords( &oldV, 1, &( posi[0] ) );MB_CHK_ERR( rval );
00296 int global_id;
00297 rval = mb->tag_get_data( gid, &oldV, 1, &global_id );MB_CHK_ERR( rval );
00298
00299 EntityHandle new_vert;
00300 // duplicate the position
00301 rval = mb->create_vertex( &( posi[0] ), new_vert );MB_CHK_ERR( rval );
00302 newNodes[oldV] = new_vert;
00303
00304 // set also the correspondent tag :)
00305 rval = mb->tag_set_data( corrTag, &oldV, 1, &new_vert );MB_CHK_ERR( rval );
00306 // also the other side
00307 // need to check if we really need this; the new vertex will never need the old vertex
00308 // we have the global id which is the same
00309 rval = mb->tag_set_data( corrTag, &new_vert, 1, &oldV );MB_CHK_ERR( rval );
00310 // set the global id on the corresponding vertex the same as the initial vertex
00311 rval = mb->tag_set_data( gid, &new_vert, 1, &global_id );MB_CHK_ERR( rval );
00312 }
00313
00314 for( Range::iterator it = polys.begin(); it != polys.end(); ++it )
00315 {
00316 EntityHandle q = *it;
00317 int nnodes;
00318 const EntityHandle* conn;
00319 rval = mb->get_connectivity( q, conn, nnodes );MB_CHK_ERR( rval );
00320
00321 int global_id;
00322 rval = mb->tag_get_data( gid, &q, 1, &global_id );MB_CHK_ERR( rval );
00323 EntityType typeElem = mb->type_from_handle( q );
00324 std::vector< EntityHandle > new_conn( nnodes );
00325 for( int i = 0; i < nnodes; i++ )
00326 {
00327 EntityHandle v1 = conn[i];
00328 new_conn[i] = newNodes[v1];
00329 }
00330 EntityHandle newElement;
00331 rval = mb->create_element( typeElem, &new_conn[0], nnodes, newElement );MB_CHK_ERR( rval );
00332
00333 // set the corresponding tag; not sure we need this one, from old to new
00334 rval = mb->tag_set_data( corrTag, &q, 1, &newElement );MB_CHK_ERR( rval );
00335 rval = mb->tag_set_data( corrTag, &newElement, 1, &q );MB_CHK_ERR( rval );
00336
00337 // set the global id
00338 rval = mb->tag_set_data( gid, &newElement, 1, &global_id );MB_CHK_ERR( rval );
00339 rval = mb->add_entities( dest_set, &newElement, 1 );MB_CHK_ERR( rval );
00340 }
00341
00342 return MB_SUCCESS;
00343 }