MAST
structural_element_base.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
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
28 #include "base/nonlinear_system.h"
29 #include "base/assembly_base.h"
32 #include "mesh/geom_elem.h"
33 #include "mesh/fe_base.h"
35 #include "numerics/utility.h"
36 
37 
39  MAST::AssemblyBase& assembly,
40  const MAST::GeomElem& elem,
42 MAST::ElementBase(sys, assembly, elem),
43 follower_forces (false),
44 _property (p),
45 _incompatible_sol (nullptr) {
46 
47 }
48 
49 
50 
52 
53 }
54 
55 
56 
57 void
59  bool if_sens) {
60 
61  // convert the vector to the local element coordinate system
62  if (!if_sens) {
63  if (_elem.dim() == 3)
64  _local_sol = vec;
65  else {
66  _local_sol = RealVectorX::Zero(vec.size());
68  }
69  }
70  else {
71 
72  // set the element solution sensitivity.
73  if (_elem.dim() == 3)
74  _local_sol_sens = vec;
75  else {
76  _local_sol_sens = RealVectorX::Zero(vec.size());
78  }
79  }
80 
81  MAST::ElementBase::set_solution(vec, if_sens);
82 }
83 
84 
85 
86 void
88  bool if_sens) {
89 
90  // convert the vector to the local element coordinate system
91  if (!if_sens) {
92  if (_elem.dim() == 3)
93  _local_delta_sol = vec;
94  else {
95  _local_delta_sol = RealVectorX::Zero(vec.size());
97  }
98  }
99  else {
100 
101  // set the element solution sensitivity.
102  if (_elem.dim() == 3)
103  _local_delta_sol_sens = vec;
104  else {
105  _local_delta_sol_sens = RealVectorX::Zero(vec.size());
107  }
108  }
109 
111 }
112 
113 
114 
115 
116 void
118  bool if_sens) {
119 
120  if (!if_sens) {
121  if (_elem.dim() == 3)
122  _local_vel = vec;
123  else {
124  _local_vel = RealVectorX::Zero(vec.size());
126  }
127  }
128  else {
129 
130  if (_elem.dim() == 3)
131  _local_vel_sens = vec;
132  else {
133  _local_vel_sens = RealVectorX::Zero(vec.size());
135  }
136  }
137 
138  MAST::ElementBase::set_velocity(vec, if_sens);
139 }
140 
141 
142 
143 void
145  bool if_sens) {
146 
147  if (!if_sens) {
148  if (_elem.dim() == 3)
149  _local_delta_vel = vec;
150  else {
151  _local_delta_vel = RealVectorX::Zero(vec.size());
153  }
154  }
155  else {
156 
157  if (_elem.dim() == 3)
158  _local_delta_vel_sens = vec;
159  else {
160  _local_delta_vel_sens = RealVectorX::Zero(vec.size());
162  }
163  }
164 
166 }
167 
168 
169 
170 void
172  bool if_sens) {
173 
174  if (!if_sens) {
175  if (_elem.dim() == 3)
176  _local_accel = vec;
177  else {
178  _local_accel = RealVectorX::Zero(vec.size());
180  }
181  }
182  else {
183 
184  if (_elem.dim() == 3)
185  _local_accel_sens = vec;
186  else {
187  _local_accel_sens = RealVectorX::Zero(vec.size());
189  }
190  }
191 
193 }
194 
195 
196 
197 void
199  bool if_sens) {
200 
201  if (!if_sens) {
202  if (_elem.dim() == 3)
203  _local_delta_accel = vec;
204  else {
205  _local_delta_accel = RealVectorX::Zero(vec.size());
207  }
208  }
209  else {
210 
211  if (_elem.dim() == 3)
213  else {
214  _local_delta_accel_sens = RealVectorX::Zero(vec.size());
216  }
217  }
218 
220 }
221 
222 
223 
224 bool
226  RealVectorX& f,
227  RealMatrixX& jac) {
228 
229 
230  // It is assumed that the structural elements implement the Jacobians.
231  // Hence, the residual for the linearized problem will be calculated
232  // using the Jacobian.
233 
234  const unsigned int
235  n_phi = (unsigned int)f.size(),
236  n2 =6*n_phi;
237 
239  v = RealVectorX::Zero(n2);
240 
242  m = RealMatrixX::Zero(n2, n2);
243 
244 
245  this->internal_residual(true, v, m);
246 
247  f += m * _local_delta_sol;
248 
249  if (request_jacobian)
250  jac += m;
251 
252  return request_jacobian;
253 }
254 
255 
256 
257 bool
259  RealVectorX& f,
260  RealMatrixX& jac_xddot,
261  RealMatrixX& jac_xdot,
262  RealMatrixX& jac) {
263 
264  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
265 
266  const std::vector<Real>& JxW = fe->get_JxW();
267  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
268  const std::vector<std::vector<Real> >& phi = fe->get_phi();
269 
270  const unsigned int
271  n_phi = (unsigned int)phi.size(),
272  n_vars = _system.system().n_vars(),
273  n1 =6,
274  n2 =6*n_phi;
275 
277  material_mat,
278  mat1_n1n2 = RealMatrixX::Zero(n1, n2),
279  mat2_n2n2 = RealMatrixX::Zero(n2, n2),
280  local_jac = RealMatrixX::Zero(n2, n2);
282  phi_vec = RealVectorX::Zero(n_phi),
283  vec1_n1 = RealVectorX::Zero(n1),
284  vec2_n2 = RealVectorX::Zero(n2),
285  local_f = RealVectorX::Zero(n2);
286 
287  std::unique_ptr<MAST::FieldFunction<RealMatrixX> >
288  mat_inertia = _property.inertia_matrix(*this);
289 
291 
293 
294  (*mat_inertia)(xyz[0], _time, material_mat);
295 
296  Real vol = 0.;
297  const unsigned int nshp = fe->n_shape_functions();
298  for (unsigned int i=0; i<JxW.size(); i++)
299  vol += JxW[i];
300  vol /= (1.* nshp);
301  for (unsigned int i_var=0; i_var<6; i_var++)
302  for (unsigned int i=0; i<nshp; i++)
303  local_jac(i_var*nshp+i, i_var*nshp+i) =
304  vol*material_mat(i_var, i_var);
305 
306  local_f = local_jac * _local_accel;
307  }
308  else {
309 
310  for (unsigned int qp=0; qp<JxW.size(); qp++) {
311 
312  (*mat_inertia)(xyz[qp], _time, material_mat);
313 
314  // now set the shape function values
315  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
316  phi_vec(i_nd) = phi[i_nd][qp];
317 
318  Bmat.reinit(n_vars, phi_vec);
319 
320  Bmat.left_multiply(mat1_n1n2, material_mat);
321 
322  vec1_n1 = mat1_n1n2 * _local_accel;
323  Bmat.vector_mult_transpose(vec2_n2, vec1_n1);
324 
325  local_f += JxW[qp] * vec2_n2;
326 
327  if (request_jacobian) {
328 
329  Bmat.right_multiply_transpose(mat2_n2n2,
330  mat1_n1n2);
331  local_jac += JxW[qp]*mat2_n2n2;
332  }
333  }
334  }
335 
336  // now transform to the global coorodinate system
337  if (_elem.dim() < 3) {
338  transform_vector_to_global_system(local_f, vec2_n2);
339  f += vec2_n2;
340 
341  if (request_jacobian) {
342  transform_matrix_to_global_system(local_jac, mat2_n2n2);
343  jac_xddot += mat2_n2n2;
344  }
345  }
346  else {
347 
348  f += local_f;
349  if (request_jacobian)
350  jac_xddot += local_jac;
351  }
352 
353  return request_jacobian;
354 }
355 
356 
357 
358 
359 bool
361 linearized_inertial_residual (bool request_jacobian,
362  RealVectorX& f,
363  RealMatrixX& jac_xddot,
364  RealMatrixX& jac_xdot,
365  RealMatrixX& jac) {
366 
367  // It is assumed that the structural elements implement the Jacobians.
368  // Hence, the residual for the linearized problem will be calculated
369  // using the Jacobian.
370 
371  const unsigned int
372  n_phi = (unsigned int)f.size(),
373  n2 =6*n_phi;
374 
376  v = RealVectorX::Zero(n2);
377 
379  m_xddot = RealMatrixX::Zero(n2, n2),
380  m_xdot = RealMatrixX::Zero(n2, n2),
381  m_x = RealMatrixX::Zero(n2, n2);
382 
383 
384  this->inertial_residual(true, v, m_xddot, m_xdot, m_x);
385 
386  f += (m_xddot * _local_delta_accel +
387  m_xdot * _local_delta_vel +
388  m_x * _local_delta_sol);
389 
390  if (request_jacobian) {
391 
392  jac_xddot += m_xddot;
393  jac_xdot += m_xdot;
394  jac += m_x;
395  }
396 
397  return request_jacobian;
398 }
399 
400 
401 
402 
403 bool
405  bool request_jacobian,
406  RealVectorX& f,
407  RealMatrixX& jac_xddot,
408  RealMatrixX& jac_xdot,
409  RealMatrixX& jac) {
410 
411  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
412 
413  const std::vector<Real>& JxW = fe->get_JxW();
414  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
415  const std::vector<std::vector<Real> >& phi = fe->get_phi();
416 
417  const unsigned int
418  n_phi = (unsigned int)phi.size(),
419  n_vars = _system.system().n_vars(),
420  n1 =6,
421  n2 =6*n_phi;
422 
424  material_mat,
425  mat1_n1n2 = RealMatrixX::Zero(n1, n2),
426  mat2_n2n2 = RealMatrixX::Zero(n2, n2),
427  local_jac = RealMatrixX::Zero(n2, n2);
429  phi_vec = RealVectorX::Zero(n_phi),
430  vec1_n1 = RealVectorX::Zero(n1),
431  vec2_n2 = RealVectorX::Zero(n2),
432  local_f = RealVectorX::Zero(n2);
433 
434  std::unique_ptr<MAST::FieldFunction<RealMatrixX> >
435  mat_inertia = _property.inertia_matrix(*this);
436 
438 
440 
441  // as an approximation, get matrix at the first quadrature point
442  mat_inertia->derivative(p, xyz[0], _time, material_mat);
443 
444  Real vol = 0.;
445  const unsigned int nshp = fe->n_shape_functions();
446  for (unsigned int i=0; i<JxW.size(); i++)
447  vol += JxW[i];
448  vol /= (1.* nshp);
449  for (unsigned int i_var=0; i_var<6; i_var++)
450  for (unsigned int i=0; i<nshp; i++)
451  local_jac(i_var*nshp+i, i_var*nshp+i) =
452  vol*material_mat(i_var, i_var);
453 
454  local_f = local_jac * _local_accel;
455  }
456  else {
457 
458  for (unsigned int qp=0; qp<JxW.size(); qp++) {
459 
460  mat_inertia->derivative(p, xyz[qp], _time, material_mat);
461 
462  // now set the shape function values
463  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
464  phi_vec(i_nd) = phi[i_nd][qp];
465 
466  Bmat.reinit(n_vars, phi_vec);
467 
468  Bmat.left_multiply(mat1_n1n2, material_mat);
469 
470  vec1_n1 = mat1_n1n2 * _local_accel;
471  Bmat.vector_mult_transpose(vec2_n2, vec1_n1);
472 
473  local_f += JxW[qp] * vec2_n2;
474 
475  if (request_jacobian) {
476 
477  Bmat.right_multiply_transpose(mat2_n2n2,
478  mat1_n1n2);
479  local_jac += JxW[qp]*mat2_n2n2;
480  }
481  }
482  }
483 
484  // now transform to the global coorodinate system
485  if (_elem.dim() < 3) {
486  transform_vector_to_global_system(local_f, vec2_n2);
487  f += vec2_n2;
488 
489  if (request_jacobian) {
490  transform_matrix_to_global_system(local_jac, mat2_n2n2);
491  jac_xddot += mat2_n2n2;
492  }
493  }
494  else {
495 
496  f += local_f;
497  if (request_jacobian)
498  jac_xddot += local_jac;
499  }
500 
501  return request_jacobian;
502 }
503 
504 
505 
506 
507 void
510  const unsigned int s,
512  bool request_jacobian,
513  RealVectorX& f,
514  RealMatrixX& jac_xddot,
515  RealMatrixX& jac_xdot,
516  RealMatrixX& jac) {
517 
518  // prepare the side finite element
519  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false));
520 
521  std::vector<Real> JxW_Vn = fe->get_JxW();
522  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
523  const std::vector<std::vector<Real> >& phi = fe->get_phi();
524  const std::vector<libMesh::Point>& face_normals = fe->get_normals_for_local_coordinate();
525 
526  const unsigned int
527  n_phi = (unsigned int)phi.size(),
528  n_vars = _system.system().n_vars(),
529  n1 =6,
530  n2 =6*n_phi,
531  dim =_elem.dim();
532 
534  material_mat,
535  mat1_n1n2 = RealMatrixX::Zero(n1, n2),
536  mat2_n2n2 = RealMatrixX::Zero(n2, n2),
537  local_jac = RealMatrixX::Zero(n2, n2);
539  phi_vec = RealVectorX::Zero(n_phi),
540  vec1_n1 = RealVectorX::Zero(n1),
541  vec2_n2 = RealVectorX::Zero(n2),
542  local_f = RealVectorX::Zero(n2),
543  vel = RealVectorX::Zero(dim);
544 
545  Real
546  vn = 0.;
547 
548  // modify the JxW_Vn by multiplying the normal velocity to it
549  for (unsigned int qp=0; qp<JxW_Vn.size(); qp++) {
550 
551  vel_f(xyz[qp], _time, vel);
552  vn = 0.;
553  for (unsigned int i=0; i<dim; i++)
554  vn += vel(i)*face_normals[qp](i);
555  JxW_Vn[qp] *= vn;
556  }
557 
558 
559  std::unique_ptr<MAST::FieldFunction<RealMatrixX> >
560  mat_inertia = _property.inertia_matrix(*this);
561 
563 
565 
566  (*mat_inertia)(xyz[0], _time, material_mat);
567 
568  Real vol = 0.;
569  const unsigned int nshp = fe->n_shape_functions();
570  for (unsigned int i=0; i<JxW_Vn.size(); i++)
571  vol += JxW_Vn[i];
572  vol /= (1.* nshp);
573  for (unsigned int i_var=0; i_var<6; i_var++)
574  for (unsigned int i=0; i<nshp; i++)
575  local_jac(i_var*nshp+i, i_var*nshp+i) =
576  vol*material_mat(i_var, i_var);
577 
578  local_f = local_jac * _local_accel;
579  }
580  else {
581 
582  for (unsigned int qp=0; qp<JxW_Vn.size(); qp++) {
583 
584  (*mat_inertia)(xyz[qp], _time, material_mat);
585 
586  // now set the shape function values
587  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
588  phi_vec(i_nd) = phi[i_nd][qp];
589 
590  Bmat.reinit(n_vars, phi_vec);
591 
592  Bmat.left_multiply(mat1_n1n2, material_mat);
593 
594  vec1_n1 = mat1_n1n2 * _local_accel;
595  Bmat.vector_mult_transpose(vec2_n2, vec1_n1);
596 
597  local_f += JxW_Vn[qp] * vec2_n2;
598 
599  if (request_jacobian) {
600 
601  Bmat.right_multiply_transpose(mat2_n2n2,
602  mat1_n1n2);
603  local_jac += JxW_Vn[qp]*mat2_n2n2;
604  }
605  }
606  }
607 
608  // now transform to the global coorodinate system
609  if (_elem.dim() < 3) {
610  transform_vector_to_global_system(local_f, vec2_n2);
611  f += vec2_n2;
612 
613  if (request_jacobian) {
614  transform_matrix_to_global_system(local_jac, mat2_n2n2);
615  jac_xddot += mat2_n2n2;
616  }
617  }
618  else {
619 
620  f += local_f;
621  if (request_jacobian)
622  jac_xddot += local_jac;
623  }
624 }
625 
626 
627 
628 
629 bool
631 side_external_residual(bool request_jacobian,
632  RealVectorX& f,
633  RealMatrixX& jac_xdot,
634  RealMatrixX& jac,
635  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
636 
637  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
639 
640  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
641  it = loads.begin(),
642  end = loads.end();
643 
644  for ( ; it != end; it++) {
645 
646  std::vector<MAST::BoundaryConditionBase*>::const_iterator
647  bc_it = it->second.begin(),
648  bc_end = it->second.end();
649 
650  for ( ; bc_it != bc_end; bc_it++) {
651 
652  // apply all the types of loading
653  switch ((*bc_it)->type()) {
654 
656  surface_pressure_residual(request_jacobian,
657  f, jac,
658  it->first,
659  **bc_it);
660  break;
661 
662 
663  case MAST::PISTON_THEORY:
664  piston_theory_residual(request_jacobian,
665  f,
666  jac_xdot,
667  jac,
668  it->first,
669  **bc_it);
670  break;
671 
672 
673  case MAST::DIRICHLET:
674  // nothing to be done here
675  break;
676 
677  default:
678  // not implemented yet
679  libmesh_error();
680  break;
681  }
682  }
683  }
684  return request_jacobian;
685 }
686 
687 bool
690 (bool request_jacobian,
691  RealVectorX& f,
692  RealMatrixX& jac_xdot,
693  RealMatrixX& jac,
694  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
695 
696  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
698 
699  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
700  it = loads.begin(),
701  end = loads.end();
702 
703  for ( ; it != end; it++) {
704 
705  std::vector<MAST::BoundaryConditionBase*>::const_iterator
706  bc_it = it->second.begin(),
707  bc_end = it->second.end();
708 
709  for ( ; bc_it != bc_end; bc_it++) {
710 
711  // apply all the types of loading
712  switch ((*bc_it)->type()) {
713 
714  case MAST::DIRICHLET:
715  // nothing to be done here
716  break;
717 
719  case MAST::PISTON_THEORY:
720  default:
721  // not implemented yet
722  libmesh_error();
723  break;
724  }
725  }
726  }
727  return request_jacobian;
728 }
729 
730 
731 
732 bool
735 (bool request_jacobian,
736  ComplexVectorX& f,
737  ComplexMatrixX& jac,
738  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
739 
740  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
742 
743  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
744  it = loads.begin(),
745  end = loads.end();
746 
747  for ( ; it != end; it++) {
748 
749  std::vector<MAST::BoundaryConditionBase*>::const_iterator
750  bc_it = it->second.begin(),
751  bc_end = it->second.end();
752 
753  for ( ; bc_it != bc_end; bc_it++) {
754 
755  // apply all the types of loading
756  switch ((*bc_it)->type()) {
757 
759 
761  (request_jacobian,
762  f, jac,
763  it->first,
764  **bc_it);
765  break;
766 
767 
768  case MAST::DIRICHLET:
769  // nothing to be done here
770  break;
771 
772  default:
773  // not implemented yet
774  libmesh_error();
775  break;
776  }
777  }
778  }
779  return request_jacobian;
780 }
781 
782 
783 
784 
785 bool
787 volume_external_residual (bool request_jacobian,
788  RealVectorX& f,
789  RealMatrixX& jac_xdot,
790  RealMatrixX& jac,
791  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>& bc) {
792 
793  // iterate over the boundary ids given in the provided force map
794  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
795  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
796 
797  // for each boundary id, check if any of the sides on the element
798  // has the associated boundary
799 
800  libMesh::subdomain_id_type sid = _elem.get_reference_elem().subdomain_id();
801  // find the loads on this boundary and evaluate the f and jac
802  it =bc.equal_range(sid);
803 
804  for ( ; it.first != it.second; it.first++) {
805  // apply all the types of loading
806  switch (it.first->second->type()) {
807 
809  surface_pressure_residual(request_jacobian,
810  f, jac,
811  *it.first->second);
812  break;
813 
814  case MAST::PISTON_THEORY:
815  piston_theory_residual(request_jacobian,
816  f,
817  jac_xdot,
818  jac,
819  *it.first->second);
820  break;
821 
822  case MAST::TEMPERATURE:
823  thermal_residual(request_jacobian,
824  f, jac,
825  *it.first->second);
826  break;
827 
828 
829  default:
830  // not implemented yet
831  libmesh_error();
832  break;
833  }
834  }
835 
836  return request_jacobian;
837 }
838 
839 
840 
841 
842 bool
844 linearized_volume_external_residual (bool request_jacobian,
845  RealVectorX& f,
846  RealMatrixX& jac_xdot,
847  RealMatrixX& jac,
848  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>& bc) {
849 
850  // iterate over the boundary ids given in the provided force map
851  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
852  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
853 
854  // for each boundary id, check if any of the sides on the element
855  // has the associated boundary
856 
857  libMesh::subdomain_id_type sid = _elem.get_reference_elem().subdomain_id();
858  // find the loads on this boundary and evaluate the f and jac
859  it =bc.equal_range(sid);
860 
861  for ( ; it.first != it.second; it.first++) {
862  // apply all the types of loading
863  switch (it.first->second->type()) {
864 
866  linearized_surface_pressure_residual(request_jacobian,
867  f, jac,
868  *it.first->second);
869  break;
870 
871  case MAST::TEMPERATURE: {
872 
873  const unsigned int
874  n = (unsigned int) f.size();
875 
877  local_f = RealVectorX::Zero(n);
879  mat = RealMatrixX::Zero(n, n);
880 
881  // this accounts for the perturbation of displacement.
882  // Perturbation in temperature is not currently handled
883  thermal_residual(true, local_f, mat, *it.first->second);
884  f += mat*_delta_sol;
885  }
886  break;
887 
888  case MAST::PISTON_THEORY:
889  default:
890  // not implemented yet
891  libmesh_error();
892  break;
893  }
894  }
895 
896  return request_jacobian;
897 }
898 
899 
900 
901 
902 bool
905 (bool request_jacobian,
906  ComplexVectorX& f,
907  ComplexMatrixX& jac,
908  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>& bc) {
909 
910  // iterate over the boundary ids given in the provided force map
911  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
912  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
913 
914  // for each boundary id, check if any of the sides on the element
915  // has the associated boundary
916 
917  libMesh::subdomain_id_type sid = _elem.get_reference_elem().subdomain_id();
918  // find the loads on this boundary and evaluate the f and jac
919  it =bc.equal_range(sid);
920 
921  for ( ; it.first != it.second; it.first++) {
922  // apply all the types of loading
923  switch (it.first->second->type()) {
924 
926 
928  (request_jacobian,
929  f, jac,
930  *it.first->second);
931  break;
932 
933  case MAST::TEMPERATURE:
934 
935  case MAST::PISTON_THEORY:
936  default:
937  // not implemented yet
938  libmesh_error();
939  break;
940  }
941  }
942 
943  return request_jacobian;
944 }
945 
946 
947 
948 
949 
950 
951 
952 bool
955  bool request_jacobian,
956  RealVectorX& f,
957  RealMatrixX& jac_xdot,
958  RealMatrixX& jac,
959  std::multimap<libMesh::boundary_id_type, MAST::BoundaryConditionBase*>& bc) {
960 
961  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>> loads;
963 
964  std::map<unsigned int, std::vector<MAST::BoundaryConditionBase*>>::const_iterator
965  it = loads.begin(),
966  end = loads.end();
967 
968  for ( ; it != end; it++) {
969 
970  std::vector<MAST::BoundaryConditionBase*>::const_iterator
971  bc_it = it->second.begin(),
972  bc_end = it->second.end();
973 
974  for ( ; bc_it != bc_end; bc_it++) {
975 
976  // apply all the types of loading
977  switch ((*bc_it)->type()) {
978 
981  request_jacobian,
982  f, jac,
983  it->first,
984  **bc_it);
985  break;
986 
987 
988  case MAST::PISTON_THEORY:
990  request_jacobian,
991  f,
992  jac_xdot,
993  jac,
994  it->first,
995  **bc_it);
996  break;
997 
998 
999  case MAST::DIRICHLET:
1000  // nothing to be done here
1001  break;
1002 
1003  default:
1004  // not implemented yet
1005  libmesh_error();
1006  break;
1007  }
1008  }
1009  }
1010  return request_jacobian;
1011 }
1012 
1013 
1014 
1015 bool
1018  bool request_jacobian,
1019  RealVectorX& f,
1020  RealMatrixX& jac_xdot,
1021  RealMatrixX& jac,
1022  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>& bc) {
1023 
1024  // iterate over the boundary ids given in the provided force map
1025  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
1026  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
1027 
1028  // for each boundary id, check if any of the sides on the element
1029  // has the associated boundary
1030 
1031  libMesh::subdomain_id_type sid = _elem.get_reference_elem().subdomain_id();
1032  // find the loads on this boundary and evaluate the f and jac
1033  it =bc.equal_range(sid);
1034 
1035  for ( ; it.first != it.second; it.first++) {
1036  // apply all the types of loading
1037  switch (it.first->second->type()) {
1038 
1041  request_jacobian,
1042  f, jac,
1043  *it.first->second);
1044  break;
1045 
1046  case MAST::PISTON_THEORY:
1048  request_jacobian,
1049  f,
1050  jac_xdot,
1051  jac,
1052  *it.first->second);
1053  break;
1054 
1055  case MAST::TEMPERATURE:
1057  request_jacobian,
1058  f, jac,
1059  *it.first->second);
1060  break;
1061 
1062  default:
1063  // not implemented yet
1064  libmesh_error();
1065  break;
1066  }
1067  }
1068 
1069  return request_jacobian;
1070 }
1071 
1072 
1073 
1074 void
1077  const unsigned int s,
1078  const MAST::FieldFunction<RealVectorX>& vel_f,
1079  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>& bc,
1080  bool request_jacobian,
1081  RealVectorX& f,
1082  RealMatrixX& jac) {
1083 
1084  // iterate over the boundary ids given in the provided force map
1085  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
1086  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
1087 
1088  // for each boundary id, check if any of the sides on the element
1089  // has the associated boundary
1090 
1091  libMesh::subdomain_id_type sid = _elem.get_reference_elem().subdomain_id();
1092  // find the loads on this boundary and evaluate the f and jac
1093  it =bc.equal_range(sid);
1094 
1095  for ( ; it.first != it.second; it.first++) {
1096  // apply all the types of loading
1097  switch (it.first->second->type()) {
1098 
1101  s,
1102  vel_f,
1103  *it.first->second,
1104  request_jacobian,
1105  f,
1106  jac);
1107  break;
1108 
1109  case MAST::TEMPERATURE:
1111  s,
1112  vel_f,
1113  *it.first->second,
1114  request_jacobian,
1115  f,
1116  jac);
1117  break;
1118 
1119  case MAST::PISTON_THEORY:
1120  default:
1121  // not implemented yet
1122  libmesh_error();
1123  break;
1124  }
1125  }
1126 }
1127 
1128 
1129 
1130 bool
1132 surface_pressure_residual(bool request_jacobian,
1133  RealVectorX &f,
1134  RealMatrixX &jac,
1136 
1137  libmesh_assert(_elem.dim() < 3); // only applicable for lower dimensional elements
1138  libmesh_assert(!follower_forces); // not implemented yet for follower forces
1139 
1140  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
1141 
1142  const std::vector<Real> &JxW = fe->get_JxW();
1143  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1144  const std::vector<std::vector<Real> >& phi = fe->get_phi();
1145  const unsigned int
1146  n_phi = (unsigned int)phi.size(),
1147  n1 =3,
1148  n2 =6*n_phi;
1149 
1150 
1151  // normal for face integration
1152  libMesh::Point normal;
1153  // direction of pressure assumed to be normal (along local z-axis)
1154  // to the element face for 2D and along local y-axis for 1D element.
1155  normal(_elem.dim()) = -1.;
1156 
1157 
1158  // get the function from this boundary condition
1160  bc.get<MAST::FieldFunction<Real> >("pressure");
1161 
1162  Real press;
1163  FEMOperatorMatrix Bmat;
1164 
1165  RealVectorX
1166  phi_vec = RealVectorX::Zero(n_phi),
1167  force = RealVectorX::Zero(2*n1),
1168  local_f = RealVectorX::Zero(n2),
1169  vec_n2 = RealVectorX::Zero(n2);
1170 
1171 
1172  for (unsigned int qp=0; qp<qpoint.size(); qp++) {
1173 
1174  // now set the shape function values
1175  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1176  phi_vec(i_nd) = phi[i_nd][qp];
1177 
1178  Bmat.reinit(2*n1, phi_vec);
1179 
1180  // get pressure value
1181  func(qpoint[qp], _time, press);
1182 
1183  // calculate force
1184  for (unsigned int i_dim=0; i_dim<n1; i_dim++)
1185  force(i_dim) = press * normal(i_dim);
1186 
1187  Bmat.vector_mult_transpose(vec_n2, force);
1188 
1189  local_f += JxW[qp] * vec_n2;
1190  }
1191 
1192  // now transform to the global system and add
1193  transform_vector_to_global_system(local_f, vec_n2);
1194  f -= vec_n2;
1195 
1196 
1197  return (request_jacobian);
1198 }
1199 
1200 
1201 
1202 
1203 
1204 
1205 bool
1208  bool request_jacobian,
1209  RealVectorX &f,
1210  RealMatrixX &jac,
1212 
1213  libmesh_assert(_elem.dim() < 3); // only applicable for lower dimensional elements
1214  libmesh_assert(!follower_forces); // not implemented yet for follower forces
1215 
1216  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
1217 
1218  const std::vector<Real> &JxW = fe->get_JxW();
1219  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1220  const std::vector<std::vector<Real> >& phi = fe->get_phi();
1221  const unsigned int
1222  n_phi = (unsigned int)phi.size(),
1223  n1 =3,
1224  n2 =6*n_phi;
1225 
1226 
1227  // normal for face integration
1228  libMesh::Point normal;
1229  // direction of pressure assumed to be normal (along local z-axis)
1230  // to the element face for 2D and along local y-axis for 1D element.
1231  normal(_elem.dim()) = -1.;
1232 
1233 
1234  // get the function from this boundary condition
1236  bc.get<MAST::FieldFunction<Real> >("pressure");
1237 
1238  Real press;
1239  FEMOperatorMatrix Bmat;
1240 
1241  RealVectorX
1242  phi_vec = RealVectorX::Zero(n_phi),
1243  force = RealVectorX::Zero(2*n1),
1244  local_f = RealVectorX::Zero(n2),
1245  vec_n2 = RealVectorX::Zero(n2);
1246 
1247 
1248  for (unsigned int qp=0; qp<qpoint.size(); qp++) {
1249 
1250  // now set the shape function values
1251  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1252  phi_vec(i_nd) = phi[i_nd][qp];
1253 
1254  Bmat.reinit(2*n1, phi_vec);
1255 
1256  // get pressure value
1257  func.derivative(p, qpoint[qp], _time, press);
1258 
1259  // calculate force
1260  for (unsigned int i_dim=0; i_dim<n1; i_dim++)
1261  force(i_dim) = press * normal(i_dim);
1262 
1263  Bmat.vector_mult_transpose(vec_n2, force);
1264 
1265  local_f += JxW[qp] * vec_n2;
1266  }
1267 
1268  // now transform to the global system and add
1269  transform_vector_to_global_system(local_f, vec_n2);
1270  f -= vec_n2;
1271 
1272 
1273  return (request_jacobian);
1274 }
1275 
1276 
1277 
1278 
1279 void
1282  const unsigned int s,
1283  const MAST::FieldFunction<RealVectorX>& vel_f,
1285  bool request_jacobian,
1286  RealVectorX& f,
1287  RealMatrixX& jac) {
1288 
1289  libmesh_assert(_elem.dim() < 3); // only applicable for lower dimensional elements
1290  libmesh_assert(!follower_forces); // not implemented yet for follower forces
1291 
1292  // prepare the side finite element
1293  std::unique_ptr<MAST::FEBase> fe(_elem.init_side_fe(s, false));
1294 
1295  std::vector<Real> JxW_Vn = fe->get_JxW();
1296  const std::vector<libMesh::Point>& xyz = fe->get_xyz();
1297  const std::vector<libMesh::Point>& face_normals = fe->get_normals_for_local_coordinate();
1298  const std::vector<std::vector<Real> >& phi = fe->get_phi();
1299 
1300  const unsigned int
1301  n_phi = (unsigned int)phi.size(),
1302  n1 = 3,
1303  n2 = 6*n_phi,
1304  dim = _elem.dim();
1305 
1306 
1307  // normal for face integration
1308  libMesh::Point normal;
1309  // direction of pressure assumed to be normal (along local z-axis)
1310  // to the element face for 2D and along local y-axis for 1D element.
1311  normal(_elem.dim()) = -1.;
1312 
1313 
1314  // get the function from this boundary condition
1316  bc.get<MAST::FieldFunction<Real> >("pressure");
1317 
1318  Real press;
1319  FEMOperatorMatrix Bmat;
1320 
1321  RealVectorX
1322  phi_vec = RealVectorX::Zero(n_phi),
1323  force = RealVectorX::Zero(2*n1),
1324  local_f = RealVectorX::Zero(n2),
1325  vec_n2 = RealVectorX::Zero(n2),
1326  vel = RealVectorX::Zero(dim);
1327 
1328  Real
1329  vn = 0.;
1330 
1331 
1332  // modify the JxW_Vn by multiplying the normal velocity to it
1333  for (unsigned int qp=0; qp<JxW_Vn.size(); qp++) {
1334 
1335  vel_f(xyz[qp], _time, vel);
1336  vn = 0.;
1337  for (unsigned int i=0; i<dim; i++)
1338  vn += vel(i)*face_normals[qp](i);
1339  JxW_Vn[qp] *= vn;
1340  }
1341 
1342 
1343  for (unsigned int qp=0; qp<xyz.size(); qp++) {
1344 
1345  // now set the shape function values
1346  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1347  phi_vec(i_nd) = phi[i_nd][qp];
1348 
1349  Bmat.reinit(2*n1, phi_vec);
1350 
1351  // get pressure value
1352  func(xyz[qp], _time, press);
1353 
1354  // calculate force
1355  for (unsigned int i_dim=0; i_dim<n1; i_dim++)
1356  force(i_dim) = press * normal(i_dim);
1357 
1358  Bmat.vector_mult_transpose(vec_n2, force);
1359 
1360  local_f += JxW_Vn[qp] * vec_n2;
1361  }
1362 
1363  // now transform to the global system and add
1364  transform_vector_to_global_system(local_f, vec_n2);
1365  f -= vec_n2;
1366 }
1367 
1368 
1369 
1370 
1371 
1372 bool
1375  RealVectorX &f,
1376  RealMatrixX &jac,
1378 
1379  libmesh_assert(_elem.dim() < 3); // only applicable for lower dimensional elements.
1380  libmesh_assert(!follower_forces); // not implemented yet for follower forces
1381  libmesh_assert_equal_to(bc.type(), MAST::SURFACE_PRESSURE);
1382 
1384  press_fn = bc.get<MAST::FieldFunction<Real> >("pressure");
1385 
1386  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
1387 
1388  const std::vector<Real> &JxW = fe->get_JxW();
1389  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1390  const std::vector<std::vector<Real> >& phi = fe->get_phi();
1391  const unsigned int
1392  n_phi = (unsigned int)phi.size(),
1393  n1 = 3,
1394  n2 = 6*n_phi;
1395 
1396  // normal for face integration
1397  libMesh::Point normal;
1398  // direction of pressure assumed to be normal (along local z-axis)
1399  // to the element face for 2D and along local y-axis for 1D element.
1400  normal(_elem.dim()) = -1.;
1401 
1402  RealVectorX
1403  phi_vec = RealVectorX::Zero(n_phi),
1404  w = RealVectorX::Zero(3),
1405  dn_rot = RealVectorX::Zero(3),
1406  force = RealVectorX::Zero(2*n1),
1407  local_f = RealVectorX::Zero(n2),
1408  vec_n2 = RealVectorX::Zero(n2);
1409 
1410  FEMOperatorMatrix Bmat;
1411  Real
1412  press = 0.,
1413  dpress = 0.;
1414 
1415 
1416  for (unsigned int qp=0; qp<qpoint.size(); qp++) {
1417 
1418  // now set the shape function values
1419  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1420  phi_vec(i_nd) = phi[i_nd][qp];
1421 
1422  Bmat.reinit(2*n1, phi_vec);
1423 
1424  // get pressure and deformation information
1425  press_fn (qpoint[qp], _time, press);
1426  press_fn.perturbation(qpoint[qp], _time, dpress);
1427 
1428  // calculate force
1429  for (unsigned int i_dim=0; i_dim<n1; i_dim++)
1430  force(i_dim) = ( press * dn_rot(i_dim) + // steady pressure
1431  dpress * normal(i_dim)); // unsteady pressure
1432 
1433  Bmat.vector_mult_transpose(vec_n2, force);
1434 
1435  local_f += JxW[qp] * vec_n2;
1436  }
1437 
1438  // now transform to the global system and add
1439  transform_vector_to_global_system(local_f, vec_n2);
1440  f -= vec_n2;
1441 
1442 
1443  return (request_jacobian);
1444 }
1445 
1446 
1447 
1448 
1449 bool
1452 (bool request_jacobian,
1453  ComplexVectorX &f,
1454  ComplexMatrixX &jac,
1456 
1457  libmesh_assert(_elem.dim() < 3); // only applicable for lower dimensional elements.
1458  libmesh_assert(!follower_forces); // not implemented yet for follower forces
1459  libmesh_assert_equal_to(bc.type(), MAST::SURFACE_PRESSURE);
1460 
1462  press_fn = bc.get<MAST::FieldFunction<Real> >("pressure");
1464  dpress_fn = bc.get<MAST::FieldFunction<Complex> >("frequency_domain_pressure");
1465 
1466  std::unique_ptr<MAST::FEBase> fe(_elem.init_fe(false, false));
1467 
1468  const std::vector<Real> &JxW = fe->get_JxW();
1469  const std::vector<libMesh::Point>& qpoint = fe->get_xyz();
1470  const std::vector<std::vector<Real> >& phi = fe->get_phi();
1471  const unsigned int
1472  n_phi = (unsigned int)phi.size(),
1473  n1 = 3,
1474  n2 = 6*n_phi;
1475 
1476  // normal for face integration
1477  libMesh::Point normal;
1478  // direction of pressure assumed to be normal (along local z-axis)
1479  // to the element face for 2D and along local y-axis for 1D element.
1480  normal(_elem.dim()) = -1.;
1481 
1482  RealVectorX phi_vec = RealVectorX::Zero(n_phi);
1484  w = ComplexVectorX::Zero(3),
1485  dn_rot = ComplexVectorX::Zero(3),
1486  force = ComplexVectorX::Zero(2*n1),
1487  local_f = ComplexVectorX::Zero(n2),
1488  vec_n2 = ComplexVectorX::Zero(n2);
1489 
1490  FEMOperatorMatrix Bmat;
1491  Real press = 0.;
1492  Complex dpress = 0.;
1493 
1494 
1495  for (unsigned int qp=0; qp<qpoint.size(); qp++) {
1496 
1497  // now set the shape function values
1498  for ( unsigned int i_nd=0; i_nd<n_phi; i_nd++ )
1499  phi_vec(i_nd) = phi[i_nd][qp];
1500 
1501  Bmat.reinit(2*n1, phi_vec);
1502 
1503  // get pressure and deformation information
1504  press_fn (qpoint[qp], _time, press);
1505  dpress_fn(qpoint[qp], _time, dpress);
1506  //dn_rot_fn.freq_domain_motion(pt, normal, w, dn_rot);
1507 
1508  // calculate force
1509  for (unsigned int i_dim=0; i_dim<n1; i_dim++)
1510  force(i_dim) = ( press * dn_rot(i_dim) + // steady pressure
1511  dpress * normal(i_dim)); // unsteady pressure
1512 
1513  Bmat.vector_mult_transpose(vec_n2, force);
1514 
1515  local_f += JxW[qp] * vec_n2;
1516  }
1517 
1518  // now transform to the global system and add
1519  transform_vector_to_global_system(local_f, vec_n2);
1520  f -= vec_n2;
1521 
1522 
1523  return (request_jacobian);
1524 }
1525 
1526 
1527 
1528 template <typename ValType>
1529 void
1531 transform_matrix_to_global_system(const ValType& local_mat,
1532  ValType& global_mat) const {
1533 
1534  // make sure this is only called for 1D and 2D elements
1535  libmesh_assert_less(_elem.dim(), 3);
1536  libmesh_assert_equal_to( local_mat.rows(), local_mat.cols());
1537  libmesh_assert_equal_to(global_mat.rows(), global_mat.cols());
1538  libmesh_assert_equal_to( local_mat.rows(), global_mat.rows());
1539 
1540  if (_elem.use_local_elem()) {
1541 
1542  // assuming same shape function for all 6 dofs.
1543  const unsigned int n_dofs = local_mat.rows()/6;
1544 
1545  ValType mat(6*n_dofs, 6*n_dofs);
1546 
1547  mat.setZero();
1548  global_mat.setZero();
1549 
1550  const RealMatrixX& Tmat = _elem.T_matrix();
1551  // now initialize the global T matrix
1552  for (unsigned int i=0; i<n_dofs; i++)
1553  for (unsigned int j=0; j<3; j++)
1554  for (unsigned int k=0; k<3; k++) {
1555  mat(j*n_dofs+i, k*n_dofs+i) = Tmat(j,k); // for u,v,w
1556  mat((j+3)*n_dofs+i, (k+3)*n_dofs+i) = Tmat(j,k); // for tx,ty,tz
1557  }
1558 
1559  // right multiply with T^tr, and left multiply with T.
1560  global_mat = mat * local_mat * mat.transpose();
1561  }
1562  else
1563  global_mat = local_mat;
1564 }
1565 
1566 
1567 
1568 template <typename ValType>
1569 void
1571 transform_vector_to_local_system(const ValType& global_vec,
1572  ValType& local_vec) const {
1573 
1574  // make sure this is only called for 1D and 2D elements
1575  libmesh_assert_less(_elem.dim(), 3);
1576  libmesh_assert_equal_to( local_vec.size(), global_vec.size());
1577 
1578  if (_elem.use_local_elem()) {
1579 
1580  // assuming same shape function for all 6 dofs.
1581  const unsigned int n_dofs = global_vec.size()/6;
1582  RealMatrixX mat = RealMatrixX::Zero(6*n_dofs, 6*n_dofs);
1583 
1584  local_vec.setZero();
1585 
1586  const RealMatrixX& Tmat = _elem.T_matrix();
1587  // now initialize the global T matrix
1588  for (unsigned int i=0; i<n_dofs; i++)
1589  for (unsigned int j=0; j<3; j++)
1590  for (unsigned int k=0; k<3; k++) {
1591  mat(j*n_dofs+i, k*n_dofs+i) = Tmat(j,k); // for u,v,w
1592  mat((j+3)*n_dofs+i, (k+3)*n_dofs+i) = Tmat(j,k); // for tx,ty,tz
1593  }
1594 
1595  // left multiply with T^tr
1596  local_vec = mat.transpose() * global_vec;
1597  }
1598  else
1599  local_vec = global_vec;
1600 }
1601 
1602 
1603 
1604 template <typename ValType>
1605 void
1607 transform_vector_to_global_system(const ValType& local_vec,
1608  ValType& global_vec) const {
1609 
1610  // make sure this is only called for 1D and 2D elements
1611  libmesh_assert_less(_elem.dim(), 3);
1612  libmesh_assert_equal_to( local_vec.size(), global_vec.size());
1613 
1614  if (_elem.use_local_elem()) {
1615 
1616  // assuming same shape function for all 6 dofs.
1617  const unsigned int n_dofs = local_vec.size()/6;
1618 
1619  RealMatrixX mat = RealMatrixX::Zero(6*n_dofs, 6*n_dofs);
1620 
1621  global_vec.setZero();
1622 
1623  const RealMatrixX& Tmat = _elem.T_matrix();
1624  // now initialize the global T matrix
1625  for (unsigned int i=0; i<n_dofs; i++)
1626  for (unsigned int j=0; j<3; j++)
1627  for (unsigned int k=0; k<3; k++) {
1628  mat(j*n_dofs+i, k*n_dofs+i) = Tmat(j,k); // for u,v,w
1629  mat((j+3)*n_dofs+i, (k+3)*n_dofs+i) = Tmat(j,k); // for tx,ty,tz
1630  }
1631 
1632  // left multiply with T
1633  global_vec = mat* local_vec;
1634  }
1635  else
1636  global_vec = local_vec;
1637 }
1638 
1639 
1640 
1641 
1642 
1643 std::unique_ptr<MAST::StructuralElementBase>
1646  const MAST::GeomElem& elem,
1647  const MAST::ElementPropertyCardBase& p) {
1648 
1649  std::unique_ptr<MAST::StructuralElementBase> e;
1650 
1651  switch (elem.dim()) {
1652  case 1:
1653  e.reset(new MAST::StructuralElement1D(sys, assembly, elem, p));
1654  break;
1655 
1656  case 2:
1657  e.reset(new MAST::StructuralElement2D(sys, assembly, elem, p));
1658  break;
1659 
1660  case 3:
1661  e.reset(new MAST::StructuralElement3D(sys, assembly, elem, p));
1662  break;
1663 
1664  default:
1665  libmesh_error();
1666  break;
1667  }
1668 
1669  return e;
1670 }
1671 
1672 
1673 
1674 Real
1676  const Real vel_U,
1677  const Real gamma,
1678  const Real mach) {
1679 
1680 
1681  Real cp = 0.0;
1682  switch (order)
1683  {
1684  case 3:
1685  cp += (gamma+1.0)/12.0*mach*mach*pow(vel_U,3);
1686  case 2:
1687  cp += (gamma+1.0)/4.0*mach*pow(vel_U,2);
1688  case 1: {
1689  cp += vel_U;
1690  cp *= 2.0/pow(mach*mach-1.,0.5);
1691  }
1692  break;
1693 
1694  default:
1695  libmesh_error_msg("Invalid Piston Theory Order: " << order);
1696  break;
1697  }
1698 
1699  return cp;
1700 }
1701 
1702 
1703 
1704 
1705 Real
1707  const Real vel_U,
1708  const Real gamma,
1709  const Real mach) {
1710 
1711 
1712  Real dcp_dvn = 0.0;
1713  switch (order)
1714  {
1715  case 3:
1716  dcp_dvn += (gamma+1.0)/4.0*mach*mach*pow(vel_U,2);
1717  case 2:
1718  dcp_dvn += (gamma+1.0)/2.0*mach*vel_U;
1719  case 1: {
1720  dcp_dvn += 1.;
1721  dcp_dvn *= 2.0/pow(mach*mach-1.,.5);
1722  }
1723  break;
1724 
1725  default:
1726  libmesh_error_msg("Invalid Piston Theory Order: " << order);
1727  break;
1728  }
1729 
1730  return dcp_dvn;
1731 }
1732 
1733 
1734 
1735 
1736 // template instantiations
1737 template
1738 void
1739 MAST::StructuralElementBase::transform_matrix_to_global_system<RealMatrixX>
1740 (const RealMatrixX& local_mat,
1741  RealMatrixX& global_mat) const;
1742 
1743 
1744 template
1745 void
1746 MAST::StructuralElementBase::transform_vector_to_local_system<RealVectorX>
1747 (const RealVectorX& global_vec,
1748  RealVectorX& local_vec) const;
1749 
1750 
1751 template
1752 void
1753 MAST::StructuralElementBase::transform_vector_to_global_system<RealVectorX>
1754 (const RealVectorX& local_vec,
1755  RealVectorX& global_vec) const;
1756 
1757 
1758 template
1759 void
1760 MAST::StructuralElementBase::transform_matrix_to_global_system<ComplexMatrixX>
1761 (const ComplexMatrixX& local_mat,
1762  ComplexMatrixX& global_mat) const;
1763 
1764 
1765 template
1766 void
1767 MAST::StructuralElementBase::transform_vector_to_local_system<ComplexVectorX>
1768 (const ComplexVectorX& global_vec,
1769  ComplexVectorX& local_vec) const;
1770 
1771 
1772 template
1773 void
1774 MAST::StructuralElementBase::transform_vector_to_global_system<ComplexVectorX>
1775 (const ComplexVectorX& local_vec,
1776  ComplexVectorX& global_vec) const;
1777 
1778 
1779 
RealVectorX _local_accel_sens
local acceleration sensitivity
void vector_mult_transpose(T &res, const T &v) const
res = v^T * [this]
bool use_local_elem() const
Vector and matrix quantities defined on one- and two-dimensional elements that are oriented in two or...
Definition: geom_elem.cpp:314
MAST::NonlinearSystem & system()
virtual void surface_pressure_boundary_velocity(const MAST::FunctionBase &p, const unsigned int s, const MAST::FieldFunction< RealVectorX > &vel_f, MAST::BoundaryConditionBase &bc, bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
Calculates the force vector and Jacobian due to surface pressure applied on the entire element domain...
virtual bool thermal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to thermal stresses.
bool volume_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > &bc)
volume external force contribution to system residual.
virtual bool linearized_frequency_domain_surface_pressure_residual(bool request_jacobian, ComplexVectorX &f, ComplexMatrixX &jac, const unsigned int side, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to small perturbation surface pressure.
virtual bool thermal_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)=0
Calculates the sensitivity of force vector and Jacobian due to thermal stresses.
const MAST::GeomElem & _elem
geometric element for which the computations are performed
Definition: elem_base.h:218
RealVectorX _local_delta_vel_sens
local perturbed velocity sensitivity
virtual bool inertial_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xddot, RealMatrixX &jac_xdot, RealMatrixX &jac)
sensitivity of the inertial force contribution to system residual
virtual bool piston_theory_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to piston-theory based surface pressure on the entire el...
virtual bool linearized_inertial_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xddot, RealMatrixX &jac_xdot, RealMatrixX &jac)
inertial force contribution to system residual of linerized problem
std::unique_ptr< MAST::StructuralElementBase > build_structural_element(MAST::SystemInitialization &sys, MAST::AssemblyBase &assembly, const MAST::GeomElem &elem, const MAST::ElementPropertyCardBase &p)
builds the structural element for the specified element type
virtual void thermal_residual_boundary_velocity(const MAST::FunctionBase &p, const unsigned int s, const MAST::FieldFunction< RealVectorX > &vel_f, MAST::BoundaryConditionBase &bc, bool request_jacobian, RealVectorX &f, RealMatrixX &jac)=0
Calculates the sensitivity of force vector and Jacobian due to thermal stresses.
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 void set_velocity(const RealVectorX &vec, bool if_sens=false)
stores vec as velocity for element level calculations, or its sensitivity if if_sens is true...
Definition: elem_base.cpp:100
virtual void set_perturbed_acceleration(const RealVectorX &vec, bool if_sens=false)
stores vec as perturbed acceleration for element level calculations, or its sensitivity if if_sens is...
virtual void set_acceleration(const RealVectorX &vec, bool if_sens=false)
stores vec as acceleration for element level calculations, or its sensitivity if if_sens is true...
const MAST::GeomElem & elem() const
Definition: elem_base.h:117
Matrix< Complex, Dynamic, 1 > ComplexVectorX
void transform_vector_to_local_system(const ValType &global_vec, ValType &local_vec) const
RealVectorX _local_delta_sol_sens
local perturbed solution sensitivity
virtual bool inertial_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xddot, RealMatrixX &jac_xdot, RealMatrixX &jac)
inertial force contribution to system residual
RealVectorX _local_delta_accel_sens
local perturbed acceleration sensitivity
RealVectorX _local_accel
local acceleration
bool side_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase * > &bc)
side external force contribution to system residual.
libMesh::Real Real
RealVectorX _local_sol_sens
local solution sensitivity
MAST::SystemInitialization & _system
SystemInitialization object associated with this element.
Definition: elem_base.h:208
MAST::AssemblyBase & assembly()
Definition: elem_base.h:103
MAST::BoundaryConditionType type() const
libMesh::Complex Complex
Real piston_theory_cp(const unsigned int order, const Real vel_U, const Real gamma, const Real mach)
virtual const libMesh::Elem & get_reference_elem() const
Definition: geom_elem.cpp:54
RealVectorX _local_delta_vel
local perturbed velocity
virtual std::unique_ptr< MAST::FieldFunction< RealMatrixX > > inertia_matrix(const MAST::ElementBase &e) const =0
virtual void set_velocity(const RealVectorX &vec, bool if_sens=false)
stores vec as velocity for element level calculations, or its sensitivity if if_sens is true...
RealVectorX _delta_sol
local solution used for linearized analysis
Definition: elem_base.h:262
bool side_external_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase * > &bc)
sensitivity of the side external force contribution to system residual
void transform_matrix_to_global_system(const ValType &local_mat, ValType &global_mat) const
RealVectorX _local_delta_sol
local perturbed solution
bool follower_forces
flag for follower forces
Matrix< Real, Dynamic, Dynamic > RealMatrixX
Matrix< Complex, Dynamic, Dynamic > ComplexMatrixX
const RealMatrixX & T_matrix() const
O.
Definition: geom_elem.cpp:228
Real piston_theory_dcp_dv(const unsigned int order, const Real vel_U, const Real gamma, const Real mach)
void volume_external_residual_boundary_velocity(const MAST::FunctionBase &p, const unsigned int s, const MAST::FieldFunction< RealVectorX > &vel_f, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > &bc, bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
boundary velocity contribution of volume external force.
virtual void set_solution(const RealVectorX &vec, bool if_sens=false)
stores vec as solution for element level calculations, or its sensitivity if if_sens is true...
Matrix< Real, Dynamic, 1 > RealVectorX
virtual bool piston_theory_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to piston-theory based surface pressure on the entire el...
bool linearized_volume_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > &bc)
volume external force contribution to system residual.
const MAST::ElementPropertyCardBase & _property
element property
virtual std::unique_ptr< MAST::FEBase > init_side_fe(unsigned int s, bool init_grads, 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:159
virtual void set_perturbed_solution(const RealVectorX &vec, bool if_sens=false)
This provides the perturbed solution (or its sensitivity if if_sens is true.) for linearized analysis...
Definition: elem_base.cpp:74
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
virtual void set_perturbed_velocity(const RealVectorX &vec, bool if_sens=false)
stores vec as perturbed velocity for element level calculations, or its sensitivity if if_sens is tru...
RealVectorX _local_vel_sens
local velocity sensitivity
virtual bool linearized_surface_pressure_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, MAST::BoundaryConditionBase &bc)
Calculates the force vector and Jacobian due to surface pressure applied on the entire element domain...
unsigned int dim() const
Definition: geom_elem.cpp:91
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:175
virtual void set_perturbed_solution(const RealVectorX &vec, bool if_sens=false)
stores vec as perturbed solution for element level calculations, or its sensitivity if if_sens is tru...
void right_multiply_transpose(T &r, const T &m) const
[R] = [this]^T * [M]
virtual void set_solution(const RealVectorX &vec, bool if_sens=false)
stores vec as solution for element level calculations, or its sensitivity if if_sens is true...
Definition: elem_base.cpp:62
bool linearized_frequency_domain_side_external_residual(bool request_jacobian, ComplexVectorX &f, ComplexMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase * > &bc)
Calculates the external force due to frequency domain side external force contribution to system resi...
StructuralElementBase(MAST::SystemInitialization &sys, MAST::AssemblyBase &assembly, const MAST::GeomElem &elem, const MAST::ElementPropertyCardBase &p)
Constructor.
void left_multiply(T &r, const T &m) const
[R] = [M] * [this]
bool volume_external_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > &bc)
sensitivity of the volume external force contribution to system residual
virtual bool linearized_internal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac)
internal force contribution to system residual of the linearized problem
RealVectorX _local_delta_accel
local perturbed acceleration
RealVectorX _local_sol
local solution
virtual bool surface_pressure_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int side, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to surface pressure.
RealVectorX _local_vel
local velocity
bool linearized_frequency_domain_volume_external_residual(bool request_jacobian, ComplexVectorX &f, ComplexMatrixX &jac, std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > &bc)
Calculates the frequency domain volume external force contribution to system residual.
const ValType & get(const std::string &nm) const
returns a constant reference to the specified function
virtual void set_perturbed_velocity(const RealVectorX &vec, bool if_sens=false)
stores vec as perturbed velocity for element level calculations, or its sensitivity if if_sens is tru...
Definition: elem_base.cpp:112
virtual bool internal_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac)=0
internal force contribution to system residual
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:142
const Real & _time
time for which system is being assembled
Definition: elem_base.h:232
virtual void set_perturbed_acceleration(const RealVectorX &vec, bool if_sens=false)
stores vec as perturbed acceleration for element level calculations, or its sensitivity if if_sens is...
Definition: elem_base.cpp:136
virtual void inertial_residual_boundary_velocity(const MAST::FunctionBase &p, const unsigned int s, const MAST::FieldFunction< RealVectorX > &vel_f, bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xddot, RealMatrixX &jac_xdot, RealMatrixX &jac)
sensitivity of the inertial force contribution to system residual
void transform_vector_to_global_system(const ValType &local_vec, ValType &global_vec) const
bool linearized_side_external_residual(bool request_jacobian, RealVectorX &f, RealMatrixX &jac_xdot, RealMatrixX &jac, std::multimap< libMesh::boundary_id_type, MAST::BoundaryConditionBase * > &bc)
side external force contribution to system residual.
virtual void set_acceleration(const RealVectorX &vec, bool if_sens=false)
stores vec as acceleration for element level calculations, or its sensitivity if if_sens is true...
Definition: elem_base.cpp:124
bool if_diagonal_mass_matrix() const
returns the type of strain to be used for this element
virtual bool surface_pressure_residual_sensitivity(const MAST::FunctionBase &p, bool request_jacobian, RealVectorX &f, RealMatrixX &jac, const unsigned int side, MAST::BoundaryConditionBase &bc)=0
Calculates the force vector and Jacobian due to surface pressure.
This is the base class for elements that implement calculation of finite element quantities over the ...
Definition: elem_base.h:72