28 #include <oomph-lib-config.h> 
   41   template<
unsigned DIM>
 
   43     const unsigned& b, DirichletBCFctPt u_fn, DirichletBCFctPt dudn_fn)
 
   46     unsigned n_node = Bulk_element_mesh_pt->nboundary_node(b);
 
   49     int face_index = Bulk_element_mesh_pt->face_index_at_boundary(b, 0);
 
   52     unsigned s_fixed_index = 0;
 
   66         throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
 
   67                             OOMPH_CURRENT_FUNCTION,
 
   68                             OOMPH_EXCEPTION_LOCATION);
 
   91     const double h = 10
e-8;
 
  101       for (
unsigned n = 0; n < n_node; n++)
 
  104         Bulk_element_mesh_pt->boundary_node_pt(b, n)
 
  105           ->get_coordinates_on_boundary(b, m);
 
  119           (*u_fn)(m[0] + h, u_R);
 
  122         else if (n == n_node - 1)
 
  124           (*u_fn)(m[0] - h, u_L);
 
  130           (*u_fn)(m[0] - 0.5 * h, u_L);
 
  131           (*u_fn)(m[0] + 0.5 * h, u_R);
 
  135         double dudm_t = (u_R - u_L) / h;
 
  138         double duds_t = m[1] * dudm_t;
 
  141         Bulk_element_mesh_pt->boundary_node_pt(b, n)->pin(0);
 
  142         Bulk_element_mesh_pt->boundary_node_pt(b, n)->set_value(0, u);
 
  145         Bulk_element_mesh_pt->boundary_node_pt(b, n)->pin(2 - s_fixed_index);
 
  146         Bulk_element_mesh_pt->boundary_node_pt(b, n)->set_value(
 
  147           2 - s_fixed_index, duds_t);
 
  155       for (
unsigned n = 0; n < n_node; n++)
 
  160         dxds_n[0] = Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(
 
  161           1 + s_fixed_index, 0);
 
  162         dxds_n[1] = Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(
 
  163           1 + s_fixed_index, 1);
 
  164         dxds_t[0] = Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(
 
  165           2 - s_fixed_index, 0);
 
  166         dxds_t[1] = Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(
 
  167           2 - s_fixed_index, 1);
 
  172           Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(3, 0);
 
  174           Bulk_element_mesh_pt->boundary_node_pt(b, n)->x_gen(3, 1);
 
  178           ((dxds_n[0] * dxds_t[1]) - (dxds_n[1] * dxds_t[0])) /
 
  179           (sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]) * edge_sign);
 
  182         double dtds_n = ((dxds_n[0] * dxds_t[0]) + (dxds_n[1] * dxds_t[1])) /
 
  183                         sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  186         double dtds_t = sqrt(pow(dxds_t[0], 2) + pow(dxds_t[1], 2));
 
  190           -1.0 * (edge_sign * sqrt(pow(dxds_t[0], 2) + pow(dxds_t[1], 2))) /
 
  191           (dxds_t[0] * dxds_n[1] - dxds_n[0] * dxds_t[1]);
 
  194         double ds_tdt = 1 / sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  198           (dxds_t[0] * d2xds_nds_t[0] + dxds_t[1] * d2xds_nds_t[1]) /
 
  199           sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  203           (dxds_t[0] * d2xds_nds_t[0] + dxds_t[1] * d2xds_nds_t[1]) /
 
  204           pow(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1], 3.0 / 2.0);
 
  208         Bulk_element_mesh_pt->boundary_node_pt(b, n)
 
  209           ->get_coordinates_on_boundary(b, m_N);
 
  213         double ddm_tdudn = 0;
 
  214         double u_2L, u_N, u_2R, dudn_L, dudn_R;
 
  218           (*u_fn)(m_N[0], u_2L);
 
  219           (*u_fn)(m_N[0] + h, u_N);
 
  220           (*u_fn)(m_N[0] - 2 * h, u_2R);
 
  221           (*dudn_fn)(m_N[0], dudn_L);
 
  222           (*dudn_fn)(m_N[0] + h, dudn_R);
 
  224         else if (n == n_node - 1)
 
  226           (*u_fn)(m_N[0] - 2 * h, u_2L);
 
  227           (*u_fn)(m_N[0] - h, u_N);
 
  228           (*u_fn)(m_N[0], u_2R);
 
  229           (*dudn_fn)(m_N[0] - h, dudn_L);
 
  230           (*dudn_fn)(m_N[0], dudn_R);
 
  234           (*u_fn)(m_N[0] - h, u_2L);
 
  235           u_N = Bulk_element_mesh_pt->boundary_node_pt(b, n)->value(0);
 
  236           (*u_fn)(m_N[0] + h, u_2R);
 
  237           (*dudn_fn)(m_N[0] - 0.5 * h, dudn_L);
 
  238           (*dudn_fn)(m_N[0] + 0.5 * h, dudn_R);
 
  241         d2udm_t2 = (u_2L + u_2R - 2 * u_N) / (h * h);
 
  242         ddm_tdudn = (dudn_R - dudn_L) / h;
 
  246         (*dudn_fn)(m_N[0], dudn);
 
  249         double d2uds_t2 = m_N[1] * m_N[1] * d2udm_t2;
 
  252         double duds_t = Bulk_element_mesh_pt->boundary_node_pt(b, n)->value(
 
  256         double dudt = ds_tdt * duds_t;
 
  259         double d2udndt = ds_tdt = dtds_t * m_N[1] * ddm_tdudn;
 
  262         double dtds_nd2udt2 =
 
  263           edge_sign * (dxds_t[0] * dxds_n[1] - dxds_n[0] * dxds_t[1]) *
 
  265            (d2udndt - ds_ndn * (d2s_tds_ndt * dudt + ds_tdt * d2uds_t2)));
 
  268         double dds_ndudt = dtds_nd2udt2 + dnds_n * d2udndt;
 
  271         double duds_n = dnds_n * dudn + dtds_n * ds_tdt * duds_t;
 
  274         double d2uds_nds_t = d2tds_nds_t * dudt + dtds_t * dds_ndudt;
 
  277         Bulk_element_mesh_pt->boundary_node_pt(b, n)->pin(1 + s_fixed_index);
 
  278         Bulk_element_mesh_pt->boundary_node_pt(b, n)->set_value(
 
  279           1 + s_fixed_index, duds_n);
 
  282         Bulk_element_mesh_pt->boundary_node_pt(b, n)->pin(3);
 
  283         Bulk_element_mesh_pt->boundary_node_pt(b, n)->set_value(3, d2uds_nds_t);
 
  293   template<
