oomph::VorticitySmoother< ELEMENT > Class Template Reference

Smoother for vorticity in 2D. More...

#include <vorticity_smoother.h>

Public Member Functions

 VorticitySmoother (const unsigned &recovery_order)
 Constructor: Set order of recovery shape functions. More...
 
 VorticitySmoother (const VorticitySmoother &)=delete
 Broken copy constructor. More...
 
void operator= (const VorticitySmoother &)=delete
 Broken assignment operator. More...
 
virtual ~VorticitySmoother ()
 Empty virtual destructor. More...
 
unsignedrecovery_order ()
 Access function for order of recovery polynomials. More...
 
void shape_rec (const Vector< double > &x, Vector< double > &psi_r)
 
Integralintegral_rec (const bool &is_q_mesh)
 
void setup_patches (Mesh *&mesh_pt, std::map< Node *, Vector< ELEMENT * > * > &adjacent_elements_pt, Vector< Node * > &vertex_node_pt)
 
void get_recovered_vorticity_in_patch (const Vector< ELEMENT * > &patch_el_pt, const unsigned &num_recovery_terms, Vector< double > *&recovered_vorticity_coefficient_pt, unsigned &n_deriv)
 
unsigned nrecovery_order () const
 Get the recovery order. More...
 
void recover_vorticity (Mesh *mesh_pt)
 Recover vorticity from patches. More...
 
void recover_vorticity (Mesh *mesh_pt, DocInfo &doc_info)
 

Private Attributes

unsigned Recovery_order
 Order of recovery polynomials. More...
 

Detailed Description

template<class ELEMENT>
class oomph::VorticitySmoother< ELEMENT >

Smoother for vorticity in 2D.

/////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////

Constructor & Destructor Documentation

◆ VorticitySmoother() [1/2]

template<class ELEMENT >
oomph::VorticitySmoother< ELEMENT >::VorticitySmoother ( const unsigned recovery_order)
inline

Constructor: Set order of recovery shape functions.

1842  {
1843  }
unsigned & recovery_order()
Access function for order of recovery polynomials.
Definition: vorticity_smoother.h:1855
unsigned Recovery_order
Order of recovery polynomials.
Definition: vorticity_smoother.h:2665

◆ VorticitySmoother() [2/2]

template<class ELEMENT >
oomph::VorticitySmoother< ELEMENT >::VorticitySmoother ( const VorticitySmoother< ELEMENT > &  )
delete

Broken copy constructor.

◆ ~VorticitySmoother()

template<class ELEMENT >
virtual oomph::VorticitySmoother< ELEMENT >::~VorticitySmoother ( )
inlinevirtual

Empty virtual destructor.

1852 {}

Member Function Documentation

◆ get_recovered_vorticity_in_patch()

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::get_recovered_vorticity_in_patch ( const Vector< ELEMENT * > &  patch_el_pt,
const unsigned num_recovery_terms,
Vector< double > *&  recovered_vorticity_coefficient_pt,
unsigned n_deriv 
)
inline

Given the vector of elements that make up a patch, compute the vector of recovered vorticity coefficients and return a pointer to it. n_deriv indicates which derivative of the vorticity is supposed to be smoothed: 0: zeroth (i.e. the vorticity itself) 1: d/dx; 2: d/dy; 3: d^2/dx^2; 4: d^2/dxdy 5: d^2/dy^2 6: d^3/dx^3, 7: d^3/dx^2dy, 8: d^3/dxdy^2, 9: d^3/dy^3, 10: du/dx, 11: du/dy, 12: dv/dx, 13: dv/dy

