GRINS-0.8.0
List of all members | Public Member Functions | Private Member Functions | Private Attributes
GRINS::RayfireMesh Class Reference

RayfireMesh. More...

#include <rayfire_mesh.h>

Public Member Functions

 RayfireMesh (libMesh::Point &origin, libMesh::Real theta)
 2D Constructor More...
 
 RayfireMesh (libMesh::Point &origin, libMesh::Real theta, libMesh::Real phi)
 3D Constructor More...
 
 RayfireMesh (const GetPot &input, const std::string &qoi_string)
 Input File Constructor. More...
 
 RayfireMesh (const RayfireMesh &original)
 Copy Constructor. More...
 
void init (const libMesh::MeshBase &mesh_base)
 Initialization. More...
 
const libMesh::Elem * map_to_rayfire_elem (const libMesh::dof_id_type elem_id)
 This function takes in an elem_id on the main mesh and returns an elem from the 1D rayfire mesh. More...
 
void elem_ids_in_rayfire (std::vector< libMesh::dof_id_type > &id_vector) const
 Returns a vector of elem IDs that are currently along the rayfire. More...
 
void reinit (const libMesh::MeshBase &mesh_base)
 Checks for refined and coarsened main mesh elements along the rayfire path. More...
 

Private Member Functions

 RayfireMesh ()
 User should never call the default constructor. More...
 
libMesh::Elem * get_rayfire_elem (const libMesh::dof_id_type elem_id)
 Private function to get a rayfire elem from main_mesh elem ID. More...
 
const libMesh::Elem * get_next_elem (const libMesh::Elem *cur_elem, libMesh::Point &start_point, libMesh::Point &end_point, bool same_parent=false)
 Calculate the intersection point. More...
 
bool check_valid_point (libMesh::Point &intersection_point, libMesh::Point &start_point, const libMesh::Elem &edge_elem, libMesh::Point &next_point)
 Ensure the calculated intersection point is on the edge_elem and is not the start_point. More...
 
const libMesh::Elem * get_correct_neighbor (libMesh::Point &start_point, libMesh::Point &end_point, const libMesh::Elem *cur_elem, unsigned int side, bool same_parent)
 Knowing the end_point, get the appropraite next elem along the path. More...
 
void check_origin_on_boundary (const libMesh::Elem *start_elem)
 Ensure the supplied origin is on a boundary of the mesh. More...
 
const libMesh::Elem * get_start_elem (const libMesh::MeshBase &mesh_base)
 Get the correct starting elem corresponding to _origin. More...
 
bool validate_edge (const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::Elem *side_elem, const libMesh::Elem *neighbor)
 Ensures the rayfire doesn't wander into the middle of an elem. More...
 
bool rayfire_in_elem (const libMesh::Point &end_point, const libMesh::Elem *elem)
 Walks a short distance along the rayfire and checks if elem contains that point. More...
 
bool newton_solve_intersection (libMesh::Point &initial_point, const libMesh::Elem *edge_elem, libMesh::Point &intersection_point)
 Iterative solver for calculating the intersection point of the rayfire on the side of an elem. More...
 
void refine (const libMesh::Elem *main_elem, libMesh::Elem *rayfire_elem)
 Refinement of a rayfire element whose main mesh counterpart was refined. More...
 
void coarsen (const libMesh::Elem *rayfire_elem)
 Coarsening of a rayfire element whose main mesh counterpart was coarsened. More...
 

Private Attributes

const unsigned int _dim
 Dimension of the main mesh. More...
 
libMesh::Point _origin
 Origin point. More...
 
libMesh::Real _theta
 Rayfire Spherical polar angle (in radians) More...
 
libMesh::Real _phi
 Rayfire Spherical azimuthal angle (in radians) More...
 
libMesh::UniquePtr< libMesh::Mesh > _mesh
 Internal 1D mesh of EDGE2 elements. More...
 
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
 Map of main mesh elem_id to rayfire mesh elem_id. More...
 

Detailed Description

RayfireMesh.

This class performs a rayfire across a given mesh. The user supplies an origin point on the mesh boundary, and spherical angle(s) theta (and phi for 3D) to describe the direction of the rayfire. As is standard in spherical coordinates, theta is the angle from the x-axis in the xy-plane, with counterclockwise being positive. -2π ≤ theta ≤ +2π. Phi is the angle from the xy-plane, with phi>0 being in the positive half of the z-plane. -π ≤ phi ≤ +π

Starting at the given origin point, this class will walk in a straight line across the mesh in the prescribed direction. On each element along the line, the class will calculate the point where it enters and leaves that element. Knowing the entering and exiting points, an EDGE2 element is created with those points as nodes, and is added to an internal 1D mesh. This repeats until a main mesh boundary is reached.

The intent of this class is to use the 1D mesh to integrate quantities along the rayfire path. Using the map_to_rayfire_elem() function, a separate integration class can access the 1D elements, prescribe a desired quadrature rule, and perform integration directly along the line, rather than using the entire 2D/3D elements of the main mesh.

Refinement and coarsening of the rayfire mesh are supported through the reinit() function.

Definition at line 65 of file rayfire_mesh.h.

Constructor & Destructor Documentation

GRINS::RayfireMesh::RayfireMesh ( libMesh::Point &  origin,
libMesh::Real  theta 
)

2D Constructor

This is restricted to 2D meshes. The init() function must be called to perform the actual rayfire.

Parameters
originOrigin point (x,y) of the rayfire on mesh boundary
thetaSpherical polar angle (in radians)

Definition at line 51 of file rayfire_mesh.C.

References _theta, and GRINS::Constants::pi.

