MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
conservative_fluid_element_base.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2020 Manav Bhatia and MAST authors
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 // MAST includes
24 #include "fluid/flight_condition.h"
29 #include "base/nonlinear_system.h"
30 #include "base/assembly_base.h"
32 #include "mesh/fe_base.h"
33 #include "mesh/geom_elem.h"
34 
35 
38  const MAST::GeomElem& elem,
39  const MAST::FlightCondition& f):
40 MAST::FluidElemBase(elem.dim(), f),
41 MAST::ElementBase(sys, elem) {
42 
43 }
44 
45 
46 
48 
49 }
50 
51 
52 
53 
54 bool
56  RealVectorX& f,
57  RealMatrixX& jac) {
58 
59  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(true, if_viscous()));
60 
61  const std::vector<Real>& JxW = fe->get_JxW();
62  const std::vector<std::vector<Real> >& phi = fe->get_phi();
63  const unsigned int
64  dim = _elem.dim(),
65  n1 = dim+2,
66  n2 = fe->n_shape_functions()*n1,
67  nphi = fe->n_shape_functions();
68 
70  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
71  mat2_n1n1 = RealMatrixX::Zero( n1, n1),
72  mat3_n1n2 = RealMatrixX::Zero( n1, n2),
73  mat4_n2n2 = RealMatrixX::Zero( n2, n2),
74  AiBi_adv = RealMatrixX::Zero( n1, n2),
75  A_sens = RealMatrixX::Zero( n1, n2),
76  LS = RealMatrixX::Zero( n1, n2),
77  LS_sens = RealMatrixX::Zero( n2, n2),
78  stress = RealMatrixX::Zero( dim, dim),
79  dprim_dcons = RealMatrixX::Zero( n1, n1),
80  dcons_dprim = RealMatrixX::Zero( n1, n1);
81 
83  vec1_n1 = RealVectorX::Zero(n1),
84  vec2_n1 = RealVectorX::Zero(n1),
85  vec3_n2 = RealVectorX::Zero(n2),
86  dc = RealVectorX::Zero(dim),
87  temp_grad = RealVectorX::Zero(dim);
88 
89 
90  std::vector<RealMatrixX>
91  Ai_adv (dim);
92 
93  std::vector<std::vector<RealMatrixX> >
94  Ai_sens (dim);
95 
96 
97  for (unsigned int i=0; i<dim; i++) {
98  Ai_sens [i].resize(n1);
99  Ai_adv [i].setZero(n1, n1);
100  for (unsigned int j=0; j<n1; j++)
101  Ai_sens[i][j].setZero(n1, n1);
102  }
103 
104 
105  std::vector<MAST::FEMOperatorMatrix> dBmat(dim);
106  std::vector<std::vector<MAST::FEMOperatorMatrix>> d2Bmat(dim);
108  MAST::PrimitiveSolution primitive_sol;
109  for (unsigned int i=0; i<dim; i++) d2Bmat[i].resize(dim);
110 
111 
112  for (unsigned int qp=0; qp<JxW.size(); qp++) {
113 
114  // initialize the Bmat operator for this term
115  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
116 
117  // calculate the local element solution
118  Bmat.right_multiply(vec1_n1, _sol);
119 
120  primitive_sol.zero();
121  primitive_sol.init(dim,
122  vec1_n1,
125  if_viscous());
126 
127  // initialize the FEM derivative operator
128  _initialize_fem_gradient_operator(qp, dim, *fe, dBmat);
129 
130  if (if_viscous()) {
131 
132  _initialize_fem_second_derivative_operator(qp, dim, *fe, d2Bmat);
133 
135  dcons_dprim,
136  dprim_dcons);
138  dBmat,
139  dprim_dcons,
140  primitive_sol,
141  stress,
142  temp_grad);
143  }
144 
145  AiBi_adv.setZero();
146  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
147 
148  calculate_advection_flux_jacobian(i_dim, primitive_sol, Ai_adv[i_dim]);
150  (i_dim, primitive_sol, Ai_sens[i_dim]);
151 
152  dBmat[i_dim].left_multiply(mat3_n1n2, Ai_adv[i_dim]);
153  AiBi_adv += mat3_n1n2;
154  }
155 
156  // intrinsic time operator for this quadrature point
158  *fe,
159  _sol,
160  primitive_sol,
161  Bmat,
162  dBmat,
163  Ai_adv,
164  AiBi_adv,
165  Ai_sens,
166  LS,
167  LS_sens);
168 
169  // discontinuity capturing operator for this quadrature point
172  *fe,
173  primitive_sol,
174  _sol,
175  dBmat,
176  AiBi_adv,
177  dc);
178 
179  // assemble the residual due to flux operator
180  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
181 
182  // first the flux
183  calculate_advection_flux(i_dim, primitive_sol, vec1_n1);
184  dBmat[i_dim].vector_mult_transpose(vec3_n2, vec1_n1);
185  f -= JxW[qp] * vec3_n2;
186 
187  // diffusive flux
188  if (if_viscous()) {
189 
191  primitive_sol,
192  stress,
193  temp_grad,
194  vec1_n1);
195  dBmat[i_dim].vector_mult_transpose(vec3_n2, vec1_n1);
196  f += JxW[qp] * vec3_n2;
197  }
198 
199  // solution derivative in i^th direction
200  // use this to calculate the discontinuity capturing term
201  dBmat[i_dim].vector_mult(vec1_n1, _sol);
202  dBmat[i_dim].vector_mult_transpose(vec3_n2, vec1_n1);
203  f += JxW[qp] * dc(i_dim) * vec3_n2;
204  }
205 
206  // stabilization term
207  f += JxW[qp] * LS.transpose() * (AiBi_adv * _sol);
208  if (if_viscous()) {
209 
210  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
211  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
212 
213 
215  j_dim,
216  primitive_sol,
217  mat1_n1n1);
218 
219  d2Bmat[i_dim][j_dim].vector_mult(vec1_n1, _sol);
220  f -= JxW[qp] * LS.transpose() * (mat1_n1n1 * vec1_n1);
221  }
222  }
223 
224 
225  if (request_jacobian) {
226 
227  A_sens.setZero();
228 
229  // contribution from flux Jacobian
230  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
231  // flux term
232  Bmat.left_multiply(mat3_n1n2, Ai_adv[i_dim]); // A_i B
233  dBmat[i_dim].right_multiply_transpose(mat4_n2n2, mat3_n1n2); // dB_i^T A_i B
234  jac -= JxW[qp]*mat4_n2n2;
235 
236  // sensitivity of Ai_Bi with respect to U: [dAi/dUj.Bi.U ... dAi/dUn.Bi.U]
237  dBmat[i_dim].vector_mult(vec1_n1, _sol);
238  for (unsigned int i_cvar=0; i_cvar<n1; i_cvar++) {
239 
240  vec2_n1 = Ai_sens[i_dim][i_cvar] * vec1_n1;
241  for (unsigned int i_phi=0; i_phi<nphi; i_phi++)
242  A_sens.col(nphi*i_cvar+i_phi) += phi[i_phi][qp] *vec2_n1; // assuming that all variables have same n_phi
243  }
244 
245  // viscous flux Jacobian
246  if (if_viscous()) {
247 
248  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
249 
251  j_dim,
252  primitive_sol,
253  mat1_n1n1);
254 
255  dBmat[j_dim].left_multiply(mat3_n1n2, mat1_n1n1); // Kij dB_j
256  dBmat[i_dim].right_multiply_transpose(mat4_n2n2, mat3_n1n2); // dB_i^T Kij dB_j
257  jac += JxW[qp]*mat4_n2n2;
258  }
259  }
260 
261  // discontinuity capturing term
262  dBmat[i_dim].right_multiply_transpose(mat4_n2n2, dBmat[i_dim]); // dB_i^T dc dB_i
263  jac += JxW[qp] * dc(i_dim) * mat4_n2n2;
264  }
265 
266  // stabilization term
267  jac += JxW[qp] * LS.transpose() * AiBi_adv; // A_i dB_i
268  if (if_viscous()) {
269 
270  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
271  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
272 
273 
275  j_dim,
276  primitive_sol,
277  mat1_n1n1);
278 
279  d2Bmat[i_dim][j_dim].left_multiply(mat3_n1n2, mat1_n1n1);
280  jac -= JxW[qp] * LS.transpose() * mat3_n1n2;
281  }
282  }
283 
284  // linearization of the Jacobian terms
285  jac += JxW[qp] * LS.transpose() * A_sens; // LS^T tau d^2F^adv_i / dx dU (Ai sensitivity)
286  // linearization of the LS terms
287  jac += JxW[qp] * LS_sens;
288 
289  }
290  }
291 
292  return request_jacobian;
293 }
294 
295 
296 
297 
298 bool
300 linearized_internal_residual (bool request_jacobian,
301  RealVectorX& f,
302  RealMatrixX& jac) {
303 
304  // first get the internal residual and Jacobian from the
305  // conservative elems, and then add to it an extra dissipation
306  // to control solution discontinuities emanating from the boundary.
307  unsigned int
308  n2 = f.size();
309 
311  f_jac_x = RealMatrixX::Zero( n2, n2),
312  fm_jac_xdot = RealMatrixX::Zero( n2, n2);
313 
315  local_f = RealVectorX::Zero(n2);
316 
317  // df/dx. We always need the Jacobian, since it is used to calculate
318  // the residual
319  this->internal_residual(true, local_f, f_jac_x);
320 
321  if (request_jacobian)
322  jac += f_jac_x;
323 
324  f += f_jac_x * _delta_sol;
325 
326  return request_jacobian;
327 }
328 
329 
330 
331 bool
333  RealVectorX& f,
334  RealMatrixX& jac_xdot,
335  RealMatrixX& jac) {
336 
337  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(true, if_viscous()));
338 
339  const std::vector<Real>& JxW = fe->get_JxW();
340  const unsigned int
341  dim = _elem.dim(),
342  n1 = dim+2,
343  n2 = fe->n_shape_functions()*n1;
344 
346  tau = RealMatrixX::Zero(n1, n1),
347  mat1_n1n1 = RealMatrixX::Zero(n1, n1),
348  mat2_n1n2 = RealMatrixX::Zero(n1, n2),
349  mat3_n2n2 = RealMatrixX::Zero(n2, n2),
350  mat4_n2n1 = RealMatrixX::Zero(n2, n1),
351  AiBi_adv = RealMatrixX::Zero(n1, n2),
352  A_sens = RealMatrixX::Zero(n1, n2),
353  LS = RealMatrixX::Zero(n1, n2),
354  LS_sens = RealMatrixX::Zero(n2, n2);
356  vec1_n1 = RealVectorX::Zero(n1),
357  vec2_n1 = RealVectorX::Zero(n1),
358  vec3_n2 = RealVectorX::Zero(n2);
359 
360  std::vector<MAST::FEMOperatorMatrix> dBmat(dim);
362  MAST::PrimitiveSolution primitive_sol;
363 
364  std::vector<RealMatrixX>
365  Ai_adv (dim);
366 
367  std::vector<std::vector<RealMatrixX> >
368  Ai_sens (dim);
369 
370 
371  for (unsigned int i=0; i<dim; i++) {
372  Ai_sens [i].resize(n1);
373  Ai_adv [i].setZero(n1, n1);
374  for (unsigned int j=0; j<n1; j++)
375  Ai_sens[i][j].setZero(n1, n1);
376  }
377 
378 
379  for (unsigned int qp=0; qp<JxW.size(); qp++) {
380 
381  // first need to set the solution of the conservative operator
382  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
383  Bmat.right_multiply(vec1_n1, _sol); // B * U
384 
385  // initialize the primitive solution
386  primitive_sol.zero();
387  primitive_sol.init(dim,
388  vec1_n1,
391  if_viscous());
392 
393  // initialize the FEM derivative operator
394  _initialize_fem_gradient_operator(qp, dim, *fe, dBmat);
395 
396  AiBi_adv.setZero();
397  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
398  calculate_advection_flux_jacobian(i_dim, primitive_sol, Ai_adv[i_dim]);
399 
400  dBmat[i_dim].left_multiply(mat2_n1n2, Ai_adv[i_dim]);
401  AiBi_adv += mat2_n1n2;
402  }
403 
404  // intrinsic time operator for this quadrature point
406  *fe,
407  _sol,
408  primitive_sol,
409  Bmat,
410  dBmat,
411  Ai_adv,
412  AiBi_adv,
413  Ai_sens,
414  LS,
415  LS_sens);
416 
417  // now evaluate the Jacobian due to the velocity term
418  Bmat.right_multiply(vec1_n1, _vel); // B * U_dot
419  Bmat.vector_mult_transpose(vec3_n2, vec1_n1); // B^T * B * U_dot
420  f += JxW[qp] * vec3_n2;
421 
422  // next, evaluate the contribution from the stabilization term
423  f += JxW[qp] * LS.transpose() * vec1_n1;
424 
425  if (request_jacobian) {
426 
427  // contribution from the velocity term
428  Bmat.right_multiply_transpose(mat3_n2n2, Bmat);
429  jac_xdot += JxW[qp] * mat3_n2n2; // B^T B
430 
431  // contribution from the stabilization term
432  // next, evaluate the contribution from the stabilization term
433  mat4_n2n1 = LS.transpose();
434  Bmat.left_multiply(mat3_n2n2, mat4_n2n1); // LS^T B
435  jac_xdot += JxW[qp]*mat3_n2n2;
436  }
437  }
438 
439 
440  return request_jacobian;
441 }
442 
443 
444 
445 bool
447 linearized_velocity_residual (bool request_jacobian,
448  RealVectorX& f,
449  RealMatrixX& jac_xdot,
450  RealMatrixX& jac) {
451 
452  // first get the internal residual and Jacobian from the
453  // conservative elems, and then add to it an extra dissipation
454  // to control solution discontinuities emanating from the boundary.
455  unsigned int
456  n2 = f.size();
457 
459  fm_jac_x = RealMatrixX::Zero( n2, n2),
460  fm_jac_xdot = RealMatrixX::Zero( n2, n2);
461 
463  local_f = RealVectorX::Zero(n2);
464 
465  // df/dx. We always need the Jacobian, since it is used to calculate
466  // the residual
467  this->velocity_residual(true, local_f, fm_jac_xdot, fm_jac_x);
468 
469  if (request_jacobian) {
470 
471  jac_xdot += fm_jac_xdot;
472  jac += fm_jac_x;
473  }
474 
475 
476  f += (fm_jac_x * _delta_sol +
477  fm_jac_xdot * _delta_vel);
478 
479  return request_jacobian;
480 }
481 
482 
483 
484 bool
486 side_external_residual (bool request_jacobian,
487  RealVectorX& f,
488  RealMatrixX& jac,
489  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
490 
491  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
493 
494  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
495  it = loads.begin(),
496  end = loads.end();
497 
498  for ( ; it != end; it++) {
499 
500  std::vector<MAST::BoundaryConditionBase*>::const_iterator
501  bc_it = it->second.begin(),
502  bc_end = it->second.end();
503 
504  for ( ; bc_it != bc_end; bc_it++) {
505 
506  // apply all the types of loading
507  switch ((*bc_it)->type()) {
508 
509  case MAST::SYMMETRY_WALL:
510  symmetry_surface_residual(request_jacobian,
511  f, jac,
512  it->first,
513  **bc_it);
514  break;
515 
516  case MAST::SLIP_WALL:
517  slip_wall_surface_residual(request_jacobian,
518  f, jac,
519  it->first,
520  **bc_it);
521  break;
522 
523  case MAST::NO_SLIP_WALL:
524  noslip_wall_surface_residual(request_jacobian,
525  f, jac,
526  it->first,
527  **bc_it);
528  break;
529 
530  case MAST::FAR_FIELD:
531  far_field_surface_residual(request_jacobian,
532  f, jac,
533  it->first,
534  **bc_it);
535  break;
536 
537  case MAST::DIRICHLET:
538  // nothing to be done here
539  break;
540 
541  default:
542  // not implemented yet
543  libmesh_error();
544  break;
545  }
546  }
547  }
548  return request_jacobian;
549 }
550 
551 
552 
553 
554 bool
556 linearized_side_external_residual (bool request_jacobian,
557  RealVectorX& f,
558  RealMatrixX& jac,
559  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
560 
561  // the far-field and symmetry wall, which are assumed to be stationary will
562  // only contribute to the real part of the complex Jacobian. Hence,
563  // we will use the parent class's methods for these two. The
564  // slip wall, which may be oscillating, is implemented for this element.
565 
566  unsigned int
567  n2 = f.size();
568 
570  f_jac_x = RealMatrixX::Zero(n2, n2);
571 
573  local_f = RealVectorX::Zero(n2);
574 
575 
576  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
578 
579  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
580  it = loads.begin(),
581  end = loads.end();
582 
583  for ( ; it != end; it++) {
584 
585  std::vector<MAST::BoundaryConditionBase*>::const_iterator
586  bc_it = it->second.begin(),
587  bc_end = it->second.end();
588 
589  for ( ; bc_it != bc_end; bc_it++) {
590 
591  // apply all the types of loading
592  switch ((*bc_it)->type()) {
593 
594  case MAST::SYMMETRY_WALL: {
595 
596  f_jac_x.setZero();
597  local_f.setZero();
598 
599  // We always need the Jacobian, since it is used to
600  // calculate the residual
601 
602  this->symmetry_surface_residual(true,
603  local_f,
604  f_jac_x,
605  it->first,
606  **bc_it);
607 
608  // multiply jacobian with the nondimensionalizing
609  // factor (V/b for flutter analysis)
610  if (request_jacobian)
611  jac += f_jac_x;
612 
613  f += f_jac_x * _delta_sol;
614  }
615  break;
616 
617  case MAST::SLIP_WALL: {
618 
619  // this calculates the Jacobian and residual contribution
620  // including the nondimensionalizing factor.
621 
622  this->linearized_slip_wall_surface_residual(request_jacobian,
623  f,
624  jac,
625  it->first,
626  **bc_it);
627  }
628  break;
629 
630  case MAST::FAR_FIELD: {
631 
632  f_jac_x.setZero();
633  local_f.setZero();
634 
635  // We always need the Jacobian, since it is used to
636  // calculate the residual
637 
638  this->far_field_surface_residual(true,
639  local_f,
640  f_jac_x,
641  it->first,
642  **bc_it);
643 
644  // multiply jacobian with the nondimensionalizing
645  // factor (V/b for flutter analysis)
646  if (request_jacobian)
647  jac += f_jac_x;
648 
649  f += f_jac_x * _delta_sol;
650  }
651  break;
652 
653  case MAST::DIRICHLET:
654  // nothing to be done here
655  break;
656 
657  default:
658  // not implemented yet
659  libmesh_error();
660  break;
661  }
662  }
663  }
664 
665  return request_jacobian;
666 }
667 
668 
669 
670 
671 bool
674  bool request_jacobian,
675  RealVectorX& f,
676  RealMatrixX& jac,
677  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
678 
679 
680  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
682 
683  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
684  it = loads.begin(),
685  end = loads.end();
686 
687  for ( ; it != end; it++) {
688 
689  std::vector<MAST::BoundaryConditionBase*>::const_iterator
690  bc_it = it->second.begin(),
691  bc_end = it->second.end();
692 
693  for ( ; bc_it != bc_end; bc_it++) {
694 
695  // apply all the types of loading
696  switch ((*bc_it)->type()) {
697 
698  case MAST::SYMMETRY_WALL:
699  symmetry_surface_residual_sensitivity(p, request_jacobian,
700  f, jac,
701  it->first,
702  **bc_it);
703  break;
704 
705  case MAST::SLIP_WALL:
706  slip_wall_surface_residual_sensitivity(p, request_jacobian,
707  f, jac,
708  it->first,
709  **bc_it);
710 
711  case MAST::NO_SLIP_WALL:
712  noslip_wall_surface_residual_sensitivity(p, request_jacobian,
713  f, jac,
714  it->first,
715  **bc_it);
716  break;
717 
718  case MAST::FAR_FIELD:
719  far_field_surface_residual_sensitivity(p, request_jacobian,
720  f, jac,
721  it->first,
722  **bc_it);
723  break;
724 
725  case MAST::DIRICHLET:
726  // nothing to be done here
727  break;
728 
729  default:
730  // not implemented yet
731  libmesh_error();
732  break;
733  }
734  }
735  }
736  return request_jacobian;
737 }
738 
739 
740 
741 
742 
743 
744 bool
747  bool request_jacobian,
748  RealVectorX& f,
749  RealMatrixX& jac) {
750 
751  return request_jacobian;
752 }
753 
754 
755 
756 bool
759  bool request_jacobian,
760  RealVectorX& f,
761  RealMatrixX& jac_xdot,
762  RealMatrixX& jac) {
763 
764  return request_jacobian;
765 }
766 
767 
768 
769 
770 
771 void
773  RealVectorX& f,
774  RealMatrixX* dfdX) {
775 
776  // prepare the side finite element
777  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, if_viscous(), false));
778 
779  const std::vector<Real> &JxW = fe->get_JxW();
780  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
781 
782  const unsigned int
783  dim = _elem.dim(),
784  n1 = dim+2,
785  n2 = fe->n_shape_functions()*n1;
786 
788  temp_grad = RealVectorX::Zero(dim),
789  dpdX = RealVectorX::Zero(n1),
790  vec1_n1 = RealVectorX::Zero(n1),
791  vec2_n2 = RealVectorX::Zero(n2);
792 
794  stress = RealMatrixX::Zero( dim, dim),
795  dprim_dcons = RealMatrixX::Zero( n1, n1),
796  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
797  mat1_n1n1 = RealMatrixX::Zero( n1, n1);
798 
799 
800  libMesh::Point pt;
801  std::vector<MAST::FEMOperatorMatrix> dBmat(dim);
803 
804  // create objects to calculate the primitive solution, flux, and Jacobian
805  MAST::PrimitiveSolution primitive_sol;
806 
807  for (unsigned int qp=0; qp<JxW.size(); qp++) {
808 
809  // initialize the Bmat operator for this term
810  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
811  Bmat.right_multiply(vec1_n1, _sol);
812 
813  // initialize the primitive solution
814  primitive_sol.zero();
815  primitive_sol.init(dim,
816  vec1_n1,
819  if_viscous());
820 
821  //
822  // first add the pressure term
823  //
824  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
825  f(i_dim) += JxW[qp] * primitive_sol.p * normals[qp](i_dim);
826 
827  //
828  // next, add the contribution from viscous stress
829  //
830  if (if_viscous()) {
831 
832  _initialize_fem_gradient_operator(qp, dim, *fe, dBmat);
833 
835  mat1_n1n1,
836  dprim_dcons);
838  dBmat,
839  dprim_dcons,
840  primitive_sol,
841  stress,
842  temp_grad);
843 
844  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
845  f.topRows(dim) -= JxW[qp] * stress.col(i_dim) * normals[qp](i_dim);
846  }
847 
848 
849  // adjoints, if requested
850  if (dfdX) {
851 
853  dpdX);
854  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
855 
856  Bmat.vector_mult_transpose(vec2_n2, dpdX);
857  dfdX->row(i_dim) += JxW[qp] * vec2_n2 * normals[qp](i_dim);
858  }
859 
860  if (if_viscous()) {
861 
862  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
863  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
864 
866  j_dim,
867  primitive_sol,
868  mat1_n1n1);
869 
870  dBmat[j_dim].left_multiply(mat2_n1n2, mat1_n1n1);
871  dfdX->topRows(dim) -= JxW[qp] * mat2_n1n2.middleRows(1,dim) * normals[qp](i_dim);
872  }
873  }
874  }
875  }
876 }
877 
878 
879 void
882  const unsigned int s,
883  RealVectorX& f) {
884 
885  // prepare the side finite element
886  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, if_viscous(), false));
887 
888  const std::vector<Real> &JxW = fe->get_JxW();
889  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
890 
891  const unsigned int
892  dim = _elem.dim(),
893  n1 = dim+2,
894  n2 = fe->n_shape_functions()*n1;
895 
897  temp_grad_sens = RealVectorX::Zero(dim),
898  dpdX = RealVectorX::Zero(n1),
899  vec1_n1 = RealVectorX::Zero(n1),
900  vec2_n2 = RealVectorX::Zero(n2);
901 
903  stress_sens = RealMatrixX::Zero( dim, dim),
904  dprim_dcons = RealMatrixX::Zero( n1, n1),
905  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
906  mat1_n1n1 = RealMatrixX::Zero( n1, n1);
907 
908 
909  libMesh::Point pt;
910  std::vector<MAST::FEMOperatorMatrix> dBmat(dim);
912 
913  // create objects to calculate the primitive solution, flux, and Jacobian
914  MAST::PrimitiveSolution primitive_sol;
915  MAST::SmallPerturbationPrimitiveSolution<Real> linearized_primitive_sol;
916 
917  for (unsigned int qp=0; qp<JxW.size(); qp++) {
918 
919  // initialize the Bmat operator for this term
920  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
921  Bmat.right_multiply(vec1_n1, _sol);
922 
923  // initialize the primitive solution
924  primitive_sol.zero();
925  primitive_sol.init(dim,
926  vec1_n1,
929  if_viscous());
930 
931  // now initialize the linearized solution
932  Bmat.right_multiply(vec1_n1, _sol_sens);
933  linearized_primitive_sol.zero();
934  linearized_primitive_sol.init(primitive_sol, vec1_n1, if_viscous());
935 
936  //
937  // first add the pressure term
938  //
939  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
940  f(i_dim) += JxW[qp] * linearized_primitive_sol.dp * normals[qp](i_dim);
941 
942  //
943  // next, add the contribution from viscous stress
944  //
945  if (if_viscous()) {
946 
947  _initialize_fem_gradient_operator(qp, dim, *fe, dBmat);
948 
950  mat1_n1n1,
951  dprim_dcons);
953  _sol_sens,
954  dBmat,
955  dprim_dcons,
956  primitive_sol,
957  linearized_primitive_sol,
958  stress_sens,
959  temp_grad_sens);
960 
961  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
962  f.topRows(dim) -= JxW[qp] * stress_sens.col(i_dim) * normals[qp](i_dim);
963  }
964  }
965 }
966 
967 
968 
969 
970 
971 
972 
973 bool
975 symmetry_surface_residual(bool request_jacobian,
976  RealVectorX& f,
977  RealMatrixX& jac,
978  const unsigned int s,
980 
981  // prepare the side finite element
982  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
983 
984  const std::vector<Real> &JxW = fe->get_JxW();
985  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
986 
987  const unsigned int
988  dim = _elem.dim(),
989  n1 = dim+2,
990  n2 = fe->n_shape_functions()*n1;
991 
993  vec1_n1 = RealVectorX::Zero(n1),
994  vec2_n2 = RealVectorX::Zero(n2),
995  dnormal = RealVectorX::Zero(dim);
996 
998  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
999  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1000  mat3_n2n2 = RealMatrixX::Zero( n2, n2);
1001 
1002  libMesh::Point pt;
1004 
1005  // create objects to calculate the primitive solution, flux, and Jacobian
1006  MAST::PrimitiveSolution primitive_sol;
1007 
1008  for (unsigned int qp=0; qp<JxW.size(); qp++) {
1009 
1010  // initialize the Bmat operator for this term
1011  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1012  Bmat.right_multiply(vec1_n1, _sol);
1013 
1014  // initialize the primitive solution
1015  primitive_sol.zero();
1016  primitive_sol.init(dim,
1017  vec1_n1,
1020  if_viscous());
1021 
1022 
1023  vec1_n1.setZero();
1024  // since vi=0, vi ni = 0, so the advection flux gets evaluated
1025  // using the slip wall condition
1026  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1027  vec1_n1(i_dim+1) += primitive_sol.p * normals[qp](i_dim);
1028 
1029  Bmat.vector_mult_transpose(vec2_n2, vec1_n1);
1030  f += JxW[qp] * vec2_n2;
1031 
1032  if (request_jacobian) {
1033 
1035  (primitive_sol,
1036  0.,
1037  normals[qp],
1038  dnormal,
1039  mat1_n1n1);
1040 
1041  Bmat.left_multiply(mat2_n1n2, mat1_n1n1);
1042  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2);
1043  jac += JxW[qp] * mat3_n2n2;
1044  }
1045  }
1046 
1047  // calculation of the load vector is independent of solution
1048  return false;
1049 }
1050 
1051 
1052 
1053 
1054 
1055 
1056 
1057 
1058 bool
1061  bool request_jacobian,
1062  RealVectorX& f,
1063  RealMatrixX& jac,
1064  const unsigned int s,
1066 
1067  return false;
1068 }
1069 
1070 
1071 
1072 
1073 
1074 bool
1076 slip_wall_surface_residual(bool request_jacobian,
1077  RealVectorX& f,
1078  RealMatrixX& jac,
1079  const unsigned int s,
1081 
1082  // inviscid boundary condition without any diffusive component
1083  // conditions enforced are
1084  // vi ni = wi_dot (ni + dni) - ui dni (moving slip wall with deformation)
1085  // tau_ij nj = 0 (because velocity gradient at wall = 0)
1086  // qi ni = 0 (since heat flux occurs only on no-slip wall and far-field bc)
1087 
1088  // prepare the side finite element
1089  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
1090 
1091  const std::vector<Real> &JxW = fe->get_JxW();
1092  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1093  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1094 
1095  const unsigned int
1096  dim = _elem.dim(),
1097  n1 = dim+2,
1098  n2 = fe->n_shape_functions()*n1;
1099 
1100  RealVectorX
1101  vec1_n1 = RealVectorX::Zero(n1),
1102  vec2_n2 = RealVectorX::Zero(n2),
1103  flux = RealVectorX::Zero(n1),
1104  dnormal = RealVectorX::Zero(dim),
1105  uvec = RealVectorX::Zero(3),
1106  ni = RealVectorX::Zero(3),
1107  vel_fe = RealVectorX::Zero(6),
1108  dwdot_i = RealVectorX::Zero(3),
1109  dni = RealVectorX::Zero(3);
1110 
1111  RealMatrixX
1112  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
1113  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1114  mat3_n2n2 = RealMatrixX::Zero( n2, n2);
1115 
1116  Real
1117  ui_ni = 0.;
1118 
1119 
1120  libMesh::Point pt;
1122 
1123  // create objects to calculate the primitive solution, flux, and Jacobian
1124  MAST::PrimitiveSolution primitive_sol;
1125 
1126 
1127  // get the surface motion object from the boundary condition object
1129  *vel = nullptr;
1131  *n_rot = nullptr;
1132 
1133  if (bc.contains("velocity"))
1134  vel = &bc.get<MAST::FieldFunction<RealVectorX> >("velocity");
1135  if (bc.contains("normal_rotation")) {
1136 
1138  tmp = bc.get<MAST::FieldFunction<RealVectorX> >("normal_rotation");
1139  n_rot = dynamic_cast<MAST::NormalRotationFunctionBase<RealVectorX>*>(&tmp);
1140  }
1141 
1142  // if displ is provided then n_rot must also be provided
1143  if (vel) libmesh_assert(n_rot);
1144 
1145  for (unsigned int qp=0; qp<JxW.size(); qp++)
1146  {
1147  // initialize the Bmat operator for this term
1148  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1149  Bmat.right_multiply(vec1_n1, _sol);
1150 
1151  // initialize the primitive solution
1152  primitive_sol.zero();
1153  primitive_sol.init(dim,
1154  vec1_n1,
1157  if_viscous());
1158 
1160  // Calculation of the surface velocity term.
1161  // vi (ni + dni) = wdot_i (ni + dni)
1162  // or vi ni = wdot_i (ni + dni) - vi dni
1164 
1165 
1166  // copy the surface normal
1167  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1168  ni(i_dim) = normals[qp](i_dim);
1169 
1170 
1171  // now check if the surface deformation is defined and
1172  // needs to be applied through transpiration boundary
1173  // condition
1174 
1175  primitive_sol.get_uvec(uvec);
1176 
1177  if (vel) { // get the surface motion data
1178 
1179  (*vel)(qpoint[qp], _time, vel_fe);
1180  dwdot_i = vel_fe.topRows(3);
1181  }
1182 
1183  if (n_rot)
1184  (*n_rot)(qpoint[qp], normals[qp], _time, dni);
1185 
1186  ui_ni = dwdot_i.dot(ni+dni) - uvec.dot(dni);
1187 
1188 
1189  flux.setZero();
1190  flux += ui_ni * vec1_n1; // vi ni cons_flux
1191  flux(n1-1) += ui_ni * primitive_sol.p; // vi ni {0, 0, 0, 0, p}
1192  flux.segment(1,dim) += primitive_sol.p * ni.segment(0,dim); // p * ni for the momentum eqs.
1193 
1194  Bmat.vector_mult_transpose(vec2_n2, flux);
1195  f += JxW[qp] * vec2_n2;
1196 
1197  if ( request_jacobian ) {
1198 
1200  (primitive_sol,
1201  ui_ni,
1202  normals[qp],
1203  dni,
1204  mat1_n1n1);
1205 
1206  Bmat.left_multiply(mat2_n1n2, mat1_n1n1);
1207  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2);
1208  jac += JxW[qp] * mat3_n2n2;
1209  }
1210  }
1211 
1212 
1213  return false;
1214 }
1215 
1216 
1217 
1218 bool
1221  RealVectorX& f,
1222  RealMatrixX& jac,
1223  const unsigned int s,
1225 
1226  // inviscid boundary condition without any diffusive component
1227  // conditions enforced are
1228  // vi ni = wi_dot (ni + dni) - ui dni (moving slip wall with deformation)
1229  // tau_ij nj = 0 (because velocity gradient at wall = 0)
1230  // qi ni = 0 (since heat flux occurs only on no-slip wall and far-field bc)
1231 
1232  // prepare the side finite element
1233  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
1234 
1235  const std::vector<Real> &JxW = fe->get_JxW();
1236  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1237  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1238 
1239  const unsigned int
1240  dim = _elem.dim(),
1241  n1 = dim+2,
1242  n2 = fe->n_shape_functions()*n1;
1243 
1244  RealVectorX
1245  vec1_n1 = RealVectorX::Zero(n1),
1246  uvec = RealVectorX::Zero(3),
1247  dwdot_i = RealVectorX::Zero(3),
1248  ni = RealVectorX::Zero(3),
1249  dni = RealVectorX::Zero(3),
1250  Dw_i = RealVectorX::Zero(3),
1251  Dni = RealVectorX::Zero(3),
1252  Duvec = RealVectorX::Zero(3),
1253  vec2_n1 = RealVectorX::Zero(n1),
1254  vec2_n2 = RealVectorX::Zero(n2),
1255  tmp = RealVectorX::Zero(6),
1256  flux = RealVectorX::Zero(n1);
1257 
1258  RealMatrixX
1259  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
1260  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1261  mat3_n2n2 = RealMatrixX::Zero( n2, n2);
1262 
1263  libMesh::Point pt;
1265 
1266  // create objects to calculate the primitive solution, flux, and Jacobian
1267  MAST::PrimitiveSolution primitive_sol;
1269 
1270  Real
1271  Dvi_ni = 0.,
1272  ui_ni_steady = 0.;
1273 
1274 
1275  // get the surface motion object from the boundary condition object
1277  *vel = nullptr;
1279  *n_rot = nullptr;
1280 
1281  if (bc.contains("velocity"))
1282  vel = &bc.get<MAST::FieldFunction<RealVectorX> >("velocity");
1283  if (bc.contains("normal_rotation")) {
1284 
1286  tmp = bc.get<MAST::FieldFunction<RealVectorX> >("normal_rotation");
1287  n_rot = dynamic_cast<MAST::NormalRotationFunctionBase<RealVectorX>*>(&tmp);
1288  }
1289 
1290  // if displ is provided then n_rot must also be provided
1291  if (vel) libmesh_assert(n_rot);
1292 
1293  for (unsigned int qp=0; qp<JxW.size(); qp++) {
1294 
1295  // initialize the Bmat operator for this term
1296  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1297  Bmat.right_multiply(vec1_n1, _sol); // conservative sol
1298  Bmat.right_multiply(vec2_n1, _delta_sol); // perturbation sol
1299 
1300  // initialize the primitive solution
1301  primitive_sol.zero();
1302  primitive_sol.init(dim,
1303  vec1_n1,
1306  if_viscous());
1307 
1308  // initialize the small-disturbance primitive sol
1309  sd_primitive_sol.zero();
1310  sd_primitive_sol.init(primitive_sol, vec2_n1, if_viscous());
1311 
1313  // Calculation of the surface velocity term. For a
1314  // steady-state system,
1315  // vi (ni + dni) = wdot_i (ni + dni)
1316  // or vi ni = wdot_i (ni + dni) - vi dni
1317  //
1318  // The first order perturbation, D(.), of this is
1319  // (vi + Dvi) (ni + dni + Dni) =
1320  // (wdot_i + Dwdot_i) (ni + dni + Dni)
1321  // or Dvi ni = Dwdot_i (ni + dni + Dni) +
1322  // wdot_i (ni + dni + Dni) -
1323  // vi (ni + dni + Dni) -
1324  // Dvi (dni + Dni)
1325  // Neglecting HOT, this becomes
1326  // Dvi ni = Dwdot_i (ni + dni) +
1327  // wdot_i (ni + dni + Dni) -
1328  // vi (ni + dni + Dni) -
1329  // Dvi dni
1330  // = Dwdot_i (ni + dni) +
1331  // wdot_i Dni - vi Dni - Dvi dni
1332  //
1334 
1335  // copy the surface normal
1336  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1337  ni(i_dim) = normals[qp](i_dim);
1338 
1339  // now check if the surface deformation is defined and
1340  // needs to be applied through transpiration boundary
1341  // condition
1342  primitive_sol.get_uvec(uvec);
1343  sd_primitive_sol.get_duvec(Duvec);
1344 
1345  flux.setZero();
1346 
1347  if (vel) {
1348 
1349  // base flow contribution
1350  (*vel)(qpoint[qp], _time, tmp);
1351  dwdot_i = tmp.topRows(3);
1352 
1353  // small-disturbance contribution
1354  vel->perturbation(qpoint[qp], _time, tmp);
1355  Dw_i = tmp.topRows(3);
1356  }
1357 
1358  if (n_rot) {
1359 
1360  // base flow contribution
1361  (*n_rot)(qpoint[qp], normals[qp], _time, dni);
1362 
1363  // small-disturbance contribution
1364  n_rot->perturbation(qpoint[qp], normals[qp], _time, Dni);
1365  }
1366 
1367  // base flow contribution to the flux
1368  ui_ni_steady = dwdot_i.dot(ni+dni) - uvec.dot(dni);
1369  flux += ui_ni_steady * vec2_n1; // vi_ni dcons_flux
1370  flux(n1-1) += ui_ni_steady * sd_primitive_sol.dp; // vi_ni {0,0,0,0,Dp}
1371 
1372  // perturbed quantity contribution to the flux
1373  Dvi_ni = (Dw_i.dot(ni+dni) +
1374  dwdot_i.dot(Dni) -
1375  uvec.dot(Dni) -
1376  Duvec.dot(dni));
1377  flux += Dvi_ni * vec1_n1; // Dvi_ni cons_flux
1378  flux(n1-1) += Dvi_ni * primitive_sol.p; // Dvi_ni {0,0,0,0,p}
1379 
1380  // ni Dp (only for the momentun eq)
1381  flux.segment(1, dim) += (sd_primitive_sol.dp * ni.segment(0,dim));
1382 
1383  Bmat.vector_mult_transpose(vec2_n2, flux);
1384  f += JxW[qp] * vec2_n2;
1385 
1386  if ( request_jacobian ) {
1387 
1388  // the Jacobian contribution comes only from the dp term in the
1389  // residual
1391  (primitive_sol,
1392  ui_ni_steady,
1393  normals[qp],
1394  dni,
1395  mat1_n1n1);
1396 
1397  Bmat.left_multiply(mat2_n1n2, mat1_n1n1);
1398  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2);
1399  jac += JxW[qp] * mat3_n2n2;
1400  }
1401  }
1402 
1403  return request_jacobian;
1404 }
1405 
1406 
1407 
1408 bool
1411  bool request_jacobian,
1412  RealVectorX& f,
1413  RealMatrixX& jac,
1414  const unsigned int s,
1416 
1417  return false;
1418 }
1419 
1420 
1421 bool
1423 noslip_wall_surface_residual(bool request_jacobian,
1424  RealVectorX& f,
1425  RealMatrixX& jac,
1426  const unsigned int s,
1428 
1429  // inviscid boundary condition without any diffusive component
1430  // conditions enforced are
1431  // vi ni = wi_dot (ni + dni) - ui dni (moving slip wall with deformation)
1432  // tau_ij nj = 0 (because velocity gradient at wall = 0)
1433  // qi ni = 0 (since heat flux occurs only on no-slip wall and far-field bc)
1434 
1435  // prepare the side finite element
1436  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, true, false));
1437 
1438  const std::vector<Real> &JxW = fe->get_JxW();
1439  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1440 
1441  const unsigned int
1442  dim = _elem.dim(),
1443  n1 = dim+2,
1444  n2 = fe->n_shape_functions()*n1;
1445 
1446  RealVectorX
1447  vec1_n1 = RealVectorX::Zero(n1),
1448  vec2_n2 = RealVectorX::Zero(n2),
1449  flux = RealVectorX::Zero(n1),
1450  dnormal = RealVectorX::Zero(dim),
1451  uvec = RealVectorX::Zero(3),
1452  ni = RealVectorX::Zero(3),
1453  dwdot_i = RealVectorX::Zero(3),
1454  dni = RealVectorX::Zero(3),
1455  temp_grad = RealVectorX::Zero(dim);
1456 
1457  RealMatrixX
1458  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
1459  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1460  mat3_n2n2 = RealMatrixX::Zero( n2, n2),
1461  stress = RealMatrixX::Zero( dim, dim),
1462  dprim_dcons = RealMatrixX::Zero( n1, n1),
1463  dcons_dprim = RealMatrixX::Zero( n1, n1);
1464 
1465  Real
1466  ui_ni = 0.;
1467 
1468 
1469  libMesh::Point pt;
1471  std::vector<MAST::FEMOperatorMatrix> dBmat(dim);
1472 
1473  // create objects to calculate the primitive solution, flux, and Jacobian
1474  MAST::PrimitiveSolution primitive_sol;
1475 
1476 
1477  // get the surface motion object from the boundary condition object
1479  *vel = nullptr;
1481  *n_rot = nullptr;
1482 
1483  if (bc.contains("velocity"))
1484  vel = &bc.get<MAST::FieldFunction<RealVectorX> >("velocity");
1485  if (bc.contains("normal_rotation")) {
1486 
1488  tmp = bc.get<MAST::FieldFunction<RealVectorX> >("normal_rotation");
1489  n_rot = dynamic_cast<MAST::NormalRotationFunctionBase<RealVectorX>*>(&tmp);
1490  }
1491 
1492 
1493  for (unsigned int qp=0; qp<JxW.size(); qp++)
1494  {
1495  // initialize the Bmat operator for this term
1496  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1497  _initialize_fem_gradient_operator(qp, dim, *fe, dBmat);
1498 
1499  Bmat.right_multiply(vec1_n1, _sol);
1500 
1501  // initialize the primitive solution
1502  primitive_sol.zero();
1503  primitive_sol.init(dim,
1504  vec1_n1,
1507  if_viscous());
1508 
1509  // copy the surface normal
1510  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1511  ni(i_dim) = normals[qp](i_dim);
1512 
1513  primitive_sol.get_uvec(uvec);
1514 
1515  /*////////////////////////////////////////////////////////////
1516  // Calculation of the surface velocity term.
1517  // vi (ni + dni) = wdot_i (ni + dni)
1518  // or vi ni = wdot_i (ni + dni) - vi dni
1520 
1521  // now check if the surface deformation is defined and
1522  // needs to be applied through transpiration boundary
1523  // condition
1524 
1525 
1526  if (motion) { // get the surface motion data
1527 
1528  motion->time_domain_motion(_time,
1529  qpoint[qp],
1530  normals[qp],
1531  dwdot_i,
1532  dni);
1533 
1534  ui_ni = dwdot_i.dot(ni+dni) - uvec.dot(dni);
1535  }*/
1536 
1537 
1538  flux.setZero();
1539 
1540  // convective flux terms
1541  flux += ui_ni * vec1_n1; // vi ni cons_flux
1542  flux(n1-1) += ui_ni * primitive_sol.p; // vi ni {0, 0, 0, 0, p}
1543  flux.segment(1,dim) += primitive_sol.p * ni.segment(0,dim); // p * ni for the momentum eqs.
1544 
1545  // now, add the viscous flux terms
1547  dcons_dprim,
1548  dprim_dcons);
1550  dBmat,
1551  dprim_dcons,
1552  primitive_sol,
1553  stress,
1554  temp_grad);
1555 
1556  // assuming adiabatic and non-moving wall
1557  uvec.setZero();
1558  temp_grad.setZero();
1559 
1560  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
1561 
1562  // stress
1563  flux.segment(1, dim) -= ni(i_dim) * stress.col(i_dim);
1564  flux(n1-1) -= ni(i_dim) * stress.col(i_dim).dot(uvec.segment(0,dim));
1565  }
1566 
1567  // temperature. If adiabatic, temp grad is set to zero
1568  flux(n1-1) -= primitive_sol.k_thermal * temp_grad.dot(ni.segment(0,dim));
1569 
1570 
1571  Bmat.vector_mult_transpose(vec2_n2, flux);
1572  f += JxW[qp] * vec2_n2;
1573 
1574  if ( request_jacobian ) {
1575 
1577  (primitive_sol,
1578  ui_ni,
1579  normals[qp],
1580  dni,
1581  mat1_n1n1);
1582 
1583  Bmat.left_multiply(mat2_n1n2, mat1_n1n1);
1584  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2);
1585  jac += JxW[qp] * mat3_n2n2;
1586 
1587  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
1588 
1589  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
1590 
1592  j_dim,
1593  uvec,
1594  true, // curretly assuming adiabatic
1595  primitive_sol,
1596  mat1_n1n1);
1597  mat1_n1n1 *= dprim_dcons;
1598  dBmat[j_dim].left_multiply(mat2_n1n2, mat1_n1n1); // Kij dB_j
1599  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2); // B^T Kij dB_j
1600  jac -= JxW[qp] * mat3_n2n2 * ni(i_dim); //jac -= JxW[qp]*mat3_n2n2;
1601  }
1602  }
1603  }
1604  }
1605 
1606  return false;
1607 }
1608 
1609 
1610 
1611 
1612 bool
1615  bool request_jacobian,
1616  RealVectorX& f,
1617  RealMatrixX& jac,
1618  const unsigned int s,
1620 
1621  return false;
1622 }
1623 
1624 
1625 
1626 bool
1628 far_field_surface_residual(bool request_jacobian,
1629  RealVectorX& f,
1630  RealMatrixX& jac,
1631  const unsigned int s,
1633 
1634  // conditions enforced are:
1635  // -- f_adv_i ni = f_adv = f_adv(+) + f_adv(-) (flux vector splitting for advection)
1636  // -- f_diff_i ni = f_diff (evaluation of diffusion flux based on domain solution)
1637 
1638  // prepare the side finite element
1639  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
1640 
1641  const std::vector<Real> &JxW = fe->get_JxW();
1642  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1643  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1644 
1645  const unsigned int
1646  dim = _elem.dim(),
1647  n1 = dim+2,
1648  n2 = fe->n_shape_functions()*n1;
1649 
1650  RealVectorX
1651  vec1_n1 = RealVectorX::Zero(n1),
1652  vec2_n1 = RealVectorX::Zero(n1),
1653  vec3_n2 = RealVectorX::Zero(n2),
1654  flux = RealVectorX::Zero(n1),
1655  eig_val = RealVectorX::Zero(n1),
1656  dnormal = RealVectorX::Zero(dim);
1657 
1658  RealMatrixX
1659  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
1660  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1661  mat3_n2n2 = RealMatrixX::Zero( n2, n2),
1662  leig_vec = RealMatrixX::Zero( n1, n1),
1663  leig_vec_inv_tr = RealMatrixX::Zero( n1, n1);
1664 
1665  libMesh::Point pt;
1667 
1668  // create objects to calculate the primitive solution, flux, and Jacobian
1669  MAST::PrimitiveSolution primitive_sol;
1670 
1671 
1672  for (unsigned int qp=0; qp<JxW.size(); qp++) {
1673 
1674 
1675  // first update the variables at the current quadrature point
1676  // initialize the Bmat operator for this term
1677  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1678  Bmat.right_multiply(vec1_n1, _sol);
1679 
1680  // initialize the primitive solution
1681  primitive_sol.zero();
1682  primitive_sol.init(dim,
1683  vec1_n1,
1686  if_viscous());
1687 
1689  (primitive_sol,
1690  normals[qp],
1691  eig_val,
1692  leig_vec,
1693  leig_vec_inv_tr);
1694 
1695  // for all eigenalues that are less than 0, the characteristics are coming into the domain, hence,
1696  // evaluate them using the given solution.
1697  mat1_n1n1 = leig_vec_inv_tr;
1698  for (unsigned int j=0; j<n1; j++)
1699  if (eig_val(j) < 0)
1700  mat1_n1n1.col(j) *= eig_val(j); // L^-T [omaga]_{-}
1701  else
1702  mat1_n1n1.col(j) *= 0.0;
1703 
1704  mat1_n1n1 *= leig_vec.transpose(); // A_{-} = L^-T [omaga]_{-} L^T
1705 
1706  if (flight_condition->inf_sol.get())
1707  (*flight_condition->inf_sol)(qpoint[qp], _time, vec2_n1);
1708  else
1709  this->get_infinity_vars( vec2_n1 );
1710  flux = mat1_n1n1 * vec2_n1; // f_{-} = A_{-} B U
1711 
1712  Bmat.vector_mult_transpose(vec3_n2, flux); // B^T f_{-} (this is flux coming into the solution domain)
1713  f += JxW[qp] * vec3_n2;
1714 
1715  // now calculate the flux for eigenvalues greater than 0,
1716  // the characteristics go out of the domain, so that
1717  // the flux is evaluated using the local solution
1718  mat1_n1n1 = leig_vec_inv_tr;
1719  for (unsigned int j=0; j<n1; j++)
1720  if (eig_val(j) > 0)
1721  mat1_n1n1.col(j) *= eig_val(j); // L^-T [omaga]_{+}
1722  else
1723  mat1_n1n1.col(j) *= 0.0;
1724 
1725  mat1_n1n1 *= leig_vec.transpose(); // A_{+} = L^-T [omaga]_{+} L^T
1726  flux = mat1_n1n1 * vec1_n1; // f_{+} = A_{+} B U
1727 
1728  Bmat.vector_mult_transpose(vec3_n2, flux); // B^T f_{+} (this is flux going out of the solution domain)
1729  f += JxW[qp] * vec3_n2;
1730 
1731 
1732  if ( request_jacobian)
1733  {
1734  // terms with negative eigenvalues do not contribute to the Jacobian
1735 
1736  // now calculate the Jacobian for eigenvalues greater than 0,
1737  // the characteristics go out of the domain, so that
1738  // the flux is evaluated using the local solution
1739  mat1_n1n1 = leig_vec_inv_tr;
1740  for (unsigned int j=0; j<n1; j++)
1741  if (eig_val(j) > 0)
1742  mat1_n1n1.col(j) *= eig_val(j); // L^-T [omaga]_{+}
1743  else
1744  mat1_n1n1.col(j) *= 0.0;
1745  mat1_n1n1 *= leig_vec.transpose(); // A_{+} = L^-T [omaga]_{+} L^T
1746  Bmat.left_multiply(mat2_n1n2, mat1_n1n1);
1747  Bmat.right_multiply_transpose(mat3_n2n2, mat2_n1n2); // B^T A_{+} B (this is flux going out of the solution domain)
1748 
1749  jac += JxW[qp] * mat3_n2n2;
1750  }
1751  }
1752 
1753  return false;
1754 }
1755 
1756 
1757 
1758 
1759 bool
1762  bool request_jacobian,
1763  RealVectorX& f,
1764  RealMatrixX& jac,
1765  const unsigned int s,
1767 
1768 
1769  // conditions enforced are:
1770  // -- f_adv_i ni = f_adv = f_adv(+) + f_adv(-) (flux vector splitting for advection)
1771  // -- f_diff_i ni = f_diff (evaluation of diffusion flux based on domain solution)
1772 
1773  // prepare the side finite element
1774  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
1775 
1776  const std::vector<Real> &JxW = fe->get_JxW();
1777  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1778 
1779  const unsigned int
1780  dim = _elem.dim(),
1781  n1 = dim+2,
1782  n2 = fe->n_shape_functions()*n1;
1783 
1784  RealVectorX
1785  vec1_n1 = RealVectorX::Zero(n1),
1786  vec2_n1 = RealVectorX::Zero(n1),
1787  vec3_n2 = RealVectorX::Zero(n2),
1788  flux = RealVectorX::Zero(n1),
1789  eig_val = RealVectorX::Zero(n1),
1790  dnormal = RealVectorX::Zero(dim);
1791 
1792  RealMatrixX
1793  mat1_n1n1 = RealMatrixX::Zero( n1, n1),
1794  mat2_n1n2 = RealMatrixX::Zero( n1, n2),
1795  mat3_n2n2 = RealMatrixX::Zero( n2, n2),
1796  leig_vec = RealMatrixX::Zero( n1, n1),
1797  leig_vec_inv_tr = RealMatrixX::Zero( n1, n1);
1798 
1799  libMesh::Point pt;
1801 
1802  // create objects to calculate the primitive solution, flux, and Jacobian
1803  MAST::PrimitiveSolution primitive_sol;
1804 
1805 
1806  for (unsigned int qp=0; qp<JxW.size(); qp++) {
1807 
1808 
1809  // first update the variables at the current quadrature point
1810  // initialize the Bmat operator for this term
1811  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1812  Bmat.right_multiply(vec1_n1, _sol);
1813 
1814  // initialize the primitive solution
1815  primitive_sol.zero();
1816  primitive_sol.init(dim,
1817  vec1_n1,
1820  if_viscous());
1821 
1823  (primitive_sol,
1824  normals[qp],
1825  eig_val,
1826  leig_vec,
1827  leig_vec_inv_tr);
1828 
1829  // for all eigenalues that are less than 0, the characteristics are coming into the domain, hence,
1830  // evaluate them using the given solution.
1831  mat1_n1n1 = leig_vec_inv_tr;
1832  for (unsigned int j=0; j<n1; j++)
1833  if (eig_val(j) < 0)
1834  mat1_n1n1.col(j) *= eig_val(j); // L^-T [omaga]_{-}
1835  else
1836  mat1_n1n1.col(j) *= 0.0;
1837 
1838  mat1_n1n1 *= leig_vec.transpose(); // A_{-} = L^-T [omaga]_{-} L^T
1839 
1841  // sens wrt mach for a 2D case
1842  vec2_n1.setZero();
1843 // vec2_n1(1) = flight_condition->rho_u1_sens_mach();
1844 // vec2_n1(2) = flight_condition->rho_u2_sens_mach();
1845 // vec2_n1(3) = flight_condition->rho_e_sens_mach();
1846  vec2_n1(0) = flight_condition->rho_sens_rho();
1847  vec2_n1(1) = flight_condition->rho_u1_sens_rho();
1848  vec2_n1(2) = flight_condition->rho_u2_sens_rho();
1849  vec2_n1(3) = flight_condition->rho_e_sens_rho();
1851 
1852  flux = mat1_n1n1 * vec2_n1; // f_{-} = A_{-} B U
1853  Bmat.vector_mult_transpose(vec3_n2, flux); // B^T f_{-} (this is flux coming into the solution domain)
1854  f += JxW[qp] * vec3_n2;
1855  }
1856 
1857  return false;
1858 }
1859 
1860 
1861 
1862 
1863 
1864 void
1866 _calculate_surface_integrated_load(bool request_derivative,
1867  const MAST::FunctionBase* p,
1868  const unsigned int s,
1870 
1871  // prepare the side finite element
1872  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false, false));
1873 
1874  const std::vector<Real> &JxW = fe->get_JxW();
1875  const std::vector<libMesh::Point>& normals = fe->get_normals_for_reference_coordinate();
1876 
1877  const unsigned int
1878  dim = _elem.dim(),
1879  n1 = dim+2,
1880  n2 = fe->n_shape_functions()*n1;
1881 
1882  RealVectorX
1883  vec1_n1 = RealVectorX::Zero(n1),
1884  vec2_n2 = RealVectorX::Zero(n2),
1885  load = RealVectorX::Zero(3),
1886  load_sens = RealVectorX::Zero(3);
1887 
1888  RealMatrixX
1889  dload_dX = RealMatrixX::Zero( 3, n1);
1890 
1891  libMesh::Point pt;
1893 
1894  // create objects to calculate the primitive solution, flux, and Jacobian
1895  MAST::PrimitiveSolution primitive_sol;
1897 
1898  for (unsigned int qp=0; qp<JxW.size(); qp++) {
1899 
1900  // initialize the Bmat operator for this term
1901  _initialize_fem_interpolation_operator(qp, dim, *fe, Bmat);
1902  Bmat.right_multiply(vec1_n1, _sol);
1903 
1904  // initialize the primitive solution
1905  primitive_sol.zero();
1906  primitive_sol.init(dim,
1907  vec1_n1,
1910  if_viscous());
1911 
1912 
1913  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1914  load(i_dim) += JxW[qp] * primitive_sol.p * normals[qp](i_dim);
1915 
1916 
1917  // calculate the derivative, if requested
1918  if (request_derivative) {
1919 
1921  (primitive_sol, vec1_n1);
1922  Bmat.vector_mult_transpose(vec2_n2, vec1_n1);
1923 
1924  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1925  dload_dX.row(i_dim) += JxW[qp] * vec2_n2 * normals[qp](i_dim);
1926  }
1927 
1928 
1929 
1930  // calculate the sensitivity, if requested
1931  if (p) {
1932 
1933  // calculate the solution sensitivity
1934  Bmat.right_multiply(vec1_n1, _sol_sens);
1935 
1936  // initialize the perturbation in primite solution, which will
1937  // give us sensitivity of pressure
1938  primitive_sol_sens.zero();
1939  primitive_sol_sens.init(primitive_sol, vec1_n1, if_viscous());
1940 
1941  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
1942  load_sens(i_dim) += JxW[qp] *
1943  (primitive_sol_sens.dp * normals[qp](i_dim) +
1944  primitive_sol.p * 0.);
1945  }
1946  }
1947 }
1948 
1949 
1950 
1951 
1952 void
1955  const unsigned int dim,
1956  const MAST::FEBase& fe,
1957  MAST::FEMOperatorMatrix& Bmat) {
1958 
1959  const std::vector<std::vector<Real> >& phi_fe = fe.get_phi();
1960 
1961  const unsigned int n_phi = (unsigned int)phi_fe.size();
1962 
1963  RealVectorX phi = RealVectorX::Zero(n_phi);
1964 
1965  // shape function values
1966  // N
1967  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1968  phi(i_nd) = phi_fe[i_nd][qp];
1969 
1970  Bmat.reinit(dim+2, phi);
1971 }
1972 
1973 
1974 
1975 
1976 void
1979  const unsigned int dim,
1980  const MAST::FEBase& fe,
1981  std::vector<MAST::FEMOperatorMatrix>& dBmat) {
1982 
1983  libmesh_assert(dBmat.size() == dim);
1984 
1985  const std::vector<std::vector<libMesh::RealVectorValue> >& dphi = fe.get_dphi();
1986 
1987  const unsigned int n_phi = (unsigned int)dphi.size();
1988  RealVectorX phi = RealVectorX::Zero(n_phi);
1989 
1990  // now set the shape function values
1991  for (unsigned int i_dim=0; i_dim<dim; i_dim++) {
1992 
1993  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1994  phi(i_nd) = dphi[i_nd][qp](i_dim);
1995  dBmat[i_dim].reinit(dim+2, phi); // dU/dx_i
1996  }
1997 }
1998 
1999 
2000 void
2003  const unsigned int dim,
2004  const MAST::FEBase& fe,
2005  std::vector<std::vector<MAST::FEMOperatorMatrix>>& d2Bmat) {
2006 
2007  libmesh_assert(d2Bmat.size() == dim);
2008  for (unsigned int i=0; i<dim; i++)
2009  libmesh_assert(d2Bmat[i].size() == dim);
2010 
2011  const std::vector<std::vector<libMesh::RealTensorValue> >& d2phi = fe.get_d2phi();
2012 
2013  const unsigned int n_phi = (unsigned int)d2phi.size();
2014  RealVectorX phi = RealVectorX::Zero(n_phi);
2015 
2016  // now set the shape function values
2017  for (unsigned int i_dim=0; i_dim<dim; i_dim++)
2018  for (unsigned int j_dim=0; j_dim<dim; j_dim++) {
2019 
2020  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
2021  phi(i_nd) = d2phi[i_nd][qp](i_dim, j_dim);
2022  d2Bmat[i_dim][j_dim].reinit(dim+2, phi); // d2U/dx_i dx_j
2023  }
2024 }
2025 
2026 
void _initialize_fem_gradient_operator(const unsigned int qp, const unsigned int dim, const MAST::FEBase &fe, std::vector< MAST::FEMOperatorMatrix > &dBmat)
For mass = true, the FEM operator matrix is initilized to the weak form of the Laplacian ...
Class defines basic operations and calculation of the small disturbance primitive variables...
void calculate_advection_flux(const unsigned int calculate_dim, const MAST::PrimitiveSolution &sol, RealVectorX &flux)
virtual bool linearized_velocity_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac)
inertial force contribution to system residual of the linearized problem
virtual void external_side_loads_for_quadrature_elem(std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc, std::map< unsigned int, std::vector< MAST::BoundaryConditionBase *>> &loads) const
From the given list of boundary loads, this identifies the sides of the quadrature element and the lo...
Definition: geom_elem.cpp:183
bool enable_shock_capturing
flag to turn on/off artificial dissipation for shock capturing terms in fluid flow analysis...
const MAST::GeomElem & _elem
geometric element for which the computations are performed
Definition: elem_base.h:205
void calculate_advection_flux_jacobian_for_moving_solid_wall_boundary(const MAST::PrimitiveSolution &sol, const Real ui_ni, const libMesh::Point &nvec, const RealVectorX &dnvec, RealMatrixX &mat)
Real rho_u2_sens_rho() const
This class provides the necessary functions to evaluate the flux vectors and their Jacobians for both...
RealVectorX _delta_vel
local velocity
Definition: elem_base.h:272
void reinit(unsigned int n_interpolated_vars, unsigned int n_discrete_vars, unsigned int n_discrete_dofs_per_var)
this initializes the operator for number of rows and variables, assuming that all variables has the s...
virtual bool noslip_wall_surface_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
void calculate_diffusion_tensors_sensitivity(const RealVectorX &elem_sol, const RealVectorX &elem_sol_sens, const std::vector< MAST::FEMOperatorMatrix > &dB_mat, const RealMatrixX &dprim_dcons, const MAST::PrimitiveSolution &psol, const MAST::SmallPerturbationPrimitiveSolution< Real > &dsol, RealMatrixX &stress_tensor_sens, RealVectorX &temp_gradient_sens)
calculates and returns the stress tensor in stress_tensor.
Class defines the conversion and some basic operations on primitive fluid variables used in calculati...
void init(const MAST::PrimitiveSolution &sol, const typename VectorType< ValType >::return_type &delta_sol, bool if_viscous)
void calculate_conservative_variable_jacobian(const MAST::PrimitiveSolution &sol, RealMatrixX &dcons_dprim, RealMatrixX &dprim_dcons)
virtual void side_integrated_force_sensitivity(const MAST::FunctionBase &p, const unsigned int s, RealVectorX &f)
This provides the base class for definitin of element level contribution of output quantity in an ana...
RealVectorX _vel
local velocity
Definition: elem_base.h:260
virtual bool linearized_internal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
internal force contribution to system residual of the linearized problem.
void get_uvec(RealVectorX &u) const
bool side_external_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc)
sensitivity of the side external force contribution to system residual
virtual bool velocity_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac)
inertial force contribution to system residual
virtual const std::vector< std::vector< libMesh::RealTensorValue > > & get_d2phi() const
Definition: fe_base.cpp:263
void calculate_advection_flux_jacobian_sensitivity_for_conservative_variable(const unsigned int calculate_dim, const MAST::PrimitiveSolution &sol, std::vector< RealMatrixX > &mat)
libMesh::Real Real
void calculate_diffusion_flux(const unsigned int calculate_dim, const MAST::PrimitiveSolution &sol, const RealMatrixX &stress_tensor, const RealVectorX &temp_gradient, RealVectorX &flux)
virtual const std::vector< std::vector< libMesh::RealVectorValue > > & get_dphi() const
Definition: fe_base.cpp:255
virtual const std::vector< std::vector< Real > > & get_phi() const
Definition: fe_base.cpp:247
void calculate_diffusion_tensors(const RealVectorX &elem_sol, const std::vector< MAST::FEMOperatorMatrix > &dB_mat, const RealMatrixX &dprim_dcons, const MAST::PrimitiveSolution &psol, RealMatrixX &stress_tensor, RealVectorX &temp_gradient)
calculates and returns the stress tensor in stress_tensor.
void calculate_diffusion_flux_jacobian(const unsigned int flux_dim, const unsigned int deriv_dim, const MAST::PrimitiveSolution &sol, RealMatrixX &mat)
virtual void perturbation(const libMesh::Point &p, const libMesh::Point &n, const Real t, ValType &dn_rot) const =0
virtual bool slip_wall_surface_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
virtual bool slip_wall_surface_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
virtual void side_integrated_force(const unsigned int s, RealVectorX &f, RealMatrixX *dfdX=nullptr)
surface integrated force
const MAST::FlightCondition * flight_condition
This defines the surface motion for use with the nonlinear fluid solver.
virtual bool symmetry_surface_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
virtual std::unique_ptr< MAST::FEBase > init_fe(bool init_grads, bool init_second_order_derivative, int extra_quadrature_order=0) const
initializes the finite element shape function and quadrature object with the order of quadrature rule...
Definition: geom_elem.cpp:148
virtual bool linearized_slip_wall_surface_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
RealVectorX _delta_sol
local solution used for linearized analysis
Definition: elem_base.h:249
bool if_viscous() const
bool contains(const std::string &nm) const
checks if the card contains the specified property value
bool side_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc)
side external force contribution to system residual
bool linearized_side_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase *> &bc)
side external force contribution to system residual
void calculate_advection_flux_jacobian(const unsigned int calculate_dim, const MAST::PrimitiveSolution &sol, RealMatrixX &mat)
virtual bool velocity_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac)
sensitivity of the damping force contribution to system residual
Matrix< Real, Dynamic, Dynamic > RealMatrixX
void calculate_aliabadi_discontinuity_operator(const unsigned int qp, const MAST::FEBase &fe, const MAST::PrimitiveSolution &sol, const RealVectorX &elem_solution, const std::vector< MAST::FEMOperatorMatrix > &dB_mat, const RealMatrixX &Ai_Bi_advection, RealVectorX &discontinuity_val)
void _calculate_surface_integrated_load(bool request_derivative, const MAST::FunctionBase *p, const unsigned int s, MAST::OutputAssemblyElemOperations &output)
calculates the surface integrated force vector
void right_multiply(T &r, const T &m) const
[R] = [this] * [M]
void get_duvec(typename VectorType< ValType >::return_type &du) const
void vector_mult_transpose(T &res, const T &v) const
res = v^T * [this]
Matrix< Real, Dynamic, 1 > RealVectorX
void calculate_differential_operator_matrix(const unsigned int qp, const MAST::FEBase &fe, const RealVectorX &elem_solution, const MAST::PrimitiveSolution &sol, const MAST::FEMOperatorMatrix &B_mat, const std::vector< MAST::FEMOperatorMatrix > &dB_mat, const std::vector< RealMatrixX > &Ai_advection, const RealMatrixX &Ai_Bi_advection, const std::vector< std::vector< RealMatrixX > > &Ai_sens, RealMatrixX &LS_operator, RealMatrixX &LS_sens)
virtual bool noslip_wall_surface_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
RealVectorX _sol_sens
local solution sensitivity
Definition: elem_base.h:231
void right_multiply_transpose(T &r, const T &m) const
[R] = [this]^T * [M]
RealVectorX _sol
local solution
Definition: elem_base.h:225
virtual bool internal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
internal force contribution to system residual
std::unique_ptr< MAST::FieldFunction< RealVectorX > > inf_sol
void init(const unsigned int dim, const RealVectorX &conservative_sol, const Real cp_val, const Real cv_val, bool if_viscous)
void calculate_pressure_derivative_wrt_conservative_variables(const MAST::PrimitiveSolution &sol, RealVectorX &dpdX)
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
unsigned int dim() const
Definition: geom_elem.cpp:91
void _initialize_fem_interpolation_operator(const unsigned int qp, const unsigned int dim, const MAST::FEBase &fe, MAST::FEMOperatorMatrix &Bmat)
virtual bool internal_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
sensitivity of the internal force contribution to system residual
GasProperty gas_property
Ambient air properties.
const ValType & get(const std::string &nm) const
returns a constant reference to the specified function
virtual std::unique_ptr< MAST::FEBase > init_side_fe(unsigned int s, bool init_grads, bool init_second_order_derivative, int extra_quadrature_order=0) const
initializes the finite element shape function and quadrature object for the side with the order of qu...
Definition: geom_elem.cpp:165
virtual bool far_field_surface_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
void _initialize_fem_second_derivative_operator(const unsigned int qp, const unsigned int dim, const MAST::FEBase &fe, std::vector< std::vector< MAST::FEMOperatorMatrix >> &d2Bmat)
d2Bmat[i][j] is the derivative d2B/dxi dxj
void left_multiply(T &r, const T &m) const
[R] = [M] * [this]
void calculate_diffusion_flux_jacobian_primitive_vars(const unsigned int flux_dim, const unsigned int deriv_dim, const RealVectorX &uvec, const bool zero_kth, const MAST::PrimitiveSolution &sol, RealMatrixX &mat)
Real rho_u1_sens_rho() const
virtual void perturbation(ValType &v) const
calculates the perturbation and returns it in v.
void get_infinity_vars(RealVectorX &vars_inf) const
virtual bool symmetry_surface_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
const Real & _time
time for which system is being assembled
Definition: elem_base.h:219
void calculate_advection_left_eigenvector_and_inverse_for_normal(const MAST::PrimitiveSolution &sol, const libMesh::Point &normal, RealVectorX &eig_vals, RealMatrixX &l_eig_mat, RealMatrixX &l_eig_mat_inv_tr)
ConservativeFluidElementBase(MAST::SystemInitialization &sys, const MAST::GeomElem &elem, const MAST::FlightCondition &f)
virtual bool far_field_surface_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int s, MAST::BoundaryConditionBase &bc)
This is the base class for elements that implement calculation of finite element quantities over the ...
Definition: elem_base.h:72