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...