navier_stokes_flux_control_elements.h
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //Include guard to prevent multiple inclusions of the header
31 #ifndef OOMPH_NAVIER_STOKES_FLUX_CONTROL_ELEMENTS
32 #define OOMPH_NAVIER_STOKES_FLUX_CONTROL_ELEMENTS
33 
34 // Config header generated by autoconfig
35 #ifdef HAVE_CONFIG_H
36  #include <oomph-lib-config.h>
37 #endif
38 
39 //OOMPH-LIB headers
40 #include "../generic/nodes.h"
41 #include "../navier_stokes/navier_stokes_surface_power_elements.h"
42 
43 namespace oomph
44 {
45 
46 //////////////////////////////////////////////////////////////////////////
47 //////////////////////////////////////////////////////////////////////////
48 //////////////////////////////////////////////////////////////////////////
49 
50 
51 //======================================================================
52 /// A template free base class for an element to imposes an applied
53 /// boundary pressure to the Navier-Stokes equations in order to
54 /// control a volume flux when used in conjunction with a
55 /// NetFluxControlElement or
56 /// NetFluxControlElementForWomersleyPressureControl).
57 //======================================================================
59 public virtual GeneralisedElement
60 {
61  public:
62 
63  /// Empty constructor
65 
66  /// Empty virtual destructor
68 
69  /// Pure virtual function to calculate integral of the volume flux
70  virtual double get_volume_flux()=0;
71 
72  /// \short Function adds to the external data the Data object whose
73  /// single value is the pressure applied by the element
74  void add_pressure_data(Data* pressure_data_pt)
75  {
76  Pressure_data_id = add_external_data(pressure_data_pt);
77  }
78 
79  protected:
80 
81  /// \short Access function gives id of external Data object whose
82  /// single value is the pressure applied by the element
83  unsigned& pressure_data_id() {return Pressure_data_id;}
84 
85  private:
86 
87  /// \short Id of external Data object whose single value is the
88  /// pressure applied by the elements
89  unsigned Pressure_data_id;
90 
91 };
92 
93 
94 
95 //////////////////////////////////////////////////////////////////////////
96 //////////////////////////////////////////////////////////////////////////
97 //////////////////////////////////////////////////////////////////////////
98 
99 
100 
101 //======================================================================
102 /// A class for an element that controls the net fluid flux across a
103 /// boundary by the imposition of an unknown applied pressure to the
104 /// Navier-Stokes equations. This element is used with a mesh of
105 /// NavierStokesFluxControlElement elements which are attached
106 /// to the boundary.
107 /// Note: fill_in_contribution_to_jacobian() does not calculate
108 /// Jacobian contributions for this element as they are calculated by
109 /// NavierStokesFluxControlElement::fill_in_contribution_to_jacobian(...)
110 //======================================================================
112 {
113  public:
114 
115  /// \short Constructor takes a mesh of
116  /// TemplateFreeNavierStokesFluxControlElementBase elements
117  /// that impose the pressure to control the flux, plus a pointer to
118  /// the double which contains the desired flux value
119  NetFluxControlElement(Mesh* flux_control_mesh_pt,
120  double* prescribed_flux_value_pt) :
121  Flux_control_mesh_pt(flux_control_mesh_pt),
122  Prescribed_flux_value_pt(prescribed_flux_value_pt)
123  {
124  // Construct Pressure_data_pt
125  Pressure_data_pt = new Data(1);
126 
127  // Add the new Data to internal Data for this element
128  add_internal_data(Pressure_data_pt);
129 
130  // There's no need to add the external data for this element since
131  // this elements Jacobian contributions are calculated by the
132  // NavierStokesFluxControlElements
133 
134  // Loop over elements in the Flux_control_mesh to add this element's
135  // Data to the external Data in the elements in the flux control mesh
136  unsigned n_el = Flux_control_mesh_pt->nelement();
137  for (unsigned e=0; e<n_el; e++)
138  {
139  // Get pointer to the element
140  GeneralisedElement* el_pt = Flux_control_mesh_pt->element_pt(e);
141 
142  // Perform cast to TemplateFreeNavierStokesFluxControlElementBase pointer
144  dynamic_cast<TemplateFreeNavierStokesFluxControlElementBase*>(el_pt);
145 
146  flux_el_pt->add_pressure_data(Pressure_data_pt);
147  }
148 
149  // Default value for Dof_number_for_unknown, indiating that it's
150  // uninitialised
151  Dof_number_for_unknown = UINT_MAX;
152  }
153 
154 
155  /// Empty Destructor - Data gets deleted automatically
157 
158  /// Broken copy constructor
160  {
161  BrokenCopy::broken_copy("NetFluxControlElement");
162  }
163 
164 
165  /// Broken assignment operator
166 //Commented out broken assignment operator because this can lead to a conflict warning
167 //when used in the virtual inheritence hierarchy. Essentially the compiler doesn't
168 //realise that two separate implementations of the broken function are the same and so,
169 //quite rightly, it shouts.
170  /*void operator=(const NetFluxControlElement&)
171  {
172  BrokenCopy::broken_assign("NetFluxControlElement");
173  }*/
174 
175  /// Spatial dimension of the problem
176  unsigned dim() const {return Dim;}
177 
178  /// \short Function to return a pointer to the Data object whose
179  /// single value is the pressure applied by the
180  /// NavierStokesFluxControlElement elements
181  Data* pressure_data_pt() const {return Pressure_data_pt;}
182 
183 
184  /// \short Add the element's contribution to its residual vector:
185  /// i.e. the flux constraint.
187  {
188  //Call the generic routine
189  fill_in_generic_residual_contribution_flux_control(residuals);
190  }
191 
192  /// \short This function returns the residuals, but adds nothing to the
193  /// Jacobian as this element's Jacobian contributions are calculated by
194  /// the NavierStokesFluxControlElements which impose the traction
195  /// used to control the flux.
197  DenseMatrix<double> &jacobian)
198  {
199  //Call the generic routine
200  fill_in_generic_residual_contribution_flux_control(residuals);
201  }
202 
203 
204  /// \short The number of "DOF types" that degrees of freedom in this element
205  /// are sub-divided into - it's set to Dof_number_for_unknown+1
206  /// because it's expected this element is added to a fluid mesh
207  /// containing navier stokes elements
208  unsigned ndof_types() const
209  {
210 #ifdef PARANOID
211  if (Dof_number_for_unknown==UINT_MAX)
212  {
213  std::ostringstream error_message;
214  error_message << "Dof_number_for_unknown hasn't been set yet!\n"
215  << "Please do so using the dof_number_for_unknown()\n"
216  << "access function\n";
217  throw OomphLibError(error_message.str(),
218  OOMPH_CURRENT_FUNCTION,
219  OOMPH_EXCEPTION_LOCATION);
220  }
221 #endif
222  return Dof_number_for_unknown+1;
223  }
224 
225  /// \short Function to set / get the nodal value of the "DOF type" to which
226  /// the degree of freedom in this element (the pressure that enforces
227  /// the required volume flux!) is added to.
228  /// This should be set to the Navier-Stokes pressure DOF type
229  /// (usually the dimension of the problem, for example, in 3D, the DOF types
230  /// for single-physics Navier-Stokes elements are usually
231  /// labelled 0, 1, 2, 3 for u, v and w
232  /// velocities and pressure respectively. It is important to note that this is
233  /// dimension dependent, so should not be hard coded in!! In particularly,
234  /// this should not simply be
235  /// set to the dimension of the problem if there is further splitting of the
236  /// velocity DOF types) if this element is added to a fluid mesh containing
237  /// Navier-Stokes elements.
238  unsigned& dof_number_for_unknown() {return Dof_number_for_unknown; }
239 
240  /// \short Create a list of pairs for all unknowns in this element,
241  /// so that the first entry in each pair contains the global equation
242  /// number of the unknown, while the second one contains the number
243  /// of the "DOF type" that this unknown is associated with.
244  /// (Function can obviously only be called if the equation numbering
245  /// scheme has been set up.) The single degree of freedom is given the
246  /// DOF type number of Dof_number_for_unknown since it's expected this
247  /// unknown is added to the Navier-Stokes pressure DOF block (it is also
248  /// assumed that the user has set the Dof_number_for_unknown variable to
249  /// the velocity DOF type using the function dof_number_for_unknown()).
251  std::list<std::pair<unsigned long, unsigned> >& dof_lookup_list) const
252  {
253 #ifdef PARANOID
254  if (Dof_number_for_unknown==UINT_MAX)
255  {
256  std::ostringstream error_message;
257  error_message << "Dof_number_for_unknown hasn't been set yet!\n"
258  << "Please do so using the dof_number_for_unknown()\n"
259  << "access function\n";
260  throw OomphLibError(error_message.str(),
261  OOMPH_CURRENT_FUNCTION,
262  OOMPH_EXCEPTION_LOCATION);
263  }
264 #endif
265 
266  // pair to store dof lookup prior to being added to list
267  std::pair<unsigned,unsigned> dof_lookup;
268 
269  dof_lookup.first = this->eqn_number(0);
270  dof_lookup.second = Dof_number_for_unknown;
271 
272  // add to list
273  dof_lookup_list.push_front(dof_lookup);
274  }
275 
276  protected:
277 
278  ///\short This function returns the residuals for the
279  ///flux control master element.
281  Vector<double> &residuals)
282  {
283 
284  // Initialise volume flux
285  double volume_flux = 0.0;
286 
287  // Loop over elements in Flux_control_mesh_pt and calculate flux
288  unsigned n_el = Flux_control_mesh_pt->nelement();
289  for (unsigned e=0; e<n_el; e++)
290  {
291  // Get a pointer to the element
292  GeneralisedElement* el_pt = Flux_control_mesh_pt->element_pt(e);
293 
294  // Cast to NavierStokesFluxControlElement
296  flux_control_el_pt =
298 
299 #ifdef PARANOID
300  if (flux_control_el_pt==0)
301  {
302  throw OomphLibError(
303  "Element must be used with a mesh of NavierStokesFluxControlElements",
304  OOMPH_CURRENT_FUNCTION,
305  OOMPH_EXCEPTION_LOCATION);
306  }
307 #endif
308 
309  // Add the elemental volume flux
310  volume_flux += flux_control_el_pt->get_volume_flux();
311  }
312 
313  residuals[0] += *Prescribed_flux_value_pt - volume_flux;
314  }
315 
316 
317 private:
318 
319  /// \short Data object whose single value is the pressure
320  /// applied by the elements in the Flux_control_mesh_pt
322 
323  /// \short Mesh of elements which impose the pressure which controls
324  /// the net flux
326 
327  /// \short Pointer to the value that stores the prescribed flux
329 
330  /// \short The id number of the "DOF type" to which the degree
331  /// of freedom in this element is added to. This should be set to the
332  /// number id of the Navier-Stokes pressure DOF block (which is dimension
333  /// dependent!) if this element is added to a fluid mesh
334  /// containing navier stokes elements
336 
337  /// spatial dim of NS system
338  unsigned Dim;
339 };
340 
341 
342 
343 
344 //////////////////////////////////////////////////////////////////////////
345 //////////////////////////////////////////////////////////////////////////
346 //////////////////////////////////////////////////////////////////////////
347 
348 
349 
350 //======================================================================
351 /// A class of element to impose an applied boundary pressure to
352 /// Navier-Stokes elements to control to control a volume flux. A mesh of
353 /// these elements are used in conjunction with a NetFluxControlElement.
354 /// The template arguement ELEMENT is a Navier-Stokes "bulk" element.
355 ///
356 /// Note: This element calculates Jacobian contributions for both itself
357 /// and also for the NetFluxControlElement with respect to its unknowns.
358 //======================================================================
359 template <class ELEMENT>
362  public virtual NavierStokesSurfacePowerElement<ELEMENT>
363 {
364  public:
365 
366  ///Constructor, which takes a "bulk" element and face index
368  const int &face_index,
369  const bool&
370  called_from_refineable_constructor=false) :
371  NavierStokesSurfacePowerElement<ELEMENT>(element_pt, face_index)
372  {
373 #ifdef PARANOID
374  {
375  //Check that the element is not a refineable 3d element
376  if (!called_from_refineable_constructor)
377  {
378  ELEMENT* elem_pt = new ELEMENT;
379  //If it's three-d
380  if(elem_pt->dim()==3)
381  {
382  //Is it refineable
383  if(dynamic_cast<RefineableElement*>(elem_pt))
384  {
385  //Throw Error
386  std::ostringstream error_message;
387  error_message
388  << "This element does not work properly with refineable bulk \n"
389  << "elements in 3D. Please use the refineable version\n"
390  << "instead.\n";
391  throw OomphLibError(
392  error_message.str(),
393  OOMPH_CURRENT_FUNCTION,
394  OOMPH_EXCEPTION_LOCATION);
395  }
396  }
397  }
398  }
399 #endif
400 
401  //Set the dimension from the dimension of the first node (since Dim is
402  //private in the parent class)
403  Dim = this->node_pt(0)->ndim();
404  }
405 
406  /// Destructor should not delete anything
408 
409  ///This function returns just the residuals
411  {
412  //Call the generic residuals function using a dummy matrix argument
413  fill_in_generic_residual_contribution_fluid_traction(
415  }
416 
417  ///\short This function returns the residuals and the Jacobian
418  /// including the Jacobian contribution from the flux control
419  ///master element with respect to dof in this
420  ///element
422  DenseMatrix<double> &jacobian)
423  {
424  //Call the generic routine
425  fill_in_generic_residual_contribution_fluid_traction(residuals,jacobian,1);
426  }
427 
428  /// Function to get the integral of the volume flux
430  {
432  }
433 
434 protected:
435 
436 
437  /// \short Access function that returns the local equation numbers
438  /// for velocity components.
439  /// u_local_eqn(n,i) = local equation number or < 0 if pinned.
440  /// The default is to asssume that n is the local node number
441  /// and the i-th velocity component is the i-th unknown stored at the node.
442  virtual inline int u_local_eqn(const unsigned &n, const unsigned &i)
443  {return this->nodal_local_eqn(n,i);}
444 
445  ///\short Function to compute the shape and test functions and to return
446  ///the Jacobian of mapping
447  inline double shape_and_test_at_knot(const unsigned &ipt,
448  Shape &psi, Shape &test)
449  const
450  {
451  //Find number of nodes
452  unsigned n_node = this->nnode();
453  //Calculate the shape functions
454  this->shape_at_knot(ipt,psi);
455  //Set the test functions to be the same as the shape functions
456  for(unsigned i=0;i<n_node;i++) {test[i] = psi[i];}
457  //Return the value of the jacobian
458  return this->J_eulerian_at_knot(ipt);
459  }
460 
461 
462  ///\short This function returns the residuals for the traction function
463  ///flag=1(or 0): do (or don't) compute the Jacobian as well.
464  ///This function also calculates the Jacobian contribution for the
465  ///NetFluxControlElement
467  Vector<double> &residuals,
468  DenseMatrix<double> &jacobian,
469  unsigned flag)
470  {
471  //Find out how many nodes there are
472  unsigned n_node = this->nnode();
473 
474  //Set up memory for the shape and test functions
475  Shape psif(n_node), testf(n_node);
476 
477  //Set the value of n_intpt
478  unsigned n_intpt = this->integral_pt()->nweight();
479 
480  //Integers to store local equation numbers
481  int local_eqn=0;
482 
483  // Get the pressure at the outflow
484  double pressure = this->external_data_pt(pressure_data_id())->value(0);
485 
486  //Loop over the integration points
487  for(unsigned ipt=0;ipt<n_intpt;ipt++)
488  {
489  //Get the integral weight
490  double w = this->integral_pt()->weight(ipt);
491 
492  //Find the shape and test functions and return the Jacobian
493  //of the mapping
494  double J = shape_and_test_at_knot(ipt,psif,testf);
495 
496  //Premultiply the weights and the Jacobian
497  double W = w*J;
498 
499  // Get the outer unit normal
500  Vector<double> unit_normal(Dim);
501  this->outer_unit_normal(ipt, unit_normal);
502 
503  // Calculate the traction
504  Vector<double> traction(Dim);
505  for (unsigned i=0; i<Dim; i++)
506  {
507  traction[i] = -pressure*unit_normal[i];
508  }
509 
510  //Loop over the test functions
511  for(unsigned l=0;l<n_node;l++)
512  {
513  //Loop over the velocity components
514  for(unsigned i=0;i<Dim;i++)
515  {
516  local_eqn = u_local_eqn(l,i);
517 
518  /*IF it's not a boundary condition*/
519  if(local_eqn >= 0)
520  {
521  //Add the user-defined traction terms
522  residuals[local_eqn] += traction[i]*testf[l]*W;
523 
524  //Calculate the Jacobian if required. It is assumed
525  //that traction DOES NOT depend upon velocities
526  //or pressures in the Navier Stokes elements, but
527  //depend in the Data value which holds the
528  //pressure.
529  if (flag)
530  {
531  //Get equation number of the pressure data unknown
532  int local_unknown =
534 
535  //IF it's not a boundary condition
536  if(local_unknown >= 0)
537  {
538  //Add to Jacobian for this element
539  double jac_contribution = -unit_normal[i]*testf[l]*W;
540  jacobian(local_eqn,local_unknown) += jac_contribution;
541 
542  //Add to Jacobian for master element
543  jacobian(local_unknown,local_eqn) += jac_contribution;
544  }
545  }
546  }
547  } //End of loop over dimension
548  } //End of loop over shape functions
549  }
550  }
551 
552 protected:
553 
554  ///The highest dimension of the problem
555  unsigned Dim;
556 
557 };
558 
559 
560 
561 /////////////////////////////////////////////////////////////////////////
562 /////////////////////////////////////////////////////////////////////////
563 /////////////////////////////////////////////////////////////////////////
564 
565 
566 
567 
568 //======================================================================
569 /// A class of element to impose an applied boundary pressure to
570 /// Navier-Stokes elements to control to control a volume flux. A mesh of
571 /// these elements are used in conjunction with a NetFluxControlElement.
572 /// The template arguement ELEMENT is a Navier-Stokes "bulk" element.
573 ///
574 /// Note: This element calculates Jacobian contributions for both itself
575 /// and also for the NetFluxControlElement with respect to its unknowns.
576 ///
577 /// THIS IS THE REFINEABLE VERSION.
578 //======================================================================
579 template <class ELEMENT>
581 public virtual NavierStokesFluxControlElement<ELEMENT>,
583 {
584  public:
585 
586  ///Constructor, which takes a "bulk" element and the face index
588  const int &face_index) :
589  NavierStokesSurfacePowerElement<ELEMENT>(element_pt, face_index),
590  // we're calling this from the constructor of the refineable version.
591  NavierStokesFluxControlElement<ELEMENT>(element_pt, face_index,true)
592  {}
593 
594  /// Destructor should not delete anything
596 
597 
598  /// \short Number of continuously interpolated values are the
599  /// same as those in the bulk element.
600  unsigned ncont_interpolated_values() const
601  {
602  return dynamic_cast<ELEMENT*>(this->bulk_element_pt())->
603  ncont_interpolated_values();
604  }
605 
606  ///This function returns just the residuals
608  {
609  //Call the generic residuals function using a dummy matrix argument
610  refineable_fill_in_generic_residual_contribution_fluid_traction(
612  }
613 
614  ///\short This function returns the residuals and the Jacobian
615  /// including the Jacobian contribution from the flux control
616  ///master element with respect to dof in this
617  ///element
619  DenseMatrix<double> &jacobian)
620  {
621  //Call the generic routine
622  refineable_fill_in_generic_residual_contribution_fluid_traction(residuals,
623  jacobian,1);
624  }
625 
626 protected:
627 
628 
629  ///\short This function returns the residuals for the traction function
630  ///flag=1(or 0): do (or don't) compute the Jacobian as well.
631  ///This function also calculates the Jacobian contribution for the
632  ///NetFluxControlElement
634  Vector<double> &residuals,
635  DenseMatrix<double> &jacobian,
636  unsigned flag)
637  {
638  // Get the indices at which the velocity components are stored
639  unsigned u_nodal_index[this->Dim];
640  for(unsigned i=0;i<this->Dim;i++)
641  {
642  u_nodal_index[i] = dynamic_cast<ELEMENT*>(
643  this->bulk_element_pt())->u_index_nst(i);
644  }
645 
646  //Pointer to hang info object
647  HangInfo* hang_info_pt=0;
648 
649  //Find out how many nodes there are
650  unsigned n_node = this->nnode();
651 
652  //Set up memory for the shape and test functions
653  Shape psif(n_node), testf(n_node);
654 
655  //Set the value of n_intpt
656  unsigned n_intpt = this->integral_pt()->nweight();
657 
658  //Integers to store local equation numbers
659  int local_eqn=0;
660 
661  // Get the pressure at the outflow
662  double pressure=this->external_data_pt(this->pressure_data_id())->value(0);
663 
664  //Loop over the integration points
665  for(unsigned ipt=0;ipt<n_intpt;ipt++)
666  {
667  //Get the integral weight
668  double w = this->integral_pt()->weight(ipt);
669 
670  //Find the shape and test functions and return the Jacobian
671  //of the mapping
672  double J = this->shape_and_test_at_knot(ipt,psif,testf);
673 
674  //Premultiply the weights and the Jacobian
675  double W = w*J;
676 
677  // Get the outer unit normal
678  Vector<double> unit_normal(this->Dim);
679  this->outer_unit_normal(ipt, unit_normal);
680 
681  // Calculate the traction
682  Vector<double> traction(this->Dim);
683  for (unsigned i=0; i<this->Dim; i++)
684  {
685  traction[i] = -pressure*unit_normal[i];
686  }
687 
688 
689 
690  //Number of master nodes and storage for the weight of the shape function
691  unsigned n_master=1; double hang_weight=1.0;
692 
693  //Loop over the nodes for the test functions/equations
694  //----------------------------------------------------
695  for(unsigned l=0;l<n_node;l++)
696  {
697  //Local boolean to indicate whether the node is hanging
698  bool is_node_hanging = this->node_pt(l)->is_hanging();
699 
700  //If the node is hanging
701  if(is_node_hanging)
702  {
703  hang_info_pt = this->node_pt(l)->hanging_pt();
704 
705  //Read out number of master nodes from hanging data
706  n_master = hang_info_pt->nmaster();
707  }
708  //Otherwise the node is its own master
709  else
710  {
711  n_master = 1;
712  }
713 
714  //Loop over the master nodes
715  for(unsigned m=0;m<n_master;m++)
716  {
717  // Loop over velocity components for equations
718  for(unsigned i=0;i<this->Dim;i++)
719  {
720  //Get the equation number
721  //If the node is hanging
722  if(is_node_hanging)
723  {
724  //Get the equation number from the master node
725  local_eqn = this->local_hang_eqn(hang_info_pt->master_node_pt(m),
726  u_nodal_index[i]);
727  //Get the hang weight from the master node
728  hang_weight = hang_info_pt->master_weight(m);
729  }
730  //If the node is not hanging
731  else
732  {
733  // Local equation number
734  local_eqn = this->nodal_local_eqn(l,u_nodal_index[i]);
735 
736  // Node contributes with full weight
737  hang_weight = 1.0;
738  }
739 
740  //If it's not a boundary condition...
741  if(local_eqn>= 0)
742  {
743 
744  //Add the user-defined traction terms
745  residuals[local_eqn] += traction[i]*testf[l]*W*hang_weight;
746 
747  //Calculate the Jacobian if required. It is assumed
748  //that traction DOES NOT depend upon velocities
749  //or pressures in the Navier Stokes elements, but
750  //depend in the Data value which holds the
751  //pressure.
752  if (flag)
753  {
754  //Get equation number of the pressure data unknown
755  int local_unknown =
756  this->external_local_eqn(this->pressure_data_id(),0);
757 
758  //IF it's not a boundary condition
759  if(local_unknown >= 0)
760  {
761  //Add to Jacobian for this element
762  double jac_contribution=-unit_normal[i]*testf[l]*W*
763  hang_weight;
764  jacobian(local_eqn,local_unknown) += jac_contribution;
765 
766  //Add to Jacobian for master element
767  jacobian(local_unknown,local_eqn) += jac_contribution;
768  }
769  }
770  }
771  } //End of loop over dimension
772  } // End of loop over master nodes
773  } //End of loop over nodes
774  }
775  }
776 
777 };
778 
779 
780 
781 
782 
783 
784 
785 }
786 
787 #endif
788 
789 
unsigned Dim
The highest dimension of the problem.
A Generalised Element class.
Definition: elements.h:76
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals and the Jacobian including the Jacobian contribution from the flu...
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition: nodes.h:291
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element&#39;s contribution to its residual vector: i.e. the flux constraint.
Mesh * Flux_control_mesh_pt
Mesh of elements which impose the pressure which controls the net flux.
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
unsigned Dof_number_for_unknown
The id number of the "DOF type" to which the degree of freedom in this element is added to...
void fill_in_contribution_to_residuals(Vector< double > &residuals)
This function returns just the residuals.
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals and the Jacobian including the Jacobian contribution from the flu...
NetFluxControlElement(const NetFluxControlElement &dummy)
Broken copy constructor.
cstr elem_len * i
Definition: cfortran.h:607
double get_volume_flux()
Function to get the integral of the volume flux.
A general Finite Element class.
Definition: elements.h:1274
~NavierStokesFluxControlElement()
Destructor should not delete anything.
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:753
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:733
Data * pressure_data_pt() const
Function to return a pointer to the Data object whose single value is the pressure applied by the Nav...
e
Definition: cfortran.h:575
void fill_in_generic_residual_contribution_fluid_traction(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
This function returns the residuals for the traction function flag=1(or 0): do (or don&#39;t) compute the...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals, but adds nothing to the Jacobian as this element&#39;s Jacobian cont...
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Definition: elements.cc:293
unsigned Dim
Dimension of zeta tuples (set by get_dim_helper) – needed because we store the scalar coordinates in...
Definition: multi_domain.cc:66
unsigned ncont_interpolated_values() const
Number of continuously interpolated values are the same as those in the bulk element.
double get_volume_flux()
Get integral of volume flux.
unsigned & dof_number_for_unknown()
Function to set / get the nodal value of the "DOF type" to which the degree of freedom in this elemen...
virtual double get_volume_flux()=0
Pure virtual function to calculate integral of the volume flux.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
This function returns just the residuals.
void fill_in_generic_residual_contribution_flux_control(Vector< double > &residuals)
This function returns the residuals for the flux control master element.
virtual int u_local_eqn(const unsigned &n, const unsigned &i)
Access function that returns the local equation numbers for velocity components. u_local_eqn(n,i) = local equation number or < 0 if pinned. The default is to asssume that n is the local node number and the i-th velocity component is the i-th unknown stored at the node.
NavierStokesFluxControlElement(FiniteElement *const &element_pt, const int &face_index, const bool &called_from_refineable_constructor=false)
Constructor, which takes a "bulk" element and face index.
void refineable_fill_in_generic_residual_contribution_fluid_traction(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
This function returns the residuals for the traction function flag=1(or 0): do (or don&#39;t) compute the...
unsigned & pressure_data_id()
Access function gives id of external Data object whose single value is the pressure applied by the el...
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
Definition: elements.h:709
NetFluxControlElement(Mesh *flux_control_mesh_pt, double *prescribed_flux_value_pt)
Constructor takes a mesh of TemplateFreeNavierStokesFluxControlElementBase elements that impose the p...
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:736
RefineableNavierStokesFluxControlElement(FiniteElement *const &element_pt, const int &face_index)
Constructor, which takes a "bulk" element and the face index.
Class that contains data for hanging nodes.
Definition: nodes.h:684
void get_dof_numbers_for_unknowns(std::list< std::pair< unsigned long, unsigned > > &dof_lookup_list) const
Create a list of pairs for all unknowns in this element, so that the first entry in each pair contain...
~NetFluxControlElement()
Empty Destructor - Data gets deleted automatically.
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
Definition: elements.h:662
unsigned Pressure_data_id
Id of external Data object whose single value is the pressure applied by the elements.
unsigned add_internal_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) internal data object to the element and return the index required to obtain it ...
Definition: elements.cc:66
void add_pressure_data(Data *pressure_data_pt)
Function adds to the external data the Data object whose single value is the pressure applied by the ...
~RefineableNavierStokesFluxControlElement()
Destructor should not delete anything.
virtual ~TemplateFreeNavierStokesFluxControlElementBase()
Empty virtual destructor.
unsigned ndof_types() const
The number of "DOF types" that degrees of freedom in this element are sub-divided into - it&#39;s set to ...
double shape_and_test_at_knot(const unsigned &ipt, Shape &psi, Shape &test) const
Function to compute the shape and test functions and to return the Jacobian of mapping.
A general mesh class.
Definition: mesh.h:74
int external_local_eqn(const unsigned &i, const unsigned &j)
Return the local equation number corresponding to the j-th value stored at the i-th external data...
Definition: elements.h:313
unsigned dim() const
Broken assignment operator.
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
Definition: elements.h:228
double * Prescribed_flux_value_pt
Pointer to the value that stores the prescribed flux.
Data * Pressure_data_pt
Data object whose single value is the pressure applied by the elements in the Flux_control_mesh_pt.