51  :
52  _dim(2),
53  _origin(origin),
54  _theta(theta),
55  _phi(-7.0) // bounds on angles are +/- 2pi
56  {
57  if (std::abs(_theta) > 2.0*Constants::pi)
58  libmesh_error_msg("Please supply a theta value between -2*pi and 2*pi");
59  }
const libMesh::Real pi
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
const unsigned int _dim
Dimension of the main mesh.
Definition: rayfire_mesh.h:136
libMesh::Real _phi
Rayfire Spherical azimuthal angle (in radians)
Definition: rayfire_mesh.h:145
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
GRINS::RayfireMesh::RayfireMesh ( libMesh::Point &  origin,
libMesh::Real  theta,
libMesh::Real  phi 
)

3D Constructor

This is restricted to 3D meshes. The init() function must be called to perform the actual rayfire.

Parameters
originOrigin point (x,y,z) of the rayfire on mesh boundary
thetaSpherical polar angle (in radians)
phiSpherical azimuthal angle (in radians)

Definition at line 41 of file rayfire_mesh.C.

41  :
42  _dim(3),
43  _origin(origin),
44  _theta(theta),
45  _phi(phi)
46  {
47  libmesh_not_implemented();
48  }
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
const unsigned int _dim
Dimension of the main mesh.
Definition: rayfire_mesh.h:136
libMesh::Real _phi
Rayfire Spherical azimuthal angle (in radians)
Definition: rayfire_mesh.h:145
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
GRINS::RayfireMesh::RayfireMesh ( const GetPot &  input,
const std::string &  qoi_string 
)

Input File Constructor.

Creates rayfire from parameters specified in input file section: QoI/'qoi_string'/Rayfire/

Definition at line 61 of file rayfire_mesh.C.

References _origin, _theta, and GRINS::Constants::pi.

61  :
62  _dim(2),
63  _phi(-7.0)
64  {
65  unsigned int rayfire_dim = input.vector_variable_size("QoI/"+qoi_string+"/Rayfire/origin");
66 
67  if (rayfire_dim != 2)
68  libmesh_error_msg("ERROR: Only 2D Rayfires are currently supported");
69 
70  if (!input.have_variable("QoI/"+qoi_string+"/Rayfire/origin"))
71  libmesh_error_msg("ERROR: No origin specified for Rayfire");
72 
73  if (input.vector_variable_size("QoI/"+qoi_string+"/Rayfire/origin") != 2)
74  libmesh_error_msg("ERROR: Please specify a 2D point (x,y) for the rayfire origin");
75 
76  libMesh::Point origin;
77  _origin(0) = input("QoI/"+qoi_string+"/Rayfire/origin", 0.0, 0);
78  _origin(1) = input("QoI/"+qoi_string+"/Rayfire/origin", 0.0, 1);
79 
80  if (input.have_variable("QoI/"+qoi_string+"/Rayfire/theta"))
81  _theta = input("QoI/"+qoi_string+"/Rayfire/theta", -7.0);
82  else
83  libmesh_error_msg("ERROR: Spherical polar angle theta must be given for Rayfire");
84 
85  if (std::abs(_theta) > 2.0*Constants::pi)
86  libmesh_error_msg("Please supply a theta value between -2*pi and 2*pi");
87 
88  if (input.have_variable("QoI/"+qoi_string+"/Rayfire/phi"))
89  libmesh_error_msg("ERROR: cannot specify spherical azimuthal angle phi for Rayfire, only 2D is currently supported");
90  }
const libMesh::Real pi
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
const unsigned int _dim
Dimension of the main mesh.
Definition: rayfire_mesh.h:136
libMesh::Real _phi
Rayfire Spherical azimuthal angle (in radians)
Definition: rayfire_mesh.h:145
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
GRINS::RayfireMesh::RayfireMesh ( const RayfireMesh original)

Copy Constructor.

Required to deep-copy _mesh and _elem_id_map

Definition at line 92 of file rayfire_mesh.C.

References _elem_id_map, and _mesh.

92  :
93  _dim(original._dim),
94  _origin(original._origin),
95  _theta(original._theta),
96  _phi(original._phi)
97  {
98  if (original._mesh.get())
99  this->_mesh.reset( new libMesh::Mesh( *((original._mesh).get()) ) );
100 
101  this->_elem_id_map = original._elem_id_map;
102  }
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
const unsigned int _dim
Dimension of the main mesh.
Definition: rayfire_mesh.h:136
libMesh::Real _phi
Rayfire Spherical azimuthal angle (in radians)
Definition: rayfire_mesh.h:145
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
GRINS::RayfireMesh::RayfireMesh ( )
private

User should never call the default constructor.

Member Function Documentation

void GRINS::RayfireMesh::check_origin_on_boundary ( const libMesh::Elem *  start_elem)
private

Ensure the supplied origin is on a boundary of the mesh.

Definition at line 247 of file rayfire_mesh.C.

References _origin.

Referenced by init().

248  {
249  libmesh_assert(start_elem);
250 
251  // first, make sure the elem is on a boundary
252  if ( !(start_elem->on_boundary()) )
253  libmesh_error_msg("The supplied origin point is not on a boundary element");
254 
255  // second, check all boundary sides of the elem
256  // to see if one of them conatins the origin point
257  bool valid = false;
258 
259  for (unsigned int s=0; s<start_elem->n_sides(); s++)
260  {
261  // neighbor_ptr() returns NULL on boundary elems
262  if ( start_elem->neighbor_ptr(s) )
263  continue;
264 
265  // we found a boundary elem, so make an edge and see if it contains the origin
266  libMesh::UniquePtr<const libMesh::Elem> edge_elem = start_elem->build_edge_ptr(s);
267  valid |= edge_elem->contains_point(_origin);
268  }
269 
270  if (!valid)
271  libmesh_error_msg("The supplied origin point is not on the boundary of the starting element");
272  }
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
bool GRINS::RayfireMesh::check_valid_point ( libMesh::Point &  intersection_point,
libMesh::Point &  start_point,
const libMesh::Elem &  edge_elem,
libMesh::Point &  next_point 
)
private