unsigned DIM>
 
  300     if (Face_element_mesh_pt == 0)
 
  302       Face_element_mesh_pt = 
new Mesh();
 
  306     unsigned n_element = Bulk_element_mesh_pt->nboundary_element(b);
 
  309     for (
unsigned e = 0; 
e < n_element; 
e++)
 
  313         Bulk_element_mesh_pt->boundary_element_pt(b, 
e));
 
  316       int face_index = Bulk_element_mesh_pt->face_index_at_boundary(b, 
e);
 
  325       if (flux1_fct_pt != 0)
 
  331       Face_element_mesh_pt->add_element_pt(flux_element_pt);
 
  340   template<
unsigned DIM>
 
  344     std::ofstream some_file;
 
  345     std::ostringstream filename;
 
  351     filename << doc_info.
directory() << 
"/soln_" << doc_info.
number() << 
".dat";
 
  352     some_file.open(filename.str().c_str());
 
  353     Bulk_element_mesh_pt->output(some_file, npts);
 
  357     if (exact_soln_pt != 0)
 
  361       filename << doc_info.
directory() << 
"/exact_soln_" << doc_info.
number()
 
  363       some_file.open(filename.str().c_str());
 
  364       Bulk_element_mesh_pt->output_fct(some_file, npts, exact_soln_pt);
 
  372       some_file.open(filename.str().c_str());
 
  373       Bulk_element_mesh_pt->compute_error(
 
  374         some_file, exact_soln_pt, error, norm);
 
  378       oomph_info << 
