39 template<
unsigned DIM>
47 const unsigned n_node = nnode();
50 Shape psi(n_node), test(n_node);
51 DShape dpsidx(n_node, DIM), dtestdx(n_node, DIM);
54 HangInfo *hang_info_pt = 0, *hang_info2_pt = 0;
57 const unsigned n_intpt = integral_pt()->nweight();
60 int local_eqn_real = 0, local_unknown_real = 0;
61 int local_eqn_imag = 0, local_unknown_imag = 0;
64 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
67 double w = integral_pt()->weight(ipt);
70 double J = this->dshape_and_dtest_eulerian_at_knot_helmholtz(
71 ipt, psi, dpsidx, test, dtestdx);
78 std::complex<double> interpolated_u(0.0, 0.0);
85 for (
unsigned l = 0; l < n_node; l++)
88 for (
unsigned j = 0; j < DIM; j++)
90 interpolated_x[j] += nodal_position(l, j) * psi(l);
94 const std::complex<double> u_value(
95 this->nodal_value(l, this->u_index_helmholtz().real()),
96 this->nodal_value(l, this->u_index_helmholtz().imag()));
99 interpolated_u += u_value * psi(l);
102 for (
unsigned j = 0; j < DIM; j++)
104 interpolated_dudx[j] += u_value * dpsidx(l, j);
110 std::complex<double> source(0.0, 0.0);
111 this->get_source_helmholtz(ipt, interpolated_x, source);
117 std::complex<double> pml_k_squared_factor =
118 std::complex<double>(1.0, 0.0);
125 this->compute_pml_coefficients(
126 ipt, interpolated_x, pml_laplace_factor, pml_k_squared_factor);
129 std::complex<double> alpha_pml_k_squared_factor =
130 std::complex<double>(pml_k_squared_factor.real() -
131 this->alpha() * pml_k_squared_factor.imag(),
132 this->alpha() * pml_k_squared_factor.real() +
133 pml_k_squared_factor.imag());
149 for (
unsigned l = 0; l < n_node; l++)
153 unsigned n_master = 1;
154 double hang_weight = 1.0;
157 bool is_node_hanging = this->node_pt(l)->is_hanging();
162 hang_info_pt = this->node_pt(l)->hanging_pt();
163 n_master = hang_info_pt->
nmaster();
172 for (
unsigned m = 0; m < n_master; m++)
181 this->u_index_helmholtz().real());
185 this->u_index_helmholtz().imag());
195 this->nodal_local_eqn(l, this->u_index_helmholtz().real());
197 this->nodal_local_eqn(l, this->u_index_helmholtz().imag());
207 if (local_eqn_real >= 0)
210 residuals[local_eqn_real] +=
211 (source.real() - (alpha_pml_k_squared_factor.real() *
212 this->k_squared() * interpolated_u.real() -
213 alpha_pml_k_squared_factor.imag() *
214 this->k_squared() * interpolated_u.imag())) *
215 test(l) *
W * hang_weight;
218 for (
unsigned k = 0; k < DIM; k++)
220 residuals[local_eqn_real] +=
221 (pml_laplace_factor[k].real() * interpolated_dudx[k].real() -
222 pml_laplace_factor[k].imag() * interpolated_dudx[k].imag()) *
223 dtestdx(l, k) *
W * hang_weight;
232 unsigned n_master2 = 1;
233 double hang_weight2 = 1.0;
236 for (
unsigned l2 = 0; l2 < n_node; l2++)
239 bool is_node2_hanging = this->node_pt(l2)->is_hanging();
242 if (is_node2_hanging)
244 hang_info2_pt = this->node_pt(l2)->hanging_pt();
245 n_master2 = hang_info2_pt->nmaster();
254 for (
unsigned m2 = 0; m2 < n_master2; m2++)
258 if (is_node2_hanging)
262 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
263 this->u_index_helmholtz().real());
265 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
266 this->u_index_helmholtz().imag());
269 hang_weight2 = hang_info2_pt->master_weight(m2);
275 local_unknown_real = this->nodal_local_eqn(
276 l2, this->u_index_helmholtz().real());
278 local_unknown_imag = this->nodal_local_eqn(
279 l2, this->u_index_helmholtz().imag());
287 if (local_unknown_real >= 0)
290 for (
unsigned i = 0;
i < DIM;
i++)
292 jacobian(local_eqn_real, local_unknown_real) +=
293 pml_laplace_factor[
i].real() * dpsidx(l2,
i) *
294 dtestdx(l,
i) *
W * hang_weight * hang_weight2;
297 jacobian(local_eqn_real, local_unknown_real) +=
298 -alpha_pml_k_squared_factor.real() * this->k_squared() *
299 psi(l2) * test(l) *
W * hang_weight * hang_weight2;
302 if (local_unknown_imag >= 0)
305 for (
unsigned i = 0;
i < DIM;
i++)
307 jacobian(local_eqn_real, local_unknown_imag) -=
308 pml_laplace_factor[
i].imag() * dpsidx(l2,
i) *
309 dtestdx(l,
i) *
W * hang_weight * hang_weight2;
312 jacobian(local_eqn_real, local_unknown_imag) +=
313 alpha_pml_k_squared_factor.imag() * this->k_squared() *
314 psi(l2) * test(l) *
W * hang_weight * hang_weight2;
325 if (local_eqn_imag >= 0)
328 residuals[local_eqn_imag] +=
329 (source.imag() - (alpha_pml_k_squared_factor.imag() *
330 this->k_squared() * interpolated_u.real() +
331 alpha_pml_k_squared_factor.real() *
332 this->k_squared() * interpolated_u.imag())) *
333 test(l) *
W * hang_weight;
336 for (
unsigned k = 0; k < DIM; k++)
338 residuals[local_eqn_imag] +=
339 (pml_laplace_factor[k].imag() * interpolated_dudx[k].real() +
340 pml_laplace_factor[k].real() * interpolated_dudx[k].imag()) *
341 dtestdx(l, k) *
W * hang_weight;
350 unsigned n_master2 = 1;
351 double hang_weight2 = 1.0;
354 for (
unsigned l2 = 0; l2 < n_node; l2++)
357 bool is_node2_hanging = this->node_pt(l2)->is_hanging();
360 if (is_node2_hanging)
362 hang_info2_pt = this->node_pt(l2)->hanging_pt();
363 n_master2 = hang_info2_pt->nmaster();
372 for (
unsigned m2 = 0; m2 < n_master2; m2++)
376 if (is_node2_hanging)
380 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
381 this->u_index_helmholtz().real());
383 this->local_hang_eqn(hang_info2_pt->master_node_pt(m2),
384 this->u_index_helmholtz().imag());
387 hang_weight2 = hang_info2_pt->master_weight(m2);
393 local_unknown_real = this->nodal_local_eqn(
394 l2, this->u_index_helmholtz().real());
396 local_unknown_imag = this->nodal_local_eqn(
397 l2, this->u_index_helmholtz().imag());
404 if (local_unknown_imag >= 0)
407 for (
unsigned i = 0;
i < DIM;
i++)
409 jacobian(local_eqn_imag, local_unknown_imag) +=
410 pml_laplace_factor[
i].real() * dpsidx(l2,
i) *
411 dtestdx(l,
i) *
W * hang_weight * hang_weight2;
414 jacobian(local_eqn_imag, local_unknown_imag) +=
415 -alpha_pml_k_squared_factor.real() * this->k_squared() *
416 psi(l2) * test(l) *
W * hang_weight * hang_weight2;
418 if (local_unknown_real >= 0)
421 for (
unsigned i = 0;
i < DIM;
i++)
423 jacobian(local_eqn_imag, local_unknown_real) +=
424 pml_laplace_factor[
i].imag() * dpsidx(l2,
i) *
425 dtestdx(l,
i) *
W * hang_weight * hang_weight2;
428 jacobian(local_eqn_imag, local_unknown_real) +=
429 -alpha_pml_k_squared_factor.imag() * this->k_squared() *
430 psi(l2) * test(l) *
W * hang_weight * hang_weight2;
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
Class that contains data for hanging nodes.
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the 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...
Refineable version of QPMLHelmholtzElement elements.
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...