Ensure the calculated intersection point is on the edge_elem and is not the start_point.

Definition at line 355 of file rayfire_mesh.C.

Referenced by get_next_elem().

356  {
357  bool is_not_start = !(intersection_point.absolute_fuzzy_equals(start_point));
358  bool is_on_edge = edge_elem.contains_point(intersection_point);
359 
360  bool is_valid = is_not_start && is_on_edge;
361 
362  if ( is_valid )
363  {
364  next_point(0) = intersection_point(0);
365  next_point(1) = intersection_point(1);
366  }
367 
368  return is_valid;
369  }
void GRINS::RayfireMesh::coarsen ( const libMesh::Elem *  rayfire_elem)
private

Coarsening of a rayfire element whose main mesh counterpart was coarsened.

Definition at line 731 of file rayfire_mesh.C.

References _elem_id_map, _mesh, _origin, and get_rayfire_elem().

Referenced by reinit().

732  {
733  libmesh_assert(child_elem);
734 
735  if (this->get_rayfire_elem(child_elem->id()))
736  {
737  const libMesh::Elem* parent_elem = child_elem->parent();
738  libmesh_assert(parent_elem);
739 
740  const libMesh::Node* start_node = NULL;
741  const libMesh::Node* end_node = NULL;
742 
743  for (unsigned int c=0; c<parent_elem->n_children(); c++)
744  {
745  libMesh::Elem* rayfire_child = this->get_rayfire_elem(parent_elem->child_ptr(c)->id());
746 
747  if (rayfire_child)
748  {
749  if (!start_node)
750  {
751  start_node = rayfire_child->node_ptr(0);
752  end_node = rayfire_child->node_ptr(1);
753  }
754  else
755  {
756  if ( (this->_origin - *(rayfire_child->node_ptr(0))).norm() < (this->_origin - *start_node).norm() )
757  start_node = rayfire_child->node_ptr(0);
758 
759  if ( (this->_origin - *(rayfire_child->node_ptr(1))).norm() > (this->_origin - *end_node).norm() )
760  end_node = rayfire_child->node_ptr(1);
761  }
762 
763  rayfire_child->set_refinement_flag(libMesh::Elem::RefinementState::INACTIVE);
764  }
765  } // for c
766 
767  // make sure we found nodes
768  libmesh_assert(start_node);
769  libmesh_assert(end_node);
770 
771  // add a new rayfire elem
772  libMesh::Elem* elem = _mesh->add_elem(new libMesh::Edge2);
773  elem->set_node(0) = _mesh->node_ptr(start_node->id());
774  elem->set_node(1) = _mesh->node_ptr(end_node->id());
775 
776  libmesh_assert_less( (*(elem->node_ptr(0))-_origin).norm(), (*(elem->node_ptr(1))-_origin).norm());
777 
778  // add new rayfire elem to the map
779  _elem_id_map[parent_elem->id()] = elem->id();
780  }
781 
782  }
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
libMesh::Elem * get_rayfire_elem(const libMesh::dof_id_type elem_id)
Private function to get a rayfire elem from main_mesh elem ID.
Definition: rayfire_mesh.C:308
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
void GRINS::RayfireMesh::elem_ids_in_rayfire ( std::vector< libMesh::dof_id_type > &  id_vector) const

Returns a vector of elem IDs that are currently along the rayfire.

Definition at line 187 of file rayfire_mesh.C.

References _elem_id_map, and _mesh.

188  {
189  std::map<libMesh::dof_id_type,libMesh::dof_id_type>::const_iterator it = _elem_id_map.begin();
190  for(; it != _elem_id_map.end(); it++)
191  {
192  if (_mesh->elem_ptr(it->second)->active())
193  id_vector.push_back(it->first);
194  }
195  }
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
const libMesh::Elem * GRINS::RayfireMesh::get_correct_neighbor ( libMesh::Point &  start_point,
libMesh::Point &  end_point,
const libMesh::Elem *  cur_elem,
unsigned int  side,
bool  same_parent 
)
private

Knowing the end_point, get the appropraite next elem along the path.

Definition at line 432 of file rayfire_mesh.C.

References rayfire_in_elem(), and validate_edge().

Referenced by get_next_elem().

