39 #include "fourier_decomposed_helmholtz.h" 42 #include "meshes/simple_rectangular_quadmesh.h" 45 #include "oomph_crbond_bessel.h" 47 using namespace oomph;
58 template<
class ELEMENT>
70 const double& r_min,
const double& r_max,
71 const double& phi_min,
const double& phi_max) :
72 SimpleRectangularQuadMesh<ELEMENT>(n_r,n_phi,1.0,1.0)
81 unsigned n_node=this->nnode();
84 for (
unsigned n=0;n<n_node;n++)
87 Node* nod_pt=this->node_pt(n);
90 double x_old=nod_pt->x(0);
91 double y_old=nod_pt->x(1);
94 double r=r_min+(r_max-r_min)*x_old;
95 double phi=(phi_min+(phi_max-phi_min)*y_old)*
96 MathematicalConstants::Pi/180.0;
99 nod_pt->x(0)=r*cos(phi);
100 nod_pt->x(1)=r*sin(phi);
119 double K=3.0*MathematicalConstants::Pi;
122 std::complex<double>
I(0.0,1.0);
128 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
131 theta=atan2(x[0],x[1]);
137 double bessel_offset=0.5;
140 Vector<double> jv(N_terms);
141 Vector<double> yv(N_terms);
142 Vector<double> djv(N_terms);
143 Vector<double> dyv(N_terms);
144 double order_max_in=double(N_terms-1)+bessel_offset;
145 double order_max_out=0;
156 CRBond_Bessel::bessjyv(order_max_in,
165 complex<double> u_ex(0.0,0.0);
166 for(
unsigned i=0;i<
N_terms;i++)
169 double p=Legendre_functions_helper::plgndr2(i,0,cos(theta));
172 u_ex+=(2.0*i+1.0)*pow(
I,i)*
173 sqrt(MathematicalConstants::Pi/(2.0*kr))*jv[i]*p;
190 ofstream some_file(
"planar_wave.dat");
192 for (
unsigned i_t=0;i_t<nt;i_t++)
194 double t=2.0*MathematicalConstants::Pi*double(i_t)/double(nt-1);
196 some_file <<
"ZONE I="<< nz <<
", J="<< nr << std::endl;
200 for (
unsigned i=0;i<nr;i++)
202 x[0]=0.001+double(i)/double(nr-1);
203 for (
unsigned j=0;j<nz;j++)
205 x[1]=double(j)/double(nz-1);
207 complex<double> uu=complex<double>(u[0],u[1])*exp(-
I*t);
208 some_file << x[0] <<
" " << x[1] <<
" " 209 << uu.real() <<
" " << uu.imag() <<
"\n";
241 Vector<double>
Coeff(N_terms,1.0);
244 std::complex<double>
I(0.0,1.0);
250 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
253 theta=atan2(x[0],x[1]);
256 double kr = sqrt(K_squared)*R;
259 double bessel_offset=0.5;
262 Vector<double> jv(N_terms);
263 Vector<double> yv(N_terms);
264 Vector<double> djv(N_terms);
265 Vector<double> dyv(N_terms);
266 double order_max_in=double(N_terms-1)+bessel_offset;
267 double order_max_out=0;
278 CRBond_Bessel::bessjyv(order_max_in,
287 complex<double> u_ex(0.0,0.0);
288 for(
unsigned i=N_fourier;i<
N_terms;i++)
291 double p=Legendre_functions_helper::plgndr2(i,N_fourier,
294 u_ex+=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*(jv[i]+
I*yv[i])*p;
309 flux=std::complex<double>(0.0,0.0);
312 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
315 theta=atan2(x[0],x[1]);
318 double kr=sqrt(K_squared)*R;
321 double k=sqrt(K_squared);
324 double bessel_offset=0.5;
327 Vector<double> jv(N_terms);
328 Vector<double> yv(N_terms);
329 Vector<double> djv(N_terms);
330 Vector<double> dyv(N_terms);
331 double order_max_in=double(N_terms-1)+bessel_offset;
332 double order_max_out=0;
343 CRBond_Bessel::bessjyv(order_max_in,
352 complex<double> u_ex(0.0,0.0);
353 for(
unsigned i=N_fourier;i<
N_terms;i++)
356 double p=Legendre_functions_helper::plgndr2(i,N_fourier,
359 flux-=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*p*
360 ( k*(djv[i]+
I*dyv[i]) - (0.5*(jv[i]+
I*yv[i])/R) );
382 template<
class ELEMENT>
402 void doc_solution(DocInfo& doc_info);
407 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
411 void check_gamma(DocInfo& doc_info);
416 void create_outer_bc_elements();
419 void create_flux_elements_on_inner_boundary();
439 template<
class ELEMENT>
453 double theta_min=-90.0;
454 double theta_max=90.0;
465 Helmholtz_outer_boundary_mesh_pt=
466 new FourierDecomposedHelmholtzDtNMesh<ELEMENT>(
470 create_outer_bc_elements();
473 Helmholtz_inner_boundary_mesh_pt=
new Mesh;
474 create_flux_elements_on_inner_boundary();
477 add_sub_mesh(Bulk_mesh_pt);
478 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
479 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
485 unsigned n_element = Bulk_mesh_pt->nelement();
486 for(
unsigned i=0;i<n_element;i++)
489 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(i));
499 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
508 template<
class ELEMENT>
514 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
519 sprintf(filename,
"%s/gamma_test%i.dat",doc_info.directory().c_str(),
521 some_file.open(filename);
524 unsigned nel=Helmholtz_outer_boundary_mesh_pt->nelement();
525 for (
unsigned e=0;e<nel;e++)
528 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* el_pt=
529 dynamic_cast<FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>*
> 530 (Helmholtz_outer_boundary_mesh_pt->element_pt(e));
533 const unsigned n_intpt =el_pt->integral_pt()->nweight();
536 Vector<std::complex<double> > gamma(
537 Helmholtz_outer_boundary_mesh_pt->gamma_at_gauss_point(el_pt));
540 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
543 Vector<double> x(el_pt->dim()+1,0.0);
546 unsigned n=el_pt->dim();
547 Vector<double> s(n,0.0);
548 for(
unsigned i=0;i<n;i++)
550 s[i]=el_pt->integral_pt()->knot(ipt,i);
554 el_pt->interpolated_x(s,x);
556 complex<double> flux;
558 some_file << atan2(x[0],x[1]) <<
" " 559 << gamma[ipt].real() <<
" " 560 << gamma[ipt].imag() <<
" " 561 << flux.real() <<
" " 562 << flux.imag() <<
" " 577 template<
class ELEMENT>
589 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
591 some_file.open(filename);
592 Bulk_mesh_pt->output(some_file,npts);
598 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
600 some_file.open(filename);
608 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
610 some_file.open(filename);
616 cout <<
"\nNorm of error : " << sqrt(error) << std::endl;
617 cout <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
620 check_gamma(doc_info);
625 sprintf(filename,
"%s/power%i.dat",doc_info.directory().c_str(),
627 some_file.open(filename);
628 sprintf(filename,
"%s/total_power%i.dat",doc_info.directory().c_str(),
633 unsigned nn_element=Helmholtz_outer_boundary_mesh_pt->nelement();
634 for(
unsigned e=0;e<nn_element;e++)
636 FourierDecomposedHelmholtzBCElementBase<ELEMENT> *el_pt =
637 dynamic_cast<FourierDecomposedHelmholtzBCElementBase<ELEMENT>*
>(
638 Helmholtz_outer_boundary_mesh_pt->element_pt(e));
639 power += el_pt->global_power_contribution(some_file);
644 oomph_info <<
"Radiated power: " 647 << power << std::endl;
648 some_file.open(filename);
651 << power << std::endl;
661 template<
class ELEMENT>
668 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
669 for(
unsigned e=0;e<n_element;e++)
672 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
673 Bulk_mesh_pt->boundary_element_pt(b,e));
676 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
679 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new 680 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,
684 Helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
689 set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
699 template<
class ELEMENT>
707 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
708 for(
unsigned e=0;e<n_element;e++)
711 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
712 Bulk_mesh_pt->boundary_element_pt(b,e));
715 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
718 FourierDecomposedHelmholtzFluxElement<ELEMENT>* flux_element_pt =
new 719 FourierDecomposedHelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
722 Helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
736 int main(
int argc,
char **argv)
740 CommandLineArgs::setup(argc,argv);
746 CommandLineArgs::specify_command_line_flag(
"--el_multiplier",
750 CommandLineArgs::parse_and_assign();
753 CommandLineArgs::doc_specified_flags();
767 double bessel_offset=0.5;
769 ofstream bessely_file(
"besselY.dat");
770 ofstream bessely_deriv_file(
"dbesselY.dat");
772 ofstream besselj_file(
"besselJ.dat");
773 ofstream besselj_deriv_file(
"dbesselJ.dat");
776 Vector<double> jv(n+1);
777 Vector<double> yv(n+1);
778 Vector<double> djv(n+1);
779 Vector<double> dyv(n+1);
783 for (
unsigned i=0;i<nplot;i++)
785 double x=x_min+(x_max-x_min)*
double(i)/double(nplot-1);
786 double order_max_in=double(n)+bessel_offset;
787 double order_max_out=0;
798 CRBond_Bessel::bessjyv(order_max_in,x,
802 bessely_file << x <<
" ";
803 for (
unsigned j=0;j<=n;j++)
805 bessely_file << yv[j] <<
" ";
807 bessely_file << std::endl;
809 besselj_file << x <<
" ";
810 for (
unsigned j=0;j<=n;j++)
812 besselj_file << jv[j] <<
" ";
814 besselj_file << std::endl;
816 bessely_deriv_file << x <<
" ";
817 for (
unsigned j=0;j<=n;j++)
819 bessely_deriv_file << dyv[j] <<
" ";
821 bessely_deriv_file << std::endl;
823 besselj_deriv_file << x <<
" ";
824 for (
unsigned j=0;j<=n;j++)
826 besselj_deriv_file << djv[j] <<
" ";
828 besselj_deriv_file << std::endl;
831 bessely_file.close();
832 besselj_file.close();
833 bessely_deriv_file.close();
834 besselj_deriv_file.close();
844 ofstream some_file(
"legendre3.dat");
846 for (
unsigned i=0;i<nplot;i++)
848 double x=double(i)/double(nplot-1)*2.0*MathematicalConstants::Pi;
850 some_file << x <<
" ";
851 for (
unsigned j=n;j<=5;j++)
853 some_file << Legendre_functions_helper::plgndr2(j,n,cos(x)) <<
" ";
855 some_file << std::endl;
862 ofstream some_file(
"legendre.dat");
864 for (
unsigned i=0;i<nplot;i++)
866 double x=double(i)/double(nplot-1);
868 some_file << x <<
" ";
869 for (
unsigned j=0;j<=3;j++)
871 some_file << Legendre_functions_helper::plgndr2(j,0,x) <<
" ";
873 some_file << std::endl;
889 doc_info.set_directory(
"RESLT");
899 problem.newton_solve();
std::complex< double > I(0.0, 1.0)
Imaginary unit.
unsigned N_terms
Number of terms in the exact solution.
Namespace for the Fourier decomposed Helmholtz problem parameters.
~FourierDecomposedHelmholtzProblem()
Destructor (empty)
Vector< double > Coeff(N_terms, 1.0)
Coefficients in the exact solution.
void check_gamma(DocInfo &doc_info)
Check gamma computation.
unsigned El_multiplier
Multiplier for number of elements.
FourierDecomposedHelmholtzProblem()
Constructor.
void actions_after_newton_solve()
Update the problem after solve (empty)
int main(int argc, char **argv)
Driver code for Fourier decomposed Helmholtz problem.
AnnularQuadMesh< ELEMENT > * Bulk_mesh_pt
Pointer to bulk mesh.
FourierDecomposedHelmholtzDtNMesh< ELEMENT > * Helmholtz_outer_boundary_mesh_pt
Pointer to mesh containing the DtN boundary condition elements.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector of size 2, containing real and imag parts.
void create_flux_elements_on_inner_boundary()
Create flux elements on inner boundary.
double K_squared
Square of the wavenumber.
int N_fourier
Fourier wave number.
Mesh * Helmholtz_inner_boundary_mesh_pt
Mesh of face elements that apply the prescribed flux on the inner boundary.
unsigned Nterms_for_DtN
Number of terms in computation of DtN boundary condition.
void doc_solution(DocInfo &doc_info)
Doc the solution. DocInfo object stores flags/labels for where the output gets written to...
void actions_before_newton_convergence_check()
Recompute gamma integral before checking Newton residuals.
void actions_before_newton_solve()
Update the problem specs before solve (empty)
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.
void create_outer_bc_elements()
Create BC elements on outer boundary.
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)