35 #include "fourier_decomposed_helmholtz.h"
38 #include "meshes/triangle_mesh.h"
41 #include "oomph_crbond_bessel.h"
43 using namespace oomph;
63 double K=3.0*MathematicalConstants::Pi;
66 std::complex<double>
I(0.0,1.0);
69 void get_exact_u(
const Vector<double>& x, Vector<double>& u)
72 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
75 theta=atan2(x[0],x[1]);
81 double bessel_offset=0.5;
88 double order_max_in=double(
N_terms-1)+bessel_offset;
89 double order_max_out=0;
100 CRBond_Bessel::bessjyv(order_max_in,
109 complex<double> u_ex(0.0,0.0);
110 for(
unsigned i=0;i<
N_terms;i++)
113 double p=Legendre_functions_helper::plgndr2(i,0,cos(theta));
116 u_ex+=(2.0*i+1.0)*pow(
I,i)*
117 sqrt(MathematicalConstants::Pi/(2.0*kr))*jv[i]*p;
134 ofstream some_file(
"planar_wave.dat");
136 for (
unsigned i_t=0;i_t<nt;i_t++)
138 double t=2.0*MathematicalConstants::Pi*double(i_t)/double(nt-1);
140 some_file <<
"ZONE I="<< nz <<
", J="<< nr << std::endl;
144 for (
unsigned i=0;i<nr;i++)
146 x[0]=0.001+double(i)/double(nr-1);
147 for (
unsigned j=0;j<nz;j++)
149 x[1]=double(j)/double(nz-1);
151 complex<double> uu=complex<double>(u[0],u[1])*exp(-
I*t);
152 some_file << x[0] <<
" " << x[1] <<
" "
153 << uu.real() <<
" " << uu.imag() <<
"\n";
188 std::complex<double>
I(0.0,1.0);
191 void get_exact_u(
const Vector<double>& x, Vector<double>& u)
194 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
197 theta=atan2(x[0],x[1]);
203 double bessel_offset=0.5;
210 double order_max_in=double(
N_terms-1)+bessel_offset;
211 double order_max_out=0;
222 CRBond_Bessel::bessjyv(order_max_in,
231 complex<double> u_ex(0.0,0.0);
235 double p=Legendre_functions_helper::plgndr2(i,
N_fourier,
238 u_ex+=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*(jv[i]+
I*yv[i])*p;
253 flux=std::complex<double>(0.0,0.0);
256 double R=sqrt(x[0]*x[0]+x[1]*x[1]);
259 theta=atan2(x[0],x[1]);
268 double bessel_offset=0.5;
275 double order_max_in=double(
N_terms-1)+bessel_offset;
276 double order_max_out=0;
287 CRBond_Bessel::bessjyv(order_max_in,
296 complex<double> u_ex(0.0,0.0);
300 double p=Legendre_functions_helper::plgndr2(i,
N_fourier,
303 flux-=
Coeff[i]*sqrt(MathematicalConstants::Pi/(2.0*kr))*p*
304 ( k*(djv[i]+
I*dyv[i]) - (0.5*(jv[i]+
I*yv[i])/R) );
323 template<
class ELEMENT>
348 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
350 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
355 void actions_before_adapt();
358 void actions_after_adapt();
376 unsigned n_element = boundary_mesh_pt->nelement();
377 for(
unsigned e=0;e<n_element;e++)
380 delete boundary_mesh_pt->element_pt(e);
384 boundary_mesh_pt->flush_element_and_node_storage();
402 FourierDecomposedHelmholtzDtNMesh<ELEMENT>* Helmholtz_outer_boundary_mesh_pt;
405 Mesh* Helmholtz_inner_boundary_mesh_pt;
417 template<
class ELEMENT>
421 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
423 delete_face_elements(Helmholtz_outer_boundary_mesh_pt);
425 delete_face_elements(Helmholtz_inner_boundary_mesh_pt);
428 rebuild_global_mesh();
436 template<
class ELEMENT>
446 unsigned n_element = Bulk_mesh_pt->nelement();
447 for(
unsigned e=0;e<n_element;e++)
450 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
462 create_flux_elements_on_inner_boundary();
463 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
465 create_outer_bc_elements();
469 rebuild_global_mesh();
477 template<
class ELEMENT>
483 Trace_file.open(
"RESLT/trace.dat");
490 Circle* inner_circle_pt=
new Circle(x_c,y_c,r_min);
491 Circle* outer_circle_pt=
new Circle(x_c,y_c,r_max);
495 Vector<TriangleMeshCurveSection*> outer_boundary_line_pt(4);
498 unsigned n_segments = 20;
501 Vector<Vector<double> > boundary_vertices(2);
506 boundary_vertices[0].resize(2);
507 boundary_vertices[0][0]=0.0;
508 boundary_vertices[0][1]=-r_min;
509 boundary_vertices[1].resize(2);
510 boundary_vertices[1][0]=0.0;
511 boundary_vertices[1][1]=-r_max;
513 unsigned boundary_id=0;
514 outer_boundary_line_pt[0]=
515 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
518 if (CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
523 Vector<Vector<double> > boundary_vertices(4);
524 boundary_vertices[0].resize(2);
525 boundary_vertices[0][0]=0.0;
526 boundary_vertices[0][1]=-r_max;
527 boundary_vertices[1].resize(2);
528 boundary_vertices[1][0]=r_max;
529 boundary_vertices[1][1]=-r_max;
530 boundary_vertices[2].resize(2);
531 boundary_vertices[2][0]=r_max;
532 boundary_vertices[2][1]=r_max;
533 boundary_vertices[3].resize(2);
534 boundary_vertices[3][0]=0.0;
535 boundary_vertices[3][1]=r_max;
538 outer_boundary_line_pt[1]=
539 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
546 double s_start = -0.5*MathematicalConstants::Pi;
547 double s_end = 0.5*MathematicalConstants::Pi;
550 outer_boundary_line_pt[1]=
551 new TriangleMeshCurviLine(outer_circle_pt,
561 boundary_vertices[0][0]=0.0;
562 boundary_vertices[0][1]=r_max;
563 boundary_vertices[1][0]=0.0;
564 boundary_vertices[1][1]=r_min;
567 outer_boundary_line_pt[2]=
568 new TriangleMeshPolyLine(boundary_vertices,boundary_id);
575 double s_start = 0.5*MathematicalConstants::Pi;
576 double s_end = -0.5*MathematicalConstants::Pi;
579 outer_boundary_line_pt[3]=
580 new TriangleMeshCurviLine(inner_circle_pt,
589 TriangleMeshClosedCurve *outer_boundary_pt =
590 new TriangleMeshClosedCurve(outer_boundary_line_pt);
596 TriangleMeshParameters triangle_mesh_parameters(outer_boundary_pt);
599 double element_area = 0.1;
600 triangle_mesh_parameters.element_area() = element_area;
605 Bulk_mesh_pt=
new RefineableTriangleMesh<ELEMENT>(triangle_mesh_parameters);
608 Bulk_mesh_pt->spatial_error_estimator_pt()=
new Z2ErrorEstimator;
611 Bulk_mesh_pt->min_permitted_error()=0.00004;
612 Bulk_mesh_pt->max_permitted_error()=0.0001;
617 Bulk_mesh_pt=
new TriangleMesh<ELEMENT>(triangle_mesh_parameters);
622 Bulk_mesh_pt->output(
"mesh.dat");
623 Bulk_mesh_pt->output_boundaries(
"boundaries.dat");
626 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
629 Helmholtz_outer_boundary_mesh_pt=
630 new FourierDecomposedHelmholtzDtNMesh<ELEMENT>(
634 create_outer_bc_elements();
638 Helmholtz_inner_boundary_mesh_pt=
new Mesh;
639 create_flux_elements_on_inner_boundary();
642 add_sub_mesh(Bulk_mesh_pt);
643 add_sub_mesh(Helmholtz_inner_boundary_mesh_pt);
644 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
646 add_sub_mesh(Helmholtz_outer_boundary_mesh_pt);
653 unsigned n_element = Bulk_mesh_pt->nelement();
654 for(
unsigned i=0;i<n_element;i++)
657 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(i));
667 cout <<
"Number of equations: " << assign_eqn_numbers() << std::endl;
676 template<
class ELEMENT>
681 Helmholtz_outer_boundary_mesh_pt->setup_gamma();
686 sprintf(filename,
"%s/gamma_test%i.dat",doc_info.directory().c_str(),
688 some_file.open(filename);
691 unsigned nel=Helmholtz_outer_boundary_mesh_pt->nelement();
692 for (
unsigned e=0;e<nel;e++)
695 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* el_pt=
696 dynamic_cast<FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>*
>
697 (Helmholtz_outer_boundary_mesh_pt->element_pt(e));
700 const unsigned n_intpt =el_pt->integral_pt()->nweight();
703 Vector<std::complex<double> > gamma(
704 Helmholtz_outer_boundary_mesh_pt->gamma_at_gauss_point(el_pt));
707 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
710 Vector<double> x(el_pt->dim()+1,0.0);
713 unsigned n=el_pt->dim();
714 Vector<double> s(n,0.0);
715 for(
unsigned i=0;i<n;i++)
717 s[i]=el_pt->integral_pt()->knot(ipt,i);
721 el_pt->interpolated_x(s,x);
723 complex<double> flux;
725 some_file << atan2(x[0],x[1]) <<
" "
726 << gamma[ipt].real() <<
" "
727 << gamma[ipt].imag() <<
" "
728 << flux.real() <<
" "
729 << flux.imag() <<
" "
744 template<
class ELEMENT>
756 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
758 some_file.open(filename);
759 Bulk_mesh_pt->output(some_file,npts);
765 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
767 some_file.open(filename);
775 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
777 some_file.open(filename);
783 cout <<
"\nNorm of error : " << sqrt(error) << std::endl;
784 cout <<
"Norm of solution: " << sqrt(norm) << std::endl << std::endl;
788 Bulk_mesh_pt->compute_norm(norm);
789 Trace_file << norm << std::endl;
792 if (!CommandLineArgs::command_line_flag_has_been_set(
"--square_domain"))
795 check_gamma(doc_info);
805 template<
class ELEMENT>
813 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
814 for(
unsigned e=0;e<n_element;e++)
817 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
818 Bulk_mesh_pt->boundary_element_pt(b,e));
821 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
824 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>* flux_element_pt =
new
825 FourierDecomposedHelmholtzDtNBoundaryElement<ELEMENT>(bulk_elem_pt,
829 Helmholtz_outer_boundary_mesh_pt->add_element_pt(flux_element_pt);
834 set_outer_boundary_mesh_pt(Helmholtz_outer_boundary_mesh_pt);
844 template<
class ELEMENT>
852 unsigned n_element = Bulk_mesh_pt->nboundary_element(b);
853 for(
unsigned e=0;e<n_element;e++)
856 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
857 Bulk_mesh_pt->boundary_element_pt(b,e));
860 int face_index = Bulk_mesh_pt->face_index_at_boundary(b,e);
863 FourierDecomposedHelmholtzFluxElement<ELEMENT>* flux_element_pt =
new
864 FourierDecomposedHelmholtzFluxElement<ELEMENT>(bulk_elem_pt,face_index);
867 Helmholtz_inner_boundary_mesh_pt->add_element_pt(flux_element_pt);
881 int main(
int argc,
char **argv)
884 CommandLineArgs::setup(argc,argv);
890 CommandLineArgs::specify_command_line_flag(
"--square_domain");
893 CommandLineArgs::parse_and_assign();
896 CommandLineArgs::doc_specified_flags();
909 double bessel_offset=0.5;
911 ofstream bessely_file(
"besselY.dat");
912 ofstream bessely_deriv_file(
"dbesselY.dat");
914 ofstream besselj_file(
"besselJ.dat");
915 ofstream besselj_deriv_file(
"dbesselJ.dat");
918 Vector<double> jv(n+1);
919 Vector<double> yv(n+1);
920 Vector<double> djv(n+1);
921 Vector<double> dyv(n+1);
925 for (
unsigned i=0;i<nplot;i++)
927 double x=x_min+(x_max-x_min)*
double(i)/double(nplot-1);
928 double order_max_in=double(n)+bessel_offset;
929 double order_max_out=0;
940 CRBond_Bessel::bessjyv(order_max_in,x,
944 bessely_file << x <<
" ";
945 for (
unsigned j=0;j<=n;j++)
947 bessely_file << yv[j] <<
" ";
949 bessely_file << std::endl;
951 besselj_file << x <<
" ";
952 for (
unsigned j=0;j<=n;j++)
954 besselj_file << jv[j] <<
" ";
956 besselj_file << std::endl;
958 bessely_deriv_file << x <<
" ";
959 for (
unsigned j=0;j<=n;j++)
961 bessely_deriv_file << dyv[j] <<
" ";
963 bessely_deriv_file << std::endl;
965 besselj_deriv_file << x <<
" ";
966 for (
unsigned j=0;j<=n;j++)
968 besselj_deriv_file << djv[j] <<
" ";
970 besselj_deriv_file << std::endl;
973 bessely_file.close();
974 besselj_file.close();
975 bessely_deriv_file.close();
976 besselj_deriv_file.close();
986 ofstream some_file(
"legendre3.dat");
988 for (
unsigned i=0;i<nplot;i++)
990 double x=double(i)/double(nplot-1);
992 some_file << x <<
" ";
993 for (
unsigned j=0;j<=n;j++)
995 some_file << Legendre_functions_helper::plgndr2(n,j,x) <<
" ";
997 some_file << std::endl;
1008 TFourierDecomposedHelmholtzElement<3> > > problem;
1023 doc_info.set_directory(
"RESLT");
1037 unsigned max_adapt=1;
1041 problem.newton_solve(max_adapt);
1046 problem.newton_solve();
1051 problem.doc_solution(doc_info);
////////////////////////////////////////////////////////////////// //////////////////////////////////...
~FourierDecomposedHelmholtzProblem()
Destructor (empty)
void actions_after_adapt()
Actions after adapt: Rebuild the mesh of prescribed flux elements.
void create_outer_bc_elements()
Create BC elements on outer boundary.
RefineableTriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
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.
void delete_face_elements(Mesh *const &boundary_mesh_pt)
Delete boundary face elements and wipe the surface mesh.
TriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
FourierDecomposedHelmholtzProblem()
Constructor.
ofstream Trace_file
Trace file.
void check_gamma(DocInfo &doc_info)
Check gamma computation.
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.
Namespace to test representation of planar wave in spherical polars.
void get_exact_u(const Vector< double > &x, Vector< double > &u)
Exact solution as a Vector of size 2, containing real and imag parts.
std::complex< double > I(0.0, 1.0)
Imaginary unit.
unsigned N_terms
Number of terms in series.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
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.
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.