433  {
434  libmesh_assert(cur_elem);
435  libmesh_assert(cur_elem->active());
436 
437  const libMesh::Elem * neighbor = cur_elem->neighbor_ptr(side);
438 
439  // a valid neighbor is an ACTIVE elem or null
440  bool is_valid = true;
441  if (neighbor)
442  is_valid = neighbor->active();
443 
444  if (is_valid)
445  {
446  // check if the intersection point is a vertex
447  bool is_vertex = false;
448  const libMesh::Node * vertex = NULL;
449  for(unsigned int n=0; n<cur_elem->n_nodes(); n++)
450  {
451  if ((cur_elem->node_ptr(n))->absolute_fuzzy_equals(end_point))
452  {
453  is_vertex = true;
454  vertex = cur_elem->node_ptr(n);
455  break;
456  }
457  }
458 
459  if (is_vertex)
460  {
461  // rayfire goes through vertex
462 
463  // check elem neighbors first
464  for (unsigned int s=0; s<cur_elem->n_sides(); s++)
465  {
466  libMesh::UniquePtr<const libMesh::Elem> side_elem = cur_elem->build_side_ptr(s);
467  if (side_elem->contains_point(end_point))
468  {
469  const libMesh::Elem * neighbor = cur_elem->neighbor_ptr(s);
470  if (!neighbor)
471  continue;
472 
473  if (same_parent)
474  {
475  if (neighbor->parent())
476  {
477  if (neighbor->parent()->id() != cur_elem->parent()->id())
478  continue;
479  else
480  if (this->rayfire_in_elem(end_point,neighbor))
481  if (this->validate_edge(start_point,end_point,side_elem.get(),neighbor))
482  return neighbor;
483  }
484  else
485  continue;
486  }
487  else
488  if (this->rayfire_in_elem(end_point,neighbor))
489  if (this->validate_edge(start_point,end_point,side_elem.get(),neighbor))
490  return neighbor;
491  }
492  }
493 
494  // next elem is not a neighbor,
495  // so get all elems that share this vertex
496  std::set<const libMesh::Elem*> elem_set;
497  cur_elem->find_point_neighbors(*vertex,elem_set);
498  std::set<const libMesh::Elem *>::const_iterator it = elem_set.begin();
499  const std::set<const libMesh::Elem *>::const_iterator end = elem_set.end();
500 
501  // iterate over each elem
502  for (; it != end; ++it)
503  {
504  const libMesh::Elem* elem = *it;
505 
506  if (elem == cur_elem) // skip the current elem
507  continue;
508 
509  if (this->rayfire_in_elem(end_point,elem))
510  return elem;
511  }
512 
513  }
514  else
515  {
516  // check if side is a boundary
517  if( !(cur_elem->neighbor_ptr(side)) )
518  return NULL;
519 
520  // not a vertex or boundary, so just get the elem on that side
521  return cur_elem->neighbor_ptr(side);
522  }
523  } // if (is_valid)
524  else
525  {
526  for (unsigned int c=0; c<neighbor->n_children(); c++)
527  {
528  const libMesh::Elem * child = neighbor->child_ptr(c);
529 
530  if (child->contains_point(end_point))
531  if (this->rayfire_in_elem(end_point,child))
532  return child;
533  }
534  // could not find a valid child elem, so we return NULL below
535  }
536 
537  return NULL;
538  }
bool validate_edge(const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::Elem *side_elem, const libMesh::Elem *neighbor)
Ensures the rayfire doesn't wander into the middle of an elem.
Definition: rayfire_mesh.C:392
bool rayfire_in_elem(const libMesh::Point &end_point, const libMesh::Elem *elem)
Walks a short distance along the rayfire and checks if elem contains that point.
Definition: rayfire_mesh.C:372
const libMesh::Elem * GRINS::RayfireMesh::get_next_elem ( const libMesh::Elem *  cur_elem,
libMesh::Point &  start_point,
libMesh::Point &  end_point,
bool  same_parent = false 
)
private

Calculate the intersection point.

Parameters
[out]end_pointThe intersection point in (x,y) coordinates
Returns
Elem* if intersection is found
NULL if no intersection point found (i.e. start_point is on a boundary)

Definition at line 323 of file rayfire_mesh.C.

References check_valid_point(), get_correct_neighbor(), and newton_solve_intersection().

Referenced by init(), and refine().

324  {
325  libmesh_assert(cur_elem);
326 
327  libMesh::Point intersection_point;
328 
329  // loop over all sides of the elem and check each one for intersection
330  for (unsigned int s=0; s<cur_elem->n_sides(); s++)
331  {
332  libMesh::UniquePtr<const libMesh::Elem> edge_elem = cur_elem->build_edge_ptr(s);
333 
334  // Using the default tol can cause a false positive when start_point is near a node,
335  // causing this loop to skip over an otherwise valid edge to check
336  if (edge_elem->contains_point(start_point,libMesh::TOLERANCE*0.1))
337  continue;
338 
339  bool converged = this->newton_solve_intersection(start_point,edge_elem.get(),intersection_point);
340 
341  if (converged)
342  {
343  if ( this->check_valid_point(intersection_point,start_point,*edge_elem,next_point) )
344  return this->get_correct_neighbor(start_point,intersection_point,cur_elem,s,same_parent);
345  }
346  else
347  continue;
348 
349  } // for s
350 
351  return NULL; // no intersection
352  }
bool check_valid_point(libMesh::Point &intersection_point, libMesh::Point &start_point, const libMesh::Elem &edge_elem, libMesh::Point &next_point)
Ensure the calculated intersection point is on the edge_elem and is not the start_point.
Definition: rayfire_mesh.C:355
const libMesh::Elem * get_correct_neighbor(libMesh::Point &start_point, libMesh::Point &end_point, const libMesh::Elem *cur_elem, unsigned int side, bool same_parent)
Knowing the end_point, get the appropraite next elem along the path.
Definition: rayfire_mesh.C:432
bool newton_solve_intersection(libMesh::Point &initial_point, const libMesh::Elem *edge_elem, libMesh::Point &intersection_point)
Iterative solver for calculating the intersection point of the rayfire on the side of an elem...
Definition: rayfire_mesh.C:541
libMesh::Elem * GRINS::RayfireMesh::get_rayfire_elem ( const libMesh::dof_id_type  elem_id)
private

Private function to get a rayfire elem from main_mesh elem ID.

Does not return a const pointer, and is used within this class to simplify rayfire elem access.

Also used by map_to_rayfire_elem(), which adds a const to prevent modification outside this class.

Definition at line 308 of file rayfire_mesh.C.

References _elem_id_map, and _mesh.

Referenced by coarsen(), and map_to_rayfire_elem().

309  {
310  // return value; set if valid rayfire elem is found
311  libMesh::Elem* retval = NULL;
312 
313  std::map<libMesh::dof_id_type,libMesh::dof_id_type>::iterator it;
314  it = _elem_id_map.find(elem_id);
315  if (it != _elem_id_map.end())
316  if (_mesh->elem_ptr(it->second)->refinement_flag() != libMesh::Elem::RefinementState::INACTIVE)
317  retval = _mesh->elem_ptr(it->second);
318 
319  return retval;
320  }
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
const libMesh::Elem * GRINS::RayfireMesh::get_start_elem ( const libMesh::MeshBase &  mesh_base)
private

Get the correct starting elem corresponding to _origin.

Returns
NULL Origin is not on the mesh
Elem* First elem on the rayfire

