37 #include "helmholtz.h"
40 #include "meshes/triangle_mesh.h"
43 #include "oomph_crbond_bessel.h"
45 using namespace oomph;
79 std::complex<double>
I(0.0,1.0);
83 void get_exact_u(
const Vector<double>& x, Vector<double>& u)
87 r=sqrt(x[0]*x[0]+x[1]*x[1]);
89 theta=atan2(x[1],x[0]);
95 complex <double > u_ex(0.0,0.0);
108 &jnp_a[0],&ynp_a[0]);
114 std::ostringstream error_stream;
115 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
116 << n_actual <<
" rather than " <<
N_fourier
117 <<
" Bessel functions.\n";
118 throw OomphLibError(error_stream.str(),
119 OOMPH_CURRENT_FUNCTION,
120 OOMPH_EXCEPTION_LOCATION);
125 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier,rr,h,hp);
128 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier
138 u_ex-=pow(
I,i)*h[i]*jnp_a[i]*pow(exp(
I*theta),
static_cast<double>(i))/hp_a[i];
142 u_ex-=pow(
I,i)*h[i]*jnp_a[i]*pow(exp(-
I*theta),
static_cast<double>(i))/hp_a[i];
156 complex<double>& flux)
160 r=sqrt(x[0]*x[0]+x[1]*x[1]);
162 theta=atan2(x[1],x[0]);
174 CRBond_Bessel::bessjyna(
N_fourier,rr,n_actual,&jn[0],&yn[0],
181 std::ostringstream error_stream;
182 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
183 << n_actual <<
" rather than " <<
N_fourier
184 <<
" Bessel functions.\n";
185 throw OomphLibError(error_stream.str(),
186 OOMPH_CURRENT_FUNCTION,
187 OOMPH_EXCEPTION_LOCATION);
193 flux=std::complex<double>(0.0,0.0);
196 flux+=pow(
I,i)*(sqrt(
K_squared))*pow(exp(
I*theta),i)*jnp[i];
200 flux+=pow(
I,i)*(sqrt(
K_squared))*pow(exp(-
I*theta),i)*jnp[i];
220 template<
class ELEMENT>
247 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
260 const unsigned &b, Mesh*
const &bulk_mesh_pt,
261 Mesh*
const & helmholtz_outer_boundary_mesh_pt);
266 Mesh*
const & helmholtz_inner_boundary_mesh_pt);
292 HelmholtzDtNMesh<ELEMENT>* Helmholtz_outer_boundary_mesh_pt;
296 Mesh* Helmholtz_inner_boundary_mesh_pt;
308 template<
class ELEMENT>
314 Trace_file.open(
"RESLT/trace.dat");
330 Circle* inner_circle_pt=
new Circle(x_c,y_c,a);
331 Circle* outer_circle_pt=
new Circle(x_c,y_c,
336 TriangleMeshClosedCurve* outer_boundary_pt=0;
338 unsigned n_segments=40;
339 Vector<TriangleMeshCurveSection*> outer_boundary_line_pt(2);
342 double s_start = 0.0;
343 double s_end = MathematicalConstants::Pi;
344 unsigned boundary_id = 2;
345 outer_boundary_line_pt[0]=
346 new TriangleMeshCurviLine(outer_circle_pt,
353 s_start = MathematicalConstants::Pi;
354 s_end = 2.0*MathematicalConstants::Pi;
356 outer_boundary_line_pt[1]=
357 new TriangleMeshCurviLine(outer_circle_pt,
364 outer_boundary_pt=
new TriangleMeshClosedCurve(outer_boundary_line_pt);
368 Vector<TriangleMeshCurveSection*> inner_boundary_line_pt(2);
372 s_end = MathematicalConstants::Pi;
374 inner_boundary_line_pt[0]=
375 new TriangleMeshCurviLine(inner_circle_pt,
382 s_start = MathematicalConstants::Pi;
383 s_end = 2.0*MathematicalConstants::Pi;
385 inner_boundary_line_pt[1]=
386 new TriangleMeshCurviLine(inner_circle_pt,
395 Vector<TriangleMeshClosedCurve*> hole_pt(1);
396 Vector<double> hole_coords(2);
399 hole_pt[0]=
new TriangleMeshClosedCurve(inner_boundary_line_pt,
407 TriangleMeshParameters triangle_mesh_parameters(outer_boundary_pt);
410 triangle_mesh_parameters.internal_closed_curve_pt() = hole_pt;
415 Bulk_mesh_pt=
new RefineableTriangleMesh<ELEMENT>(triangle_mesh_parameters);
418 Bulk_mesh_pt->spatial_error_estimator_pt()=
new Z2ErrorEstimator;
421 Bulk_mesh_pt->min_permitted_error()=0.00004;
422 Bulk_mesh_pt->max_permitted_error()=0.0001;
427 Bulk_mesh_pt=
new TriangleMesh<ELEMENT>(triangle_mesh_parameters);
434 Helmholtz_outer_boundary_mesh_pt =
439 create_outer_bc_elements(2,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
440 create_outer_bc_elements(3,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
444 Helmholtz_inner_boundary_mesh_pt =
new Mesh;
448 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
449 create_flux_elements(1,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
452 add_sub_mesh(Bulk_mesh_pt);
453 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
454 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
464 unsigned n_element = Bulk_mesh_pt->nelement();
465 for(
unsigned e=0;e<n_element;e++)
468 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
475 setup_outer_boundary();
478 set_prescribed_incoming_flux_pt();
481 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
488 template<
class ELEMENT>
492 delete_face_elements(Helmholtz_outer_boundary_mesh_pt);
493 delete_face_elements(Helmholtz_inner_boundary_mesh_pt);
496 rebuild_global_mesh();
504 template<
class ELEMENT>
514 unsigned n_element = Bulk_mesh_pt->nelement();
515 for(
unsigned e=0;e<n_element;e++)
518 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
527 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
528 create_flux_elements(1,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
529 create_outer_bc_elements(2,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
530 create_outer_bc_elements(3,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
533 rebuild_global_mesh();
536 setup_outer_boundary();
537 set_prescribed_incoming_flux_pt();
546 template<
class ELEMENT>
551 unsigned n_element=Helmholtz_outer_boundary_mesh_pt->nelement();
552 for(
unsigned e=0;e<n_element;e++)
558 HelmholtzDtNBoundaryElement<ELEMENT> *el_pt =
559 dynamic_cast< HelmholtzDtNBoundaryElement<ELEMENT>*
>(
560 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
564 el_pt->set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
570 HelmholtzAbsorbingBCElement<ELEMENT> *el_pt =
571 dynamic_cast< HelmholtzAbsorbingBCElement<ELEMENT>*
>(
572 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
588 template<
class ELEMENT>
593 unsigned n_element=Helmholtz_inner_boundary_mesh_pt->nelement();
594 for(
unsigned e=0;e<n_element;e++)
597 HelmholtzFluxElement<ELEMENT> *el_pt =
598 dynamic_cast< HelmholtzFluxElement<ELEMENT>*
>(
599 Helmholtz_inner_boundary_mesh_pt->element_pt(e));
602 el_pt->flux_fct_pt() =
611 template<
class ELEMENT>
616 ofstream some_file,some_file2;
628 sprintf(filename,
"%s/power%i.dat",doc_info.directory().c_str(),
630 some_file.open(filename);
633 unsigned nn_element=Helmholtz_outer_boundary_mesh_pt->nelement();
634 for(
unsigned e=0;e<nn_element;e++)
636 HelmholtzBCElementBase<ELEMENT> *el_pt =
637 dynamic_cast< HelmholtzBCElementBase<ELEMENT>*
>(
638 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
639 power += el_pt->global_power_contribution(some_file);
642 oomph_info <<
"Total radiated power: " << power << std::endl;
646 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
648 some_file.open(filename);
649 Bulk_mesh_pt->output(some_file,npts);
654 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
656 some_file.open(filename);
661 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
663 some_file.open(filename);
669 oomph_info <<
"\nNorm of error : " << sqrt(error) << std::endl;
670 oomph_info <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
674 Trace_file << power << std::endl;
679 for (
unsigned i=0;i<nstep;i++)
681 sprintf(filename,
"%s/helmholtz_animation%i_frame%i.dat",
682 doc_info.directory().c_str(),
683 doc_info.number(),i);
684 some_file.open(filename);
685 sprintf(filename,
"%s/exact_helmholtz_animation%i_frame%i.dat",
686 doc_info.directory().c_str(),
687 doc_info.number(),i);
688 some_file2.open(filename);
689 double phi=2.0*MathematicalConstants::Pi*double(i)/double(nstep-1);
690 unsigned nelem=Bulk_mesh_pt->nelement();
691 for (
unsigned e=0;e<nelem;e++)
693 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(
694 Bulk_mesh_pt->element_pt(e));
695 el_pt->output_real(some_file,phi,npts);
696 el_pt->output_real_fct(some_file2,phi,npts,
710 template<
class ELEMENT>
713 Mesh*
const & helmholtz_inner_boundary_mesh_pt)
716 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
717 for(
unsigned e=0;e<n_element;e++)
720 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
721 bulk_mesh_pt->boundary_element_pt(b,e));
724 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
727 HelmholtzFluxElement<ELEMENT>* flux_element_pt =
new
728 HelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
731 helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
744 template<
class ELEMENT>
747 Mesh*
const & helmholtz_outer_boundary_mesh_pt)
750 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
751 for(
unsigned e=0;e<n_element;e++)
754 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
755 bulk_mesh_pt->boundary_element_pt(b,e));
758 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
765 HelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new
766 HelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,face_index);
769 helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
774 HelmholtzAbsorbingBCElement<ELEMENT>* flux_element_pt =
new
775 HelmholtzAbsorbingBCElement<ELEMENT>(bulk_elem_pt,face_index);
778 helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
787 template<
class ELEMENT>
792 unsigned n_element = boundary_mesh_pt->nelement();
793 for(
unsigned e=0;e<n_element;e++)
796 delete boundary_mesh_pt->element_pt(e);
800 boundary_mesh_pt->flush_element_and_node_storage();
810 int main(
int argc,
char **argv)
813 CommandLineArgs::setup(argc,argv);
817 CommandLineArgs::specify_command_line_flag(
"--case",&i_case);
820 CommandLineArgs::parse_and_assign();
823 CommandLineArgs::doc_specified_flags();
873 doc_info.set_directory(
"RESLT");
879 unsigned max_adapt=1;
883 problem.newton_solve(max_adapt);
888 problem.newton_solve();
////////////////////////////////////////////////////////////////// //////////////////////////////////...
~ScatteringProblem()
Destructor (empty)
void actions_after_adapt()
Actions after adapt: Rebuild the mesh of prescribed flux elements.
void create_outer_bc_elements(const unsigned &b, Mesh *const &bulk_mesh_pt, Mesh *const &helmholtz_outer_boundary_mesh_pt)
Create BC elements on boundary b of the Mesh pointed to by bulk_mesh_pt and add them to the specified...
ofstream Trace_file
Trace file.
TriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
void setup_outer_boundary()
Set up boundary condition elements on outer boundary.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
ScatteringProblem()
Constructor.
void delete_face_elements(Mesh *const &boundary_mesh_pt)
Delete boundary face elements and wipe the surface mesh.
void actions_after_newton_solve()
Update the problem specs after solve (empty)
void actions_before_adapt()
Actions before adapt: Wipe the mesh of prescribed flux elements.
void actions_before_newton_convergence_check()
Recompute gamma integral before checking Newton residuals.
void set_prescribed_incoming_flux_pt()
Set pointer to prescribed-flux function for all elements in the surface mesh on the surface of the un...
RefineableTriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
void create_flux_elements(const unsigned &b, Mesh *const &bulk_mesh_pt, Mesh *const &helmholtz_inner_boundary_mesh_pt)
Create Helmholtz flux elements on boundary b of the Mesh pointed to by bulk_mesh_pt and add them to t...
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to.
Namespace for "global" problem parameters.
void prescribed_incoming_flux(const Vector< double > &x, complex< double > &flux)
Flux (normal derivative) on the unit disk for a planar incoming wave.
unsigned ABC_order
Flag to choose wich order to use.
double Outer_radius
Radius of outer boundary (must be a circle!)
bool DtN_BC
Flag to choose the Dirichlet to Neumann BC or ABC BC.
std::complex< double > I(0.0, 1.0)
Imaginary unit.
double K_squared
Square of the wavenumber.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution for scattered field (vector returns real and impaginary parts).
unsigned N_fourier
Number of terms used in the computation of the exact solution.
int main(int argc, char **argv)
Solve 2D Helmholtz problem for scattering of a planar wave from a unit disk.