2120  {
2121  // Find the number of elements in the patch
2122  unsigned nelem = patch_el_pt.size();
2123 
2124  // Get a pointer to any element
2125  ELEMENT* el_pt = patch_el_pt[0];
2126 
2127 #ifdef PARANOID
2128  // If there's at least one element
2129  if (nelem > 0)
2130  {
2131  // Get the number of vorticity derivatives to recover
2132  int n_vort_derivs = el_pt->get_maximum_order_of_vorticity_derivative();
2133 
2134  // Get the number of vorticity derivatives to recover
2135  int n_veloc_derivs = el_pt->get_maximum_order_of_velocity_derivative();
2136 
2137  // If we're not recovering anything, we shouldn't be here
2138  if (n_vort_derivs + n_veloc_derivs == -1)
2139  {
2140  // Create an ostringstream object to create an error message
2141  std::ostringstream error_stream;
2142 
2143  // Create the error message
2144  error_stream << "Not recovering anything. Change the maximum number "
2145  << "of derivatives to recover.";
2146 
2147  // Throw an error
2148  throw OomphLibError(error_stream.str(),
2151  }
2152  } // if (nelem>0)
2153 #endif
2154 
2155  // Find the container indices associated with n_deriv
2156  std::pair<unsigned, unsigned> container_id =
2157  el_pt->vorticity_dof_to_container_id(n_deriv);
2158 
2159  // Maximum vorticity derivative order we can recover
2160  unsigned max_recoverable_vort_order =
2161  el_pt->get_maximum_order_of_recoverable_vorticity_derivative();
2162 
2163  // Maximum velocity derivative order we can recover
2164  unsigned max_recoverable_veloc_order =
2165  el_pt->get_maximum_order_of_recoverable_velocity_derivative();
2166 
2167  // Make a counter
2168  unsigned counter = 0;
2169 
2170  // Calculate the case value (initialise to -1 so we know if it's set
2171  // later)
2172  int case_value = -1;
2173 
2174  // Loop over the derivatives
2175  for (unsigned i = 0; i < max_recoverable_vort_order + 1; i++)
2176  {
2177  // Increment by the number of partial derivatives of order i
2178  counter += el_pt->npartial_derivative(i);
2179 
2180  // If we've exceeded the value of n_deriv then we know which vorticity
2181  // derivative to recover
2182  if (n_deriv < counter)
2183  {
2184  // We need to recover the i-th order of derivative of the vorticity
2185  case_value = i;
2186 
2187  // We're done here
2188  break;
2189  }
2190  } // for (unsigned i=0;i<max_recoverable_order+1;i++)
2191 
2192  // If we haven't set the case value yet then we must be recovering a
2193  // velocity derivative
2194  if (case_value == -1)
2195  {
2196  // Loop over the velocity order
2197  for (unsigned i = 1; i < max_recoverable_veloc_order + 1; i++)
2198  {
2199  // Increment by the number of velocity partial derivatives of order i
2200  counter += 2 * el_pt->npartial_derivative(i);
2201 
2202  // If we've exceeded the value of n_deriv then we know which vorticity
2203  // derivative to recover
2204  if (n_deriv < counter)
2205  {
2206  // We need to recover the i-th order of derivative of the vorticity
2207  case_value = max_recoverable_vort_order + i;
2208 
2209  // We're done here
2210  break;
2211  }
2212  } // for (unsigned i=1;i<max_recoverable_veloc_order+1;i++)
2213  } // if (case_value==-1)
2214 
2215 #ifdef PARANOID
2216  // Sanity check: if the case value hasn't been set then something's wrong
2217  if (case_value == -1)
2218  {
2219  // Create a ostringstream object to create an error message
2220  std::ostringstream error_message_stream;
2221 
2222  // Create an error message
2223  error_message_stream
2224  << "Case order has not been set. Something's wrong!";
2225 
2226  // Throw an error
2227  throw OomphLibError(error_message_stream.str(),
2230  }
2231 #endif
2232 
2233  // Create space for the recovered quantity
2234  double recovered_quantity = 0.0;
2235 
2236  // Create/initialise matrix for linear system
2237  DenseDoubleMatrix recovery_mat(
2238  num_recovery_terms, num_recovery_terms, 0.0);
2239 
2240  // Create/initialise vector for RHS
2241  Vector<double> rhs(num_recovery_terms, 0.0);
2242 
2243  // Create a new integration scheme based on the recovery order
2244  // in the elements. Need to find the type of the element, default
2245  // is to assume a quad
2246  bool is_q_mesh = true;
2247 
2248  // If we can dynamic cast to the TElementBase, then it's a triangle/tet
2249  // Note that I'm assuming that all elements are of the same geometry, but
2250  // if they weren't we could adapt...
2251  if (dynamic_cast<TElementBase*>(patch_el_pt[0]))
2252  {
2253  // We're dealing with a triangle-based mesh so change the bool value
2254  is_q_mesh = false;
2255  }
2256 
2257  // Get a pointer to the appropriate integration type
2258  Integral* const integ_pt = this->integral_rec(is_q_mesh);
2259 
2260  // Loop over all elements in patch to assemble linear system
2261  for (unsigned e = 0; e < nelem; e++)
2262  {
2263  // Get pointer to element
2264  ELEMENT* const el_pt = patch_el_pt[e];
2265 
2266  // Create storage for the recovery shape function values
2267  Vector<double> psi_r(num_recovery_terms);
2268 
2269  // Create vector to hold local coordinates
2270  Vector<double> s(2, 0.0);
2271 
2272  // Find the number of integration points
2273  unsigned n_intpt = integ_pt->nweight();
2274 
2275  // Loop over the integration points
2276  for (unsigned ipt = 0; ipt < n_intpt; ipt++)
2277  {
2278  // Assign values of s, the local coordinate
2279  for (unsigned i = 0; i < 2; i++)
2280  {
2281  // Get the i-th entry of the local coordinate
2282  s[i] = integ_pt->knot(ipt, i);
2283  }
2284 
2285  // Get the integral weight
2286  double w = integ_pt->weight(ipt);
2287 
2288  // Jacobian of mapping
2289  double J = el_pt->J_eulerian(s);
2290 
2291  // Allocate space for the global coordinates
2292  Vector<double> x(2, 0.0);
2293 
2294  // Interpolate the global (Eulerian) coordinate
2295  el_pt->interpolated_x(s, x);
2296 
2297  // Premultiply the weights and the Jacobian and the geometric
2298  // Jacobian weight (used in axisymmetric and spherical coordinate
2299  // systems) -- hierher really fct of x? probably yes, actually).
2300  double W = w * J * (el_pt->geometric_jacobian(x));
2301 
2302  // Recovery shape functions at global (Eulerian) coordinate
2303  shape_rec(x, psi_r);
2304 
2305  // Use a switch statement to decide on which function to call
2306  switch (case_value)
2307  {
2308  case 0:
2309  {
2310  Vector<double> vorticity(1, 0.0);
2311  el_pt->get_vorticity(s, vorticity);
2312  recovered_quantity = vorticity[0];
2313  break;
2314  }
2315  case 1:
2316  {
2317  el_pt->get_raw_vorticity_deriv(
2318  s, recovered_quantity, container_id.second);
2319  break;
2320  }
2321  case 2:
2322  {
2323  el_pt->get_raw_vorticity_second_deriv(
2324  s, recovered_quantity, container_id.second);
2325  break;
2326  }
2327  case 3:
2328  {
2329  el_pt->get_raw_vorticity_third_deriv(
2330  s, recovered_quantity, container_id.second);
2331  break;
2332  }
2333  case 4:
2334  {
2335  el_pt->get_raw_velocity_deriv(
2336  s, recovered_quantity, container_id.second);
2337  break;
2338  }
2339  default:
2340  {
2341  oomph_info << "Never get here." << std::endl;
2342  abort();
2343  }
2344  }
2345 
2346  // Add elemental RHSs and recovery matrix to global versions
2347  //----------------------------------------------------------
2348  // RHS: Loop over the nodes for the test functions
2349  for (unsigned l = 0; l < num_recovery_terms; l++)
2350  {
2351  // Update the RHS entry ()
2352  rhs[l] += recovered_quantity * psi_r[l] * W;
2353  }
2354 
2355  // Loop over the nodes for the test functions
2356  for (unsigned l = 0; l < num_recovery_terms; l++)
2357  {
2358  // Loop over the nodes for the variables
2359  for (unsigned l2 = 0; l2 < num_recovery_terms; l2++)
2360  {
2361  // Add contribution to recovery matrix
2362  recovery_mat(l, l2) += psi_r[l] * psi_r[l2] * W;
2363  }
2364  } // for (unsigned l=0;l<num_recovery_terms;l++)
2365  } // for (unsigned ipt=0;ipt<n_intpt;ipt++)
2366  } // End of loop over elements that make up patch.
2367 
2368  // Delete the integration scheme
2369  delete integ_pt;
2370 
2371  // Linear system is now assembled: Solve recovery system
2372  //------------------------------------------------------
2373  // LU decompose the recovery matrix
2374  recovery_mat.ludecompose();
2375 
2376  // Back-substitute
2377  recovery_mat.lubksub(rhs);
2378 
2379  // Now create a matrix to store the vorticity recovery coefficients.
2380  // Pointer to this matrix will be returned.
2381  recovered_vorticity_coefficient_pt =
2382  new Vector<double>(num_recovery_terms);
2383 
2384  // Loop over the number of recovered terms
2385  for (unsigned icoeff = 0; icoeff < num_recovery_terms; icoeff++)
2386  {
2387  // Copy the RHS value over
2388  (*recovered_vorticity_coefficient_pt)[icoeff] = rhs[icoeff];
2389  }
2390  } // End of get_recovered_vorticity_in_patch
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
JacobiRotation< float > J
Definition: Jacobi_makeJacobi.cpp:3
RowVector3d w
Definition: Matrix_resize_int.cpp:3
void shape_rec(const Vector< double > &x, Vector< double > &psi_r)
Definition: vorticity_smoother.h:1864
Integral * integral_rec(const bool &is_q_mesh)
Definition: vorticity_smoother.h:1926
RealScalar s
Definition: level1_cplx_impl.h:130
@ W
Definition: quadtree.h:63
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References e(), i, oomph::VorticitySmoother< ELEMENT >::integral_rec(), J, oomph::Integral::knot(), oomph::DenseDoubleMatrix::lubksub(), oomph::DenseDoubleMatrix::ludecompose(), oomph::Integral::nweight(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, s, oomph::VorticitySmoother< ELEMENT >::shape_rec(), w, oomph::QuadTreeNames::W, oomph::Integral::weight(), and plotDoE::x.

Referenced by oomph::VorticitySmoother< ELEMENT >::recover_vorticity().

◆ integral_rec()

template<class ELEMENT >
Integral* oomph::VorticitySmoother< ELEMENT >::integral_rec ( const bool is_q_mesh)
inline

Integation scheme associated with the recovery shape functions must be of sufficiently high order to integrate the mass matrix associated with the recovery shape functions. The argument is the dimension of the elements. The integration is performed locally over the elements, so the integration scheme does depend on the geometry of the element. The type of element is specified by the boolean which is true if elements in the patch are QElements and false if they are TElements (will need change if we ever have other element types)

Find order of recovery shape functions

1927  {
1928  // Create an ostringstream object to create a string
1929  std::ostringstream error_stream;
1930 
1931  //----
1932  // 2D:
1933  //----
1935  switch (recovery_order())
1936  {
1937  case 1:
1938  // Complete linear polynomial in 2D:
1939  if (is_q_mesh)
1940  {
1941  // Return the appropriate Gauss integration scheme
1942  return (new Gauss<2, 2>);
1943  }
1944  else
1945  {
1946  // Return the appropriate Gauss integration scheme
1947  return (new TGauss<2, 2>);
1948  }
1949  break;
1950 
1951  case 2:
1952  // Complete quadratic polynomial in 2D:
1953  if (is_q_mesh)
1954  {
1955  // Return the appropriate Gauss integration scheme
1956  return (new Gauss<2, 3>);
1957  }
1958  else
1959  {
1960  // Return the appropriate Gauss integration scheme
1961  return (new TGauss<2, 3>);
1962  }
1963  break;
1964 
1965  case 3:
1966  // Complete cubic polynomial in 2D:
1967  if (is_q_mesh)
1968  {
1969  // Return the appropriate Gauss integration scheme
1970  return (new Gauss<2, 4>);
1971  }
1972  else
1973  {
1974  // Return the appropriate Gauss integration scheme
1975  return (new TGauss<2, 4>);
1976  }
1977  break;
1978 
1979  default:
1980  // Create an error messaage
1981  error_stream << "Recovery shape functions for recovery order "
1982  << recovery_order()
1983  << " haven't yet been implemented for 2D" << std::endl;
1984 
1985  // Throw an error
1986  throw OomphLibError(error_stream.str(),
1989  }
1990 
1991  // Dummy return (never get here)
1992  return 0;
1993  } // End of integral_rec

References OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and oomph::VorticitySmoother< ELEMENT >::recovery_order().

Referenced by oomph::VorticitySmoother< ELEMENT >::get_recovered_vorticity_in_patch().

◆ nrecovery_order()

template<class ELEMENT >
unsigned oomph::VorticitySmoother< ELEMENT >::nrecovery_order ( ) const
inline

Get the recovery order.

2394  {
2395  // Use a switch statement
2396  switch (Recovery_order)
2397  {
2398  case 1:
2399  // Linear recovery shape functions
2400  //--------------------------------
2401  return 3; // 1, x, y
2402  break;
2403 
2404  case 2:
2405  // Quadratic recovery shape functions
2406  //-----------------------------------
2407  return 6; // 1, x, y, x^2, xy, y^2
2408  break;
2409 
2410  case 3:
2411  // Cubic recovery shape functions
2412  //--------------------------------
2413  return 10; // 1, x, y, x^2, xy, y^2, x^3, x^2 y, x y^2, y^3
2414  break;
2415 
2416  default:
2417  // Any other recovery order?
2418  //--------------------------
2419  // Use an ostringstream object to create an error message
2420  std::ostringstream error_stream;
2421 
2422  // Create an error message
2423  error_stream << "Wrong Recovery_order " << Recovery_order
2424  << std::endl;
2425 
2426  // Throw an error
2427  throw OomphLibError(error_stream.str(),
2430  }
2431  } // End of nrecovery_order

References OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and oomph::VorticitySmoother< ELEMENT >::Recovery_order.

Referenced by oomph::VorticitySmoother< ELEMENT >::recover_vorticity().

◆ operator=()

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::operator= ( const VorticitySmoother< ELEMENT > &  )
delete

Broken assignment operator.

◆ recover_vorticity() [1/2]

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::recover_vorticity ( Mesh mesh_pt)
inline

Recover vorticity from patches.

2435  {
2436  // Create a DocInfo object (used as a dummy argument)
2437  DocInfo doc_info;
2438 
2439  // Disable any documentation
2440  doc_info.disable_doc();
2441 
2442  // Recover the vorticity
2443  recover_vorticity(mesh_pt, doc_info);
2444  }
void recover_vorticity(Mesh *mesh_pt)
Recover vorticity from patches.
Definition: vorticity_smoother.h:2434

References oomph::DocInfo::disable_doc().

◆ recover_vorticity() [2/2]

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::recover_vorticity ( Mesh mesh_pt,
DocInfo doc_info 
)
inline

Recover vorticity from patches – output intermediate steps to directory specified by DocInfo object

2449  {
2450  // Start the timer
2451  double t_start = TimingHelpers::timer();
2452 
2453  // Allocate space for the local coordinates
2454  Vector<double> s(2, 0.0);
2455 
2456  // Allocate space for the global coordinates
2457  Vector<double> x(2, 0.0);
2458 
2459  // Make patches
2460  //-------------
2461  // Allocate space for the mapping from nodes to elements
2462  std::map<Node*, Vector<ELEMENT*>*> adjacent_elements_pt;
2463 
2464  // Allocate space for the vertex nodes
2465  Vector<Node*> vertex_node_pt;
2466 
2467  // Set up the patches information
2468  setup_patches(mesh_pt, adjacent_elements_pt, vertex_node_pt);
2469 
2470  // Grab any element (this shouldn't be a null pointer)
2471  ELEMENT* const el_pt = dynamic_cast<ELEMENT*>(mesh_pt->element_pt(0));
2472 
2473  // Get the index of the vorticity
2474  unsigned smoothed_vorticity_index = el_pt->smoothed_vorticity_index();
2475 
2476  // Maximum order of vorticity derivative (that can be recovered)
2477  unsigned max_vort_order =
2478  el_pt->get_maximum_order_of_recoverable_vorticity_derivative();
2479 
2480  // Maximum order of velocity derivative (that can be recovered)
2481  unsigned max_veloc_order =
2482  el_pt->get_maximum_order_of_recoverable_velocity_derivative();
2483 
2484  // Maximum number of recoverable vorticity terms
2485  unsigned max_vort_recov = 0;
2486 
2487  // Maximum number of recoverable velocity terms
2488  unsigned max_veloc_recov = 0;
2489 
2490  // Loop over the entries of the vector
2491  for (unsigned i = 0; i < max_vort_order + 1; i++)
2492  {
2493  // Get the number of partial derivatives of the vorticity
2494  max_vort_recov += el_pt->npartial_derivative(i);
2495  }
2496 
2497  // Loop over the entries of the vector
2498  for (unsigned i = 1; i < max_veloc_order + 1; i++)
2499  {
2500  // Get the number of partial derivatives of the vorticity
2501  max_veloc_recov += 2 * el_pt->npartial_derivative(i);
2502  }
2503 
2504  // Number of recovered vorticity derivatives
2505  unsigned n_recovered_vort_derivs =
2506  el_pt->nvorticity_derivatives_to_recover();
2507 
2508  // Number of recovered velocity derivatives
2509  unsigned n_recovered_veloc_derivs =
2510  el_pt->nvelocity_derivatives_to_recover();
2511 
2512  // Determine number of coefficients for expansion of recovered vorticity.
2513  // Use complete polynomial of given order for recovery
2514  unsigned num_recovery_terms = nrecovery_order();
2515 
2516  // Counter for averaging of recovered vorticity and its derivatives
2517  std::map<Node*, unsigned> count;
2518 
2519  // Counter for which nodal value we're assigning
2520  unsigned nodal_dof = 0;
2521 
2522  // Loop over derivatives
2523  for (unsigned deriv = 0; deriv < max_vort_recov + max_veloc_recov;
2524  deriv++)
2525  {
2526  // If we're not recovering this vorticity derivative. Note, we cast
2527  // to an int because n_recovered_vort_derivs can be zero (so subtracting
2528  // any positive integer can cause trouble)
2529  if ((int(deriv) > int(n_recovered_vort_derivs - 1)) &&
2530  (deriv < max_vort_recov))
2531  {
2532  // We're done here
2533  continue;
2534  }
2535  // If we're not recovering any of the velocity derivatives and we're
2536  // finished with the vorticity derivatives
2537  else if ((n_recovered_veloc_derivs == 0) && (deriv >= max_vort_recov))
2538  {
2539  // We're done here
2540  continue;
2541  }
2542 
2543  // Storage for accumulated nodal vorticity (used to compute nodal
2544  // averages)
2545  std::map<Node*, double> averaged_recovered_vort;
2546 
2547  // Calculation of vorticity
2548  //-------------------------
2549  // Do patch recovery
2550  // unsigned counter=0;
2551  for (typename std::map<Node*, Vector<ELEMENT*>*>::iterator it =
2552  adjacent_elements_pt.begin();
2553  it != adjacent_elements_pt.end();
2554  it++)
2555  {
2556  // Pointer to the recovered vorticity coefficients
2557  Vector<double>* recovered_vorticity_coefficient_pt;
2558 
2559  // Setup smoothed vorticity field for patches
2560  get_recovered_vorticity_in_patch(*(it->second),
2561  num_recovery_terms,
2562  recovered_vorticity_coefficient_pt,
2563  deriv);
2564 
2565  // Now get the nodal average of the recovered vorticity (nodes are
2566  // generally part of multiple patches):
2567 
2568  // Get the number of elements in adjacent_elements_pt
2569  unsigned nelem = (*(it->second)).size();
2570 
2571  // Loop over all elements to get recovered vorticity
2572  for (unsigned e = 0; e < nelem; e++)
2573  {
2574  // Get pointer to element
2575  ELEMENT* const el_pt = (*(it->second))[e];
2576 
2577  // Get the number of nodes by element
2578  unsigned nnode_el = el_pt->nnode();
2579 
2580  // Loop over the nodes in the element
2581  for (unsigned j = 0; j < nnode_el; j++)
2582  {
2583  // Get a pointer to the j-th node in this element
2584  Node* nod_pt = el_pt->node_pt(j);
2585 
2586  // Get the local coordinates of the node
2587  el_pt->local_coordinate_of_node(j, s);
2588 
2589  // Interpolate the global (Eulerian) coordinate
2590  el_pt->interpolated_x(s, x);
2591 
2592  // Recovery shape functions at global (Eulerian) coordinate
2593  Vector<double> psi_r(num_recovery_terms);
2594 
2595  // Recover the shape function values at the position x
2596  shape_rec(x, psi_r);
2597 
2598  // Initialise the value of the recovered quantity
2599  double recovered_vort = 0.0;
2600 
2601  // Loop over the recovery terms
2602  for (unsigned i = 0; i < num_recovery_terms; i++)
2603  {
2604  // Assemble recovered vorticity
2605  recovered_vort +=
2606  (*recovered_vorticity_coefficient_pt)[i] * psi_r[i];
2607  }
2608 
2609  // Keep adding
2610  averaged_recovered_vort[nod_pt] += recovered_vort;
2611 
2612  // Increment the counter
2613  count[nod_pt]++;
2614  } // for (unsigned j=0;j<nnode_el;j++)
2615  } // for (unsigned e=0;e<nelem;e++)
2616 
2617  // Delete the recovered coefficient data
2618  delete recovered_vorticity_coefficient_pt;
2619 
2620  // Make it a null pointer
2621  recovered_vorticity_coefficient_pt = 0;
2622  } // for (typename std::map<Node*,Vector<ELEMENT*>*>::iterator it=...
2623 
2624  // Find out how many nodes there are in the mesh
2625  unsigned nnod = mesh_pt->nnode();
2626 
2627  // Loop over all nodes to actually work out the average
2628  for (unsigned j = 0; j < nnod; j++)
2629  {
2630  // Make a pointer to the j-th node
2631  Node* nod_pt = mesh_pt->node_pt(j);
2632 
2633  // Calculate the values of the smoothed vorticity
2634  averaged_recovered_vort[nod_pt] /= count[nod_pt];
2635 
2636  // Assign smoothed vorticity to nodal values
2637  nod_pt->set_value(smoothed_vorticity_index + nodal_dof,
2638  averaged_recovered_vort[nod_pt]);
2639  }
2640 
2641  // We're done with this dof so increment the counter
2642  nodal_dof++;
2643 
2644  // Start again
2645  count.clear();
2646  } // for (unsigned deriv=0;deriv<max_vort_recov+max_veloc_recov;deriv++)
2647 
2648  // Cleanup
2649  for (typename std::map<Node*, Vector<ELEMENT*>*>::iterator it =
2650  adjacent_elements_pt.begin();
2651  it != adjacent_elements_pt.end();
2652  it++)
2653  {
2654  // Delete the vector of element pointers
2655  delete it->second;
2656  }
2657 
2658  // Inform the user
2659  oomph_info << "Time for vorticity recovery [sec]: "
2660  << TimingHelpers::timer() - t_start << std::endl;
2661  } // End of recover_vorticity
unsigned nrecovery_order() const
Get the recovery order.
Definition: vorticity_smoother.h:2393
void get_recovered_vorticity_in_patch(const Vector< ELEMENT * > &patch_el_pt, const unsigned &num_recovery_terms, Vector< double > *&recovered_vorticity_coefficient_pt, unsigned &n_deriv)
Definition: vorticity_smoother.h:2115
void setup_patches(Mesh *&mesh_pt, std::map< Node *, Vector< ELEMENT * > * > &adjacent_elements_pt, Vector< Node * > &vertex_node_pt)
Definition: vorticity_smoother.h:1999
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References e(), oomph::Mesh::element_pt(), oomph::VorticitySmoother< ELEMENT >::get_recovered_vorticity_in_patch(), i, j, oomph::Mesh::nnode(), oomph::Mesh::node_pt(), oomph::VorticitySmoother< ELEMENT >::nrecovery_order(), oomph::oomph_info, s, oomph::Data::set_value(), oomph::VorticitySmoother< ELEMENT >::setup_patches(), oomph::VorticitySmoother< ELEMENT >::shape_rec(), oomph::TimingHelpers::timer(), and plotDoE::x.

◆ recovery_order()

template<class ELEMENT >
unsigned& oomph::VorticitySmoother< ELEMENT >::recovery_order ( )
inline

Access function for order of recovery polynomials.

1856  {
1857  // Return the order of recovery
1858  return Recovery_order;
1859  }

References oomph::VorticitySmoother< ELEMENT >::Recovery_order.

Referenced by oomph::VorticitySmoother< ELEMENT >::integral_rec(), and oomph::VorticitySmoother< ELEMENT >::shape_rec().

◆ setup_patches()

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::setup_patches ( Mesh *&  mesh_pt,
std::map< Node *, Vector< ELEMENT * > * > &  adjacent_elements_pt,
Vector< Node * > &  vertex_node_pt 
)
inline

Setup patches: For each vertex node pointed to by nod_pt, adjacent_elements_pt[nod_pt] contains the pointer to the vector that contains the pointers to the elements that the node is part of. Also returns a Vector of vertex nodes for use in get_element_errors.

2002  {
2003  // Clear: hierher should we do this in Z2 as well?
2004  adjacent_elements_pt.clear();
2005 
2006  // Auxiliary map that contains element-adjacency for ALL nodes
2007  std::map<Node*, Vector<ELEMENT*>*> aux_adjacent_elements_pt;
2008 
2009 #ifdef PARANOID
2010  // Check if all elements request the same recovery order
2011  unsigned ndisagree = 0;
2012 #endif
2013 
2014  // Loop over all elements to setup adjacency for all nodes.
2015  // Need to do this because midside nodes can be corner nodes for
2016  // adjacent smaller elements! Admittedly, the inclusion of interior
2017  // nodes is wasteful...
2018  unsigned nelem = mesh_pt->nelement();
2019  for (unsigned e = 0; e < nelem; e++)
2020  {
2021  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt->element_pt(e));
2022 
2023 #ifdef PARANOID
2024  // Check if all elements request the same recovery order
2025  if (el_pt->nrecovery_order() != Recovery_order)
2026  {
2027  ndisagree++;
2028  }
2029 #endif
2030 
2031  // Loop all nodes in element
2032  unsigned nnod = el_pt->nnode();
2033  for (unsigned n = 0; n < nnod; n++)
2034  {
2035  // Make a pointer to the n-th node
2036  Node* nod_pt = el_pt->node_pt(n);
2037 
2038  // Has this node been considered before?
2039  if (aux_adjacent_elements_pt[nod_pt] == 0)
2040  {
2041  // Create Vector of pointers to its adjacent elements
2042  aux_adjacent_elements_pt[nod_pt] = new Vector<ELEMENT*>;
2043  }
2044 
2045  // Add pointer to adjacent element
2046  (*aux_adjacent_elements_pt[nod_pt]).push_back(el_pt);
2047  }
2048  } // end element loop
2049 
2050 #ifdef PARANOID
2051  // Check if all elements request the same recovery order
2052  if (ndisagree != 0)
2053  {
2054  oomph_info
2055  << "\n\n======================================================\n"
2056  << "WARNING:\n"
2057  << ndisagree << " out of " << mesh_pt->nelement() << " elements"
2058  << "\nhave different preferences for the order of the recovery"
2059  << "\nshape functions. We are using: Recovery_order="
2060  << Recovery_order << std::endl;
2061  oomph_info
2062  << "======================================================\n\n";
2063  }
2064 #endif
2065 
2066  // Loop over all elements, extract adjacency for corner nodes only
2067  nelem = mesh_pt->nelement();
2068  for (unsigned e = 0; e < nelem; e++)
2069  {
2070  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt->element_pt(e));
2071 
2072  // Loop over corner nodes
2073  unsigned n_node = el_pt->nvertex_node();
2074  for (unsigned n = 0; n < n_node; n++)
2075  {
2076  Node* nod_pt = el_pt->vertex_node_pt(n);
2077 
2078  // Has this node been considered before?
2079  if (adjacent_elements_pt[nod_pt] == 0)
2080  {
2081  // Add the node pointer to the vertex node container
2082  vertex_node_pt.push_back(nod_pt);
2083 
2084  // Create Vector of pointers to its adjacent elements
2085  adjacent_elements_pt[nod_pt] = new Vector<ELEMENT*>;
2086 
2087  // Copy across:
2088  unsigned nel = (*aux_adjacent_elements_pt[nod_pt]).size();
2089  for (unsigned e = 0; e < nel; e++)
2090  {
2091  (*adjacent_elements_pt[nod_pt])
2092  .push_back((*aux_adjacent_elements_pt[nod_pt])[e]);
2093  }
2094  }
2095  }
2096  } // End of loop over elements
2097 
2098  // Cleanup
2099  for (typename std::map<Node*, Vector<ELEMENT*>*>::iterator it =
2100  aux_adjacent_elements_pt.begin();
2101  it != aux_adjacent_elements_pt.end();
2102  it++)
2103  {
2104  delete it->second;
2105  }
2106  } // End of setup_patches
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Scalar Scalar int size
Definition: benchVecAdd.cpp:17

References e(), oomph::Mesh::element_pt(), n, oomph::Mesh::nelement(), oomph::oomph_info, oomph::VorticitySmoother< ELEMENT >::Recovery_order, and size.

Referenced by oomph::VorticitySmoother< ELEMENT >::recover_vorticity().

◆ shape_rec()

template<class ELEMENT >
void oomph::VorticitySmoother< ELEMENT >::shape_rec ( const Vector< double > &  x,
Vector< double > &  psi_r 
)
inline

Recovery shape functions as functions of the global, Eulerian coordinate x of dimension dim. The recovery shape functions are complete polynomials of the order specified by Recovery_order.

1865  {
1866  // Create an ostringstream object to create a string
1867  std::ostringstream error_stream;
1868 
1869  // Find order of recovery shape functions
1870  switch (recovery_order())
1871  {
1872  case 1:
1873  // Complete linear polynomial in 2D:
1874  psi_r[0] = 1.0;
1875  psi_r[1] = x[0];
1876  psi_r[2] = x[1];
1877  break;
1878 
1879  case 2:
1880  // Complete quadratic polynomial in 2D:
1881  psi_r[0] = 1.0;
1882  psi_r[1] = x[0];
1883  psi_r[2] = x[1];
1884  psi_r[3] = x[0] * x[0];
1885  psi_r[4] = x[0] * x[1];
1886  psi_r[5] = x[1] * x[1];
1887  break;
1888 
1889  case 3:
1890  // Complete cubic polynomial in 2D:
1891  psi_r[0] = 1.0;
1892  psi_r[1] = x[0];
1893  psi_r[2] = x[1];
1894  psi_r[3] = x[0] * x[0];
1895  psi_r[4] = x[0] * x[1];
1896  psi_r[5] = x[1] * x[1];
1897  psi_r[6] = x[0] * x[0] * x[0];
1898  psi_r[7] = x[0] * x[0] * x[1];
1899  psi_r[8] = x[0] * x[1] * x[1];
1900  psi_r[9] = x[1] * x[1] * x[1];
1901  break;
1902 
1903  default:
1904  // Create an error message for this case
1905  error_stream << "Recovery shape functions for recovery order "
1906  << recovery_order()
1907  << " haven't yet been implemented for 2D" << std::endl;
1908 
1909  // Throw an error
1910  throw OomphLibError(error_stream.str(),
1913  }
1914  } // End of shape_rec

References OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::VorticitySmoother< ELEMENT >::recovery_order(), and plotDoE::x.

Referenced by oomph::VorticitySmoother< ELEMENT >::get_recovered_vorticity_in_patch(), and oomph::VorticitySmoother< ELEMENT >::recover_vorticity().

Member Data Documentation

◆ Recovery_order


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