Definition at line 275 of file rayfire_mesh.C.

References _origin, and rayfire_in_elem().

Referenced by init().

276  {
277  const libMesh::Elem* start_elem = NULL;
278 
279  libMesh::UniquePtr<libMesh::PointLocatorBase> locator = mesh_base.sub_point_locator();
280  const libMesh::Elem* elem = (*locator)(_origin);
281 
282  // elem would be NULL if origin is not on mesh
283  if (elem)
284  {
285  if (this->rayfire_in_elem(_origin,elem))
286  start_elem = elem;
287  else
288  {
289  for (unsigned int i=0; i<elem->n_neighbors(); i++)
290  {
291  const libMesh::Elem* neighbor_elem = elem->neighbor_ptr(i);
292  if (!neighbor_elem)
293  continue;
294 
295  if (this->rayfire_in_elem(_origin,neighbor_elem))
296  {
297  start_elem = neighbor_elem;
298  break;
299  }
300  }
301  }
302  }
303 
304  return start_elem; // might be NULL if _origin is not on mesh
305  }
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
bool rayfire_in_elem(const libMesh::Point &end_point, const libMesh::Elem *elem)
Walks a short distance along the rayfire and checks if elem contains that point.
Definition: rayfire_mesh.C:372
void GRINS::RayfireMesh::init ( const libMesh::MeshBase &  mesh_base)

Initialization.

This function performs the rayfire and assembles the 1D mesh. Call this immediately after the constructor. Must be called before any refinements of the main mesh.

Parameters
mesh_baseReference to the main mesh

Definition at line 104 of file rayfire_mesh.C.

References _dim, _elem_id_map, _mesh, _origin, check_origin_on_boundary(), get_next_elem(), and get_start_elem().

105  {
106  // consistency check
107  if(mesh_base.mesh_dimension() != _dim)
108  {
109  std::stringstream ss;
110  ss <<"The supplied mesh object is " <<mesh_base.mesh_dimension()
111  <<"D, but the RayfireMesh object was created with the "
112  <<_dim <<"D constructor";
113 
114  libmesh_error_msg(ss.str());
115  }
116 
117  _mesh.reset( new libMesh::Mesh(mesh_base.comm(),(unsigned char)1) );
118 
119  libMesh::Point start_point(_origin);
120 
121  // get first element
122  const libMesh::Elem* start_elem = this->get_start_elem(mesh_base);
123 
124  if (!start_elem)
125  libmesh_error_msg("Origin is not on mesh");
126 
127  // ensure the origin is on a boundary element
128  // AND on the boundary of said element
129  this->check_origin_on_boundary(start_elem);
130 
131  // add the origin point to the point list
132  libMesh::Node * start_node = _mesh->add_point(start_point);
133  libMesh::Node * end_node = NULL;
134 
135  libMesh::Point end_point;
136 
137  const libMesh::Elem* next_elem;
138  const libMesh::Elem* prev_elem = start_elem;
139 
140  do
141  {
142  // calculate the end point and
143  // get the next elem in the rayfire
144  next_elem = this->get_next_elem(prev_elem,start_point,end_point);
145 
146 #ifndef NDEBUG
147  // make sure we are only picking up active elements
148  if (next_elem)
149  libmesh_assert( next_elem->active() );
150 #endif
151 
152  // add end point as node on the rayfire mesh
153  end_node = _mesh->add_point(end_point);
154  libMesh::Elem* elem = _mesh->add_elem(new libMesh::Edge2);
155  elem->set_node(0) = start_node;
156  elem->set_node(1) = end_node;
157 
158  // warn if rayfire elem is shorter than TOLERANCE
159  if ( (start_point-end_point).norm() < libMesh::TOLERANCE)
160  {
161  std::stringstream ss;
162  ss <<"********\n"
163  <<"WARNING\n"
164  <<"Detected rayfire element shorter than TOLERANCE\n"
165  <<"Element ID: " <<prev_elem->id() <<", rayfire element length: " <<(start_point-end_point).norm();
166 
167  libmesh_warning(ss.str());
168  }
169 
170  // add new rayfire elem to the map
171  _elem_id_map[prev_elem->id()] = elem->id();
172 
173  start_point = end_point;
174  start_node = end_node;
175  prev_elem = next_elem;
176  } while(next_elem);
177 
178  }
const libMesh::Elem * get_next_elem(const libMesh::Elem *cur_elem, libMesh::Point &start_point, libMesh::Point &end_point, bool same_parent=false)
Calculate the intersection point.
Definition: rayfire_mesh.C:323
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
const libMesh::Elem * get_start_elem(const libMesh::MeshBase &mesh_base)
Get the correct starting elem corresponding to _origin.
Definition: rayfire_mesh.C:275
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
const unsigned int _dim
Dimension of the main mesh.
Definition: rayfire_mesh.h:136
void check_origin_on_boundary(const libMesh::Elem *start_elem)
Ensure the supplied origin is on a boundary of the mesh.
Definition: rayfire_mesh.C:247
const libMesh::Elem * GRINS::RayfireMesh::map_to_rayfire_elem ( const libMesh::dof_id_type  elem_id)

This function takes in an elem_id on the main mesh and returns an elem from the 1D rayfire mesh.

Parameters
elem_idThe ID of the elem on the main mesh
Returns
Elem* to 1D elem from the rayfire mesh if the elem_id falls along the rayfire path
NULL if the given elem_id does not correspond to an elem through which the rayfire passes

Definition at line 181 of file rayfire_mesh.C.

References get_rayfire_elem().

182  {
183  return this->get_rayfire_elem(elem_id);
184  }
libMesh::Elem * get_rayfire_elem(const libMesh::dof_id_type elem_id)
Private function to get a rayfire elem from main_mesh elem ID.
Definition: rayfire_mesh.C:308
bool GRINS::RayfireMesh::newton_solve_intersection ( libMesh::Point &  initial_point,
const libMesh::Elem *  edge_elem,
libMesh::Point &  intersection_point 
)
private

