39 #include "helmholtz.h"
42 #include "pml_helmholtz.h"
45 #include "meshes/triangle_mesh.h"
46 #include "meshes/rectangular_quadmesh.h"
49 #include "oomph_crbond_bessel.h"
51 using namespace oomph;
76 std::complex<double>
I(0.0,1.0);
84 r=sqrt(x[0]*x[0]+x[1]*x[1]);
86 theta=atan2(x[1],x[0]);
92 complex <double > u_ex(0.0,0.0);
105 &jnp_a[0],&ynp_a[0]);
111 std::ostringstream error_stream;
112 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
113 << n_actual <<
" rather than " <<
N_fourier
114 <<
" Bessel functions.\n";
115 throw OomphLibError(error_stream.str(),
116 OOMPH_CURRENT_FUNCTION,
117 OOMPH_EXCEPTION_LOCATION);
122 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier,rr,h,hp);
125 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier
135 u_ex-=pow(
I,i)*h[i]*jnp_a[i]*pow(exp(
I*theta),
static_cast<double>(i))/hp_a[i];
139 u_ex-=pow(
I,i)*h[i]*jnp_a[i]*pow(exp(-
I*theta),
static_cast<double>(i))/hp_a[i];
153 complex<double>& flux)
157 r=sqrt(x[0]*x[0]+x[1]*x[1]);
159 theta=atan2(x[1],x[0]);
171 CRBond_Bessel::bessjyna(
N_fourier,rr,n_actual,&jn[0],&yn[0],
178 std::ostringstream error_stream;
179 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
180 << n_actual <<
" rather than " <<
N_fourier
181 <<
" Bessel functions.\n";
182 throw OomphLibError(error_stream.str(),
183 OOMPH_CURRENT_FUNCTION,
184 OOMPH_EXCEPTION_LOCATION);
190 flux=std::complex<double>(0.0,0.0);
197 flux+=pow(
I,i)*(
Wavenumber)*pow(exp(-
I*theta),i)*jnp[i];
212 std::complex<double>
gamma(
const double& nu_i,
213 const double& pml_width_i,
214 const double& k_squared_local,
215 const double& alpha_shift=0.0)
221 return 1.0 + (1.0 / std::complex<double> (sqrt(k_squared_local), 0))
222 * std::complex<double>
223 (0.0, 2.0/(std::fabs(pml_width_i - nu_i)));
241 template<
class ELEMENT>
268 void create_flux_elements(
const unsigned &b, Mesh*
const &bulk_mesh_pt,
269 Mesh*
const & helmholtz_inner_boundary_mesh_pt);
273 void create_power_elements(
const unsigned &b, Mesh*
const &bulk_mesh_pt,
274 Mesh*
const & helmholtz_power_boundary_mesh_pt);
294 RefineableTriangleMesh<ELEMENT>* Bulk_mesh_pt;
301 TriangleMesh<ELEMENT>* Bulk_mesh_pt;
307 Mesh* PML_right_mesh_pt;
310 Mesh* PML_top_mesh_pt;
313 Mesh* PML_left_mesh_pt;
316 Mesh* PML_bottom_mesh_pt;
319 Mesh* PML_top_right_mesh_pt;
322 Mesh* PML_top_left_mesh_pt;
325 Mesh* PML_bottom_right_mesh_pt;
328 Mesh* PML_bottom_left_mesh_pt;
347 template<
class ELEMENT>
352 Trace_file.open(
"RESLT/trace.dat");
358 Circle* inner_circle_pt=
new Circle(x_c,y_c,a);
362 TriangleMeshClosedCurve* outer_boundary_pt=0;
364 unsigned n_segments = 20;
365 Vector<TriangleMeshCurveSection*> outer_boundary_line_pt(4);
369 Vector<Vector<double> > vertex_coord(2);
370 for(
unsigned i=0;i<2;i++)
372 vertex_coord[i].resize(2);
376 vertex_coord[0][0]=-2.0;
377 vertex_coord[0][1]=-2.0;
378 vertex_coord[1][0]=-2.0;
379 vertex_coord[1][1]=2.0;
382 unsigned boundary_id=2;
383 outer_boundary_line_pt[0] =
new TriangleMeshPolyLine(vertex_coord,
387 vertex_coord[0][0]=-2.0;
388 vertex_coord[0][1]=2.0;
389 vertex_coord[1][0]=2.0;
390 vertex_coord[1][1]=2.0;
394 outer_boundary_line_pt[1] =
new TriangleMeshPolyLine(vertex_coord,
398 vertex_coord[0][0]=2.0;
399 vertex_coord[0][1]=2.0;
400 vertex_coord[1][0]=2.0;
401 vertex_coord[1][1]=-2.0;
405 outer_boundary_line_pt[2] =
new TriangleMeshPolyLine(vertex_coord,
409 vertex_coord[0][0]=2.0;
410 vertex_coord[0][1]=-2.0;
411 vertex_coord[1][0]=-2.0;
412 vertex_coord[1][1]=-2.0;
416 outer_boundary_line_pt[3] =
new TriangleMeshPolyLine(vertex_coord,
420 outer_boundary_pt =
new TriangleMeshPolygon(outer_boundary_line_pt);
424 Vector<TriangleMeshCurveSection*> inner_boundary_line_pt(2);
427 double s_start = 0.0;
428 double s_end = MathematicalConstants::Pi;
430 inner_boundary_line_pt[0]=
431 new TriangleMeshCurviLine(inner_circle_pt,
438 s_start = MathematicalConstants::Pi;
439 s_end = 2.0*MathematicalConstants::Pi;
441 inner_boundary_line_pt[1]=
442 new TriangleMeshCurviLine(inner_circle_pt,
451 Vector<TriangleMeshClosedCurve*> hole_pt(1);
452 Vector<double> hole_coords(2);
455 hole_pt[0]=
new TriangleMeshClosedCurve(inner_boundary_line_pt,
462 TriangleMeshParameters triangle_mesh_parameters(outer_boundary_pt);
465 triangle_mesh_parameters.internal_closed_curve_pt() = hole_pt;
468 triangle_mesh_parameters.element_area() = 0.05;
473 Bulk_mesh_pt=
new RefineableTriangleMesh<ELEMENT>(triangle_mesh_parameters);
476 Bulk_mesh_pt->spatial_error_estimator_pt()=
new Z2ErrorEstimator;
479 Bulk_mesh_pt->min_permitted_error()=0.00004;
480 Bulk_mesh_pt->max_permitted_error()=0.0001;
485 Bulk_mesh_pt=
new TriangleMesh<ELEMENT>(triangle_mesh_parameters);
491 Helmholtz_inner_boundary_mesh_pt =
new Mesh;
495 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
496 create_flux_elements(1,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
500 Helmholtz_power_boundary_mesh_pt =
new Mesh;
504 create_power_elements(0,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
505 create_power_elements(1,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
508 add_sub_mesh(Bulk_mesh_pt);
514 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
520 unsigned n_element = this->mesh_pt()->nelement();
521 for(
unsigned e=0;e<n_element;e++)
524 PMLHelmholtzEquations<2> *el_pt =
525 dynamic_cast<PMLHelmholtzEquations<2>*
>(mesh_pt()->element_pt(e));
538 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
548 template<
class ELEMENT>
554 delete PML_right_mesh_pt;
556 delete PML_top_mesh_pt;
558 delete PML_left_mesh_pt;
560 delete PML_bottom_mesh_pt;
561 PML_bottom_mesh_pt=0;
562 delete PML_top_right_mesh_pt;
563 PML_top_right_mesh_pt=0;
564 delete PML_top_left_mesh_pt;
565 PML_top_left_mesh_pt=0;
566 delete PML_bottom_right_mesh_pt;
567 PML_bottom_right_mesh_pt=0;
568 delete PML_bottom_left_mesh_pt;
569 PML_bottom_left_mesh_pt=0;
576 add_sub_mesh(Bulk_mesh_pt);
580 rebuild_global_mesh();
588 template<
class ELEMENT>
591 create_inner_bc_elements(0,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
592 create_inner_bc_elements(1,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
600 unsigned n_element = this->mesh_pt()->nelement();
602 for(
unsigned e=0;e<n_element;e++)
605 PMLHelmholtzEquations<2> *el_pt =
606 dynamic_cast<PMLHelmholtzEquations<2>*
>(mesh_pt()->element_pt(e));
618 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
619 create_flux_elements(1,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
623 create_power_elements(0,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
624 create_power_elements(1,Bulk_mesh_pt,Helmholtz_power_boundary_mesh_pt);
627 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
630 rebuild_global_mesh();
639 template<
class ELEMENT>
643 ofstream some_file,some_file2;
652 sprintf(filename,
"%s/power%i.dat",doc_info.directory().c_str(),
654 some_file.open(filename);
658 unsigned nn_element=Helmholtz_power_boundary_mesh_pt->nelement();
659 for(
unsigned e=0;e<nn_element;e++)
661 PMLHelmholtzPowerElement<ELEMENT> *el_pt =
662 dynamic_cast<PMLHelmholtzPowerElement<ELEMENT>*
>(
663 Helmholtz_power_boundary_mesh_pt->element_pt(e));
664 power += el_pt->global_power_contribution(some_file);
667 oomph_info <<
"Total radiated power: " << power << std::endl;
671 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
673 some_file.open(filename);
674 Bulk_mesh_pt->output(some_file,npts);
679 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
681 some_file.open(filename);
686 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
688 some_file.open(filename);
694 oomph_info <<
"\nNorm of error : " << sqrt(error) << std::endl;
695 oomph_info <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
699 sprintf(filename,
"%s/pml_soln%i.dat",doc_info.directory().c_str(),
701 some_file.open(filename);
702 PML_right_mesh_pt->output(some_file,npts);
703 PML_left_mesh_pt->output(some_file,npts);
704 PML_top_mesh_pt->output(some_file,npts);
705 PML_bottom_mesh_pt->output(some_file,npts);
706 PML_bottom_right_mesh_pt->output(some_file,npts);
707 PML_top_right_mesh_pt->output(some_file,npts);
708 PML_bottom_left_mesh_pt->output(some_file,npts);
709 PML_top_left_mesh_pt->output(some_file,npts);
716 Bulk_mesh_pt->compute_norm(norm2);
717 Trace_file << norm2 << std::endl;
746 template<
class ELEMENT>
749 Mesh*
const & helmholtz_inner_boundary_mesh_pt)
752 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
753 for(
unsigned e=0;e<n_element;e++)
756 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
757 bulk_mesh_pt->boundary_element_pt(b,e));
760 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
763 PMLHelmholtzFluxElement<ELEMENT>* flux_element_pt =
new
764 PMLHelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
767 helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
770 flux_element_pt->flux_fct_pt() =
782 template<
class ELEMENT>
785 Mesh*
const & helmholtz_power_boundary_mesh_pt)
788 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
789 for(
unsigned e=0;e<n_element;e++)
792 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
793 bulk_mesh_pt->boundary_element_pt(b,e));
796 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
799 PMLHelmholtzPowerElement<ELEMENT>* power_element_pt =
new
800 PMLHelmholtzPowerElement<ELEMENT>(bulk_elem_pt,face_index);
803 helmholtz_power_boundary_mesh_pt->add_element_pt(power_element_pt);
813 template<
class ELEMENT>
818 unsigned int left_boundary_id = 2;
821 unsigned int top_boundary_id = 3;
824 unsigned int right_boundary_id = 4;
827 unsigned int bottom_boundary_id = 5;
830 unsigned n_x_right_pml = 3;
833 unsigned n_y_top_pml = 3;
836 unsigned n_x_left_pml = 3;
839 unsigned n_y_bottom_pml = 3;
844 double width_x_right_pml = 0.2;
845 double width_y_top_pml = 0.2;
846 double width_x_left_pml = 0.2;
847 double width_y_bottom_pml = 0.2;
851 TwoDimensionalPMLHelper::create_right_pml_mesh
852 <PMLLayerElement<ELEMENT> >
853 (Bulk_mesh_pt,right_boundary_id,
854 n_x_right_pml, width_x_right_pml);
856 TwoDimensionalPMLHelper::create_top_pml_mesh
857 <PMLLayerElement<ELEMENT> >
858 (Bulk_mesh_pt, top_boundary_id,
859 n_y_top_pml, width_y_top_pml);
861 TwoDimensionalPMLHelper::create_left_pml_mesh
862 <PMLLayerElement<ELEMENT> >
863 (Bulk_mesh_pt, left_boundary_id,
864 n_x_left_pml, width_x_left_pml);
866 TwoDimensionalPMLHelper::create_bottom_pml_mesh
867 <PMLLayerElement<ELEMENT> >
868 (Bulk_mesh_pt, bottom_boundary_id,
869 n_y_bottom_pml, width_y_bottom_pml);
872 add_sub_mesh(PML_right_mesh_pt);
873 add_sub_mesh(PML_top_mesh_pt);
874 add_sub_mesh(PML_left_mesh_pt);
875 add_sub_mesh(PML_bottom_mesh_pt);
878 PML_top_right_mesh_pt =
879 TwoDimensionalPMLHelper::create_top_right_pml_mesh
880 <PMLLayerElement<ELEMENT> >
881 (PML_right_mesh_pt, PML_top_mesh_pt,
882 Bulk_mesh_pt, right_boundary_id);
884 PML_bottom_right_mesh_pt =
885 TwoDimensionalPMLHelper::create_bottom_right_pml_mesh
886 <PMLLayerElement<ELEMENT> >
887 (PML_right_mesh_pt, PML_bottom_mesh_pt,
888 Bulk_mesh_pt, right_boundary_id);
890 PML_top_left_mesh_pt =
891 TwoDimensionalPMLHelper::create_top_left_pml_mesh
892 <PMLLayerElement<ELEMENT> >
893 (PML_left_mesh_pt, PML_top_mesh_pt,
894 Bulk_mesh_pt, left_boundary_id);
896 PML_bottom_left_mesh_pt =
897 TwoDimensionalPMLHelper::create_bottom_left_pml_mesh
898 <PMLLayerElement<ELEMENT> >
899 (PML_left_mesh_pt, PML_bottom_mesh_pt,
900 Bulk_mesh_pt, left_boundary_id);
903 add_sub_mesh(PML_top_right_mesh_pt);
904 add_sub_mesh(PML_bottom_right_mesh_pt);
905 add_sub_mesh(PML_top_left_mesh_pt);
906 add_sub_mesh(PML_bottom_left_mesh_pt);
915 int main(
int argc,
char **argv)
925 <TPMLHelmholtzElement<2,3> > > problem;
939 doc_info.set_directory(
"RESLT");
945 unsigned max_adapt=1;
949 problem.newton_solve(max_adapt);
954 problem.newton_solve();
std::complex< double > gamma(const double &nu_i, const double &pml_width_i, const double &k_squared_local, const double &alpha_shift=0.0)
Overwrite the pure PML mapping coefficient function to return the coeffcients proposed by Bermudez et...
TestPMLMapping()
Default constructor (empty)
////////////////////////////////////////////////////////////////// //////////////////////////////////...
void actions_before_newton_solve()
Update the problem specs before solve (empty)
void actions_before_adapt()
Actions before adapt: Wipe the PML meshes.
~PMLProblem()
Destructor (empty)
void actions_after_adapt()
Actions after adapt: Rebuild the PML meshes.
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...
Mesh * Helmholtz_inner_boundary_mesh_pt
Pointer to the mesh containing the Helmholtz inner boundary condition elements.
void create_pml_meshes()
Create PML meshes.
Mesh * Helmholtz_power_boundary_mesh_pt
Pointer to mesh of elements that compute the radiated power.
void actions_after_newton_solve()
Update the problem specs after solve (empty)
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to.
void create_power_elements(const unsigned &b, Mesh *const &bulk_mesh_pt, Mesh *const &helmholtz_power_boundary_mesh_pt)
Create Helmholtz power elements on boundary b of the Mesh pointed to by bulk_mesh_pt and add them to ...
////////////////////////////////////////////////////////////////// //////////////////////////////////...
void prescribed_incoming_flux(const Vector< double > &x, complex< double > &flux)
Flux (normal derivative) on the unit disk for a planar incoming wave.
std::complex< double > I(0.0, 1.0)
Imaginary unit.
double Wavenumber
Wavenumber (also known as k), k=omega/c.
TestPMLMapping * Test_pml_mapping_pt
double K_squared
Square of the wavenumber (also known as k^2)
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.