libMesh
mesh_function.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local Includes
21 #include "libmesh/mesh_function.h"
22 #include "libmesh/dense_vector.h"
23 #include "libmesh/equation_systems.h"
24 #include "libmesh/numeric_vector.h"
25 #include "libmesh/dof_map.h"
26 #include "libmesh/point_locator_tree.h"
27 #include "libmesh/fe_base.h"
28 #include "libmesh/fe_interface.h"
29 #include "libmesh/fe_compute_data.h"
30 #include "libmesh/mesh_base.h"
31 #include "libmesh/point.h"
32 #include "libmesh/elem.h"
33 #include "libmesh/int_range.h"
34 #include "libmesh/fe_map.h"
35 
36 namespace libMesh
37 {
38 
39 
40 //------------------------------------------------------------------
41 // MeshFunction methods
43  const NumericVector<Number> & vec,
44  const DofMap & dof_map,
45  std::vector<unsigned int> vars,
46  const FunctionBase<Number> * master) :
47  FunctionBase<Number> (master),
48  ParallelObject (eqn_systems),
49  _eqn_systems (eqn_systems),
50  _vector (vec),
51  _dof_map (dof_map),
52  _system_vars (std::move(vars)),
53  _out_of_mesh_mode (false)
54 {
55 }
56 
57 
58 
60  const NumericVector<Number> & vec,
61  const DofMap & dof_map,
62  const unsigned int var,
63  const FunctionBase<Number> * master) :
64  FunctionBase<Number> (master),
65  ParallelObject (eqn_systems),
66  _eqn_systems (eqn_systems),
67  _vector (vec),
68  _dof_map (dof_map),
69  _system_vars (1,var),
70  _out_of_mesh_mode (false)
71 {
72 }
73 
75  FunctionBase<Number> (mf._master),
76  ParallelObject (mf._eqn_systems),
77  _eqn_systems (mf._eqn_systems),
78  _vector (mf._vector),
79  _dof_map (mf._dof_map),
80  _system_vars (mf._system_vars),
81  _out_of_mesh_mode (mf._out_of_mesh_mode)
82 {
83  // Initialize the mf and set the point locator if the
84  // input mf had done so.
85  if(mf.initialized())
86  {
87  this->MeshFunction::init();
88 
91 
92  }
93 
94  if (mf._subdomain_ids)
96  std::make_unique<std::set<subdomain_id_type>>
97  (*mf._subdomain_ids);
98 }
99 
100 MeshFunction::~MeshFunction () = default;
101 
102 
103 
105 {
106  // are indices of the desired variable(s) provided?
107  libmesh_assert_greater (this->_system_vars.size(), 0);
108 
109  // Don't do twice...
110  if (this->_initialized)
111  {
113  return;
114  }
115 
116  // The Mesh owns the "master" PointLocator, while handing us a
117  // PointLocator "proxy" that forwards all requests to the master.
118  const MeshBase & mesh = this->_eqn_systems.get_mesh();
120 
121  // ready for use
122  this->_initialized = true;
123 }
124 
125 
126 
127 void
129 {
130  // only delete the point locator when we are the master
131  if (_point_locator && !_master)
132  _point_locator.reset();
133 
134  this->_initialized = false;
135 }
136 
137 
138 
139 std::unique_ptr<FunctionBase<Number>> MeshFunction::clone () const
140 {
141  return std::make_unique<MeshFunction>(*this);
142 }
143 
144 
145 
147  const Real time)
148 {
149  libmesh_assert (this->initialized());
150 
151  DenseVector<Number> buf (1);
152  this->operator() (p, time, buf);
153  return buf(0);
154 }
155 
156 std::map<const Elem *, Number> MeshFunction::discontinuous_value (const Point & p,
157  const Real time)
158 {
159  libmesh_assert (this->initialized());
160 
161  std::map<const Elem *, DenseVector<Number>> buffer;
162  this->discontinuous_value (p, time, buffer);
163  std::map<const Elem *, Number> return_value;
164  for (const auto & [elem, vec] : buffer)
165  return_value[elem] = vec(0);
166  // NOTE: If no suitable element is found, then the map return_value is empty. This
167  // puts burden on the user of this function but I don't really see a better way.
168  return return_value;
169 }
170 
172  const Real time)
173 {
174  libmesh_assert (this->initialized());
175 
176  std::vector<Gradient> buf (1);
177  this->gradient(p, time, buf);
178  return buf[0];
179 }
180 
181 std::map<const Elem *, Gradient> MeshFunction::discontinuous_gradient (const Point & p,
182  const Real time)
183 {
184  libmesh_assert (this->initialized());
185 
186  std::map<const Elem *, std::vector<Gradient>> buffer;
187  this->discontinuous_gradient (p, time, buffer);
188  std::map<const Elem *, Gradient> return_value;
189  for (const auto & [elem, vec] : buffer)
190  return_value[elem] = vec[0];
191  // NOTE: If no suitable element is found, then the map return_value is empty. This
192  // puts burden on the user of this function but I don't really see a better way.
193  return return_value;
194 }
195 
196 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
198  const Real time)
199 {
200  libmesh_assert (this->initialized());
201 
202  std::vector<Tensor> buf (1);
203  this->hessian(p, time, buf);
204  return buf[0];
205 }
206 #endif
207 
209  const Real time,
210  DenseVector<Number> & output)
211 {
212  this->operator() (p, time, output, this->_subdomain_ids.get());
213 }
214 
216  const Real,
217  DenseVector<Number> & output,
218  const std::set<subdomain_id_type> * subdomain_ids)
219 {
220  libmesh_assert (this->initialized());
221 
222  const Elem * element = this->find_element(p,subdomain_ids);
223 
224  if (!element)
225  {
226  // We'd better be in out_of_mesh_mode if we couldn't find an
227  // element in the mesh
229  output = _out_of_mesh_value;
230  }
231  else
232  {
233  {
234  const unsigned int dim = element->dim();
235 
236 
237  // Get local coordinates to feed these into compute_data().
238  // Note that the fe_type can safely be used from the 0-variable,
239  // since the inverse mapping is the same for all FEFamilies
240  const Point mapped_point (FEMap::inverse_map (dim, element,
241  p));
242 
243  // resize the output vector to the number of output values
244  // that the user told us, this include multiple entries for
245  // the spatial components of vector variable
246  unsigned int output_size = 0;
247  for (auto index : index_range(this->_system_vars))
248  {
249  const unsigned int var = _system_vars[index];
250 
251  if (var == libMesh::invalid_uint)
252  {
254  index < _out_of_mesh_value.size());
255  output(index) = _out_of_mesh_value(index);
256  continue;
257  }
258 
259  const FEType & fe_type = this->_dof_map.variable_type(var);
260 
261  // Adding entries for each scalar variable and spatial components of
262  // vector variables
263  switch (fe_type.family)
264  {
265  case HIERARCHIC_VEC:
266  case L2_HIERARCHIC_VEC:
267  case LAGRANGE_VEC:
268  case L2_LAGRANGE_VEC:
269  case MONOMIAL_VEC:
270  case NEDELEC_ONE:
271  case RAVIART_THOMAS:
272  case L2_RAVIART_THOMAS:
273  {
274  output_size = output_size + dim;
275  break;
276  }
277  default:
278  {
279  output_size++;
280  break;
281  }
282  }
283 
284  }
285  output.resize(output_size);
286 
287  // Adding a counter to keep the output indexing correct for mix scalar-vector output sets
288  unsigned int vec_count = 0;
289 
290  // loop over all vars
291  for (auto index : index_range(this->_system_vars))
292  {
293  // the data for this variable
294  const unsigned int var = _system_vars[index];
295 
296  if (var == libMesh::invalid_uint)
297  {
299  index < _out_of_mesh_value.size());
300  output(index) = _out_of_mesh_value(index);
301  continue;
302  }
303 
304  const FEType & fe_type = this->_dof_map.variable_type(var);
305 
306  // The method between vector and scalar variable are different:
307  // For scalar variables, we use the previous established method of using FEInterface::compute_data
308  // For vector variables, we call the phi() data directly to build the variable solution
309  switch (fe_type.family)
310  {
311  case HIERARCHIC_VEC:
312  case L2_HIERARCHIC_VEC:
313  case LAGRANGE_VEC:
314  case L2_LAGRANGE_VEC:
315  case MONOMIAL_VEC:
316  case NEDELEC_ONE:
317  case RAVIART_THOMAS:
318  case L2_RAVIART_THOMAS:
319  {
320  // Calling the physical mesh point needed for the shape function
321  FEComputeData data (this->_eqn_systems, mapped_point);
322  const Point & pt = data.p;
323 
324  // where the solution values for the var-th variable are stored
325  std::vector<dof_id_type> dof_indices;
326  this->_dof_map.dof_indices (element, dof_indices, var);
327 
328  // Calling the properly-transformed shape function using get_phi()
329  std::unique_ptr<FEVectorBase> vec_fe = FEVectorBase::build(dim, fe_type);
330  std::vector<Point> vec_pt = {pt};
331  const std::vector<std::vector<RealGradient>> & vec_phi = vec_fe->get_phi();
332  vec_fe->reinit(element, &vec_pt);
333 
334  // interpolate the solution
335  {
336  for (unsigned int d = 0; d < dim; d++)
337  {
338  Number value = 0.;
339 
340  for (auto i : index_range(dof_indices))
341  value += this->_vector(dof_indices[i]) * (vec_phi[i][0](d));
342 
343  output(index+vec_count*(dim-1)+d) = value;
344  }
345  }
346 
347  vec_count++;
348  break;
349  }
350  default:
351  {
352  // Build an FEComputeData that contains both input and output data
353  // for the specific compute_data method.
354 
355  FEComputeData data (this->_eqn_systems, mapped_point);
356 
357  FEInterface::compute_data (dim, fe_type, element, data);
358 
359  // where the solution values for the var-th variable are stored
360  std::vector<dof_id_type> dof_indices;
361  this->_dof_map.dof_indices (element, dof_indices, var);
362 
363  // interpolate the solution
364  {
365  Number value = 0.;
366 
367  for (auto i : index_range(dof_indices))
368  value += this->_vector(dof_indices[i]) * data.shape[i];
369 
370  output(index+vec_count*(dim-1)) = value;
371  }
372  break;
373  }
374  }
375 
376  // next variable
377  }
378  }
379  }
380 }
381 
383  const Real time,
384  std::map<const Elem *, DenseVector<Number>> & output)
385 {
386  this->discontinuous_value (p, time, output, this->_subdomain_ids.get());
387 }
388 
389 
390 
392  const Real,
393  std::map<const Elem *, DenseVector<Number>> & output,
394  const std::set<subdomain_id_type> * subdomain_ids)
395 {
396  libmesh_assert (this->initialized());
397 
398  // clear the output map
399  output.clear();
400 
401  // get the candidate elements
402  std::set<const Elem *> candidate_element = this->find_elements(p,subdomain_ids);
403 
404  // loop through all candidates, if the set is empty this function will return an
405  // empty map
406  for (const auto & element : candidate_element)
407  {
408  if (!element)
409  {
410  // We'd better be in out_of_mesh_mode if we couldn't find an
411  // element in the mesh
413  output[element] = _out_of_mesh_value;
414  continue;
415  }
416 
417  const unsigned int dim = element->dim();
418 
419  // define a temporary vector to store all values
420  DenseVector<Number> temp_output (cast_int<unsigned int>(this->_system_vars.size()));
421 
422  // Get local coordinates to feed these into compute_data().
423  // Note that the fe_type can safely be used from the 0-variable,
424  // since the inverse mapping is the same for all FEFamilies
425  const Point mapped_point (FEMap::inverse_map (dim, element, p));
426 
427  // loop over all vars
428  for (auto index : index_range(this->_system_vars))
429  {
430  // the data for this variable
431  const unsigned int var = _system_vars[index];
432 
433  if (var == libMesh::invalid_uint)
434  {
436  index < _out_of_mesh_value.size());
437  temp_output(index) = _out_of_mesh_value(index);
438  continue;
439  }
440 
441  const FEType & fe_type = this->_dof_map.variable_type(var);
442 
443  // Build an FEComputeData that contains both input and output data
444  // for the specific compute_data method.
445  {
446  FEComputeData data (this->_eqn_systems, mapped_point);
447 
448  FEInterface::compute_data (dim, fe_type, element, data);
449 
450  // where the solution values for the var-th variable are stored
451  std::vector<dof_id_type> dof_indices;
452  this->_dof_map.dof_indices (element, dof_indices, var);
453 
454  // interpolate the solution
455  {
456  Number value = 0.;
457 
458  for (auto i : index_range(dof_indices))
459  value += this->_vector(dof_indices[i]) * data.shape[i];
460 
461  temp_output(index) = value;
462  }
463 
464  }
465 
466  // next variable
467  }
468 
469  // Insert temp_output into output
470  output[element] = temp_output;
471  }
472 }
473 
474 
475 
477  const Real time,
478  std::vector<Gradient> & output)
479 {
480  this->gradient(p, time, output, this->_subdomain_ids.get());
481 }
482 
483 
484 
486  const Real,
487  std::vector<Gradient> & output,
488  const std::set<subdomain_id_type> * subdomain_ids)
489 {
490  libmesh_assert (this->initialized());
491 
492  const Elem * element = this->find_element(p,subdomain_ids);
493 
494  this->_gradient_on_elem(p, element, output);
495 }
496 
497 
499  const Real time,
500  std::map<const Elem *, std::vector<Gradient>> & output)
501 {
502  this->discontinuous_gradient (p, time, output, this->_subdomain_ids.get());
503 }
504 
505 
506 
508  const Real,
509  std::map<const Elem *, std::vector<Gradient>> & output,
510  const std::set<subdomain_id_type> * subdomain_ids)
511 {
512  libmesh_assert (this->initialized());
513 
514  // clear the output map
515  output.clear();
516 
517  // get the candidate elements
518  std::set<const Elem *> candidate_element = this->find_elements(p,subdomain_ids);
519 
520  // loop through all candidates, if the set is empty this function will return an
521  // empty map
522  for (const auto & element : candidate_element)
523  {
524  // define a temporary vector to store all values
525  std::vector<Gradient> temp_output (cast_int<unsigned int>(this->_system_vars.size()));
526 
527  this->_gradient_on_elem(p, element, temp_output);
528 
529  // Insert temp_output into output
530  output.emplace(element, std::move(temp_output));
531  }
532 }
533 
534 
535 
537  const Elem * element,
538  std::vector<Gradient> & output)
539 {
540  // resize the output vector to the number of output values
541  // that the user told us
542  output.resize (this->_system_vars.size());
543 
544  if (!element)
545  {
546  libmesh_error_msg_if(!_out_of_mesh_mode,
547  "MeshFunction couldn't find element at p=" <<
548  p << ", but is not in out-of-mesh mode");
549  libmesh_assert_equal_to (_out_of_mesh_value.size(),
550  this->_system_vars.size());
551  for (auto i : index_range(this->_system_vars))
552  output[i] = Gradient(_out_of_mesh_value[i]);
553  return;
554  }
555 
556  const unsigned int dim = element->dim();
557 
558  // Get local coordinates to feed these into compute_data().
559  // Note that the fe_type can safely be used from the 0-variable,
560  // since the inverse mapping is the same for all FEFamilies
561  const Point mapped_point (FEMap::inverse_map (dim, element,
562  p));
563 
564  std::vector<Point> point_list (1, mapped_point);
565 
566  // loop over all vars
567  for (auto index : index_range(this->_system_vars))
568  {
569  // the data for this variable
570  const unsigned int var = _system_vars[index];
571 
572  if (var == libMesh::invalid_uint)
573  {
575  index < _out_of_mesh_value.size());
576  output[index] = Gradient(_out_of_mesh_value(index));
577  continue;
578  }
579 
580  const FEType & fe_type = this->_dof_map.variable_type(var);
581 
582  // where the solution values for the var-th variable are stored
583  std::vector<dof_id_type> dof_indices;
584  this->_dof_map.dof_indices (element, dof_indices, var);
585 
586  // interpolate the solution
587  Gradient grad(0.);
588 
589  // for performance-reasons, we use different algorithms now.
590  // TODO: Check that both give the same result for finite elements.
591  // Otherwive it is wrong...
592  if (!element->infinite())
593  {
594  std::unique_ptr<FEBase> point_fe (FEBase::build(dim, fe_type));
595  const std::vector<std::vector<RealGradient>> & dphi = point_fe->get_dphi();
596  point_fe->reinit(element, &point_list);
597 
598  for (auto i : index_range(dof_indices))
599  grad.add_scaled(dphi[i][0], this->_vector(dof_indices[i]));
600 
601  }
602 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
603  else
604  {
605  // Build an FEComputeData that contains both input and output data
606  // for the specific compute_data method.
607  //
608  // TODO: enable this for a vector of points as well...
609  FEComputeData data (this->_eqn_systems, mapped_point);
610  data.enable_derivative();
611  FEInterface::compute_data (dim, fe_type, element, data);
612 
613  // grad [x] = data.dshape[i](v) * dv/dx * dof_index [i]
614  // sum over all indices
615  for (auto i : index_range(dof_indices))
616  {
617  // local coordinates
618  for (std::size_t v=0; v<dim; v++)
619  for (std::size_t xyz=0; xyz<LIBMESH_DIM; xyz++)
620  {
621  // FIXME: this needs better syntax: It is matrix-vector multiplication.
622  grad(xyz) += data.local_transform[v][xyz]
623  * data.dshape[i](v)
624  * this->_vector(dof_indices[i]);
625  }
626  }
627  }
628 #endif
629  output[index] = grad;
630  }
631 }
632 
633 
634 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
635 void MeshFunction::hessian (const Point & p,
636  const Real time,
637  std::vector<Tensor> & output)
638 {
639  this->hessian(p, time, output, this->_subdomain_ids.get());
640 }
641 
642 
643 
644 void MeshFunction::hessian (const Point & p,
645  const Real,
646  std::vector<Tensor> & output,
647  const std::set<subdomain_id_type> * subdomain_ids)
648 {
649  libmesh_assert (this->initialized());
650 
651  // resize the output vector to the number of output values
652  // that the user told us
653  output.resize (this->_system_vars.size());
654 
655  const Elem * element = this->find_element(p,subdomain_ids);
656 
657  if (!element)
658  {
659  libmesh_error_msg_if(!_out_of_mesh_mode,
660  "MeshFunction couldn't find element at p=" <<
661  p << ", but is not in out-of-mesh mode");
662  libmesh_assert_equal_to (_out_of_mesh_value.size(),
663  this->_system_vars.size());
664  for (auto i : index_range(this->_system_vars))
665  output[i] = Tensor(_out_of_mesh_value[i]);
666  return;
667  }
668  else
669  {
670  if(element->infinite())
671  libmesh_warning("Warning: Requested the Hessian of an Infinite element."
672  << "Second derivatives for Infinite elements"
673  << " are not yet implemented!"
674  << std::endl);
675 
676  {
677  const unsigned int dim = element->dim();
678 
679 
680  // Get local coordinates to feed these into compute_data().
681  // Note that the fe_type can safely be used from the 0-variable,
682  // since the inverse mapping is the same for all FEFamilies
683  const Point mapped_point (FEMap::inverse_map (dim, element,
684  p));
685 
686  std::vector<Point> point_list (1, mapped_point);
687 
688  // loop over all vars
689  for (auto index : index_range(this->_system_vars))
690  {
691  // the data for this variable
692  const unsigned int var = _system_vars[index];
693 
694  if (var == libMesh::invalid_uint)
695  {
697  index < _out_of_mesh_value.size());
698  output[index] = Tensor(_out_of_mesh_value(index));
699  continue;
700  }
701  const FEType & fe_type = this->_dof_map.variable_type(var);
702 
703  std::unique_ptr<FEBase> point_fe (FEBase::build(dim, fe_type));
704  const std::vector<std::vector<RealTensor>> & d2phi =
705  point_fe->get_d2phi();
706  point_fe->reinit(element, &point_list);
707 
708  // where the solution values for the var-th variable are stored
709  std::vector<dof_id_type> dof_indices;
710  this->_dof_map.dof_indices (element, dof_indices, var);
711 
712  // interpolate the solution
713  Tensor hess;
714 
715  for (auto i : index_range(dof_indices))
716  hess.add_scaled(d2phi[i][0], this->_vector(dof_indices[i]));
717 
718  output[index] = hess;
719  }
720  }
721  }
722 }
723 #endif
724 
726  const std::set<subdomain_id_type> * subdomain_ids) const
727 {
728  // Ensure that in the case of a master mesh function, the
729  // out-of-mesh mode is enabled either for both or for none. This is
730  // important because the out-of-mesh mode is also communicated to
731  // the point locator. Since this is time consuming, enable it only
732  // in debug mode.
733 #ifdef DEBUG
734  if (this->_master != nullptr)
735  {
736  const MeshFunction * master =
737  cast_ptr<const MeshFunction *>(this->_master);
738  libmesh_error_msg_if(_out_of_mesh_mode!=master->_out_of_mesh_mode,
739  "ERROR: If you use out-of-mesh-mode in connection with master mesh "
740  "functions, you must enable out-of-mesh mode for both the master and the slave mesh function.");
741  }
742 #endif
743 
744  // locate the point in the other mesh
745  const Elem * element = (*_point_locator)(p, subdomain_ids);
746 
747  // Make sure that the element found is evaluable
748  return this->check_found_elem(element, p);
749 }
750 
751 std::set<const Elem *> MeshFunction::find_elements(const Point & p,
752  const std::set<subdomain_id_type> * subdomain_ids) const
753 {
754  // Ensure that in the case of a master mesh function, the
755  // out-of-mesh mode is enabled either for both or for none. This is
756  // important because the out-of-mesh mode is also communicated to
757  // the point locator. Since this is time consuming, enable it only
758  // in debug mode.
759 #ifdef DEBUG
760  if (this->_master != nullptr)
761  {
762  const MeshFunction * master =
763  cast_ptr<const MeshFunction *>(this->_master);
764  libmesh_error_msg_if(_out_of_mesh_mode!=master->_out_of_mesh_mode,
765  "ERROR: If you use out-of-mesh-mode in connection with master mesh "
766  "functions, you must enable out-of-mesh mode for both the master and the slave mesh function.");
767  }
768 #endif
769 
770  // locate the point in the other mesh
771  std::set<const Elem *> candidate_elements;
772  std::set<const Elem *> final_candidate_elements;
773  (*_point_locator)(p, candidate_elements, subdomain_ids);
774 
775  // For each candidate Elem, if it is evaluable, add it to the set of
776  // final candidate Elems.
777  for (const auto & element : candidate_elements)
778  final_candidate_elements.insert(this->check_found_elem(element, p));
779 
780  return final_candidate_elements;
781 }
782 
783 const Elem *
784 MeshFunction::check_found_elem(const Elem * element, const Point & p) const
785 {
786  // If the PointLocator did not find an Element containing Point p,
787  // OR if the PointLocator found a local element containting Point p,
788  // we can simply return it.
789  if (!element || (element->processor_id() == this->processor_id()))
790  return element;
791 
792  // Otherwise, the PointLocator returned a valid but non-local
793  // element. Therefore, we have to do some further checks:
794  //
795  // 1.) If we have a SERIAL _vector, then we can just return the
796  // non-local element, because all the DOFs are available.
797  if (_vector.type() == SERIAL)
798  return element;
799 
800  // 2.) If we have a GHOSTED _vector, then we can return a non-local
801  // Element provided that all of its DOFs are ghosted on this
802  // processor. That should be faster than the other option, which
803  // is to search through all the Elem's point_neighbors() for a
804  // suitable local Elem.
805  if (_vector.type() == GHOSTED && _dof_map.is_evaluable(*element))
806  return element;
807 
808  // 3.) If we have a PARALLEL vector, then we search the non-local
809  // Elem's point neighbors for a local one to return instead. If
810  // we don't eventually find one, we just return nullptr.
811  std::set<const Elem *> point_neighbors;
812  element->find_point_neighbors(p, point_neighbors);
813  element = nullptr;
814  for (const auto & elem : point_neighbors)
815  if (elem->processor_id() == this->processor_id())
816  {
817  element = elem;
818  break;
819  }
820 
821  return element;
822 }
823 
825 {
826  libmesh_assert (this->initialized());
827  return *_point_locator;
828 }
829 
831 {
832  libmesh_assert (this->initialized());
833  return *_point_locator;
834 }
835 
837 {
838  libmesh_assert (this->initialized());
839  _point_locator->enable_out_of_mesh_mode();
840  _out_of_mesh_mode = true;
842 }
843 
845 {
846  DenseVector<Number> v(1);
847  v(0) = value;
848  this->enable_out_of_mesh_mode(v);
849 }
850 
852 {
853  libmesh_assert (this->initialized());
854  _point_locator->disable_out_of_mesh_mode();
855  _out_of_mesh_mode = false;
856 }
857 
859 {
860  _point_locator->set_close_to_point_tol(tol);
861  _point_locator->set_contains_point_tol(tol);
862 }
863 
865 {
866  _point_locator->unset_close_to_point_tol();
867 }
868 
869 void MeshFunction::set_subdomain_ids(const std::set<subdomain_id_type> * subdomain_ids)
870 {
871  if (subdomain_ids)
872  _subdomain_ids = std::make_unique<std::set<subdomain_id_type>>(*subdomain_ids);
873  else
874  _subdomain_ids.reset();
875 }
876 
877 } // namespace libMesh
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
std::unique_ptr< std::set< subdomain_id_type > > _subdomain_ids
A default set of subdomain ids in which to search for points.
FEFamily family
The type of finite element.
Definition: fe_type.h:228
This is the EquationSystems class.
const EquationSystems & _eqn_systems
The equation systems handler, from which the data are gathered.
virtual std::unique_ptr< FunctionBase< Number > > clone() const override
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
Definition: type_vector.h:629
const NumericVector< Number > & _vector
A reference to the vector that holds the data that is to be interpolated.
bool _out_of_mesh_mode
true if out-of-mesh mode is enabled.
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:303
std::unique_ptr< PointLocatorBase > sub_point_locator() const
Definition: mesh_base.C:1826
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
Definition: dof_map.C:2201
unsigned int dim
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition: fe_map.C:1512
class FEComputeData hides arbitrary data to be passed to and from children of FEBase through the FEIn...
const Point & p
Holds the point where the data are to be computed.
const DofMap & _dof_map
Need access to the DofMap of the other system.
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:396
const Elem * find_element(const Point &p, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
Helper function to reduce code duplication.
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
const FunctionBase * _master
Const pointer to our master, initialized to nullptr.
bool _initialized
When init() was called so that everything is ready for calls to operator() (...), then this bool is t...
Gradient gradient(const Point &p, const Real time=0.)
std::vector< Gradient > dshape
Storage for the computed shape derivative values.
This class defines a vector in LIBMESH_DIM dimensional Real or Complex space.
~MeshFunction()
Destructor.
std::vector< std::vector< Real > > local_transform
Storage for local to global mapping at p.
The libMesh namespace provides an interface to certain functionality in the library.
void disable_out_of_mesh_mode()
Disables out-of-mesh mode.
Real get_close_to_point_tol() const
Get the close-to-point tolerance.
This is the MeshBase class.
Definition: mesh_base.h:80
void _gradient_on_elem(const Point &p, const Elem *element, std::vector< Gradient > &output)
Helper function for finding a gradient as evaluated from a specific element.
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
DenseVector< Number > _out_of_mesh_value
Value to return outside the mesh if out-of-mesh mode is enabled.
void enable_out_of_mesh_mode(const DenseVector< Number > &value)
Enables out-of-mesh mode.
virtual void clear() override
Clears the function.
std::set< const Elem * > find_elements(const Point &p, const std::set< subdomain_id_type > *subdomain_ids=nullptr) const
std::map< const Elem *, Number > discontinuous_value(const Point &p, const Real time=0.)
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
This function finds all active elements (including this one) which are in the same manifold as this e...
Definition: elem.C:967
static void compute_data(const unsigned int dim, const FEType &fe_t, const Elem *elem, FEComputeData &data)
Lets the appropriate child of FEBase compute the requested data for the input specified in data...
NumberVectorValue Gradient
void unset_point_locator_tolerance()
Turn off the user-specified PointLocator tolerance.
virtual void init() override
Override the FunctionBase::init() member function.
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
libmesh_assert(ctx)
const FEType & variable_type(const unsigned int i) const
Definition: dof_map.h:2388
const PointLocatorBase & get_point_locator() const
This is the base class for point locators.
An object whose state is distributed along a set of processors.
void add_scaled(const TypeTensor< T2 > &, const T &)
Add a scaled tensor to this tensor without creating a temporary.
Definition: type_tensor.h:858
std::vector< Number > shape
Storage for the computed shape function values.
ParallelType type() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
NumberTensorValue Tensor
virtual unsigned short dim() const =0
virtual Number operator()(const Point &p, const Real time=0.) override
bool initialized() const
MeshFunction(const EquationSystems &eqn_systems, const NumericVector< Number > &vec, const DofMap &dof_map, std::vector< unsigned int > vars, const FunctionBase< Number > *master=nullptr)
Constructor for mesh based functions with vectors as return value.
Definition: mesh_function.C:42
const MeshBase & get_mesh() const
static const bool value
Definition: xdr_io.C:55
virtual unsigned int size() const override final
Definition: dense_vector.h:104
virtual bool infinite() const =0
This class provides function-like objects for data distributed over a mesh.
Definition: mesh_function.h:54
void set_point_locator_tolerance(Real tol)
We may want to specify a tolerance for the PointLocator to use, since in some cases the point we want...
const Elem * check_found_elem(const Elem *element, const Point &p) const
Helper function that is called by MeshFunction::find_element() and MeshFunction::find_elements() to e...
processor_id_type processor_id() const
void enable_derivative()
Enable the computation of shape gradients (dshape).
processor_id_type processor_id() const
Definition: dof_object.h:881
std::map< const Elem *, Gradient > discontinuous_gradient(const Point &p, const Real time=0.)
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
Tensor hessian(const Point &p, const Real time=0.)
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:153
void set_subdomain_ids(const std::set< subdomain_id_type > *subdomain_ids)
Choose a default list of subdomain ids to be searched for points.
std::unique_ptr< PointLocatorBase > _point_locator
A point locator is needed to locate the points in the mesh.
bool is_evaluable(const DofObjectSubclass &obj, unsigned int var_num=libMesh::invalid_uint) const
Definition: dof_map.C:2673
This class defines a tensor in LIBMESH_DIM dimensional Real or Complex space.
const std::vector< unsigned int > _system_vars
The indices of the variables within the other system for which data are to be gathered.