Iterative solver for calculating the intersection point of the rayfire on the side of an elem.

The rayfire line can be represented in point-slope form:

y-y0 = m(x-x0)

where m is the slope and (x0,y0) is the known initial_point. To find the intersection point, we will use a parametric representation of the edge utilizing the shape functions as such:

X(ξ) = sum( xj φj(ξ) )

Y(ξ) = sum( yj φj(ξ) )

where xj and yj are the node x- and y-coordinates, respectively, and φj is the value of shape function j at reference coordinate ξ

The intersection point is then where the x and y coordinates from the point-slope equation equal the X and Y coordinates from the parametric equations for the given edge, respectively. We can then form a residual by substituting the parametric coordinates into the point slope form and bringing all terms to one side of the equation as:

f = 0 = m(X(ξ)-x0) - (Y(ξ)-y0)

The residual is then a function of a single parameter, namely the reference coordinate ξ. The derivative is rather trivial and can be expressed as

df = m*dX - dY

where

dX = sum( xjj/dξ )

dY = sum( yjj/dξ )

Parameters
[out]intersection_pointThe calculated intersection point (only set if convergence is achieved)
Returns
Whether or not the solver converged before hitting the iteration limit

Definition at line 541 of file rayfire_mesh.C.

References _theta.

Referenced by get_next_elem().

542  {
543  libmesh_assert(edge_elem);
544 
545  unsigned int iter_max = 20; // max iterations
546 
547  // the number of shape functions needed for the edge_elem
548  unsigned int n_sf = libMesh::FE<1,libMesh::LAGRANGE>::n_shape_functions(edge_elem->type(),edge_elem->default_order());
549 
550  // starting point on the elem
551  libMesh::Real x0 = initial_point(0);
552  libMesh::Real y0 = initial_point(1);
553 
554  // shape functions and derivatives w.r.t reference coordinate
555  std::vector<libMesh::Real> phi(n_sf);
556  std::vector<libMesh::Real> dphi(n_sf);
557 
558  // Newton iteration step
559  libMesh::Real d_xi;
560 
561  // tan(theta) is the slope, so precompute since it is used repeatedly
562  libMesh::Real tan_theta = std::tan(_theta);
563 
564  // Initial guess is center of the edge_elem
565  libMesh::Real xi = 0.0;
566 
567  // Newton iteration
568  for(unsigned int it=0; it<iter_max; it++)
569  {
570  // Get the shape function and derivative values at the reference coordinate
571  // phi.size() == dphi.size()
572  for(unsigned int i=0; i<phi.size(); i++)
573  {
574  phi[i] = libMesh::FE<1,libMesh::LAGRANGE>::shape(edge_elem->type(),
575  edge_elem->default_order(),
576  i,
577  xi);
578 
579  dphi[i] = libMesh::FE<1,libMesh::LAGRANGE>::shape_deriv(edge_elem->type(),
580  edge_elem->default_order(),
581  i,
582  0, // const unsigned int libmesh_dbg_varj
583  xi);
584  } // for i
585 
586  libMesh::Real X=0.0, Y=0.0, dX=0.0, dY=0.0;
587 
588  for(unsigned int i=0; i<phi.size(); i++)
589  {
590  X += (*(edge_elem->node_ptr(i)))(0) * phi[i];
591  dX += (*(edge_elem->node_ptr(i)))(0) * dphi[i];
592  Y += (*(edge_elem->node_ptr(i)))(1) * phi[i];
593  dY += (*(edge_elem->node_ptr(i)))(1) * dphi[i];
594  }
595 
596  libMesh::Real f = tan_theta*(X-x0) - (Y-y0);
597  libMesh::Real df = tan_theta*(dX) - dY;
598 
599  d_xi = f/df;
600 
601  if(std::abs(d_xi) < libMesh::TOLERANCE)
602  {
603  // convergence
604  intersection_point(0) = X;
605  intersection_point(1) = Y;
606  return true;
607  }
608  else
609  xi -= d_xi;
610 
611  } // for it
612 
613  // no convergence
614  return false;
615  }
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
bool GRINS::RayfireMesh::rayfire_in_elem ( const libMesh::Point &  end_point,
const libMesh::Elem *  elem 
)
private

Walks a short distance along the rayfire and checks if elem contains that point.

Definition at line 372 of file rayfire_mesh.C.

References _theta.

Referenced by get_correct_neighbor(), get_start_elem(), and refine().

373  {
374  libmesh_assert(elem);
375 
376  // move a little bit along the rayfire and see if we are still in the elem
377  // need to move more than TOLERANCE to avoid false positive on contains_point()
378  libMesh::Real L = 2*libMesh::TOLERANCE;
379 
380  // If the elem is too small, need to shorten L so we stay within the elem
381  if ( elem->hmin() < libMesh::TOLERANCE )
382  L = elem->hmin() * 0.1;
383 
384  // parametric representation of rayfire line
385  libMesh::Real x = end_point(0) + L*std::cos(_theta);
386  libMesh::Real y = end_point(1) + L*std::sin(_theta);
387 
388  return elem->contains_point(libMesh::Point(x,y));
389  }
libMesh::Real _theta
Rayfire Spherical polar angle (in radians)
Definition: rayfire_mesh.h:142
void GRINS::RayfireMesh::refine ( const libMesh::Elem *  main_elem,
libMesh::Elem *  rayfire_elem 
)
private

Refinement of a rayfire element whose main mesh counterpart was refined.

Definition at line 618 of file rayfire_mesh.C.

References _elem_id_map, _mesh, _origin, get_next_elem(), and rayfire_in_elem().

Referenced by reinit().

