35 #include "fourier_decomposed_helmholtz.h"
38 #include "meshes/simple_rectangular_quadmesh.h"
41 #include "oomph_crbond_bessel.h"
43 using namespace oomph;
54 template<
class ELEMENT>
66 const double& r_min,
const double& r_max,
67 const double& phi_min,
const double& phi_max) :
68 SimpleRectangularQuadMesh<ELEMENT>(n_r,n_phi,1.0,1.0)
77 unsigned n_node=this->nnode();
80 for (
unsigned n=0;n<n_node;n++)
83 Node* nod_pt=this->node_pt(n);
86 double x_old=nod_pt->x(0);
87 double y_old=nod_pt->x(1);
90 double r=r_min+(r_max-r_min)*x_old;
91 double phi=(phi_min+(phi_max-phi_min)*y_old)*
92 MathematicalConstants::Pi/180.0;
95 nod_pt->x(0)=r*cos(phi);
96 nod_pt->x(1)=r*sin(phi);
115 double K=3.0*MathematicalConstants::Pi;
118 std::complex<double>
I(0.0,1.0);
124 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
127 theta=atan2(x[0],x[1]);
133 double bessel_offset=0.5;
140 double order_max_in=double(
N_terms-1)+bessel_offset;
141 double order_max_out=0;
152 CRBond_Bessel::bessjyv(order_max_in,
161 complex<double> u_ex(0.0,0.0);
162 for(
unsigned i=0;i<
N_terms;i++)
165 double p=Legendre_functions_helper::plgndr2(i,0,cos(theta));
168 u_ex+=(2.0*i+1.0)*pow(
I,i)*
169 sqrt(MathematicalConstants::Pi/(2.0*kr))*jv[i]*p;
186 ofstream some_file(
"planar_wave.dat");
188 for (
unsigned i_t=0;i_t<nt;i_t++)
190 double t=2.0*MathematicalConstants::Pi*double(i_t)/double(nt-1);
192 some_file <<
"ZONE I="<< nz <<
", J="<< nr << std::endl;
196 for (
unsigned i=0;i<nr;i++)
198 x[0]=0.001+double(i)/double(nr-1);
199 for (
unsigned j=0;j<nz;j++)
201 x[1]=double(j)/double(nz-1);
203 complex<double> uu=complex<double>(u[0],u[1])*exp(-
I*t);
204 some_file << x[0] <<
" " << x[1] <<
" "
205 << uu.real() <<
" " << uu.imag() <<
"\n";
240 std::complex<double>
I(0.0,1.0);
246 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
249 theta=atan2(x[0],x[1]);
255 double bessel_offset=0.5;
262 double order_max_in=double(
N_terms-1)+bessel_offset;
263 double order_max_out=0;
274 CRBond_Bessel::bessjyv(order_max_in,
283 complex<double> u_ex(0.0,0.0);
287 double p=Legendre_functions_helper::plgndr2(i,
N_fourier,
290 u_ex+=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*(jv[i]+
I*yv[i])*p;
305 flux=std::complex<double>(0.0,0.0);
308 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
311 theta=atan2(x[0],x[1]);
320 double bessel_offset=0.5;
327 double order_max_in=double(
N_terms-1)+bessel_offset;
328 double order_max_out=0;
339 CRBond_Bessel::bessjyv(order_max_in,
348 complex<double> u_ex(0.0,0.0);
352 double p=Legendre_functions_helper::plgndr2(i,
N_fourier,
355 flux-=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*p*
356 ( k*(djv[i]+
I*dyv[i]) - (0.5*(jv[i]+
I*yv[i])/R) );
378 template<
class ELEMENT>
398 void doc_solution(DocInfo& doc_info);
403 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
407 void check_gamma(DocInfo& doc_info);
412 void create_outer_bc_elements();
415 void create_flux_elements_on_inner_boundary();
435 template<
class ELEMENT>
449 double theta_min=-90.0;
450 double theta_max=90.0;
461 Helmholtz_outer_boundary_mesh_pt=
462 new FourierDecomposedHelmholtzDtNMesh<ELEMENT>(
466 create_outer_bc_elements();
469 Helmholtz_inner_boundary_mesh_pt=
new Mesh;
470 create_flux_elements_on_inner_boundary();
473 add_sub_mesh(Bulk_mesh_pt);
474 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
475 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
481 unsigned n_element = Bulk_mesh_pt->nelement();
482 for(
unsigned i=0;i<n_element;i++)
485 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(i));
495 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
504 template<
class ELEMENT>
510 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
515 sprintf(filename,
"%s/gamma_test%i.dat",doc_info.directory().c_str(),
517 some_file.open(filename);
520 unsigned nel=Helmholtz_outer_boundary_mesh_pt->nelement();
521 for (
unsigned e=0;e<nel;e++)
524 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* el_pt=
525 dynamic_cast<FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>*
>
526 (Helmholtz_outer_boundary_mesh_pt->element_pt(e));
529 const unsigned n_intpt =el_pt->integral_pt()->nweight();
532 Vector<std::complex<double> > gamma(
533 Helmholtz_outer_boundary_mesh_pt->gamma_at_gauss_point(el_pt));
536 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
539 Vector<double> x(el_pt->dim()+1,0.0);
542 unsigned n=el_pt->dim();
543 Vector<double> s(n,0.0);
544 for(
unsigned i=0;i<n;i++)
546 s[i]=el_pt->integral_pt()->knot(ipt,i);
550 el_pt->interpolated_x(s,x);
552 complex<double> flux;
554 some_file << atan2(x[0],x[1]) <<
" "
555 << gamma[ipt].real() <<
" "
556 << gamma[ipt].imag() <<
" "
557 << flux.real() <<
" "
558 << flux.imag() <<
" "
573 template<
class ELEMENT>
585 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
587 some_file.open(filename);
588 Bulk_mesh_pt->output(some_file,npts);
594 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
596 some_file.open(filename);
604 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
606 some_file.open(filename);
612 cout <<
"\nNorm of error : " << sqrt(error) << std::endl;
613 cout <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
616 check_gamma(doc_info);
621 sprintf(filename,
"%s/power%i.dat",doc_info.directory().c_str(),
623 some_file.open(filename);
624 sprintf(filename,
"%s/total_power%i.dat",doc_info.directory().c_str(),
629 unsigned nn_element=Helmholtz_outer_boundary_mesh_pt->nelement();
630 for(
unsigned e=0;e<nn_element;e++)
632 FourierDecomposedHelmholtzBCElementBase<ELEMENT> *el_pt =
633 dynamic_cast<FourierDecomposedHelmholtzBCElementBase<ELEMENT>*
>(
634 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
635 power += el_pt->global_power_contribution(some_file);
640 oomph_info <<
"Radiated power: "
643 << power << std::endl;
644 some_file.open(filename);
647 << power << std::endl;
657 template<
class ELEMENT>
664 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
665 for(
unsigned e=0;e<n_element;e++)
668 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
669 Bulk_mesh_pt->boundary_element_pt(b,e));
672 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
675 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new
676 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,
680 Helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
685 set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
695 template<
class ELEMENT>
703 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
704 for(
unsigned e=0;e<n_element;e++)
707 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
708 Bulk_mesh_pt->boundary_element_pt(b,e));
711 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
714 FourierDecomposedHelmholtzFluxElement<ELEMENT>* flux_element_pt =
new
715 FourierDecomposedHelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
718 Helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
732 int main(
int argc,
char **argv)
736 CommandLineArgs::setup(argc,argv);
742 CommandLineArgs::specify_command_line_flag(
"--el_multiplier",
746 CommandLineArgs::parse_and_assign();
749 CommandLineArgs::doc_specified_flags();
763 double bessel_offset=0.5;
765 ofstream bessely_file(
"besselY.dat");
766 ofstream bessely_deriv_file(
"dbesselY.dat");
768 ofstream besselj_file(
"besselJ.dat");
769 ofstream besselj_deriv_file(
"dbesselJ.dat");
772 Vector<double> jv(n+1);
773 Vector<double> yv(n+1);
774 Vector<double> djv(n+1);
775 Vector<double> dyv(n+1);
779 for (
unsigned i=0;i<nplot;i++)
781 double x=x_min+(x_max-x_min)*
double(i)/double(nplot-1);
782 double order_max_in=double(n)+bessel_offset;
783 double order_max_out=0;
794 CRBond_Bessel::bessjyv(order_max_in,x,
798 bessely_file << x <<
" ";
799 for (
unsigned j=0;j<=n;j++)
801 bessely_file << yv[j] <<
" ";
803 bessely_file << std::endl;
805 besselj_file << x <<
" ";
806 for (
unsigned j=0;j<=n;j++)
808 besselj_file << jv[j] <<
" ";
810 besselj_file << std::endl;
812 bessely_deriv_file << x <<
" ";
813 for (
unsigned j=0;j<=n;j++)
815 bessely_deriv_file << dyv[j] <<
" ";
817 bessely_deriv_file << std::endl;
819 besselj_deriv_file << x <<
" ";
820 for (
unsigned j=0;j<=n;j++)
822 besselj_deriv_file << djv[j] <<
" ";
824 besselj_deriv_file << std::endl;
827 bessely_file.close();
828 besselj_file.close();
829 bessely_deriv_file.close();
830 besselj_deriv_file.close();
840 ofstream some_file(
"legendre3.dat");
842 for (
unsigned i=0;i<nplot;i++)
844 double x=double(i)/double(nplot-1)*2.0*MathematicalConstants::Pi;
846 some_file << x <<
" ";
847 for (
unsigned j=n;j<=5;j++)
849 some_file << Legendre_functions_helper::plgndr2(j,n,cos(x)) <<
" ";
851 some_file << std::endl;
858 ofstream some_file(
"legendre.dat");
860 for (
unsigned i=0;i<nplot;i++)
862 double x=double(i)/double(nplot-1);
864 some_file << x <<
" ";
865 for (
unsigned j=0;j<=3;j++)
867 some_file << Legendre_functions_helper::plgndr2(j,0,x) <<
" ";
869 some_file << std::endl;
885 doc_info.set_directory(
"RESLT");
895 problem.newton_solve();
////////////////////////////////////////////////////////////////// //////////////////////////////////...
AnnularQuadMesh(const unsigned &n_r, const unsigned &n_phi, const double &r_min, const double &r_max, const double &phi_min, const double &phi_max)
////////////////////////////////////////////////////////////////// //////////////////////////////////...
~FourierDecomposedHelmholtzProblem()
Destructor (empty)
void create_outer_bc_elements()
Create BC elements on outer boundary.
Mesh * Helmholtz_inner_boundary_mesh_pt
Mesh of face elements that apply the prescribed flux on the inner boundary.
void actions_after_newton_solve()
Update the problem after solve (empty)
void create_flux_elements_on_inner_boundary()
Create flux elements on inner boundary.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to.
FourierDecomposedHelmholtzProblem()
Constructor.
FourierDecomposedHelmholtzDtNMesh< ELEMENT > * Helmholtz_outer_boundary_mesh_pt
Pointer to mesh containing the DtN boundary condition elements.
void check_gamma(DocInfo &doc_info)
Check gamma computation.
AnnularQuadMesh< ELEMENT > * Bulk_mesh_pt
Pointer to bulk mesh.
void actions_before_newton_convergence_check()
Recompute gamma integral before checking Newton residuals.
Namespace to test representation of planar wave in spherical polars.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
unsigned El_multiplier
Multiplier for number of elements.
unsigned N_terms
Number of terms in the exact solution.
unsigned Nterms_for_DtN
Number of terms in computation of DtN boundary condition.
double K_squared
Square of the wavenumber.
void exact_minus_dudr(const Vector< double > &x, std::complex< double > &flux)
Get -du/dr (spherical r) for exact solution. Equal to prescribed flux on inner boundary.
int N_fourier
Fourier wave number.
Vector< double > Coeff(N_terms, 1.0)
Coefficients in the exact solution.
std::complex< double > I(0.0, 1.0)
Imaginary unit.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector of size 2, containing real and imag parts.
int main(int argc, char **argv)
Driver code for Fourier decomposed Helmholtz problem.