40 #include "helmholtz.h"
43 #include "meshes/annular_mesh.h"
46 #include "oomph_crbond_bessel.h"
48 using namespace oomph;
82 std::complex<double>
I(0.0,1.0);
90 r=sqrt(x[0]*x[0]+x[1]*x[1]);
92 theta=atan2(x[1],x[0]);
98 complex <double > u_ex(0.0,0.0);
111 &jnp_a[0],&ynp_a[0]);
117 std::ostringstream error_stream;
118 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
119 << n_actual <<
" rather than " <<
N_fourier
120 <<
" Bessel functions.\n";
121 throw OomphLibError(error_stream.str(),
122 OOMPH_CURRENT_FUNCTION,
123 OOMPH_EXCEPTION_LOCATION);
128 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier,rr,h,hp);
131 Hankel_functions_for_helmholtz_problem::Hankel_first(
N_fourier
139 u_ex-=pow(
I,i)*h[i]*((jnp_a[i])/hp_a[i])*pow(exp(
I*theta),i);
143 u_ex-=pow(
I,i)*h[i]*((jnp_a[i])/hp_a[i])*pow(exp(-
I*theta),i);
157 complex<double>& flux)
161 r=sqrt(x[0]*x[0]+x[1]*x[1]);
163 theta=atan2(x[1],x[0]);
175 CRBond_Bessel::bessjyna(
N_fourier,rr,n_actual,&jn[0],&yn[0],
182 std::ostringstream error_stream;
183 error_stream <<
"CRBond_Bessel::bessjyna() only computed "
184 << n_actual <<
" rather than " <<
N_fourier
185 <<
" Bessel functions.\n";
186 throw OomphLibError(error_stream.str(),
187 OOMPH_CURRENT_FUNCTION,
188 OOMPH_EXCEPTION_LOCATION);
194 flux=std::complex<double>(0.0,0.0);
197 flux+=pow(
I,i)*(sqrt(
K_squared))*pow(exp(
I*theta),i)*jnp[i];
201 flux+=pow(
I,i)*(sqrt(
K_squared))*pow(exp(-
I*theta),i)*jnp[i];
221 template<
class ELEMENT>
235 void doc_solution(DocInfo& doc_info);
248 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
253 void actions_before_adapt();
256 void actions_after_adapt();
260 void create_outer_bc_elements(
261 const unsigned &b, Mesh*
const &bulk_mesh_pt,
262 Mesh*
const & helmholtz_outer_boundary_mesh_pt);
266 void create_flux_elements(
const unsigned &b, Mesh*
const &bulk_mesh_pt,
267 Mesh*
const & helmholtz_inner_boundary_mesh_pt);
270 void delete_face_elements( Mesh*
const & boundary_mesh_pt);
274 void set_prescribed_incoming_flux_pt();
277 void setup_outer_boundary();
306 template<
class ELEMENT>
332 double azimuthal_fraction=1.0;
338 new RefineableTwoDAnnularMesh<ELEMENT>(periodic,
339 azimuthal_fraction,n_theta,n_r,a,h);
342 Bulk_mesh_pt->spatial_error_estimator_pt()=
new Z2ErrorEstimator;
345 Bulk_mesh_pt->min_permitted_error()=0.004;
346 Bulk_mesh_pt->max_permitted_error()=0.01;
352 new TwoDAnnularMesh<ELEMENT>(periodic,
353 azimuthal_fraction,n_theta,n_r,a,h);
360 Helmholtz_outer_boundary_mesh_pt =
365 Helmholtz_inner_boundary_mesh_pt =
new Mesh;
369 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
373 create_outer_bc_elements(2,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
376 add_sub_mesh(Bulk_mesh_pt);
377 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
378 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
388 unsigned n_element = Bulk_mesh_pt->nelement();
389 for(
unsigned e=0;e<n_element;e++)
392 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
399 setup_outer_boundary();
402 set_prescribed_incoming_flux_pt();
405 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
412 template<
class ELEMENT>
416 delete_face_elements(Helmholtz_outer_boundary_mesh_pt);
417 delete_face_elements(Helmholtz_inner_boundary_mesh_pt);
420 rebuild_global_mesh();
428 template<
class ELEMENT>
434 create_outer_bc_elements(2,Bulk_mesh_pt,Helmholtz_outer_boundary_mesh_pt);
435 create_flux_elements(0,Bulk_mesh_pt,Helmholtz_inner_boundary_mesh_pt);
438 rebuild_global_mesh();
441 setup_outer_boundary();
442 set_prescribed_incoming_flux_pt();
450 template<
class ELEMENT>
455 unsigned n_element=Helmholtz_outer_boundary_mesh_pt->nelement();
456 for(
unsigned e=0;e<n_element;e++)
462 HelmholtzDtNBoundaryElement<ELEMENT> *el_pt =
463 dynamic_cast< HelmholtzDtNBoundaryElement<ELEMENT>*
>(
464 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
468 el_pt->set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
474 HelmholtzAbsorbingBCElement<ELEMENT> *el_pt =
475 dynamic_cast< HelmholtzAbsorbingBCElement<ELEMENT>*
>(
476 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
492 template<
class ELEMENT>
497 unsigned n_element=Helmholtz_inner_boundary_mesh_pt->nelement();
498 for(
unsigned e=0;e<n_element;e++)
501 HelmholtzFluxElement<ELEMENT> *el_pt =
502 dynamic_cast< HelmholtzFluxElement<ELEMENT>*
>(
503 Helmholtz_inner_boundary_mesh_pt->element_pt(e));
506 el_pt->flux_fct_pt() =
515 template<
class ELEMENT>
520 ofstream some_file,some_file2;
529 sprintf(filename,
"%s/power%i.dat",doc_info.directory().c_str(),
531 some_file.open(filename);
535 unsigned nn_element=Helmholtz_outer_boundary_mesh_pt->nelement();
536 for(
unsigned e=0;e<nn_element;e++)
538 HelmholtzBCElementBase<ELEMENT> *el_pt =
539 dynamic_cast< HelmholtzBCElementBase<ELEMENT>*
>(
540 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
541 power += el_pt->global_power_contribution(some_file);
544 oomph_info <<
"Total radiated power: " << power << std::endl;
548 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
550 some_file.open(filename);
551 Bulk_mesh_pt->output(some_file,npts);
556 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
558 some_file.open(filename);
563 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
565 some_file.open(filename);
571 oomph_info <<
"\nNorm of error : " << sqrt(error) << std::endl;
572 oomph_info <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
578 for (
unsigned i=0;i<nstep;i++)
580 sprintf(filename,
"%s/helmholtz_animation%i_frame%i.dat",
581 doc_info.directory().c_str(),
582 doc_info.number(),i);
583 some_file.open(filename);
584 sprintf(filename,
"%s/exact_helmholtz_animation%i_frame%i.dat",
585 doc_info.directory().c_str(),
586 doc_info.number(),i);
587 some_file2.open(filename);
588 double phi=2.0*MathematicalConstants::Pi*double(i)/double(nstep-1);
589 unsigned nelem=Bulk_mesh_pt->nelement();
590 for (
unsigned e=0;e<nelem;e++)
592 ELEMENT* el_pt=
dynamic_cast<ELEMENT*
>(
593 Bulk_mesh_pt->element_pt(e));
594 el_pt->output_real(some_file,phi,npts);
595 el_pt->output_real_fct(some_file2,phi,npts,
609 template<
class ELEMENT>
612 Mesh*
const & helmholtz_inner_boundary_mesh_pt)
615 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
616 for(
unsigned e=0;e<n_element;e++)
619 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
620 bulk_mesh_pt->boundary_element_pt(b,e));
623 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
626 HelmholtzFluxElement<ELEMENT>* flux_element_pt =
new
627 HelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
630 helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
643 template<
class ELEMENT>
646 Mesh*
const & helmholtz_outer_boundary_mesh_pt)
649 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
650 for(
unsigned e=0;e<n_element;e++)
653 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
654 bulk_mesh_pt->boundary_element_pt(b,e));
657 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
664 HelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new
665 HelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,face_index);
668 helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
673 HelmholtzAbsorbingBCElement<ELEMENT>* flux_element_pt =
new
674 HelmholtzAbsorbingBCElement<ELEMENT>(bulk_elem_pt,face_index);
677 helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
686 template<
class ELEMENT>
691 unsigned n_element = boundary_mesh_pt->nelement();
692 for(
unsigned e=0;e<n_element;e++)
695 delete boundary_mesh_pt->element_pt(e);
699 boundary_mesh_pt->flush_element_and_node_storage();
709 int main(
int argc,
char **argv)
713 CommandLineArgs::setup(argc,argv);
717 CommandLineArgs::specify_command_line_flag(
"--case",&i_case);
720 CommandLineArgs::parse_and_assign();
723 CommandLineArgs::doc_specified_flags();
774 doc_info.set_directory(
"RESLT");
780 unsigned max_adapt=1;
784 problem.newton_solve(max_adapt);
789 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...
Mesh * Helmholtz_inner_boundary_mesh_pt
Pointer to the mesh containing the Helmholtz inner boundary condition elements.
void setup_outer_boundary()
Set up boundary condition elements on outer boundary.
RefineableTwoDAnnularMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
ScatteringProblem()
Constructor.
HelmholtzDtNMesh< ELEMENT > * Helmholtz_outer_boundary_mesh_pt
Pointer to mesh containing the DtN (or ABC) boundary condition elements.
TwoDAnnularMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
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...
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.