619  {
620  libmesh_assert(main_elem);
621  libmesh_assert(rayfire_elem);
622 
623  libmesh_assert_equal_to(main_elem->refinement_flag(),libMesh::Elem::RefinementState::INACTIVE);
624 
625  // these nodes cannot change
626  libMesh::Node* start_node = rayfire_elem->node_ptr(0);
627  libMesh::Node* end_node = rayfire_elem->node_ptr(1);
628 
629  // set the rayfire_elem as INACTIVE
630  rayfire_elem->set_refinement_flag(libMesh::Elem::RefinementState::INACTIVE);
631 
632  // find which child elem we start with
633  libMesh::dof_id_type start_child = libMesh::invalid_uint;
634  for(unsigned int i=0; i<main_elem->n_children(); i++)
635  {
636  if ( (main_elem->child_ptr(i))->contains_point(*start_node) )
637  {
638  // check if the start point is a vertex
639  bool is_vertex = false;
640  for(unsigned int n=0; n<main_elem->child_ptr(i)->n_nodes(); n++)
641  {
642  if ((main_elem->child_ptr(i)->node_ptr(n))->absolute_fuzzy_equals(*start_node))
643  {
644  is_vertex = true;
645  break;
646  }
647  }
648 
649  if (is_vertex)
650  {
651  if ( this->rayfire_in_elem(*start_node, main_elem->child_ptr(i)) )
652  {
653  start_child = i;
654  break;
655  }
656  }
657  else
658  {
659  start_child = i;
660  break;
661  }
662  }
663  }
664 
665  // make sure we found a starting child elem
666  libmesh_assert_not_equal_to(start_child,libMesh::invalid_uint);
667 
668  // we found the starting element, so perform the rayfire
669  // until we reach the stored end_node
670  libMesh::Point start_point = *start_node;
671  libMesh::Point end_point;
672 
673  const libMesh::Elem* next_elem;
674  const libMesh::Elem* prev_elem = main_elem->child_ptr(start_child);
675 
676  // if prev_elem is INACTIVE, then more than one refinement
677  // has taken place between reinit() calls and will
678  // break this
679  libmesh_assert_equal_to( prev_elem->refinement_flag(), libMesh::Elem::RefinementState::JUST_REFINED );
680 
681  libMesh::Node * prev_node = start_node;
682  libMesh::Node * new_node = NULL;
683 
684  // iterate until we reach the stored end_node
685  do
686  {
687  next_elem = this->get_next_elem(prev_elem,start_point,end_point,true);
688 
689 #ifndef NDEBUG
690  // make sure we are only picking up active elements
691  if (next_elem)
692  libmesh_assert( next_elem->active() );
693 #endif
694 
695  // add end point as node on the rayfire mesh
696  new_node = _mesh->add_point(end_point);
697  libMesh::Elem* elem = _mesh->add_elem(new libMesh::Edge2);
698 
699  elem->set_node(0) = prev_node;
700  elem->set_node(1) = new_node;
701 
702  libmesh_assert_less( (*(elem->node_ptr(0))-_origin).norm(), (*(elem->node_ptr(1))-_origin).norm());
703 
704  // warn if rayfire elem is shorter than TOLERANCE
705  if ( (start_point-end_point).norm() < libMesh::TOLERANCE)
706  {
707  std::stringstream ss;
708  ss <<"********\n"
709  <<"WARNING\n"
710  <<"Detected rayfire element shorter than TOLERANCE on refinement\n"
711  <<"Element ID: " <<prev_elem->id() <<", rayfire element length: " <<(start_point-end_point).norm();
712 
713  libmesh_warning(ss.str());
714  }
715 
716  // set rayfire_elem as the parent of this new elem
717  // in case it gets coarsened
718  elem->set_parent(rayfire_elem);
719 
720  // add new rayfire elem to the map
721  _elem_id_map[prev_elem->id()] = elem->id();
722  start_point = end_point;
723  prev_elem = next_elem;
724  prev_node = new_node;
725 
726  } while(!(new_node->absolute_fuzzy_equals(*end_node)));
727 
728  }
const libMesh::Elem * get_next_elem(const libMesh::Elem *cur_elem, libMesh::Point &start_point, libMesh::Point &end_point, bool same_parent=false)
Calculate the intersection point.
Definition: rayfire_mesh.C:323
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
libMesh::Point _origin
Origin point.
Definition: rayfire_mesh.h:139
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
bool rayfire_in_elem(const libMesh::Point &end_point, const libMesh::Elem *elem)
Walks a short distance along the rayfire and checks if elem contains that point.
Definition: rayfire_mesh.C:372
void GRINS::RayfireMesh::reinit ( const libMesh::MeshBase &  mesh_base)

Checks for refined and coarsened main mesh elements along the rayfire path.

They are then passed to refine() and coarsen(), respectively, to update the rayfire mesh.

Only 1 level of refinement and/or coarsening can be done between reinit() calls. Note that this is not limited to doing either refinement or coarsening between reinits. Both can be done on different elements, as long as they are only 1 level in either direction.

Parameters
meshreference to main mesh, needed to get Elem* from the stored elem_id's

Definition at line 198 of file rayfire_mesh.C.

References _elem_id_map, _mesh, coarsen(), and refine().