"\nNorm of error   : " << sqrt(error) << std::endl;
 
  379       oomph_info << 
"Norm of solution: " << sqrt(norm) << std::endl
 
  414     double dtds_n = ((dxds_n[0] * dxds_t[0]) + (dxds_n[1] * dxds_t[1])) /
 
  415                     sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  418     double ds_tdt = 1 / sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  429          dtds_n * ds_tdt * this->
node_pt(0)->
value(k_tangential));
 
  436         if (local_dof_number >= 0)
 
  441         if (local_dof_number >= 0)
 
  456   template<
unsigned DIM>
 
  458     const unsigned& b, 
const double& psi)
 
  461     unsigned n_node = mesh_pt()->nboundary_node(b);
 
  464     for (
unsigned n = 0; n < n_node; n++)
 
  467       for (
unsigned k = 1; k < 4; k++)
 
  470         mesh_pt()->boundary_node_pt(b, n)->pin(k);
 
  471         mesh_pt()->boundary_node_pt(b, n)->set_value(k, 0.0);
 
  473       mesh_pt()->boundary_node_pt(b, n)->pin(0);
 
  474       mesh_pt()->boundary_node_pt(b, n)->set_value(0, psi);
 
  488   template<
unsigned DIM>
 
  492     int face_index = mesh_pt()->face_index_at_boundary(b, 0);
 
  495     unsigned s_fixed_index = 0;
 
  509         throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
 
  510                             OOMPH_CURRENT_FUNCTION,
 
  511                             OOMPH_EXCEPTION_LOCATION);
 
  522     unsigned n_node = mesh_pt()->nboundary_node(b);
 
  525     for (
unsigned n = 0; n < n_node; n++)
 
  529         mesh_pt()->boundary_node_pt(b, n)->x_gen(1 + s_fixed_index, 0);
 
  531         mesh_pt()->boundary_node_pt(b, n)->x_gen(1 + s_fixed_index, 1);
 
  533         mesh_pt()->boundary_node_pt(b, n)->x_gen(2 - s_fixed_index, 0);
 
  535         mesh_pt()->boundary_node_pt(b, n)->x_gen(2 - s_fixed_index, 1);
 
  538       double dtds_n = ((dxds_n[0] * dxds_t[0]) + (dxds_n[1] * dxds_t[1])) /
 
  539                       sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  547         mesh_pt()->boundary_node_pt(b, n)->pin(1 + s_fixed_index);
 
  548         mesh_pt()->boundary_node_pt(b, n)->set_value(1 + s_fixed_index, 0.0);
 
  562               mesh_pt()->boundary_element_pt(b, n - 1));
 
  567           if (n < (n_node - 1))
 
  570               mesh_pt()->boundary_element_pt(b, n));
 
  582               mesh_pt()->boundary_element_pt(b, n - 1));
 
  590               mesh_pt()->boundary_element_pt(b, n));
 
  603               mesh_pt()->boundary_element_pt(b, n - 1));
 
  611               mesh_pt()->boundary_element_pt(b, n));
 
  623               mesh_pt()->boundary_element_pt(b, n - 1));
 
  631               mesh_pt()->boundary_element_pt(b, n));
 
  643         mesh_pt()->add_element_pt(boundary_point_element_pt);
 
  657   template<
unsigned DIM>
 
  659     const unsigned& b, FluidBCFctPt u_imposed_fn)
 
  662     unsigned n_node = mesh_pt()->nboundary_node(b);
 
  665     int face_index = mesh_pt()->face_index_at_boundary(b, 0);
 
  668     unsigned s_fixed_index = 0;
 
  695         throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
 
  696                             OOMPH_CURRENT_FUNCTION,
 
  697                             OOMPH_EXCEPTION_LOCATION);
 
  706     const double h = 10
