29 #ifndef OOMPH_WOMERSLEY_ELEMENTS_HEADER
30 #define OOMPH_WOMERSLEY_ELEMENTS_HEADER
34 #include <oomph-lib-config.h>
39 #include "../generic/nodes.h"
40 #include "../generic/Qelements.h"
41 #include "../generic/mesh.h"
42 #include "../generic/problem.h"
43 #include "../generic/oomph_utilities.h"
44 #include "../navier_stokes/navier_stokes_flux_control_elements.h"
114 std::map<unsigned, double>* aux_integral_pt) = 0;
120 std::map<unsigned, double>* aux_integral_pt) = 0;
136 Mesh* navier_stokes_outflow_mesh_pt_mesh_pt) = 0;
184 template<
unsigned DIM>
205 if (pressure_gradient_data_pt->
nvalue() != 1)
208 "Pressure gradient Data must only contain a single value!\n",
209 OOMPH_CURRENT_FUNCTION,
210 OOMPH_EXCEPTION_LOCATION);
271 for (
unsigned t = 0;
t < n_time;
t++)
291 const unsigned& n_plot,
292 const double& z_out);
296 void output(std::ostream& outfile,
const unsigned& nplot);
309 void output(FILE* file_pt,
const unsigned& n_plot);
314 const unsigned& nplot,
321 std::ostream& outfile,
322 const unsigned& nplot,
345 unsigned n_node =
nnode();
352 DShape dpsidx(n_node, DIM);
358 for (
unsigned j = 0; j < DIM; j++)
364 for (
unsigned l = 0; l < n_node; l++)
367 for (
unsigned j = 0; j < DIM; j++)
369 flux[j] +=
nodal_value(l, u_nodal_index) * dpsidx(l, j);
398 unsigned n_node =
nnode();
410 double interpolated_u = 0.0;
413 for (
unsigned l = 0; l < n_node; l++)
415 interpolated_u +=
nodal_value(l, u_nodal_index) * psi[l];
418 return (interpolated_u);
435 DShape& dtestdx)
const = 0;
445 DShape& dtestdx)
const = 0;
462 template<
unsigned DIMM>
479 Data* pressure_gradient_data_pt)
502 template<
unsigned DIM>
511 double* prescribed_flux_pt)
526 unsigned n_element = womersley_mesh_pt->
nelement();
531 for (
unsigned e = 0;
e < n_element;
e++)
560 for (
unsigned e = 0;
e < nelem;
e++)
595 unsigned n_dof =
ndof();
596 for (
unsigned i = 0;
i < n_dof;
i++)
598 for (
unsigned j = 0; j < n_dof; j++)
600 jacobian(
i, j) = 0.0;
629 template<
unsigned DIM,
unsigned NNODE_1D>
668 void output(std::ostream& outfile,
const unsigned& n_plot)
684 void output(FILE* file_pt,
const unsigned& n_plot)
693 const unsigned& n_plot,
704 const unsigned& n_plot,
741 template<
class ELEMENT,
unsigned DIM>
759 double* prescribed_volume_flux_pt,
761 Mesh* womersley_mesh_pt);
774 Mesh* womersley_mesh_pt);
801 std::ofstream& trace_file,
802 const double& z_out = 0.0);
807 std::ofstream trace_file;
846 template<
class ELEMENT,
unsigned DIM>
849 PrescribedPressureGradientFctPt pressure_gradient_fct_pt,
851 Mesh* womersley_mesh_pt)
852 : Prescribed_volume_flux_pt(0),
854 Prescribed_pressure_gradient_fct_pt(pressure_gradient_fct_pt)
873 for (
unsigned i = 0;
i < n_element;
i++)
879 el_pt->re_st_pt() = re_st_pt;
888 for (
unsigned e = 0;
e < nelem;
e++)
899 oomph_info <<
"Number of equations in WomersleyProblem: "
914 template<
class ELEMENT,
unsigned DIM>
917 double* prescribed_volume_flux_pt,
919 Mesh* womersley_mesh_pt)
920 : Prescribed_volume_flux_pt(prescribed_volume_flux_pt),
922 Prescribed_pressure_gradient_fct_pt(0)
942 for (
unsigned i = 0;
i < n_element;
i++)
948 el_pt->re_st_pt() = re_st_pt;
967 oomph_info <<
"Number of equations in WomersleyProblem: "
976 template<
class ELEMENT,
unsigned DIM>
989 template<
class ELEMENT,
unsigned DIM>
991 std::ofstream& trace_file,
994 std::ofstream some_file;
995 std::ofstream some_file1;
996 std::ostringstream filename;
1008 filename << doc_info.
directory() <<
"/womersley_soln" << doc_info.
number()
1010 some_file1.open(filename.str().c_str());
1013 filename << doc_info.
directory() <<
"/womersley_soln_3d_"
1014 << doc_info.
number() <<
".dat";
1015 some_file.open(filename.str().c_str());
1018 unsigned nelem = mesh_pt()->nelement();
1019 for (
unsigned e = 0;
e < nelem;
e++)
1021 ELEMENT* el_pt =
dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(
e));
1024 flux += el_pt->get_volume_flux();
1025 el_pt->output_3d(some_file, npts, z_out);
1026 el_pt->output(some_file1, npts);
1032 double prescribed_g = 0.0;
1033 if (Prescribed_pressure_gradient_fct_pt != 0)
1035 prescribed_g = Prescribed_pressure_gradient_fct_pt(time_pt()->time());
1039 double prescribed_q = 0.0;
1040 if (Prescribed_volume_flux_pt != 0)
1042 prescribed_q = *Prescribed_volume_flux_pt;
1045 if (trace_file.is_open())
1047 trace_file << time_pt()->time() <<
" "
1048 << pressure_gradient_data_pt()->value(0) <<
" " << flux <<
" "
1049 << prescribed_g <<
" " << prescribed_q <<
" " << std::endl;
1068 template<
class ELEMENT,
unsigned DIM>
1081 const double& length,
1104 Mesh* navier_stokes_outflow_mesh_pt)
1119 navier_stokes_outflow_mesh_pt->
element_pt(0)))
1132 unsigned nelem = navier_stokes_outflow_mesh_pt->
nelement();
1133 for (
unsigned e = 0;
e < nelem;
e++)
1145 navier_stokes_outflow_mesh_pt);
1153 navier_stokes_outflow_mesh_pt->
element_pt(0)))
1155 std::ostringstream error_message;
1157 <<
"WomersleyImpedanceTubeBase requires a Navier-Stokes\n"
1158 <<
"outflow mesh of elements which inherit from either\n"
1159 <<
"TemplateFreeNavierStokesFluxControlElementBase or\n"
1160 <<
"NavierStokesImpedanceTractionElementBase.\n";
1162 OOMPH_CURRENT_FUNCTION,
1163 OOMPH_EXCEPTION_LOCATION);
1190 double* re_st_pt = &
Zero;
1192 double q_initial = 0;
1194 setup(re_st_pt, dt, q_initial, time_stepper_pt);
1209 const double& q_initial,
1213 if (time_stepper_pt == 0)
1215 time_stepper_pt =
new BDF<2>;
1229 oomph_info <<
"NOTE: We're suppressing timings etc from \n"
1230 <<
" Newton solver in WomersleyImpedanceTubeBase. "
1324 for (
unsigned i = 0;
i < n_time_steppers;
i++)
1349 for (
unsigned e = 0;
e < nelem;
e++)
1354 ->get_volume_flux();
1359 for (
unsigned e = 0;
e < nelem;
e++)
1363 ->get_volume_flux();
1404 for (
unsigned e = 0;
e < nelem;
e++)
1419 for (
unsigned e = 0;
e < nelem;
e++)
1483 template<
unsigned DIM,
unsigned NNODE_1D>
1492 double J = this->dshape_eulerian(
s, psi, dpsidx);
1496 for (
unsigned i = 0;
i < NNODE_1D;
i++)
1499 for (
unsigned j = 0; j < DIM; j++)
1501 dtestdx(
i, j) = dpsidx(
i, j);
1516 template<
unsigned DIM,
unsigned NNODE_1D>
1525 double J = this->dshape_eulerian_at_knot(ipt, psi, dpsidx);
1547 template<
unsigned DIM,
unsigned NNODE_1D>
1549 :
public virtual QElement<DIM - 1, NNODE_1D>
1566 template<
unsigned NNODE_1D>
1603 template<
class WOMERSLEY_ELEMENT>
1618 const unsigned& fixed_coordinate,
1619 const unsigned& w_index)
1622 unsigned nelem = n_st_outflow_mesh_pt->
nelement();
1628 std::set<Node*> n_st_nodes;
1629 for (
unsigned e = 0;
e < nelem;
e++)
1632 unsigned nnod_el = el_pt->
nnode();
1633 for (
unsigned j = 0; j < nnod_el; j++)
1635 n_st_nodes.insert(el_pt->
node_pt(j));
1641 "Cannot build WomersleyMesh from mesh with hanging nodes!",
1642 OOMPH_CURRENT_FUNCTION,
1643 OOMPH_EXCEPTION_LOCATION);
1649 unsigned nnode_n_st = n_st_nodes.size();
1656 for (
unsigned e = 0;
e < nelem;
e++)
1664 "Number of nodes in existing and new elements don't match",
1665 OOMPH_CURRENT_FUNCTION,
1666 OOMPH_EXCEPTION_LOCATION);
1673 std::map<Node*, bool> n_st_node_done;
1677 std::map<Node*, Node*> equivalent_womersley_node_pt;
1680 unsigned node_count = 0;
1690 unsigned n_pinned_nodes = 0;
1694 for (
unsigned e = 0;
e < nelem;
e++)
1697 unsigned nnod_el = n_st_el_pt->
nnode();
1698 for (
unsigned j = 0; j < nnod_el; j++)
1704 if (!n_st_node_done[n_st_node_pt])
1711 Node_pt[node_count] = new_node_pt;
1716 unsigned dim = n_st_node_pt->
ndim();
1717 unsigned icount = 0;
1718 for (
unsigned i = 0;
i < dim;
i++)
1720 if (
i != fixed_coordinate)
1722 new_node_pt->
x(icount) = n_st_node_pt->
x(
i);
1730 new_node_pt->
pin(0);
1736 new_node_pt->
unpin(0);
1741 equivalent_womersley_node_pt[n_st_node_pt] = new_node_pt;
1744 n_st_node_done[n_st_node_pt] =
true;
1751 equivalent_womersley_node_pt[n_st_node_pt];
1762 for (
unsigned j = 0; j < nnod; j++)
1766 for (
unsigned j = 0; j < nnod; j++)
1774 throw OomphLibError(
"Element remains inverted even after reversing "
1775 "the local node numbers",
1776 OOMPH_CURRENT_FUNCTION,
1777 OOMPH_EXCEPTION_LOCATION);
1786 if (n_pinned_nodes == 0)
1788 std::stringstream bla;
1789 bla <<
"Boundary conditions must be applied in Navier-Stokes\n"
1790 <<
"problem before attaching impedance elements.\n"
1791 <<
"Note: This warning can be suppressed by setting the\n"
1792 <<
"global static boolean\n\n"
1794 "TemplateFreeWomersleyMeshBase::Suppress_warning_about_"
1795 "unpinned_nst_dofs\n\n"
1798 bla.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1804 if (
nnode() != nnode_n_st)
1807 "Number of nodes in the new mesh don't match that in the old one",
1808 OOMPH_CURRENT_FUNCTION,
1809 OOMPH_EXCEPTION_LOCATION);
1825 template<
class ELEMENT,
unsigned DIM>
1840 Mesh* navier_stokes_outflow_mesh_pt,
1841 const unsigned& fixed_coordinate,
1842 const unsigned& w_index)
1844 navier_stokes_outflow_mesh_pt),
1865 return womersley_mesh_pt;
1972 template<
class BULK_NAVIER_STOKES_ELEMENT,
1973 class WOMERSLEY_ELEMENT,
1976 :
public virtual FaceGeometry<BULK_NAVIER_STOKES_ELEMENT>,
2009 unsigned n_node =
nnode();
2015 for (
unsigned i = 0;
i < n_node;
i++)
2061 BULK_NAVIER_STOKES_ELEMENT* elem_pt =
2062 dynamic_cast<BULK_NAVIER_STOKES_ELEMENT*
>(element_pt);
2064 if (elem_pt->dim() == 3)
2073 throw OomphLibError(
"This flux element will not work correctly "
2074 "if nodes are hanging\n",
2075 OOMPH_CURRENT_FUNCTION,
2076 OOMPH_EXCEPTION_LOCATION);
2100 double volume_flux_integral = 0.0;
2115 BULK_NAVIER_STOKES_ELEMENT* bulk_el_pt =
2119 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
2123 for (
unsigned i = 0;
i < DIM;
i++)
2148 bulk_el_pt->interpolated_x(s_bulk, x_bulk);
2150 double max_legal_error = 1.0e-12;
2152 for (
unsigned i = 0;
i < DIM + 1;
i++)
2154 error += std::fabs(x[
i] - x_bulk[
i]);
2156 if (error > max_legal_error)
2158 std::ostringstream error_stream;
2159 error_stream <<
"difference in Eulerian posn from bulk and face: "
2160 << error <<
" exceeds threshold " << max_legal_error
2163 OOMPH_CURRENT_FUNCTION,
2164 OOMPH_EXCEPTION_LOCATION);
2174 bulk_el_pt->interpolated_u_nst(s_bulk, veloc);
2177 double volume_flux = 0.0;
2178 for (
unsigned i = 0;
i < DIM + 1;
i++)
2180 volume_flux += normal[
i] * veloc[
i];
2184 volume_flux_integral += volume_flux *
W;
2187 return volume_flux_integral;
2205 std::set<Data*> external_data_set;
2207 for (
unsigned e = 0;
e < nelem;
e++)
2211 unsigned nnod = el_pt->
nnode();
2212 for (
unsigned j = 0; j < nnod; j++)
2214 external_data_set.insert(el_pt->
node_pt(j));
2219 unsigned nnod =
nnode();
2220 for (
unsigned j = 0; j < nnod; j++)
2222 external_data_set.erase(
node_pt(j));
2226 for (std::set<Data*>::iterator it = external_data_set.begin();
2227 it != external_data_set.end();
2255 "Navier_stokes_outflow_mesh_pt==0 -- set it with \n "
2256 "set_external_data_from_navier_stokes_outflow_mesh() before calling "
2258 OOMPH_CURRENT_FUNCTION,
2259 OOMPH_EXCEPTION_LOCATION);
2264 double total_flux = 0.0;
2266 for (
unsigned e = 0;
e < nelem;
e++)
2298 std::map<unsigned, double>* aux_integral_pt)
2307 unsigned nnod =
nnode();
2314 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
2318 for (
unsigned i = 0;
i < DIM;
i++)
2340 for (
unsigned j = 0; j < nnod; j++)
2346 for (
unsigned i = 0;
i < (DIM + 1);
i++)
2354 (*aux_integral_pt)[i_global] += psi[j] * normal[
i] *
W;
2379 residuals, jacobian, 1);
2390 const unsigned&
i)
const
2403 void output(std::ostream& outfile,
const unsigned& nplot)
2419 template<
class BULK_NAVIER_STOKES_ELEMENT,
2420 class WOMERSLEY_ELEMENT,
2422 void NavierStokesImpedanceTractionElement<BULK_NAVIER_STOKES_ELEMENT,
2425 fill_in_generic_residual_contribution_fluid_traction(
2429 unsigned n_node = nnode();
2432 Shape psif(n_node), testf(n_node);
2435 unsigned n_intpt = integral_pt()->nweight();
2439 int local_unknown = 0;
2442 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
2445 double w = integral_pt()->weight(ipt);
2449 double J = shape_and_test_at_knot(ipt, psif, testf);
2459 double dp_in_dq = 0.0;
2463 if (Navier_stokes_outflow_mesh_pt != 0)
2466 Impedance_tube_pt->get_response(p_in, dp_in_dq);
2471 outer_unit_normal(ipt, unit_normal);
2474 for (
unsigned i = 0;
i < DIM + 1;
i++)
2476 traction[
i] = -unit_normal[
i] * p_in;
2481 for (
unsigned l = 0; l < n_node; l++)
2484 for (
unsigned i = 0;
i < DIM + 1;
i++)
2486 local_eqn = u_local_eqn(l,
i);
2491 residuals[local_eqn] += traction[
i] * testf[l] *
W;
2494 if (flag && (Navier_stokes_outflow_mesh_pt != 0))
2497 for (
unsigned j = 0; j < n_node; j++)
2500 Node* nod_pt = node_pt(j);
2503 for (
unsigned ii = 0; ii < DIM + 1; ii++)
2505 local_unknown = u_local_eqn(j, ii);
2508 if (local_unknown >= 0)
2511 unsigned global_unknown = nod_pt->
eqn_number(ii);
2514 jacobian(local_eqn, local_unknown) -=
2515 (*Aux_integral_pt)[global_unknown] * psif[l] *
2516 unit_normal[
i] * dp_in_dq *
W;
2523 unsigned n_ext = nexternal_data();
2524 for (
unsigned j = 0; j < n_ext; j++)
2527 Data* ext_data_pt = external_data_pt(j);
2530 for (
unsigned ii = 0; ii < DIM + 1; ii++)
2533 int local_unknown = external_local_eqn(j, ii);
2536 if (local_unknown >= 0)
2539 unsigned global_unknown = ext_data_pt->
eqn_number(ii);
2542 jacobian(local_eqn, local_unknown) -=
2543 (*Aux_integral_pt)[global_unknown] * psif[l] *
2544 unit_normal[
i] * dp_in_dq *
W;
2613 residuals, jacobian, 1);
2644 std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list)
const
2647 std::pair<unsigned, unsigned> dof_lookup;
2650 dof_lookup.second = 0;
2653 dof_lookup_list.push_front(dof_lookup);
2664 const unsigned& flag)
2667 double womersley_pressure = 0.0;
2668 double d_womersley_pressure_d_q = 0.0;
2672 d_womersley_pressure_d_q);
2681 residuals[local_eq] += pressure - womersley_pressure;
2690 jacobian(local_eq, local_eq) -= d_womersley_pressure_d_q;
2691 jacobian(local_eq, local_unknown) += 1.0;
2692 jacobian(local_unknown, local_eq) += 1.0;
2741 Mesh* flux_control_mesh_pt,
2744 flux_control_mesh_pt,
2745 pressure_control_element_pt->volume_flux_data_pt()->value_pt(0))
2784 std::list<std::pair<unsigned long, unsigned>>& dof_lookup_list)
const
2787 std::pair<unsigned, unsigned> dof_lookup;
2790 dof_lookup.second = 0;
2793 dof_lookup_list.push_front(dof_lookup);
////////////////////////////////////////////////////////////////////// //////////////////////////////...
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
A class that represents a collection of data; each Data object may contain many different individual ...
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
void pin(const unsigned &i)
Pin the i-th stored variable.
void unpin(const unsigned &i)
Unpin the i-th stored variable.
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
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 ...
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Information for documentation of results: Directory and file number to enable output in the form RESL...
std::string directory() const
Output directory.
unsigned & number()
Number used (e.g.) for labeling output files.
A vector in the mathematical sense, initially developed for linear algebra type applications....
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
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,...
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s. Overloaded to get information from bulk...
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s....
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...
void get_local_coordinate_in_bulk(const Vector< double > &s, Vector< double > &s_bulk) const
Calculate the vector of local coordinate in the bulk element given the local coordinates in this Face...
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement.
FaceGeometry()
Constructor: Call the constructor for the appropriate lower-dimensional QElement.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
A general Finite Element class.
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
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...
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing.
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...
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.
unsigned nnode() const
Return the number of nodes.
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as .
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
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...
void check_J_eulerian_at_knots(bool &passed) const
Check that Jacobian of mapping between local and Eulerian coordinates at all integration points is po...
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....
void(* UnsteadyExactSolutionFctPt)(const double &, const Vector< double > &, Vector< double > &)
Function pointer for function that computes Vector-valued time-dependent function as .
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
bool has_hanging_nodes() const
Return boolean to indicate if any of the element's nodes are geometrically hanging.
A Generalised Element class.
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 ...
unsigned ndof() const
Return the number of equations/dofs in the element.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number.
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Return the local equation number corresponding to the j-th value stored at the i-th internal data.
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.
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
//////////////////////////////////////////////////////////////////////// ////////////////////////////...
double * Prescribed_flux_pt
Pointer to current value of prescribed flux.
Data * Pressure_gradient_data_pt
Data item whose one and only value contains the pressure gradient.
void get_residuals(Vector< double > &residuals)
Compute residual vector: the volume flux constraint determines this element's one-and-only internal D...
Data * pressure_gradient_data_pt()
Read-only access to the single-valued Data item that stores the pressure gradient (to be determined v...
void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute element residual Vector and element Jacobian matrix Note: Jacobian is zero because the deriva...
double total_volume_flux()
Get volume flux through all Womersley elements.
Mesh * Womersley_mesh_pt
Pointer to mesh that contains the Womersley elements.
ImposeFluxForWomersleyElement(Mesh *womersley_mesh_pt, double *prescribed_flux_pt)
Constructor: Pass pointer to mesh that contains the Womersley elements whose volume flux is controlle...
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.
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
Vector< Node * > Node_pt
Vector of pointers to nodes.
static Steady< 0 > Default_TimeStepper
Default Steady Timestepper, to be used in default arguments to Mesh constructors.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
unsigned long nnode() const
Return number of nodes in the mesh.
void add_element_pt(GeneralisedElement *const &element_pt)
Add a (pointer to) an element to the mesh.
unsigned long nelement() const
Return number of elements in the mesh.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
virtual ~NavierStokesImpedanceTractionElementBase()
Empty vitual destructor.
Mesh * Navier_stokes_outflow_mesh_pt
Pointer to mesh containing the NavierStokesImpedanceTractionElements that contribute to the volume fl...
virtual void add_element_contribution_to_aux_integral(std::map< unsigned, double > *aux_integral_pt)=0
Add the element's contribution to the auxiliary integral used in the element's Jacobian....
NavierStokesImpedanceTractionElementBase()
virtual void set_external_data_from_navier_stokes_outflow_mesh(Mesh *navier_stokes_outflow_mesh_pt_mesh_pt)=0
Pass the pointer to the mesh containing all NavierStokesImpedanceTractionElements that contribute to ...
virtual double get_volume_flux()=0
Pure virtual function that must be implemented to compute the volume flux that passes through this el...
virtual void set_aux_integral_pt(std::map< unsigned, double > *aux_integral_pt)=0
Pass the pointer to the pre-computed auxiliary integral to the element so it can be accessed when com...
virtual void set_impedance_tube_pt(TemplateFreeWomersleyImpedanceTubeBase *impedance_tube_pt)=0
Pass the pointer to the "impedance tube" that computes the flow resistance via the solution of Womers...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
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't) compute th...
void output(std::ostream &outfile, const unsigned &nplot)
Output function: x,y,[z],u,v,[w],p in tecplot format.
~NavierStokesImpedanceTractionElement()
Destructor should not delete anything.
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 output(std::ostream &outfile)
Overload the output function.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Fill in the element's contribution to the element's residual vector.
WomersleyImpedanceTubeBase< WOMERSLEY_ELEMENT, DIM > * Impedance_tube_pt
Pointer to ImpedanceTubeProblem that computes the flow resistance.
NavierStokesImpedanceTractionElement(FiniteElement *const &element_pt, const int &face_index)
Constructor, which takes a "bulk" element and the value of the index and its limit.
Mesh *& navier_stokes_outflow_mesh_pt()
Access to mesh containing all NavierStokesImpedanceTractionElements that contribute to the volume flu...
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Fill in the element's contribution to the element's residual vector and Jacobian matrix.
std::map< unsigned, double > * Aux_integral_pt
Pointer to auxiliary integral, containing the derivative of the total volume flux through the outflow...
double get_volume_flux()
Get integral of volume flux through element.
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.
void set_impedance_tube_pt(TemplateFreeWomersleyImpedanceTubeBase *impedance_tube_pt)
Set pointer to "impedance tube" that provides the flow resistance.
void set_aux_integral_pt(std::map< unsigned, double > *aux_integral_pt)
Set pointer to the precomputed auxiliary integral that contains the derivative of the total volume fl...
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,...
void add_element_contribution_to_aux_integral(std::map< unsigned, double > *aux_integral_pt)
Add the element's contribution to the auxiliary integral that contains the derivative of the total vo...
double total_volume_flux_into_downstream_tube()
Compute total volume flux into the "downstream tube" that provides the impedance (computed by adding ...
void set_external_data_from_navier_stokes_outflow_mesh(Mesh *navier_stokes_outflow_mesh_pt)
NavierStokesImpedanceTractionElements that contribute to the volume flux into the downstream "impedan...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
Data * volume_flux_data_pt() const
Function to return a pointer to the Data object whose single value is the flux degree of freedom.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
This function returns the residuals.
void fill_in_generic_residual_contribution_pressure_control(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
This function returns the residuals. flag=1(or 0): do (or don't) compute the Jacobian as well....
unsigned ndof_types() const
The number of "DOF types" that degrees of freedom in this element are sub-divided into - set to 1.
void add_pressure_data(Data *pressure_data_pt)
Function to add to external data the Data object whose single value is the pressure applied at the bo...
TemplateFreeWomersleyImpedanceTubeBase * Womersley_tube_pt
Pointer to the Womersley impedance tube.
unsigned Volume_flux_data_id
Id of internal Data object whose single value is the volume flux.
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
This function returns the residuals and the Jacobian, plus the Jacobian contribution for the NetFluxC...
~NavierStokesWomersleyPressureControlElement()
Destructor should not delete anything.
Data * Volume_flux_data_pt
Data object whose single value is the volume flux applied by the elements in the Flux_control_mesh_pt...
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...
unsigned Pressure_data_id
Id of external Data object whose single value is the pressure.
NavierStokesWomersleyPressureControlElement(TemplateFreeWomersleyImpedanceTubeBase *womersley_tube_pt)
Constructor takes a pointer to a suitable Womersley impedance tube which defines the pressure via get...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
void operator=(const NetFluxControlElementForWomersleyPressureControl &)=delete
Broken assignment operator.
NetFluxControlElementForWomersleyPressureControl(const NetFluxControlElementForWomersleyPressureControl &dummy)=delete
Broken copy constructor.
NetFluxControlElementForWomersleyPressureControl(Mesh *flux_control_mesh_pt, NavierStokesWomersleyPressureControlElement *pressure_control_element_pt)
Constructor takes the mesh of TemplateFreeNavierStokesFluxControlElementBase which impose the pressur...
unsigned ndof_types() const
The number of "DOF types" that degrees of freedom in this element are sub-divided into - set to 1.
~NetFluxControlElementForWomersleyPressureControl()
Empty Destructor - Data gets deleted automatically.
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...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
Data * pressure_data_pt() const
Function to return a pointer to the Data object whose single value is the pressure applied by the Nav...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
bool is_hanging() const
Test whether the node is geometrically hanging.
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
////////////////////////////////////////////////////////////////// //////////////////////////////////...
unsigned long assign_eqn_numbers(const bool &assign_local_eqn_numbers=true)
Assign all equation numbers for problem: Deals with global data (= data that isn't attached to any el...
Time *& time_pt()
Return a pointer to the global time object.
void add_time_stepper_pt(TimeStepper *const &time_stepper_pt)
Add a timestepper to the problem. The function will automatically create or resize the Time object so...
Mesh *& mesh_pt()
Return a pointer to the global mesh.
double & time()
Return the current value of continuous time.
TimeStepper *& time_stepper_pt()
Access function for the pointer to the first (presumably only) timestepper.
bool Problem_is_nonlinear
Boolean flag indicating if we're dealing with a linear or nonlinear Problem – if set to false the New...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
//////////////////////////////////////////////////////////////////////// ////////////////////////////...
void operator=(const QWomersleyElement< DIM, NNODE_1D > &)=delete
Broken assignment operator.
void output_fct(std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt)
Output function for a time-dependent exact solution. x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot ...
void output(FILE *file_pt)
C-style output function: x,y,u or x,y,z,u.
unsigned required_nvalue(const unsigned &n) const
Required # of ‘values’ (pinned or dofs) at node n.
QWomersleyElement()
Constructor: Call constructors for QElement and Womersley equations.
void output(std::ostream &outfile)
Output function: x,y,u or x,y,z,u.
double dshape_and_dtest_eulerian_at_knot_womersley(const unsigned &ipt, Shape &psi, DShape &dpsidx, Shape &test, DShape &dtestdx) const
Shape/test functions and derivs w.r.t. to global coords at integration point ipt; return Jacobian of ...
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: x,y,u or x,y,z,u at n_plot^DIM plot points.
QWomersleyElement(const QWomersleyElement< DIM, NNODE_1D > &dummy)=delete
Broken copy constructor.
void output_fct(std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output function for an exact solution: x,y,u_exact or x,y,z,u_exact at n_plot^DIM plot points.
static const unsigned Initial_Nvalue
Static array of ints to hold number of variables at nodes: Initial_Nvalue[n].
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function: x,y,u or x,y,z,u at n_plot^DIM plot points.
double dshape_and_dtest_eulerian_womersley(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.
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...
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
TemplateFreeWomersleyImpedanceTubeBase()
Empty constructor.
virtual ~TemplateFreeWomersleyImpedanceTubeBase()
Empty virtual destructor.
virtual void get_response(double &p_in, double &dp_in_dq)=0
Empty virtual dummy member function – every base class needs at least one virtual member function if ...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
static bool Suppress_warning_about_unpinned_nst_dofs
Static bool to suppress warning.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
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...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
void operator=(const WomersleyEquations &)=delete
Broken assignment operator.
WomersleyEquations()
Constructor: Initialises the Pressure_gradient_data_pt to null.
virtual double dshape_and_dtest_eulerian_womersley(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 compute_error(std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
Get error against and norm of exact solution.
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute element residual Vector and element Jacobian matrix (wrapper)
const double & re_st() const
Product of Reynolds and Strouhal number (=Womersley number)
virtual void fill_in_generic_residual_contribution_womersley(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Compute element residual Vector only (if flag=and/or element Jacobian matrix.
void get_flux(const Vector< double > &s, Vector< double > &flux) const
Get flux: flux[i] = du/dx_i.
virtual double dshape_and_dtest_eulerian_at_knot_womersley(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 ...
double du_dt_womersley(const unsigned &n) const
du/dt at local node n. Uses suitably interpolated value for hanging nodes.
double interpolated_u_womersley(const Vector< double > &s) const
Return FE representation of function value u(s) at local coordinate s.
Data * set_pressure_gradient_pt() const
Read-only access to pointer to pressure gradient.
void output(std::ostream &outfile)
Output with default number of plot points.
static double Default_ReSt_value
Static default value for the Womersley number.
double get_volume_flux()
Compute total volume flux through element.
void output(FILE *file_pt)
C_style output with default number of plot points.
unsigned self_test()
Self-test: Return 0 for OK.
Data * Pressure_gradient_data_pt
Pointer to pressure gradient Data (single value Data item)
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Compute element residual Vector (wrapper)
void set_pressure_gradient_pt(Data *&pressure_gradient_data_pt)
Set pointer to pressure gradient (single-valued Data)
void set_pressure_gradient_and_add_as_external_data(Data *pressure_gradient_data_pt)
Set pointer to pressure gradient (single-valued Data) and treat it as external data – this can only b...
void output_fct(std::ostream &outfile, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt)
Output exact soln: x,y,u_exact or x,y,z,u_exact at nplot^DIM plot points.
double *& re_st_pt()
Pointer to product of Reynolds and Strouhal number (=Womersley number)
double * ReSt_pt
Pointer to global Reynolds number x Strouhal number (=Womersley)
WomersleyEquations(const WomersleyEquations &dummy)=delete
Broken copy constructor.
void output_3d(std::ostream &outfile, const unsigned &n_plot, const double &z_out)
Output function: x,y,z_out,0,0,u,0 to allow comparison against full Navier Stokes at n_nplot x n_plot...
virtual unsigned u_index_womersley() const
Return the index at which the unknown value is stored. The default value, 0, is appropriate for singl...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
bool Using_flux_control_elements
WomersleyProblem< ELEMENT, DIM > * womersley_problem_pt()
Access to underlying Womersley problem.
double(* PrescribedVolumeFluxFctPt)(const double &time)
Function pointer to fct that prescribes volume flux q=fct(t) – mainly used for validation purposes.
double Length
Length of the tube.
double Dp_in_dq
Derivative of inflow pressure w.r.t. instantaenous volume flux (Note: Can be pre-computed)
WomersleyImpedanceTubeBase(const double &length, PrescribedVolumeFluxFctPt prescribed_volume_flux_fct_pt)
Constructor: Specify length of tube and pointer to function that specifies the prescribed volume flux...
Mesh * Navier_stokes_outflow_mesh_pt
Pointer to the mesh of NavierStokesImpedanceTractionElements that are attached to the outflow cross-s...
void get_response(double &p_in, double &dp_in_dq)
Compute inlet pressure, p_in, required to achieve the currently imposed, instantaneous volume flux q ...
void precompute_aux_integrals()
Precompute auxiliary integrals required for the computation of the Jacobian in the NavierStokesImpeda...
double * Current_volume_flux_pt
Pointer to double that specifies the currently imposed instantaneous volume flux into the impedance t...
WomersleyImpedanceTubeBase(const double &length, Mesh *navier_stokes_outflow_mesh_pt)
Constructor: Specify length of tube and the pointer to the mesh of either NavierStokesImpedanceTracti...
void setup()
Set up the Womersley tubes so that a subsequent call to get_response(...) computes the inlet pressure...
void setup(double *re_st_pt, const double &dt, const double &q_initial, TimeStepper *time_stepper_pt=0)
Set up the Womersley tubes so that a subsequent call to get_response(...) computes the inlet pressure...
double total_volume_flux_into_impedance_tube()
Compute total current volume flux into the "impedance tube" that provides the flow resistance (flux i...
WomersleyProblem< ELEMENT, DIM > * Womersley_problem_pt
Pointer to Womersley problem that determines the pressure gradient along the tube.
double & p_out()
Access fct to outlet pressure.
std::map< unsigned, double > * Aux_integral_pt
Pointer to auxiliary integral, containing the derivative of the total volume flux through the outflow...
void shift_time_values(const double &dt)
Shift history values to allow coputation of next timestep. Note: When used with a full Navier-Stokes ...
PrescribedVolumeFluxFctPt Prescribed_volume_flux_fct_pt
Pointer to function that specifies the prescribed volume flux.
double P_out
Outlet pressure.
virtual Mesh * build_mesh_and_apply_boundary_conditions(TimeStepper *time_stepper_pt)=0
Pure virtual function in which the user of a derived class must create the mesh of WomersleyElements ...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
WomersleyMesh(Mesh *n_st_outflow_mesh_pt, TimeStepper *time_stepper_pt, const unsigned &fixed_coordinate, const unsigned &w_index)
Constructor: Pass pointer to mesh of face elements in the outflow cross-section of a full Navier-Stok...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Mesh * build_mesh_and_apply_boundary_conditions(TimeStepper *time_stepper_pt)
Implement pure virtual fct (defined in the base class WomersleyImpedanceTubeBase) that builds the mes...
WomersleyOutflowImpedanceTube(const double &length, Mesh *navier_stokes_outflow_mesh_pt, const unsigned &fixed_coordinate, const unsigned &w_index)
Constructor: Pass length and mesh of face elements that are attached to the outflow cross-section of ...
unsigned Fixed_coordinate
The coordinate (in the higher-dimensional Navier-Stokes mesh) that is constant in the outflow cross-s...
unsigned W_index
The velocity component (in terms of the nodal index) that represents the outflow component – the latt...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void actions_after_newton_solve()
Update the problem specs after solve (empty)
void doc_solution(DocInfo &doc_info, const double &z_out=0.0)
Doc the solution.
ImposeFluxForWomersleyElement< DIM > * Flux_el_pt
Pointer to element that imposes the flux through the collection of Womersley elements.
PrescribedPressureGradientFctPt Prescribed_pressure_gradient_fct_pt
Fct pointer to fct that prescribes pressure gradient.
Data * pressure_gradient_data_pt()
Access function to the single-valued Data object that contains the unknown pressure gradient (used if...
void doc_solution(DocInfo &doc_info, std::ofstream &trace_file, const double &z_out=0.0)
Doc the solution incl. trace file for various quantities of interest (to some...)
void actions_before_newton_solve()
Update the problem specs before solve (empty)
double * Prescribed_volume_flux_pt
Pointer to currently prescribed volume flux.
~WomersleyProblem()
Destructor to clean up memory.
WomersleyProblem(double *re_st_pt, double *prescribed_volume_flux_pt, TimeStepper *time_stepper_pt, Mesh *womersley_mesh_pt)
Constructor: Pass pointer to Womersley number, pointer to the double that stores the currently impose...
double(* PrescribedPressureGradientFctPt)(const double &time)
Function pointer to fct that prescribes pressure gradient g=fct(t)
Data * Pressure_gradient_data_pt
Pointer to single-valued Data item that stores pressure gradient.
void actions_before_implicit_timestep()
Update the problem specs before next timestep: Update time-varying pressure gradient (if prescribed)
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...