199  {
200  // store the elems to be refined until later
201  // so we don't mess with the _elem_id_map while we
202  // iterate over it
203  std::vector<std::pair<const libMesh::Elem*,libMesh::Elem*> > elems_to_refine;
204 
205  // same with elems to coarsen
206  // store the main_mesh elem
207  std::vector<const libMesh::Elem*> elems_to_coarsen;
208 
209  // iterate over all main elems along the rayfire and look for
210  // refinement: INACTIVE parent with JUST_REFINED children
211  // coarsening: JUST_COARSENED parent
212  std::map<libMesh::dof_id_type,libMesh::dof_id_type>::iterator it = _elem_id_map.begin();
213  for(; it != _elem_id_map.end(); it++)
214  {
215  const libMesh::Elem* main_elem = mesh_base.elem_ptr(it->first);
216  libmesh_assert(main_elem);
217 
218  if (main_elem->parent())
219  {
220  if (main_elem->parent()->refinement_flag() == libMesh::Elem::RefinementState::JUST_COARSENED)
221  elems_to_coarsen.push_back(main_elem);
222  }
223 
224  libMesh::Elem::RefinementState state = main_elem->refinement_flag();
225 
226  if (state == libMesh::Elem::RefinementState::INACTIVE)
227  {
228  if (main_elem->has_children())
229  if (main_elem->child_ptr(0)->refinement_flag() == libMesh::Elem::RefinementState::JUST_REFINED)
230  elems_to_refine.push_back(std::pair<const libMesh::Elem*, libMesh::Elem*>(main_elem,_mesh->elem_ptr(it->second)));
231  }
232  }
233 
234  // refine the elements that need it
235  for (unsigned int i=0; i<elems_to_refine.size(); i++)
236  this->refine(elems_to_refine[i].first, elems_to_refine[i].second);
237 
238  // coarsen the elements that need it
239  for (unsigned int i=0; i<elems_to_coarsen.size(); i++)
240  this->coarsen(elems_to_coarsen[i]);
241 
242  }
void coarsen(const libMesh::Elem *rayfire_elem)
Coarsening of a rayfire element whose main mesh counterpart was coarsened.
Definition: rayfire_mesh.C:731
void refine(const libMesh::Elem *main_elem, libMesh::Elem *rayfire_elem)
Refinement of a rayfire element whose main mesh counterpart was refined.
Definition: rayfire_mesh.C:618
libMesh::UniquePtr< libMesh::Mesh > _mesh
Internal 1D mesh of EDGE2 elements.
Definition: rayfire_mesh.h:148
std::map< libMesh::dof_id_type, libMesh::dof_id_type > _elem_id_map
Map of main mesh elem_id to rayfire mesh elem_id.
Definition: rayfire_mesh.h:151
bool GRINS::RayfireMesh::validate_edge ( const libMesh::Point &  start_point,
const libMesh::Point &  end_point,
const libMesh::Elem *  side_elem,
const libMesh::Elem *  neighbor 
)
private

Ensures the rayfire doesn't wander into the middle of an elem.

Definition at line 392 of file rayfire_mesh.C.

Referenced by get_correct_neighbor().

393  {
394  bool is_valid = true;
395 
396  const libMesh::Node * node0 = side_elem->node_ptr(0);
397  const libMesh::Node * node1 = side_elem->node_ptr(1);
398 
399  unsigned int side = libMesh::invalid_uint;
400 
401  for (unsigned int s=0; s<neighbor->n_sides(); s++)
402  {
403  libMesh::UniquePtr<const libMesh::Elem> side_elem = neighbor->build_side_ptr(s);
404 
405  if ( (side_elem->contains_point(*node0)) && (side_elem->contains_point(*node1)) )
406  {
407  side = s;
408  break;
409  }
410  }
411 
412  if ( side != libMesh::invalid_uint )
413  {
414  libMesh::UniquePtr<const libMesh::Elem> edge_elem = neighbor->build_side_ptr(side);
415 
416  bool start_point_on_edge = edge_elem->contains_point(start_point);
417  bool end_point_on_edge = edge_elem->contains_point(end_point);
418 
419  if ( end_point_on_edge && start_point_on_edge )
420  {
421  bool l_to_r = ( start_point.absolute_fuzzy_equals(*(edge_elem->node_ptr(0))) ) && ( end_point.absolute_fuzzy_equals(*(edge_elem->node_ptr(1))) );
422  bool r_to_l = ( end_point.absolute_fuzzy_equals(*(edge_elem->node_ptr(0))) ) && ( start_point.absolute_fuzzy_equals(*(edge_elem->node_ptr(1))) );
423 
424  is_valid &= ( l_to_r || r_to_l );
425  }
426  }
427 
428  return is_valid;
429  }

Member Data Documentation

const unsigned int GRINS::RayfireMesh::_dim
private

Dimension of the main mesh.

Definition at line 136 of file rayfire_mesh.h.

Referenced by init().

std::map<libMesh::dof_id_type,libMesh::dof_id_type> GRINS::RayfireMesh::_elem_id_map
private

Map of main mesh elem_id to rayfire mesh elem_id.

Definition at line 151 of file rayfire_mesh.h.

Referenced by coarsen(), elem_ids_in_rayfire(), get_rayfire_elem(), init(), RayfireMesh(), refine(), and reinit().

libMesh::UniquePtr<libMesh::Mesh> GRINS::RayfireMesh::_mesh
private

Internal 1D mesh of EDGE2 elements.

Definition at line 148 of file rayfire_mesh.h.

Referenced by coarsen(), elem_ids_in_rayfire(), get_rayfire_elem(), init(), RayfireMesh(), refine(), and reinit().

libMesh::Point GRINS::RayfireMesh::_origin
private

Origin point.

Definition at line 139 of file rayfire_mesh.h.

Referenced by check_origin_on_boundary(), coarsen(), get_start_elem(), init(), RayfireMesh(), and refine().

libMesh::Real GRINS::RayfireMesh::_phi
private

Rayfire Spherical azimuthal angle (in radians)

Definition at line 145 of file rayfire_mesh.h.

libMesh::Real GRINS::RayfireMesh::_theta
private

Rayfire Spherical polar angle (in radians)

Definition at line 142 of file rayfire_mesh.h.

Referenced by newton_solve_intersection(), rayfire_in_elem(), and RayfireMesh().


The documentation for this class was generated from the following files:

Generated on Tue Dec 19 2017 12:47:32 for GRINS-0.8.0 by  doxygen 1.8.9.1