e-8;
 
  709     for (
unsigned n = 0; n < n_node; n++)
 
  713       mesh_pt()->boundary_node_pt(b, n)->get_coordinates_on_boundary(b, m_N);
 
  719         mesh_pt()->boundary_node_pt(b, n)->x_gen(1 + s_fixed_index, 0);
 
  721         mesh_pt()->boundary_node_pt(b, n)->x_gen(1 + s_fixed_index, 1);
 
  723         mesh_pt()->boundary_node_pt(b, n)->x_gen(2 - s_fixed_index, 0);
 
  725         mesh_pt()->boundary_node_pt(b, n)->x_gen(2 - s_fixed_index, 1);
 
  729       d2xds_nds_t[0] = mesh_pt()->boundary_node_pt(b, n)->x_gen(3, 0);
 
  730       d2xds_nds_t[1] = mesh_pt()->boundary_node_pt(b, n)->x_gen(3, 1);
 
  734         ((dxds_n[0] * dxds_t[1]) - (dxds_n[1] * dxds_t[0])) /
 
  735         (sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]) * edge_sign);
 
  738       double dtds_n = ((dxds_n[0] * dxds_t[0]) + (dxds_n[1] * dxds_t[1])) /
 
  739                       sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  742       double dtds_t = sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  746         (dxds_t[0] * d2xds_nds_t[0] + dxds_t[1] * d2xds_nds_t[1]) /
 
  747         sqrt(dxds_t[0] * dxds_t[0] + dxds_t[1] * dxds_t[1]);
 
  751       (*u_imposed_fn)(m_N[0], u);
 
  756       double ddm_tdudn = 0;
 
  757       double ddm_tdudt = 0;
 
  763         (*u_imposed_fn)(m_N[0], u_L);
 
  764         (*u_imposed_fn)(m_N[0] + h, u_R);
 
  766       else if (n == n_node - 1)
 
  768         (*u_imposed_fn)(m_N[0] - h, u_L);
 
  769         (*u_imposed_fn)(m_N[0], u_R);
 
  773         (*u_imposed_fn)(m_N[0] - 0.5 * h, u_L);
 
  774         (*u_imposed_fn)(m_N[0] + 0.5 * h, u_R);
 
  777       ddm_tdudn = (u_R[1] - u_L[1]) / h;
 
  778       ddm_tdudt = (u_R[0] - u_L[0]) / h;
 
  781       double duds_t = dtds_t * u[0];
 
  784       double duds_n = dnds_n * u[1] + dtds_n * u[0];
 
  787       double d2uds_nds_t = dnds_n * m_N[1] * ddm_tdudn + d2tds_nds_t * u[0] +
 
  788                            dtds_n * m_N[1] * ddm_tdudt;
 
  791       mesh_pt()->boundary_node_pt(b, n)->pin(1 + s_fixed_index);
 
  792       mesh_pt()->boundary_node_pt(b, n)->set_value(1 + s_fixed_index, duds_n);
 
  795       mesh_pt()->boundary_node_pt(b, n)->pin(2 - s_fixed_index);
 
  796       mesh_pt()->boundary_node_pt(b, n)->set_value(2 - s_fixed_index, duds_t);
 
  799       mesh_pt()->boundary_node_pt(b, n)->pin(3);
 
  800       mesh_pt()->boundary_node_pt(b, n)->set_value(3, d2uds_nds_t);
 
  809   template<
unsigned DIM>
 
  814     std::ofstream some_file;
 
  815     std::ostringstream filename;
 
  821     filename << doc_info.
directory() << 
"/soln_" << doc_info.
label() << 
".dat";
 
  822     some_file.open(filename.str().c_str());
 
  823     mesh_pt()->output(some_file, npts);
 
  828     filename << doc_info.
