32 #include <oomph-lib-config.h> 46 template<
unsigned DIM>
49 DirichletBCFctPt dudn_fn)
52 unsigned n_node = Bulk_element_mesh_pt->nboundary_node(b);
55 int face_index = Bulk_element_mesh_pt->face_index_at_boundary(b,0);
58 unsigned s_fixed_index = 0;
72 throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
73 OOMPH_CURRENT_FUNCTION,
74 OOMPH_EXCEPTION_LOCATION);
97 const double h = 10
e-8;
108 for (
unsigned n = 0; n < n_node; n++)
112 Bulk_element_mesh_pt->boundary_node_pt(b,n)->
113 get_coordinates_on_boundary(b,m);
130 else if (n == n_node-1)
138 (*u_fn)(m[0]-0.5*h,u_L);
139 (*u_fn)(m[0]+0.5*h,u_R);
143 double dudm_t = (u_R-u_L)/h;
146 double duds_t = m[1]*dudm_t;
149 Bulk_element_mesh_pt->boundary_node_pt(b,n)->pin(0);
150 Bulk_element_mesh_pt->boundary_node_pt(b,n)->set_value(0,u);
153 Bulk_element_mesh_pt->boundary_node_pt(b,n)->pin(2-s_fixed_index);
154 Bulk_element_mesh_pt->boundary_node_pt(b,n)
155 ->set_value(2-s_fixed_index,duds_t);
164 for (
unsigned n = 0; n < n_node; n++)
170 Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,0);
172 Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,1);
174 Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,0);
176 Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,1);
180 d2xds_nds_t[0] = Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(3,0);
181 d2xds_nds_t[1] = Bulk_element_mesh_pt->boundary_node_pt(b,n)->x_gen(3,1);
184 double dnds_n = ((dxds_n[0]*dxds_t[1])-(dxds_n[1]*dxds_t[0]))
185 / (sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1])*edge_sign);
188 double dtds_n = ((dxds_n[0]*dxds_t[0])+(dxds_n[1]*dxds_t[1]))
189 /sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
192 double dtds_t = sqrt(pow(dxds_t[0],2)+pow(dxds_t[1],2));
195 double ds_ndn = -1.0*(edge_sign*sqrt(pow(dxds_t[0],2)+pow(dxds_t[1],2)))/
196 (dxds_t[0]*dxds_n[1]-dxds_n[0]*dxds_t[1]);
199 double ds_tdt = 1/sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
202 double d2tds_nds_t = (dxds_t[0]*d2xds_nds_t[0] + dxds_t[1]*d2xds_nds_t[1])
203 /sqrt(dxds_t[0]*dxds_t[0] + dxds_t[1]*dxds_t[1]);
206 double d2s_tds_ndt = (dxds_t[0]*d2xds_nds_t[0] + dxds_t[1]*d2xds_nds_t[1])
207 /pow(dxds_t[0]*dxds_t[0] + dxds_t[1]*dxds_t[1],3.0/2.0);
211 Bulk_element_mesh_pt->boundary_node_pt(b,n)
212 ->get_coordinates_on_boundary(b,m_N);
216 double ddm_tdudn = 0;
217 double u_2L,u_N,u_2R,dudn_L,dudn_R;
221 (*u_fn)(m_N[0],u_2L);
222 (*u_fn)(m_N[0]+h,u_N);
223 (*u_fn)(m_N[0]-2*h,u_2R);
224 (*dudn_fn)(m_N[0],dudn_L);
225 (*dudn_fn)(m_N[0]+h,dudn_R);
227 else if (n == n_node-1)
229 (*u_fn)(m_N[0]-2*h,u_2L);
230 (*u_fn)(m_N[0]-h,u_N);
231 (*u_fn)(m_N[0],u_2R);
232 (*dudn_fn)(m_N[0]-h,dudn_L);
233 (*dudn_fn)(m_N[0],dudn_R);
237 (*u_fn)(m_N[0]-h,u_2L);
238 u_N = Bulk_element_mesh_pt->boundary_node_pt(b,n)->value(0);
239 (*u_fn)(m_N[0]+h,u_2R);
240 (*dudn_fn)(m_N[0]-0.5*h,dudn_L);
241 (*dudn_fn)(m_N[0]+0.5*h,dudn_R);
244 d2udm_t2 = (u_2L+u_2R-2*u_N)/(h*h);
245 ddm_tdudn = (dudn_R-dudn_L)/h;
249 (*dudn_fn)(m_N[0],dudn);
252 double d2uds_t2 = m_N[1]*m_N[1]*d2udm_t2;
255 double duds_t = Bulk_element_mesh_pt->
256 boundary_node_pt(b,n)->value(2-s_fixed_index);
259 double dudt = ds_tdt*duds_t;
262 double d2udndt = ds_tdt= dtds_t*m_N[1]*ddm_tdudn;
265 double dtds_nd2udt2 = edge_sign*(dxds_t[0]*dxds_n[1]-
266 dxds_n[0]*dxds_t[1])*
267 (ds_tdt*(d2udndt - ds_ndn*(d2s_tds_ndt*dudt+
271 double dds_ndudt = dtds_nd2udt2 + dnds_n*d2udndt;
274 double duds_n = dnds_n*dudn + dtds_n*ds_tdt*duds_t;
277 double d2uds_nds_t = d2tds_nds_t*dudt+dtds_t*dds_ndudt;
280 Bulk_element_mesh_pt->boundary_node_pt(b,n)->pin(1+s_fixed_index);
281 Bulk_element_mesh_pt->boundary_node_pt(b,n)->
282 set_value(1+s_fixed_index,duds_n);
285 Bulk_element_mesh_pt->boundary_node_pt(b,n)->pin(3);
286 Bulk_element_mesh_pt->boundary_node_pt(b,n)->set_value(3,d2uds_nds_t);
297 template<
unsigned DIM>
307 if (Face_element_mesh_pt == 0)
309 Face_element_mesh_pt =
new Mesh();
313 unsigned n_element = Bulk_element_mesh_pt->nboundary_element(b);
316 for(
unsigned e=0;
e<n_element;
e++)
321 dynamic_cast<FiniteElement*
>(Bulk_element_mesh_pt->boundary_element_pt(b,
e));
324 int face_index = Bulk_element_mesh_pt->face_index_at_boundary(b,
e);
329 (bulk_elem_pt, face_index, b);
334 if (flux1_fct_pt != 0)
340 Face_element_mesh_pt->add_element_pt(flux_element_pt);
349 template<
unsigned DIM>
354 std::ofstream some_file;
355 std::ostringstream filename;
361 filename << doc_info.
directory() <<
"/soln_" << doc_info.
number() <<
".dat";
362 some_file.open(filename.str().c_str());
363 Bulk_element_mesh_pt->output(some_file,npts);
367 if (exact_soln_pt != 0)
372 filename << doc_info.
directory() <<
"/exact_soln_" 373 << doc_info.
number() <<
".dat";
374 some_file.open(filename.str().c_str());
375 Bulk_element_mesh_pt->output_fct(some_file,npts, exact_soln_pt);
381 filename << doc_info.
directory() <<
"/error_" 382 << doc_info.
number() <<
".dat";
383 some_file.open(filename.str().c_str());
384 Bulk_element_mesh_pt->compute_error(some_file, exact_soln_pt, error, norm);
388 oomph_info <<
"\nNorm of error : " << sqrt(error) << std::endl;
389 oomph_info <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
428 double dtds_n = ((dxds_n[0]*dxds_t[0])+(dxds_n[1]*dxds_t[1]))
429 /sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
432 double ds_tdt = 1/sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
438 if (local_eqn_number >= 0)
452 if (local_dof_number >= 0)
454 jacobian(local_eqn_number,local_dof_number) += 1.0;
457 if (local_dof_number >= 0)
459 jacobian(local_eqn_number,local_dof_number) -= dtds_n*ds_tdt;
476 template<
unsigned DIM>
481 unsigned n_node = mesh_pt()->nboundary_node(b);
484 for (
unsigned n = 0; n < n_node; n++)
487 for (
unsigned k = 1; k < 4; k++)
490 mesh_pt()->boundary_node_pt(b,n)->pin(k);
491 mesh_pt()->boundary_node_pt(b,n)->set_value(k,0.0);
493 mesh_pt()->boundary_node_pt(b,n)->pin(0);
494 mesh_pt()->boundary_node_pt(b,n)->set_value(0,psi);
508 template<
unsigned DIM>
513 int face_index = mesh_pt()->face_index_at_boundary(b,0);
516 unsigned s_fixed_index = 0;
530 throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
531 OOMPH_CURRENT_FUNCTION,
532 OOMPH_EXCEPTION_LOCATION);
543 unsigned n_node = mesh_pt()->nboundary_node(b);
546 for (
unsigned n = 0; n < n_node; n++)
550 dxds_n[0] = mesh_pt()->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,0);
551 dxds_n[1] = mesh_pt()->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,1);
552 dxds_t[0] = mesh_pt()->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,0);
553 dxds_t[1] = mesh_pt()->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,1);
556 double dtds_n = ((dxds_n[0]*dxds_t[0])+(dxds_n[1]*dxds_t[1]))
557 /sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
565 mesh_pt()->boundary_node_pt(b,n)->pin(1+s_fixed_index);
566 mesh_pt()->boundary_node_pt(b,n)->set_value(1+s_fixed_index,0.0);
579 hijacked_element_pt =
581 (mesh_pt()->boundary_element_pt(b,n-1));
587 hijacked_element_pt =
589 (mesh_pt()->boundary_element_pt(b,n));
599 hijacked_element_pt =
601 (mesh_pt()->boundary_element_pt(b,n-1));
607 hijacked_element_pt =
609 (mesh_pt()->boundary_element_pt(b,n));
620 hijacked_element_pt =
622 (mesh_pt()->boundary_element_pt(b,n-1));
628 hijacked_element_pt =
630 (mesh_pt()->boundary_element_pt(b,n));
640 hijacked_element_pt =
642 (mesh_pt()->boundary_element_pt(b,n-1));
648 hijacked_element_pt =
650 (mesh_pt()->boundary_element_pt(b,n));
661 mesh_pt()->add_element_pt(boundary_point_element_pt);
675 template<
unsigned DIM>
681 unsigned n_node = mesh_pt()->nboundary_node(b);
684 int face_index = mesh_pt()->face_index_at_boundary(b,0);
687 unsigned s_fixed_index = 0;
714 throw OomphLibError(
"Face Index not +/-1 or +/-2: Need 2D QElements",
715 OOMPH_CURRENT_FUNCTION,
716 OOMPH_EXCEPTION_LOCATION);
725 const double h = 10
e-8;
728 for (
unsigned n = 0; n < n_node; n++)
733 mesh_pt()->boundary_node_pt(b,n)->get_coordinates_on_boundary(b,m_N);
738 dxds_n[0] = mesh_pt()->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,0);
739 dxds_n[1] = mesh_pt()->boundary_node_pt(b,n)->x_gen(1+s_fixed_index,1);
740 dxds_t[0] = mesh_pt()->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,0);
741 dxds_t[1] = mesh_pt()->boundary_node_pt(b,n)->x_gen(2-s_fixed_index,1);
745 d2xds_nds_t[0] = mesh_pt()->boundary_node_pt(b,n)->x_gen(3,0);
746 d2xds_nds_t[1] = mesh_pt()->boundary_node_pt(b,n)->x_gen(3,1);
749 double dnds_n = ((dxds_n[0]*dxds_t[1])-(dxds_n[1]*dxds_t[0]))
750 / (sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1])*edge_sign);
753 double dtds_n = ((dxds_n[0]*dxds_t[0])+(dxds_n[1]*dxds_t[1]))
754 /sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
757 double dtds_t = sqrt(dxds_t[0]*dxds_t[0]+dxds_t[1]*dxds_t[1]);
760 double d2tds_nds_t = (dxds_t[0]*d2xds_nds_t[0] + dxds_t[1]*d2xds_nds_t[1])
761 /sqrt(dxds_t[0]*dxds_t[0] + dxds_t[1]*dxds_t[1]);
765 (*u_imposed_fn)(m_N[0],u);
770 double ddm_tdudn = 0;
771 double ddm_tdudt = 0;
777 (*u_imposed_fn)(m_N[0],u_L);
778 (*u_imposed_fn)(m_N[0]+h,u_R);
780 else if (n == n_node-1)
782 (*u_imposed_fn)(m_N[0]-h,u_L);
783 (*u_imposed_fn)(m_N[0],u_R);
787 (*u_imposed_fn)(m_N[0]-0.5*h,u_L);
788 (*u_imposed_fn)(m_N[0]+0.5*h,u_R);
791 ddm_tdudn = (u_R[1]-u_L[1])/h;
792 ddm_tdudt = (u_R[0]-u_L[0])/h;
795 double duds_t = dtds_t*u[0];
798 double duds_n = dnds_n*u[1] + dtds_n*u[0];
801 double d2uds_nds_t = dnds_n*m_N[1]*ddm_tdudn + d2tds_nds_t*u[0]
802 + dtds_n*m_N[1]*ddm_tdudt;
805 mesh_pt()->boundary_node_pt(b,n)->pin(1+s_fixed_index);
806 mesh_pt()->boundary_node_pt(b,n)->set_value(1+s_fixed_index,duds_n);
809 mesh_pt()->boundary_node_pt(b,n)->pin(2-s_fixed_index);
810 mesh_pt()->boundary_node_pt(b,n)->set_value(2-s_fixed_index,duds_t);
813 mesh_pt()->boundary_node_pt(b,n)->pin(3);
814 mesh_pt()->boundary_node_pt(b,n)->set_value(3,d2uds_nds_t);
823 template<
unsigned DIM>
829 std::ofstream some_file;
830 std::ostringstream filename;
836 filename << doc_info.
directory() <<
"/soln_" 837 << doc_info.
label() <<
".dat";
838 some_file.open(filename.str().c_str());
839 mesh_pt()->output(some_file,npts);
844 filename << doc_info.
directory() <<
"/soln_velocity_" 845 << doc_info.
label() <<
".dat";
846 some_file.open(filename.str().c_str());
847 unsigned n_element = mesh_pt()->nelement();
848 for (
unsigned i = 0;
i < n_element-Npoint_element;
i++)
857 if (exact_soln_pt != 0)
862 filename << doc_info.
directory() <<
"/exact_soln_" 863 << doc_info.
label() <<
".dat";
864 some_file.open(filename.str().c_str());
865 mesh_pt()->output_fct(some_file,npts, exact_soln_pt);
871 filename << doc_info.
directory() <<
"/error_" 872 << doc_info.
label() <<
".dat";
873 some_file.open(filename.str().c_str());
874 mesh_pt()->compute_error(some_file, exact_soln_pt, error, norm);
878 oomph_info <<
"\nNorm of error : " << sqrt(error) << std::endl;
879 oomph_info <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
Information for documentation of results: Directory and file number to enable output in the form RESL...
std::string directory() const
Output directory.
std::string & label()
String used (e.g.) for labeling output files.
A general Finite Element class.
FluxFctPt & flux0_fct_pt()
Access function for the flux0 function pointer.
void output_fluid_velocity(std::ostream &outfile, const unsigned &nplot)
output fluid velocity field
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...
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...
unsigned & number()
Number used (e.g.) for labeling output files.
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(* SteadyExactSolutionFctPt)(const Vector< double > &, Vector< double > &)
Function pointer for function that computes vector-valued steady "exact solution" as ...
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 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...
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i).
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
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...
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...
Point equation element used to impose the traction free edge (i.e. du/dn = 0) on the boundary when dt...
BiharmonicFluidBoundaryElement(Node *node_pt, const unsigned s_fixed_index)
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'...
Hijacked elements are elements in which one or more Data values that affect the element's residuals...
Biharmonic Fluid Problem Class - describes stokes flow in 2D. Developed for the topologically rectang...
int local_eqn_number(const unsigned long &ieqn_global) const
Return the local equation number corresponding to the ieqn_global-th global equation number...
Biharmonic Plate Problem Class - for problems where the load can be assumed to be acting normal to th...
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
FluxFctPt & flux1_fct_pt()
Access function for the flux1 function pointer.
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...
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...