32 #ifndef OOMPH_PML_HELMHOLTZ_FLUX_ELEMENTS_HEADER 33 #define OOMPH_PML_HELMHOLTZ_FLUX_ELEMENTS_HEADER 38 #include <oomph-lib-config.h> 42 #include "../generic/Qelements.h" 57 template <
class ELEMENT>
74 "Don't call empty constructor for PMLHelmholtzPowerElement",
75 OOMPH_CURRENT_FUNCTION,
76 OOMPH_EXCEPTION_LOCATION);
102 const unsigned &
i)
const 121 std::ofstream outfile;
132 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(this->
bulk_element_pt());
135 unsigned nnode_bulk=bulk_elem_pt->nnode();
136 const unsigned n_node_local =
nnode();
139 const unsigned bulk_dim= bulk_elem_pt->dim();
140 const unsigned local_dim=this->
dim();
143 Shape psi(n_node_local);
146 Shape psi_bulk(nnode_bulk);
147 DShape dpsi_bulk_dx(nnode_bulk,bulk_dim);
160 if (outfile.is_open())
167 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
170 for(
unsigned i=0;
i<local_dim;
i++)
192 (void)bulk_elem_pt->dshape_eulerian(s_bulk,psi_bulk,dpsi_bulk_dx);
196 std::complex<double> dphi_dn(0.0,0.0);
198 interpolated_dphidx(bulk_dim,std::complex<double>(0.0,0.0));
199 std::complex<double> interpolated_phi(0.0,0.0);
205 for(
unsigned l=0;l<nnode_bulk;l++)
208 const std::complex<double> phi_value(
209 bulk_elem_pt->nodal_value(l,bulk_elem_pt->u_index_helmholtz().real()),
210 bulk_elem_pt->nodal_value(l,bulk_elem_pt->u_index_helmholtz().imag()));
213 for(
unsigned i=0;
i<bulk_dim;
i++)
215 interpolated_dphidx[
i] += phi_value*dpsi_bulk_dx(l,
i);
219 for(
unsigned l=0;l<n_node_local;l++)
222 const std::complex<double> phi_value(
226 interpolated_phi += phi_value*psi(l);
230 for(
unsigned i=0;
i<bulk_dim;
i++)
232 dphi_dn += interpolated_dphidx[
i]*unit_normal[
i];
236 double integrand=0.5*
237 (interpolated_phi.real()*dphi_dn.imag()-
238 interpolated_phi.imag()*dphi_dn.real());
241 if (outfile.is_open())
244 double phi=atan2(x[1],x[0]);
245 outfile << x[0] <<
" " 248 << integrand <<
"\n";
266 std::ofstream outfile;
277 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(this->
bulk_element_pt());
280 unsigned nnode_bulk=bulk_elem_pt->nnode();
281 const unsigned n_node_local =
nnode();
284 const unsigned bulk_dim= bulk_elem_pt->dim();
285 const unsigned local_dim=this->
dim();
288 Shape psi(n_node_local);
291 Shape psi_bulk(nnode_bulk);
292 DShape dpsi_bulk_dx(nnode_bulk,bulk_dim);
302 std::complex<double> flux (0.0,0.0);
305 if (outfile.is_open())
312 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
315 for(
unsigned i=0;
i<local_dim;
i++)
337 (void)bulk_elem_pt->dshape_eulerian(s_bulk,psi_bulk,dpsi_bulk_dx);
341 std::complex<double> dphi_dn(0.0,0.0);
343 interpolated_dphidx(bulk_dim,std::complex<double>(0.0,0.0));
349 for(
unsigned l=0;l<nnode_bulk;l++)
352 const std::complex<double> phi_value(
353 bulk_elem_pt->nodal_value(l,bulk_elem_pt->u_index_helmholtz().real()),
354 bulk_elem_pt->nodal_value(l,bulk_elem_pt->u_index_helmholtz().imag()));
357 for(
unsigned i=0;
i<bulk_dim;
i++)
359 interpolated_dphidx[
i] += phi_value*dpsi_bulk_dx(l,
i);
365 for(
unsigned i=0;
i<bulk_dim;
i++)
367 dphi_dn += interpolated_dphidx[
i]*unit_normal[
i];
371 if (outfile.is_open())
374 outfile << x[0] <<
" " 376 << dphi_dn.real() <<
" " 377 << dphi_dn.imag() <<
"\n";
416 template<
class ELEMENT>
425 ELEMENT* elem_pt =
dynamic_cast<ELEMENT*
>(bulk_el_pt);
427 if(elem_pt->dim()==3)
436 "This flux element will not work correctly if nodes are hanging\n",
437 OOMPH_CURRENT_FUNCTION,
438 OOMPH_EXCEPTION_LOCATION);
474 "Bulk element must inherit from PMLHelmholtzEquations.";
476 "Nodes are one dimensional, but cannot cast the bulk element to\n";
477 error_string +=
"PMLHelmholtzEquations<1>\n.";
479 "If you desire this functionality, you must implement it yourself\n";
482 OOMPH_CURRENT_FUNCTION,
483 OOMPH_EXCEPTION_LOCATION);
503 "Bulk element must inherit from PMLHelmholtzEquations.";
505 "Nodes are two dimensional, but cannot cast the bulk element to\n";
506 error_string +=
"PMLHelmholtzEquations<2>\n.";
508 "If you desire this functionality, you must implement it yourself\n";
511 OOMPH_CURRENT_FUNCTION,
512 OOMPH_EXCEPTION_LOCATION);
532 "Bulk element must inherit from PMLHelmholtzEquations.";
534 "Nodes are three dimensional, but cannot cast the bulk element to\n";
535 error_string +=
"PMLHelmholtzEquations<3>\n.";
537 "If you desire this functionality, you must implement it yourself\n";
540 OOMPH_CURRENT_FUNCTION,
541 OOMPH_EXCEPTION_LOCATION);
553 std::ostringstream error_stream;
554 error_stream <<
"Dimension of node is " <<
Dim 555 <<
". It should be 1,2, or 3!" << std::endl;
558 OOMPH_CURRENT_FUNCTION,
559 OOMPH_EXCEPTION_LOCATION);
579 template <
class ELEMENT>
589 typedef void (*PMLHelmholtzPrescribedFluxFctPt)
601 "Don't call empty constructor for PMLHelmholtzFluxElement",
602 OOMPH_CURRENT_FUNCTION,
603 OOMPH_EXCEPTION_LOCATION);
620 PMLHelmholtzPrescribedFluxFctPt&
flux_fct_pt() {
return Flux_fct_pt;}
628 fill_in_generic_residual_contribution_helmholtz_flux(
639 fill_in_generic_residual_contribution_helmholtz_flux(residuals,jacobian,1);
649 const unsigned &
i)
const 659 void output(std::ostream &outfile,
const unsigned &n_plot)
670 void output(FILE* file_pt,
const unsigned &n_plot)
694 std::list<std::pair<unsigned long,unsigned> >& dof_lookup_list)
const 697 std::pair<unsigned,unsigned> dof_lookup;
700 unsigned n_node = this->
nnode();
703 for (
unsigned n = 0; n < n_node; n++)
710 if (local_eqn_number >= 0)
714 dof_lookup.first = this->
eqn_number(local_eqn_number);
715 dof_lookup.second = 0;
718 dof_lookup_list.push_front(dof_lookup);
726 if (local_eqn_number >= 0)
730 dof_lookup.first = this->
eqn_number(local_eqn_number);
731 dof_lookup.second = 1;
734 dof_lookup_list.push_front(dof_lookup);
747 unsigned n_node =
nnode();
753 for(
unsigned i=0;
i<n_node;
i++) {test[
i] = psi[
i];}
768 unsigned n_node =
nnode();
774 for(
unsigned i=0;
i<n_node;
i++) {test[
i] = psi[
i];}
788 flux = std::complex<double>(0.0,0.0);
793 (*Flux_fct_pt)(x,flux);
806 virtual void fill_in_generic_residual_contribution_helmholtz_flux(
808 const unsigned& flag);
833 template<
class ELEMENT>
842 ELEMENT* elem_pt =
dynamic_cast<ELEMENT*
>(bulk_el_pt);
844 if(elem_pt->dim()==3)
853 "This flux element will not work correctly if nodes are hanging\n",
854 OOMPH_CURRENT_FUNCTION,
855 OOMPH_EXCEPTION_LOCATION);
894 "Bulk element must inherit from PMLHelmholtzEquations.";
896 "Nodes are one dimensional, but cannot cast the bulk element to\n";
897 error_string +=
"PMLHelmholtzEquations<1>\n.";
899 "If you desire this functionality, you must implement it yourself\n";
902 OOMPH_CURRENT_FUNCTION,
903 OOMPH_EXCEPTION_LOCATION);
923 "Bulk element must inherit from PMLHelmholtzEquations.";
925 "Nodes are two dimensional, but cannot cast the bulk element to\n";
926 error_string +=
"PMLHelmholtzEquations<2>\n.";
928 "If you desire this functionality, you must implement it yourself\n";
931 OOMPH_CURRENT_FUNCTION,
932 OOMPH_EXCEPTION_LOCATION);
952 "Bulk element must inherit from PMLHelmholtzEquations.";
954 "Nodes are three dimensional, but cannot cast the bulk element to\n";
955 error_string +=
"PMLHelmholtzEquations<3>\n.";
957 "If you desire this functionality, you must implement it yourself\n";
960 OOMPH_CURRENT_FUNCTION,
961 OOMPH_EXCEPTION_LOCATION);
973 std::ostringstream error_stream;
974 error_stream <<
"Dimension of node is " <<
Dim 975 <<
". It should be 1,2, or 3!" << std::endl;
978 OOMPH_CURRENT_FUNCTION,
979 OOMPH_EXCEPTION_LOCATION);
988 template<
class ELEMENT>
992 const unsigned& flag)
995 const unsigned n_node =
nnode();
998 Shape psif(n_node), testf(n_node);
1007 int local_eqn_real=0 ,local_eqn_imag=0;
1011 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
1031 for(
unsigned l=0;l<n_node;l++)
1033 for(
unsigned i=0;
i<
Dim;
i++)
1040 std::complex<double> flux(0.0,0.0);
1045 for(
unsigned l=0;l<n_node;l++)
1049 if(local_eqn_real >= 0)
1052 residuals[local_eqn_real] -= flux.real()*testf[l]*
W;
1060 if(local_eqn_imag >= 0)
1063 residuals[local_eqn_imag] -= flux.imag()*testf[l]*
W;
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...
bool has_hanging_nodes() const
Return boolean to indicate if any of the element's nodes are geometrically hanging.
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
virtual void fill_in_generic_residual_contribution_helmholtz_flux(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Add the element's contribution to its residual vector. flag=1(or 0): do (or don't) compute the contri...
virtual void output(std::ostream &outfile)
Output the element data — typically the values at the nodes in a format suitable for post-processing...
virtual std::complex< unsigned > u_index_helmholtz() const
Return the index at which the unknown value is stored.
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 ...
PMLHelmholtzFluxElement(const PMLHelmholtzFluxElement &dummy)
Broken copy constructor.
std::complex< unsigned > U_index_helmholtz
The index at which the real and imag part of the unknown is stored at the nodes.
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
PMLHelmholtzPrescribedFluxFctPt Flux_fct_pt
Function pointer to the (global) prescribed-flux function.
void output(FILE *file_pt)
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
void output(std::ostream &outfile, const unsigned &n_plot)
Output function – forward to broken version in FiniteElement until somebody decides what exactly the...
A general Finite Element class.
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, when viewed as part of a compound geometric object is specified using the boundary coordinate defined by the mesh. Note: Boundary coordinates will have been set up when creating the underlying mesh, and their values will have been stored at the nodes.
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...
A class for elements that allow the imposition of an applied flux on the boundaries of PMLHelmholtz e...
unsigned Dim
The spatial dimension of the problem.
void get_flux(const Vector< double > &x, std::complex< double > &flux)
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
PMLHelmholtzPowerElement(const PMLHelmholtzPowerElement &dummy)
Broken copy constructor.
double global_power_contribution(std::ofstream &outfile)
Compute the element's contribution to the time-averaged radiated power over the artificial boundary...
std::complex< double > global_flux_contribution()
Compute the element's contribution to the time-averaged flux.
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...
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s...
std::complex< double > global_flux_contribution(std::ofstream &outfile)
Compute the element's contribution to the integral of the flux over the artificial boundary...
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
void output(std::ostream &outfile)
unsigned ndof_types() const
The number of "DOF types" that degrees of freedom in this element are sub-divided into: real and imag...
virtual std::complex< unsigned > u_index_helmholtz() const
Return the index at which the unknown value is stored.
double global_power_contribution()
Compute the element's contribution to the time-averaged radiated power over the artificial boundary...
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
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.
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
unsigned long eqn_number(const unsigned &ieqn_local) const
Return the global equation number corresponding to the ieqn_local-th local equation number...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
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 ...
PMLHelmholtzPowerElement()
Broken empty constructor.
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...
PMLHelmholtzFluxElement()
Broken empty constructor.
double zeta_nodal(const unsigned &n, const unsigned &k, const unsigned &i) const
Broken assignment operator.
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
std::complex< unsigned > U_index_helmholtz
The index at which the real and imag part of the unknown is stored at the nodes.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
virtual std::complex< unsigned > u_index_helmholtz() const
Broken assignment operator.
PMLHelmholtzPrescribedFluxFctPt & flux_fct_pt()
Broken assignment operator.
A class for elements that allow the post-processing of radiated power and flux on the boundaries of P...
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...
unsigned Dim
The spatial dimension of the problem.
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...
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number...
unsigned nnode() const
Return the number of nodes.
Vector< double > local_coordinate_in_bulk(const Vector< double > &s) const
Return vector of local coordinates in bulk element, given the local coordinates in this FaceElement...
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function – forward to broken version in FiniteElement until somebody decides what exa...
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...
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
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...
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 ...