directory() << 
"/soln_velocity_" << doc_info.
label()
 
  830     some_file.open(filename.str().c_str());
 
  831     unsigned n_element = mesh_pt()->nelement();
 
  832     for (
unsigned i = 0; 
i < n_element - Npoint_element; 
i++)
 
  841     if (exact_soln_pt != 0)
 
  845       filename << doc_info.
directory() << 
"/exact_soln_" << doc_info.
label()
 
  847       some_file.open(filename.str().c_str());
 
  848       mesh_pt()->output_fct(some_file, npts, exact_soln_pt);
 
  856       some_file.open(filename.str().c_str());
 
  857       mesh_pt()->compute_error(some_file, exact_soln_pt, error, norm);
 
  861       oomph_info << 
"\nNorm of error   : " << sqrt(error) << std::endl;
 
  862       oomph_info << 
"Norm of solution: " << sqrt(norm) << std::endl
 
void output_fluid_velocity(std::ostream &outfile, const unsigned &nplot)
output fluid velocity field
Point equation element used to impose the traction free edge (i.e. du/dn = 0) on the boundary when dt...
virtual void fill_in_generic_residual_contribution_biharmonic_boundary(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned JFLAG)
Computes the elemental residual vector and the elemental jacobian matrix if JFLAG = 0 Imposes the equ...
Biharmonic Fluid Problem Class - describes stokes flow in 2D. Developed for the topologically rectang...
void doc_solution(DocInfo &doc_info, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt=0)
documents the solution, and if an exact solution is provided, then the error between the numerical an...
void impose_fluid_flow_on_edge(const unsigned &b, FluidBCFctPt u_imposed_fn)
Impose a prescribed fluid flow comprising the velocity normal to the boundary (u_imposed_fn[0]) and t...
void impose_solid_boundary_on_edge(const unsigned &b, const double &psi=0)
Imposes a solid boundary on boundary b - no flow into boundary or along boundary v_n = 0 and v_t = 0....
void impose_traction_free_edge(const unsigned &b)
Impose a traction free edge - i.e. v_t = 0 or dpsi/dn = 0. In general dpsi/dn = 0 can only be imposed...
FluxFctPt & flux0_fct_pt()
Access function for the flux0 function pointer.
FluxFctPt & flux1_fct_pt()
Access function for the flux1 function pointer.
Biharmonic Plate Problem Class - for problems where the load can be assumed to be acting normal to th...
void set_neumann_boundary_condition(const unsigned &b, BiharmonicFluxElement< 2 >::FluxFctPt flux0_fct_pt, BiharmonicFluxElement< 2 >::FluxFctPt flux1_fct_pt=0)
Imposes the prescribed Neumann BCs laplacian(u) (flux0_fct_pt) and dlaplacian(u)/dn (flux1_fct_pt) wi...
void doc_solution(DocInfo &doc_info, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt=0)
documents the solution, and if an exact solution is provided, then the error between the numerical an...
void set_dirichlet_boundary_condition(const unsigned &b, DirichletBCFctPt u_fn=0, DirichletBCFctPt dudn_fn=0)
Imposes the prescribed dirichlet BCs u (u_fn) and du/dn (dudn_fn) dirichlet BCs by 'pinning'.
Information for documentation of results: Directory and file number to enable output in the form RESL...
std::string & label()
String used (e.g.) for labeling output files.
std::string directory() const
Output directory.
unsigned & number()
Number used (e.g.) for labeling output files.
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
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.
void(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution"  as .
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number....
Hijacked elements are elements in which one or more Data values that affect the element's residuals,...
Data * hijack_nodal_value(const unsigned &n, const unsigned &i, const bool &return_data=true)
Hijack the i-th value stored at node n. Optionally return a custom-made (copied) data object that con...
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i.
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
An OomphLibError object which should be thrown when an run-time error is encountered....
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...