46 template <
unsigned DIM,
class PML_ELEMENT>
53 const unsigned n_node = nnode();
56 Shape psi(n_node), test(n_node);
57 DShape dpsidx(n_node,DIM), dtestdx(n_node,DIM);
60 HangInfo *hang_info_pt=0, *hang_info2_pt=0;
63 const unsigned n_intpt = integral_pt()->nweight();
66 int local_eqn_real=0, local_unknown_real=0;
67 int local_eqn_imag=0, local_unknown_imag=0;
70 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
73 double w = integral_pt()->weight(ipt);
76 double J = this->dshape_and_dtest_eulerian_at_knot_helmholtz(ipt,psi,dpsidx,
84 std::complex<double> interpolated_u(0.0,0.0);
91 for(
unsigned l=0;l<n_node;l++)
94 for(
unsigned j=0;j<DIM;j++)
96 interpolated_x[j] += nodal_position(l,j)*psi(l);
100 const std::complex<double>
101 u_value(this->nodal_value(l,this->u_index_helmholtz().real()),
102 this->nodal_value(l,this->u_index_helmholtz().imag()));
105 interpolated_u += u_value*psi(l);
108 for(
unsigned j=0;j<DIM;j++)
110 interpolated_dudx[j] += u_value*dpsidx(l,j);
116 std::complex<double> source(0.0,0.0);
117 this->get_source_helmholtz(ipt,interpolated_x,source);
123 std::complex<double> pml_k_squared_factor = std::complex<double>(1.0,0.0);
132 this->pml_transformation_jacobian(ipt, s, interpolated_x, pml_jacobian);
135 this->compute_laplace_matrix_and_det(pml_jacobian, laplace_matrix, pml_k_squared_factor);
137 for (
unsigned i=0;
i<DIM;
i++)
139 pml_laplace_factor[
i] = laplace_matrix(
i,
i);
143 std::complex<double> alpha_pml_k_squared_factor = std::complex<double>(
144 pml_k_squared_factor.real() - this->alpha() * pml_k_squared_factor.imag(),
145 this->alpha() * pml_k_squared_factor.real() + pml_k_squared_factor.imag()
160 for(
unsigned l=0;l<n_node;l++)
165 unsigned n_master=1;
double hang_weight=1.0;
168 bool is_node_hanging = this->node_pt(l)->is_hanging();
173 hang_info_pt = this->node_pt(l)->hanging_pt();
174 n_master = hang_info_pt->
nmaster();
183 for(
unsigned m=0;m<n_master;m++)
192 this->u_index_helmholtz().real());
196 this->u_index_helmholtz().imag());
206 this->nodal_local_eqn(l,this->u_index_helmholtz().real());
208 this->nodal_local_eqn(l,this->u_index_helmholtz().imag());
218 if(local_eqn_real >= 0)
221 residuals[local_eqn_real] +=
224 alpha_pml_k_squared_factor.real() *
225 this->k_squared() * interpolated_u.real()
226 -alpha_pml_k_squared_factor.imag() *
227 this->k_squared() * interpolated_u.imag()
229 )*test(l)*W*hang_weight;
232 for(
unsigned k=0;k<DIM;k++)
234 residuals[local_eqn_real] +=
236 pml_laplace_factor[k].real() * interpolated_dudx[k].real()
237 -pml_laplace_factor[k].imag() * interpolated_dudx[k].imag()
238 )*dtestdx(l,k)*W*hang_weight;
247 unsigned n_master2=1;
double hang_weight2=1.0;
250 for(
unsigned l2=0;l2<n_node;l2++)
253 bool is_node2_hanging = this->node_pt(l2)->is_hanging();
258 hang_info2_pt = this->node_pt(l2)->hanging_pt();
259 n_master2 = hang_info2_pt->nmaster();
268 for(
unsigned m2=0;m2<n_master2;m2++)
276 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
277 this->u_index_helmholtz().real());
279 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
280 this->u_index_helmholtz().imag());
283 hang_weight2 = hang_info2_pt->master_weight(m2);
290 this->nodal_local_eqn(l2,this->u_index_helmholtz().real());
293 this->nodal_local_eqn(l2,this->u_index_helmholtz().imag());
301 if(local_unknown_real >= 0)
304 for(
unsigned i=0;
i<DIM;
i++)
306 jacobian(local_eqn_real,local_unknown_real)
307 += pml_laplace_factor[
i].real() *
308 dpsidx(l2,
i)*dtestdx(l,
i)*
309 W*hang_weight*hang_weight2;
312 jacobian(local_eqn_real,local_unknown_real)
313 += -alpha_pml_k_squared_factor.real() *
314 this->k_squared()*psi(l2)*test(l)*
315 W*hang_weight*hang_weight2;
318 if(local_unknown_imag >= 0)
321 for(
unsigned i=0;
i<DIM;
i++)
323 jacobian(local_eqn_real,local_unknown_imag)
324 -= pml_laplace_factor[
i].imag() *
325 dpsidx(l2,
i)*dtestdx(l,
i)*
326 W*hang_weight*hang_weight2;
329 jacobian(local_eqn_real,local_unknown_imag)
330 += alpha_pml_k_squared_factor.imag() *
331 this->k_squared()*psi(l2)*test(l)*
332 W*hang_weight*hang_weight2;
343 if(local_eqn_imag >= 0)
346 residuals[local_eqn_imag] +=
349 alpha_pml_k_squared_factor.imag() *
350 this->k_squared()*interpolated_u.real()
351 + alpha_pml_k_squared_factor.real() *
352 this->k_squared()*interpolated_u.imag()
354 )*test(l)*W*hang_weight;
357 for(
unsigned k=0;k<DIM;k++)
359 residuals[local_eqn_imag] += (
360 pml_laplace_factor[k].imag() * interpolated_dudx[k].real()
361 +pml_laplace_factor[k].real() * interpolated_dudx[k].imag()
362 )*dtestdx(l,k)*W*hang_weight;
371 unsigned n_master2=1;
double hang_weight2=1.0;
374 for(
unsigned l2=0;l2<n_node;l2++)
377 bool is_node2_hanging = this->node_pt(l2)->is_hanging();
382 hang_info2_pt = this->node_pt(l2)->hanging_pt();
383 n_master2 = hang_info2_pt->nmaster();
392 for(
unsigned m2=0;m2<n_master2;m2++)
400 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
401 this->u_index_helmholtz().real());
403 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
404 this->u_index_helmholtz().imag());
407 hang_weight2 = hang_info2_pt->master_weight(m2);
414 this->nodal_local_eqn(l2,this->u_index_helmholtz().real());
417 this->nodal_local_eqn(l2,this->u_index_helmholtz().imag());
424 if(local_unknown_imag >= 0)
427 for(
unsigned i=0;
i<DIM;
i++)
429 jacobian(local_eqn_imag,local_unknown_imag)
430 += pml_laplace_factor[
i].real() *
431 dpsidx(l2,
i)*dtestdx(l,
i)*
432 W*hang_weight*hang_weight2;
435 jacobian(local_eqn_imag,local_unknown_imag)
436 += -alpha_pml_k_squared_factor.real()*
437 this->k_squared() * psi(l2)*test(l)*
438 W*hang_weight*hang_weight2;
440 if(local_unknown_real >= 0)
443 for(
unsigned i=0;
i<DIM;
i++)
445 jacobian(local_eqn_imag,local_unknown_real)
446 +=pml_laplace_factor[
i].imag()*dpsidx(l2,
i)*dtestdx(l,
i)*
447 W*hang_weight*hang_weight2;
450 jacobian(local_eqn_imag,local_unknown_real)
451 += -alpha_pml_k_squared_factor.imag()*
452 this->k_squared() * psi(l2)*test(l)*
453 W*hang_weight*hang_weight2;
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
unsigned nmaster() const
Return the number of master nodes.
void fill_in_generic_residual_contribution_helmholtz(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Add element's contribution to elemental residual vector and/or Jacobian matrix flag=1: compute both f...
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Class that contains data for hanging nodes.