spherical_advection_diffusion_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// Copyright (C) 2006-2026 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26// Header file for advection diffusion elements in a spherical polar coordinate
27// system
28#ifndef OOMPH_SPHERICAL_ADV_DIFF_ELEMENTS_HEADER
29#define OOMPH_SPHERICAL_ADV_DIFF_ELEMENTS_HEADER
30
31
32// Config header
33#ifdef HAVE_CONFIG_H
34#include <oomph-lib-config.h>
35#endif
36
37// OOMPH-LIB headers
38#include "generic/nodes.h"
39#include "generic/Qelements.h"
42
43namespace oomph
44{
45 //=============================================================
46 /// A class for all elements that solve the
47 /// Advection Diffusion equations in a spherical polar coordinate system
48 /// using isoparametric elements.
49 /// \f[ Pe \mathbf{w}\cdot(\mathbf{x}) \nabla u = \nabla \cdot \left( \nabla u \right) + f(\mathbf{x}) \f]
50 /// This contains the generic maths. Shape functions, geometric
51 /// mapping etc. must get implemented in derived class.
52 //=============================================================
54 {
55 public:
56 /// Function pointer to source function fct(x,f(x)) --
57 /// x is a Vector!
59 const Vector<double>& x, double& f);
60
61
62 /// Function pointer to wind function fct(x,w(x)) --
63 /// x is a Vector!
65 const Vector<double>& x, Vector<double>& wind);
66
67
68 /// Constructor: Initialise the Source_fct_pt and Wind_fct_pt
69 /// to null and set (pointer to) Peclet number to default
71 {
72 // Set pointer to Peclet number to the default value zero
75 }
76
77 /// Broken copy constructor
80
81 /// Broken assignment operator
83
84 /// Return the index at which the unknown value
85 /// is stored. The default value, 0, is appropriate for single-physics
86 /// problems, when there is only one variable, the value that satisfies
87 /// the spherical advection-diffusion equation.
88 /// In derived multi-physics elements, this function should be overloaded
89 /// to reflect the chosen storage scheme. Note that these equations require
90 /// that the unknown is always stored at the same index at each node.
91 virtual inline unsigned u_index_spherical_adv_diff() const
92 {
93 return 0;
94 }
95
96
97 /// du/dt at local node n.
98 /// Uses suitably interpolated value for hanging nodes.
99 double du_dt_spherical_adv_diff(const unsigned& n) const
100 {
101 // Get the data's timestepper
103
104 // Initialise dudt
105 double dudt = 0.0;
106 // Loop over the timesteps, if there is a non Steady timestepper
108 {
109 // Find the index at which the variable is stored
110 const unsigned u_nodal_index = u_index_spherical_adv_diff();
111
112 // Number of timsteps (past & present)
113 const unsigned n_time = time_stepper_pt->ntstorage();
114
115 for (unsigned t = 0; t < n_time; t++)
116 {
117 dudt +=
119 }
120 }
121 return dudt;
122 }
123
124
125 /// Disable ALE -- empty overload to suppress warning.
126 /// ALE isn't implemented anyway
127 void disable_ALE() {}
128
129 /// Output with default number of plot points
130 void output(std::ostream& outfile)
131 {
132 unsigned nplot = 5;
134 }
135
136 /// Output FE representation of soln: r,z,u at
137 /// nplot^2 plot points
138 void output(std::ostream& outfile, const unsigned& nplot);
139
140
141 /// C_style output with default number of plot points
143 {
144 unsigned n_plot = 5;
146 }
147
148 /// C-style output FE representation of soln: r,z,u at
149 /// n_plot^2 plot points
150 void output(FILE* file_pt, const unsigned& n_plot);
151
152
153 /// Output exact soln: r,z,u_exact at nplot^2 plot points
154 void output_fct(std::ostream& outfile,
155 const unsigned& nplot,
157
158 /// Get error against and norm of exact solution
159 void compute_error(std::ostream& outfile,
161 double& error,
162 double& norm);
163
164 /// Access function: Pointer to source function
169
170
171 /// Access function: Pointer to source function. Const version
176
177
178 /// Access function: Pointer to wind function
183
184
185 /// Access function: Pointer to wind function. Const version
187 {
188 return Wind_fct_pt;
189 }
190
191 // Access functions for the physical constants
192
193 /// Peclet number
194 inline const double& pe() const
195 {
196 return *Pe_pt;
197 }
198
199 /// Pointer to Peclet number
200 inline double*& pe_pt()
201 {
202 return Pe_pt;
203 }
204
205 /// Peclet number multiplied by Strouhal number
206 inline const double& pe_st() const
207 {
208 return *PeSt_pt;
209 }
210
211 /// Pointer to Peclet number multipled by Strouha number
212 inline double*& pe_st_pt()
213 {
214 return PeSt_pt;
215 }
216
217 /// Get source term at (Eulerian) position x. This function is
218 /// virtual to allow overloading in multi-physics problems where
219 /// the strength of the source function might be determined by
220 /// another system of equations
221 inline virtual void get_source_spherical_adv_diff(const unsigned& ipt,
222 const Vector<double>& x,
223 double& source) const
224 {
225 // If no source function has been set, return zero
226 if (Source_fct_pt == 0)
227 {
228 source = 0.0;
229 }
230 else
231 {
232 // Get source strength
233 (*Source_fct_pt)(x, source);
234 }
235 }
236
237 /// Get wind at (Eulerian) position x and/or local coordinate s.
238 /// This function is
239 /// virtual to allow overloading in multi-physics problems where
240 /// the wind function might be determined by
241 /// another system of equations
242 inline virtual void get_wind_spherical_adv_diff(const unsigned& ipt,
243 const Vector<double>& s,
244 const Vector<double>& x,
245 Vector<double>& wind) const
246 {
247 // If no wind function has been set, return zero
248 if (Wind_fct_pt == 0)
249 {
250 for (unsigned i = 0; i < 3; i++)
251 {
252 wind[i] = 0.0;
253 }
254 }
255 else
256 {
257 // Get wind
258 (*Wind_fct_pt)(x, wind);
259 }
260 }
261
262 /// Get flux:
263 /// \f[ \mbox{flux}[i] = \nabla u = \mbox{d}u / \mbox{d} r + 1/r \mbox{d}u / \mbox{d} \theta \f]
264 void get_flux(const Vector<double>& s, Vector<double>& flux) const
265 {
266 // Find out how many nodes there are in the element
267 const unsigned n_node = nnode();
268
269 // Get the nodal index at which the unknown is stored
270 const unsigned u_nodal_index = u_index_spherical_adv_diff();
271
272 // Set up memory for the shape and test functions
274 DShape dpsidx(n_node, 2);
275
276 // Call the derivatives of the shape and test functions
278
279 // Initialise to zero
280 for (unsigned j = 0; j < 2; j++)
281 {
282 flux[j] = 0.0;
283 }
284
285 // Loop over nodes
286 for (unsigned l = 0; l < n_node; l++)
287 {
288 const double u_value = this->nodal_value(l, u_nodal_index);
289 const double r = this->nodal_position(l, 0);
290 // Add in the derivative directions
291 flux[0] += u_value * dpsidx(l, 0);
292 flux[1] += u_value * dpsidx(l, 1) / r;
293 }
294 }
295
296
297 /// Add the element's contribution to its residual vector (wrapper)
299 {
300 // Call the generic residuals function with flag set to 0 and using
301 // a dummy matrix
303 residuals,
306 0);
307 }
308
309
310 /// Add the element's contribution to its residual vector and
311 /// the element Jacobian matrix (wrapper)
313 DenseMatrix<double>& jacobian)
314 {
315 // Call the generic routine with the flag set to 1
318 }
319
320 /// Add the element's contribution to its residual vector and
321 /// the element Jacobian matrix (wrapper) and mass matrix
324 DenseMatrix<double>& jacobian,
326 {
327 // Call the generic routine with the flag set to 2
329 residuals, jacobian, mass_matrix, 2);
330 }
331
332
333 /// Return FE representation of function value u(s) at local coordinate s
335 const Vector<double>& s) const
336 {
337 // Find number of nodes
338 const unsigned n_node = nnode();
339
340 // Get the nodal index at which the unknown is stored
341 const unsigned u_nodal_index = u_index_spherical_adv_diff();
342
343 // Local shape function
345
346 // Find values of shape function
347 shape(s, psi);
348
349 // Initialise value of u
350 double interpolated_u = 0.0;
351
352 // Loop over the local nodes and sum
353 for (unsigned l = 0; l < n_node; l++)
354 {
355 interpolated_u += nodal_value(l, u_nodal_index) * psi[l];
356 }
357
358 return (interpolated_u);
359 }
360
361
362 /// Return derivative of u at point s with respect to all data
363 /// that can affect its value.
364 /// In addition, return the global equation numbers corresponding to the
365 /// data. This is virtual so that it can be overloaded in the
366 /// refineable version
368 const Vector<double>& s,
370 Vector<unsigned>& global_eqn_number)
371 {
372 // Find number of nodes
373 const unsigned n_node = nnode();
374
375 // Get the nodal index at which the unknown is stored
376 const unsigned u_nodal_index = u_index_spherical_adv_diff();
377
378 // Local shape function
380
381 // Find values of shape function
382 shape(s, psi);
383
384 // Find the number of dofs associated with interpolated u
385 unsigned n_u_dof = 0;
386 for (unsigned l = 0; l < n_node; l++)
387 {
389 // If it's positive add to the count
390 if (global_eqn >= 0)
391 {
392 ++n_u_dof;
393 }
394 }
395
396 // Now resize the storage schemes
397 du_ddata.resize(n_u_dof, 0.0);
398 global_eqn_number.resize(n_u_dof, 0);
399
400 // Loop over the nodes again and set the derivatives
401 unsigned count = 0;
402 for (unsigned l = 0; l < n_node; l++)
403 {
404 // Get the global equation number
406 // If it's positive
407 if (global_eqn >= 0)
408 {
409 // Set the global equation number
410 global_eqn_number[count] = global_eqn;
411 // Set the derivative with respect to the unknown
412 du_ddata[count] = psi[l];
413 // Increase the counter
414 ++count;
415 }
416 }
417 }
418
419
420 /// Self-test: Return 0 for OK
421 unsigned self_test();
422
423 protected:
424 /// Shape/test functions and derivs w.r.t. to global coords at
425 /// local coord. s; return Jacobian of mapping
427 const Vector<double>& s,
428 Shape& psi,
429 DShape& dpsidx,
430 Shape& test,
431 DShape& dtestdx) const = 0;
432
433 /// Shape/test functions and derivs w.r.t. to global coords at
434 /// integration point ipt; return Jacobian of mapping
436 const unsigned& ipt,
437 Shape& psi,
438 DShape& dpsidx,
439 Shape& test,
440 DShape& dtestdx) const = 0;
441
442 /// Add the element's contribution to its residual vector only
443 /// (if flag=and/or element Jacobian matrix
446 DenseMatrix<double>& jacobian,
448 unsigned flag);
449
450 // Physical constants
451
452 /// Pointer to global Peclet number
453 double* Pe_pt;
454
455 /// Pointer to global Peclet number multiplied by Strouhal number
456 double* PeSt_pt;
457
458 /// Pointer to source function:
460
461 /// Pointer to wind function:
463
464 private:
465 /// Static default value for the Peclet number
467
468
469 }; // End class SphericalAdvectionDiffusionEquations
470
471
472 ///////////////////////////////////////////////////////////////////////////
473 ///////////////////////////////////////////////////////////////////////////
474 ///////////////////////////////////////////////////////////////////////////
475
476
477 //======================================================================
478 /// QSphericalAdvectionDiffusionElement elements are
479 /// linear/quadrilateral/brick-shaped Axisymmetric Advection Diffusion
480 /// elements with isoparametric interpolation for the function.
481 //======================================================================
482 template<unsigned NNODE_1D>
484 : public virtual QElement<2, NNODE_1D>,
486 {
487 private:
488 /// Static array of ints to hold number of variables at
489 /// nodes: Initial_Nvalue[n]
490 static const unsigned Initial_Nvalue;
491
492 public:
493 /// Constructor: Call constructors for QElement and
494 /// Advection Diffusion equations
499
500 /// Broken copy constructor
503
504 /// Broken assignment operator
506 delete;
507
508 /// Required # of `values' (pinned or dofs)
509 /// at node n
510 inline unsigned required_nvalue(const unsigned& n) const
511 {
512 return Initial_Nvalue;
513 }
514
515 /// Output function:
516 /// r,z,u
521
522 /// Output function:
523 /// r,z,u at n_plot^2 plot points
524 void output(std::ostream& outfile, const unsigned& n_plot)
525 {
527 }
528
529
530 /// C-style output function:
531 /// r,z,u
536
537 /// C-style output function:
538 /// r,z,u at n_plot^2 plot points
543
544 /// Output function for an exact solution:
545 /// r,z,u_exact at n_plot^2 plot points
553
554
555 protected:
556 /// Shape, test functions & derivs. w.r.t. to global coords. Return
557 /// Jacobian.
559 const Vector<double>& s,
560 Shape& psi,
561 DShape& dpsidx,
562 Shape& test,
563 DShape& dtestdx) const;
564
565 /// Shape, test functions & derivs. w.r.t. to global coords. at
566 /// integration point ipt. Return Jacobian.
568 const unsigned& ipt,
569 Shape& psi,
570 DShape& dpsidx,
571 Shape& test,
572 DShape& dtestdx) const;
573
574 }; // End class QSphericalAdvectionDiffusionElement
575
576 // Inline functions:
577
578 //======================================================================
579 /// Define the shape functions and test functions and derivatives
580 /// w.r.t. global coordinates and return Jacobian of mapping.
581 ///
582 /// Galerkin: Test functions = shape functions
583 //======================================================================
584
585 template<unsigned NNODE_1D>
588 Shape& psi,
589 DShape& dpsidx,
590 Shape& test,
591 DShape& dtestdx) const
592 {
593 // Call the geometrical shape functions and derivatives
594 double J = this->dshape_eulerian(s, psi, dpsidx);
595
596 // Set the test functions equal to the shape functions
597 test.shallow_copy_from(psi);
598 dtestdx.shallow_copy_from(dpsidx);
599
600 // Return the jacobian
601 return J;
602 }
603
604
605 //======================================================================
606 /// Define the shape functions and test functions and derivatives
607 /// w.r.t. global coordinates and return Jacobian of mapping.
608 ///
609 /// Galerkin: Test functions = shape functions
610 //======================================================================
611
612 template<unsigned NNODE_1D>
615 Shape& psi,
616 DShape& dpsidx,
617 Shape& test,
618 DShape& dtestdx) const
619 {
620 // Call the geometrical shape functions and derivatives
621 double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
622
623 // Set the test functions equal to the shape functions (pointer copy)
624 test.shallow_copy_from(psi);
625 dtestdx.shallow_copy_from(dpsidx);
626
627 // Return the jacobian
628 return J;
629 }
630
631 ////////////////////////////////////////////////////////////////////////
632 ////////////////////////////////////////////////////////////////////////
633 ////////////////////////////////////////////////////////////////////////
634
635 template<unsigned NNODE_1D>
637 : public virtual QElement<1, NNODE_1D>
638 {
639 public:
640 /// Constructor: Call the constructor for the
641 /// appropriate lower-dimensional QElement
643 };
644
645
646 ////////////////////////////////////////////////////////////////////////
647 ////////////////////////////////////////////////////////////////////////
648 ////////////////////////////////////////////////////////////////////////
649
650 //======================================================================
651 /// A class for elements that allow the imposition of an
652 /// applied Robin boundary condition on the boundaries of Steady
653 /// Axisymmnetric Advection Diffusion Flux elements.
654 /// \f[ -\Delta u \cdot \mathbf{n} + \alpha(r,z) u = \beta(r,z) \f]
655 /// The element geometry is obtained from the FaceGeometry<ELEMENT>
656 /// policy class.
657 //======================================================================
658 template<class ELEMENT>
660 : public virtual FaceGeometry<ELEMENT>,
661 public virtual FaceElement
662 {
663 public:
664 /// Function pointer to the prescribed-beta function fct(x,beta(x))
665 /// -- x is a Vector!
667 const Vector<double>& x, double& beta);
668
669 /// Function pointer to the prescribed-alpha function fct(x,alpha(x))
670 /// -- x is a Vector!
672 const Vector<double>& x, double& alpha);
673
674
675 /// Constructor, takes the pointer to the "bulk" element
676 /// and the index of the face to be created
678 const int& face_index);
679
680
681 /// Broken empty constructor
683 {
684 throw OomphLibError("Don't call empty constructor for "
685 "SphericalAdvectionDiffusionFluxElement",
688 }
689
690 /// Broken copy constructor
693
694 /// Broken assignment operator
696
697 /// Access function for the prescribed-beta function pointer
702
703 /// Access function for the prescribed-alpha function pointer
708
709
710 /// Add the element's contribution to its residual vector
712 {
713 // Call the generic residuals function with flag set to 0
714 // using a dummy matrix
717 }
718
719
720 /// Add the element's contribution to its residual vector and
721 /// its Jacobian matrix
723 DenseMatrix<double>& jacobian)
724 {
725 // Call the generic routine with the flag set to 1
727 residuals, jacobian, 1);
728 }
729
730 /// Specify the value of nodal zeta from the face geometry
731 /// The "global" intrinsic coordinate of the element when
732 /// viewed as part of a geometric object should be given by
733 /// the FaceElement representation, by default (needed to break
734 /// indeterminacy if bulk element is SolidElement)
735 double zeta_nodal(const unsigned& n,
736 const unsigned& k,
737 const unsigned& i) const
738 {
739 return FaceElement::zeta_nodal(n, k, i);
740 }
741
742 /// Output function -- forward to broken version in FiniteElement
743 /// until somebody decides what exactly they want to plot here...
744 void output(std::ostream& outfile)
745 {
747 }
748
749 /// Output function -- forward to broken version in FiniteElement
750 /// until somebody decides what exactly they want to plot here...
751 void output(std::ostream& outfile, const unsigned& nplot)
752 {
754 }
755
756
757 protected:
758 /// Function to compute the shape and test functions and to return
759 /// the Jacobian of mapping between local and global (Eulerian)
760 /// coordinates
761 inline double shape_and_test(const Vector<double>& s,
762 Shape& psi,
763 Shape& test) const
764 {
765 // Find number of nodes
766 unsigned n_node = nnode();
767
768 // Get the shape functions
769 shape(s, psi);
770
771 // Set the test functions to be the same as the shape functions
772 for (unsigned i = 0; i < n_node; i++)
773 {
774 test[i] = psi[i];
775 }
776
777 // Return the value of the jacobian
778 return J_eulerian(s);
779 }
780
781
782 /// Function to compute the shape and test functions and to return
783 /// the Jacobian of mapping between local and global (Eulerian)
784 /// coordinates
785 inline double shape_and_test_at_knot(const unsigned& ipt,
786 Shape& psi,
787 Shape& test) const
788 {
789 // Find number of nodes
790 unsigned n_node = nnode();
791
792 // Get the shape functions
794
795 // Set the test functions to be the same as the shape functions
796 for (unsigned i = 0; i < n_node; i++)
797 {
798 test[i] = psi[i];
799 }
800
801 // Return the value of the jacobian
802 return J_eulerian_at_knot(ipt);
803 }
804
805 /// Function to calculate the prescribed beta at a given spatial
806 /// position
807 void get_beta(const Vector<double>& x, double& beta)
808 {
809 // If the function pointer is zero return zero
810 if (Beta_fct_pt == 0)
811 {
812 beta = 0.0;
813 }
814 // Otherwise call the function
815 else
816 {
817 (*Beta_fct_pt)(x, beta);
818 }
819 }
820
821 /// Function to calculate the prescribed alpha at a given spatial
822 /// position
823 void get_alpha(const Vector<double>& x, double& alpha)
824 {
825 // If the function pointer is zero return zero
826 if (Alpha_fct_pt == 0)
827 {
828 alpha = 0.0;
829 }
830 // Otherwise call the function
831 else
832 {
833 (*Alpha_fct_pt)(x, alpha);
834 }
835 }
836
837 private:
838 /// Add the element's contribution to its residual vector.
839 /// flag=1(or 0): do (or don't) compute the Jacobian as well.
841 Vector<double>& residuals, DenseMatrix<double>& jacobian, unsigned flag);
842
843
844 /// Function pointer to the (global) prescribed-beta function
846
847 /// Function pointer to the (global) prescribed-alpha function
849
850 /// The index at which the unknown is stored at the nodes
852
853
854 }; // End class SphericalAdvectionDiffusionFluxElement
855
856
857 ///////////////////////////////////////////////////////////////////////
858 ///////////////////////////////////////////////////////////////////////
859 ///////////////////////////////////////////////////////////////////////
860
861
862 //===========================================================================
863 /// Constructor, takes the pointer to the "bulk" element and the index
864 /// of the face to be created
865 //===========================================================================
866 template<class ELEMENT>
869 const int& face_index)
870 : FaceGeometry<ELEMENT>(), FaceElement()
871
872 {
873 // Let the bulk element build the FaceElement, i.e. setup the pointers
874 // to its nodes (by referring to the appropriate nodes in the bulk
875 // element), etc.
877
878#ifdef PARANOID
879 {
880 // Check that the element is not a refineable 3d element
881 ELEMENT* elem_pt = dynamic_cast<ELEMENT*>(bulk_el_pt);
882
883 // If it's three-d
884 if (elem_pt->dim() == 3)
885 {
886 // Is it refineable
888 dynamic_cast<RefineableElement*>(elem_pt);
889 if (ref_el_pt != 0)
890 {
891 if (this->has_hanging_nodes())
892 {
893 throw OomphLibError("This flux element will not work correctly if "
894 "nodes are hanging\n",
897 }
898 }
899 }
900 }
901#endif
902
903 // Initialise the prescribed-beta function pointer to zero
904 Beta_fct_pt = 0;
905
906 // Set up U_index_adv_diff. Initialise to zero, which probably won't change
907 // in most cases, oh well, the price we pay for generality
909
910 // Cast to the appropriate AdvectionDiffusionEquation so that we can
911 // find the index at which the variable is stored
912 // We assume that the dimension of the full problem is the same
913 // as the dimension of the node, if this is not the case you will have
914 // to write custom elements, sorry
917
918 // If the cast has failed die
919 if (eqn_pt == 0)
920 {
921 std::string error_string =
922 "Bulk element must inherit from SphericalAdvectionDiffusionEquations.";
923 error_string +=
924 "Nodes are two dimensional, but cannot cast the bulk element to\n";
925 error_string += "SphericalAdvectionDiffusionEquations<2>\n.";
926 error_string +=
927 "If you desire this functionality, you must implement it yourself\n";
928
929 throw OomphLibError(
931 }
932 else
933 {
934 // Read the index from the (cast) bulk element.
935 U_index_adv_diff = eqn_pt->u_index_spherical_adv_diff();
936 }
937 }
938
939
940 //===========================================================================
941 /// Compute the element's residual vector and the (zero) Jacobian
942 /// matrix for the Robin boundary condition:
943 /// \f[ \Delta u \cdot \mathbf{n} + \alpha (\mathbf{x}) = \beta (\mathbf{x}) \f]
944 //===========================================================================
945 template<class ELEMENT>
948 Vector<double>& residuals, DenseMatrix<double>& jacobian, unsigned flag)
949 {
950 // Find out how many nodes there are
951 const unsigned n_node = nnode();
952
953 // Locally cache the index at which the variable is stored
954 const unsigned u_index_spherical_adv_diff = U_index_adv_diff;
955
956 // Set up memory for the shape and test functions
958
959 // Set the value of n_intpt
960 const unsigned n_intpt = integral_pt()->nweight();
961
962 // Set the Vector to hold local coordinates
963 Vector<double> s(1);
964
965 // Integers used to store the local equation number and local unknown
966 // indices for the residuals and jacobians
967 int local_eqn = 0, local_unknown = 0;
968
969 // Loop over the integration points
970 //--------------------------------
971 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
972 {
973 // Assign values of s
974 for (unsigned i = 0; i < 1; i++)
975 {
976 s[i] = integral_pt()->knot(ipt, i);
977 }
978
979 // Get the integral weight
980 double w = integral_pt()->weight(ipt);
981
982 // Find the shape and test functions and return the Jacobian
983 // of the mapping
984 double J = shape_and_test(s, psif, testf);
985
986 // Premultiply the weights and the Jacobian
987 double W = w * J;
988
989 // Calculate local values of the solution and its derivatives
990 // Allocate
991 double interpolated_u = 0.0;
993
994 // Calculate position
995 for (unsigned l = 0; l < n_node; l++)
996 {
997 // Get the value at the node
998 double u_value = raw_nodal_value(l, u_index_spherical_adv_diff);
999 interpolated_u += u_value * psif(l);
1000 // Loop over coordinate direction
1001 for (unsigned i = 0; i < 2; i++)
1002 {
1004 }
1005 }
1006
1007 // Get the imposed beta (beta=flux when alpha=0.0)
1008 double beta;
1009 get_beta(interpolated_x, beta);
1010
1011 // Get the imposed alpha
1012 double alpha;
1013 get_alpha(interpolated_x, alpha);
1014
1015 // calculate the area weighting dS = r^{2} sin theta dr dtheta
1016 // r = x[0] and theta = x[1]
1017 double dS =
1019
1020 // Now add to the appropriate equations
1021
1022 // Loop over the test functions
1023 for (unsigned l = 0; l < n_node; l++)
1024 {
1025 // Set the local equation number
1026 local_eqn = nodal_local_eqn(l, u_index_spherical_adv_diff);
1027 /*IF it's not a boundary condition*/
1028 if (local_eqn >= 0)
1029 {
1030 // Add the prescribed beta terms
1032 dS * (beta - alpha * interpolated_u) * testf(l) * W;
1033
1034 // Calculate the Jacobian
1035 //----------------------
1036 if ((flag) && (alpha != 0.0))
1037 {
1038 // Loop over the velocity shape functions again
1039 for (unsigned l2 = 0; l2 < n_node; l2++)
1040 {
1041 // Set the number of the unknown
1042 local_unknown = nodal_local_eqn(l2, u_index_spherical_adv_diff);
1043
1044 // If at a non-zero degree of freedom add in the entry
1045 if (local_unknown >= 0)
1046 {
1047 jacobian(local_eqn, local_unknown) +=
1048 dS * alpha * psif[l2] * testf[l] * W;
1049 }
1050 }
1051 }
1052 }
1053 } // end loop over test functions
1054
1055 } // end loop over integration points
1056
1057 } // end fill_in_generic_residual_contribution_adv_diff_flux
1058
1059
1060} // namespace oomph
1061
1062#endif
static char t char * s
Definition cfortran.h:568
cstr elem_len * i
Definition cfortran.h:603
char t
Definition cfortran.h:568
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Definition shape.h:359
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition nodes.h:238
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition nodes.h:367
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
Definition elements.h:4342
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
Definition elements.h:4630
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
In a FaceElement, the "global" intrinsic coordinate of the element along the boundary,...
Definition elements.h:4501
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s....
Definition elements.cc:5273
double J_eulerian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to global coordinates at the ipt-th integration point O...
Definition elements.cc:5359
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement.
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
A general Finite Element class.
Definition elements.h:1317
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition elements.h:1967
double nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n. Produces suitably interpolated values for hanging nodes...
Definition elements.h:2597
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing.
Definition elements.h:3054
virtual double dshape_eulerian_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsidx) const
Return the geometric shape functions and also first derivatives w.r.t. global coordinates at the ipt-...
Definition elements.cc:3355
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition elements.cc:3992
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node.
Definition elements.h:1436
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition elements.h:2615
unsigned nnode() const
Return the number of nodes.
Definition elements.h:2214
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as .
Definition elements.h:1763
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
Definition elements.h:2321
double dshape_eulerian(const Vector< double > &s, Shape &psi, DShape &dpsidx) const
Compute the geometric shape functions and also first derivatives w.r.t. global coordinates at local c...
Definition elements.cc:3328
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Function for building a lower dimensional FaceElement on the specified face of the FiniteElement....
Definition elements.cc:5163
double raw_nodal_value(const unsigned &n, const unsigned &i) const
Return the i-th value stored at local node n but do NOT take hanging nodes into account.
Definition elements.h:2580
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
Definition elements.cc:3250
bool has_hanging_nodes() const
Return boolean to indicate if any of the element's nodes are geometrically hanging.
Definition elements.h:2474
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:227
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
An OomphLibError object which should be thrown when an run-time error is encountered....
General QElement class.
Definition Qelements.h:459
QSphericalAdvectionDiffusionElement elements are linear/quadrilateral/brick-shaped Axisymmetric Advec...
void output(FILE *file_pt)
C-style output function: r,z,u.
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function: r,z,u at n_plot^2 plot points.
QSphericalAdvectionDiffusionElement(const QSphericalAdvectionDiffusionElement< NNODE_1D > &dummy)=delete
Broken copy constructor.
void operator=(const QSphericalAdvectionDiffusionElement< NNODE_1D > &)=delete
Broken assignment operator.
double dshape_and_dtest_eulerian_spherical_adv_diff(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. Return Jacobian.
QSphericalAdvectionDiffusionElement()
Constructor: Call constructors for QElement and Advection Diffusion equations.
static const unsigned Initial_Nvalue
Static array of ints to hold number of variables at nodes: Initial_Nvalue[n].
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: r,z,u at n_plot^2 plot points.
double dshape_and_dtest_eulerian_at_knot_spherical_adv_diff(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape, test functions & derivs. w.r.t. to global coords. at integration point ipt....
unsigned required_nvalue(const unsigned &n) const
Required # of ‘values’ (pinned or dofs) at node n.
void output(std::ostream &outfile)
Output function: r,z,u.
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for an exact solution: r,z,u_exact at n_plot^2 plot points.
RefineableElements are FiniteElements that may be subdivided into children to provide a better local ...
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
Definition shape.h:77
A class for all elements that solve the Advection Diffusion equations in a spherical polar coordinate...
void disable_ALE()
Disable ALE – empty overload to suppress warning. ALE isn't implemented anyway.
virtual void get_source_spherical_adv_diff(const unsigned &ipt, const Vector< double > &x, double &source) const
Get source term at (Eulerian) position x. This function is virtual to allow overloading in multi-phys...
SphericalAdvectionDiffusionWindFctPt wind_fct_pt() const
Access function: Pointer to wind function. Const version.
double interpolated_u_spherical_adv_diff(const Vector< double > &s) const
Return FE representation of function value u(s) at local coordinate s.
SphericalAdvectionDiffusionSourceFctPt & source_fct_pt()
Access function: Pointer to source function.
virtual double dshape_and_dtest_eulerian_at_knot_spherical_adv_diff(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: r,z,u_exact at nplot^2 plot points.
double *& pe_st_pt()
Pointer to Peclet number multipled by Strouha number.
double * PeSt_pt
Pointer to global Peclet number multiplied by Strouhal number.
void output(std::ostream &outfile)
Output with default number of plot points.
double du_dt_spherical_adv_diff(const unsigned &n) const
du/dt at local node n. Uses suitably interpolated value for hanging nodes.
void get_flux(const Vector< double > &s, Vector< double > &flux) const
Get flux:
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector (wrapper)
SphericalAdvectionDiffusionSourceFctPt Source_fct_pt
Pointer to source function:
void output(FILE *file_pt)
C_style output with default number of plot points.
SphericalAdvectionDiffusionWindFctPt Wind_fct_pt
Pointer to wind function:
const double & pe_st() const
Peclet number multiplied by Strouhal number.
SphericalAdvectionDiffusionEquations(const SphericalAdvectionDiffusionEquations &dummy)=delete
Broken copy constructor.
void fill_in_contribution_to_jacobian_and_mass_matrix(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix)
Add the element's contribution to its residual vector and the element Jacobian matrix (wrapper) and m...
SphericalAdvectionDiffusionWindFctPt & wind_fct_pt()
Access function: Pointer to wind function.
void compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
virtual unsigned u_index_spherical_adv_diff() const
Return the index at which the unknown value is stored. The default value, 0, is appropriate for singl...
SphericalAdvectionDiffusionSourceFctPt source_fct_pt() const
Access function: Pointer to source function. Const version.
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the element's contribution to its residual vector and the element Jacobian matrix (wrapper)
void(* SphericalAdvectionDiffusionSourceFctPt)(const Vector< double > &x, double &f)
Function pointer to source function fct(x,f(x)) – x is a Vector!
static double Default_peclet_number
Static default value for the Peclet number.
virtual void fill_in_generic_residual_contribution_spherical_adv_diff(Vector< double > &residuals, DenseMatrix< double > &jacobian, DenseMatrix< double > &mass_matrix, unsigned flag)
Add the element's contribution to its residual vector only (if flag=and/or element Jacobian matrix.
virtual double dshape_and_dtest_eulerian_spherical_adv_diff(const Vector< double > &s, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const =0
Shape/test functions and derivs w.r.t. to global coords at local coord. s; return Jacobian of mapping...
void(* SphericalAdvectionDiffusionWindFctPt)(const Vector< double > &x, Vector< double > &wind)
Function pointer to wind function fct(x,w(x)) – x is a Vector!
void operator=(const SphericalAdvectionDiffusionEquations &)=delete
Broken assignment operator.
virtual void dinterpolated_u_adv_diff_ddata(const Vector< double > &s, Vector< double > &du_ddata, Vector< unsigned > &global_eqn_number)
Return derivative of u at point s with respect to all data that can affect its value....
SphericalAdvectionDiffusionEquations()
Constructor: Initialise the Source_fct_pt and Wind_fct_pt to null and set (pointer to) Peclet number ...
virtual void get_wind_spherical_adv_diff(const unsigned &ipt, const Vector< double > &s, const Vector< double > &x, Vector< double > &wind) const
Get wind at (Eulerian) position x and/or local coordinate s. This function is virtual to allow overlo...
A class for elements that allow the imposition of an applied Robin boundary condition on the boundari...
unsigned U_index_adv_diff
The index at which the unknown is stored at the nodes.
SphericalAdvectionDiffusionPrescribedAlphaFctPt Alpha_fct_pt
Function pointer to the (global) prescribed-alpha function.
void get_alpha(const Vector< double > &x, double &alpha)
Function to calculate the prescribed alpha at a given spatial position.
void(* SphericalAdvectionDiffusionPrescribedBetaFctPt)(const Vector< double > &x, double &beta)
Function pointer to the prescribed-beta function fct(x,beta(x)) – x is a Vector!
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 between local ...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Add the element's contribution to its residual vector and its Jacobian matrix.
void get_beta(const Vector< double > &x, double &beta)
Function to calculate the prescribed beta at a given spatial position.
void fill_in_generic_residual_contribution_spherical_adv_diff_flux(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Add the element's contribution to its residual vector. flag=1(or 0): do (or don't) compute the Jacobi...
void output(std::ostream &outfile, const unsigned &nplot)
Output function – forward to broken version in FiniteElement until somebody decides what exactly they...
void output(std::ostream &outfile)
Output function – forward to broken version in FiniteElement until somebody decides what exactly they...
void(* SphericalAdvectionDiffusionPrescribedAlphaFctPt)(const Vector< double > &x, double &alpha)
Function pointer to the prescribed-alpha function fct(x,alpha(x)) – x is a Vector!
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Specify the value of nodal zeta from the face geometry The "global" intrinsic coordinate of the eleme...
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector.
SphericalAdvectionDiffusionPrescribedBetaFctPt & beta_fct_pt()
Access function for the prescribed-beta function pointer.
void operator=(const SphericalAdvectionDiffusionFluxElement &)=delete
Broken assignment operator.
double shape_and_test(const Vector< double > &s, Shape &psi, Shape &test) const
Function to compute the shape and test functions and to return the Jacobian of mapping between local ...
SphericalAdvectionDiffusionPrescribedAlphaFctPt & alpha_fct_pt()
Access function for the prescribed-alpha function pointer.
SphericalAdvectionDiffusionFluxElement(const SphericalAdvectionDiffusionFluxElement &dummy)=delete
Broken copy constructor.
SphericalAdvectionDiffusionPrescribedBetaFctPt Beta_fct_pt
Function pointer to the (global) prescribed-beta function.
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
bool is_steady() const
Flag to indicate if a timestepper has been made steady (possibly temporarily to switch off time-depen...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).