MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
stress_output_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 
21 // MAST includes
24 #include "base/assembly_base.h"
26 #include "base/nonlinear_system.h"
32 #include "mesh/geom_elem.h"
33 
34 // libMesh includes
35 #include "libmesh/parallel.h"
36 
38  const RealVectorX& strain,
39  const libMesh::Point& qp,
40  const libMesh::Point& xyz,
41  Real JxW):
42 _stress(stress),
43 _strain(strain),
44 _qp(qp),
45 _xyz(xyz),
46 _JxW(JxW) {
47 
48  // make sure that both the stress and strain are for a 3D configuration,
49  // which is the default for this data structure
50  libmesh_assert_equal_to(stress.size(), 6);
51  libmesh_assert_equal_to(strain.size(), 6);
52 
53 }
54 
55 
56 
57 void
59 
60  _stress_sensitivity.clear();
61  _strain_sensitivity.clear();
62 }
63 
64 
65 const libMesh::Point&
68 
69  return _qp;
70 }
71 
72 
73 const RealVectorX&
75 
76  return _stress;
77 }
78 
79 
80 
81 const RealVectorX&
83  return _strain;
84 }
85 
86 
87 
88 void
90  const RealMatrixX& dstrain_dX) {
91 
92  // make sure that the number of rows is 6.
93  libmesh_assert_equal_to(dstress_dX.rows(), 6);
94  libmesh_assert_equal_to(dstrain_dX.rows(), 6);
95 
96  _dstress_dX = dstress_dX;
97  _dstrain_dX = dstrain_dX;
98 }
99 
100 
101 
102 const RealMatrixX&
104 
105  return _dstress_dX;
106 }
107 
108 
109 const RealMatrixX&
111 
112  return _dstrain_dX;
113 }
114 
115 
116 Real
118 
119  return _JxW;
120 }
121 
122 
123 void
125  const RealVectorX& dstress_df,
126  const RealVectorX& dstrain_df) {
127 
128  // make sure that both the stress and strain are for a 3D configuration,
129  // which is the default for this data structure
130  libmesh_assert_equal_to(dstress_df.size(), 6);
131  libmesh_assert_equal_to(dstrain_df.size(), 6);
132 
133  _stress_sensitivity[&f] = dstress_df;
134  _strain_sensitivity[&f] = dstrain_df;
135 }
136 
137 
138 bool
141 
142  // make sure that the data exists
143  std::map<const MAST::FunctionBase*, RealVectorX>::const_iterator
144  it = _stress_sensitivity.find(&f);
145 
146  return it != _stress_sensitivity.end();
147 }
148 
149 
150 const RealVectorX&
153 
154  // make sure that the data exists
155  std::map<const MAST::FunctionBase*, RealVectorX>::const_iterator
156  it = _stress_sensitivity.find(&f);
157 
158  libmesh_assert(it != _stress_sensitivity.end());
159 
160 
161  return it->second;
162 }
163 
164 
165 
166 const RealVectorX&
169 
170  // make sure that the data exists
171  std::map<const MAST::FunctionBase*, RealVectorX>::const_iterator
172  it = _strain_sensitivity.find(&f);
173 
174  libmesh_assert(it != _strain_sensitivity.end());
175 
176 
177  return it->second;
178 }
179 
180 
181 
182 Real
184 
185  // make sure that the data is available
186  libmesh_assert_equal_to(_stress.size(), 6);
187 
188  return
189  pow(0.5 * (pow(_stress(0)-_stress(1),2) + //(((sigma_xx - sigma_yy)^2 +
190  pow(_stress(1)-_stress(2),2) + // (sigma_yy - sigma_zz)^2 +
191  pow(_stress(2)-_stress(0),2)) + // (sigma_zz - sigma_xx)^2)/2 +
192  3.0 * (pow(_stress(3), 2) + // 3* (tau_xx^2 +
193  pow(_stress(4), 2) + // tau_yy^2 +
194  pow(_stress(5), 2)), 0.5); // tau_zz^2))^.5
195 }
196 
197 
198 
201 
202  // make sure that the data is available
203  libmesh_assert_equal_to(_stress.size(), 6);
204  libmesh_assert_equal_to(_dstress_dX.rows(), 6);
205 
206  Real
207  p =
208  0.5 * (pow(_stress(0)-_stress(1),2) + //((sigma_xx - sigma_yy)^2 +
209  pow(_stress(1)-_stress(2),2) + // (sigma_yy - sigma_zz)^2 +
210  pow(_stress(2)-_stress(0),2)) + // (sigma_zz - sigma_xx)^2)/2 +
211  3.0 * (pow(_stress(3), 2) + // 3* (tau_xx^2 +
212  pow(_stress(4), 2) + // tau_yy^2 +
213  pow(_stress(5), 2)); // tau_zz^2)
214 
216  dp = RealVectorX::Zero(_dstress_dX.cols());
217 
218  // if p == 0, then the sensitivity returns nan
219  // Hence, we are avoiding this by setting it to zero whenever p = 0.
220  if (fabs(p) > 0.)
221  dp =
222  (((_dstress_dX.row(0) - _dstress_dX.row(1)) * (_stress(0) - _stress(1)) +
223  (_dstress_dX.row(1) - _dstress_dX.row(2)) * (_stress(1) - _stress(2)) +
224  (_dstress_dX.row(2) - _dstress_dX.row(0)) * (_stress(2) - _stress(0))) +
225  6.0 * (_dstress_dX.row(3) * _stress(3)+
226  _dstress_dX.row(4) * _stress(4)+
227  _dstress_dX.row(5) * _stress(5))) * 0.5 * pow(p, -0.5);
228 
229  return dp;
230 }
231 
232 
233 
234 
235 Real
238 
239  // make sure that the data is available
240  libmesh_assert_equal_to(_stress.size(), 6);
241 
242  if (!this->has_stress_sensitivity(f))
243  return 0.;
244 
245  // get the stress sensitivity data
246  const RealVectorX dstress_dp = this->get_stress_sensitivity(f);
247 
248 
249  Real
250  p =
251  0.5 * (pow(_stress(0)-_stress(1),2) + //((sigma_xx - sigma_yy)^2 +
252  pow(_stress(1)-_stress(2),2) + // (sigma_yy - sigma_zz)^2 +
253  pow(_stress(2)-_stress(0),2)) + // (sigma_zz - sigma_xx)^2)/2 +
254  3.0 * (pow(_stress(3), 2) + // 3* (tau_xx^2 +
255  pow(_stress(4), 2) + // tau_yy^2 +
256  pow(_stress(5), 2)), // tau_zz^2)
257  dp = 0.;
258 
259  // if p == 0, then the sensitivity returns nan
260  // Hence, we are avoiding this by setting it to zero whenever p = 0.
261  if (fabs(p) > 0.)
262  dp =
263  (((dstress_dp(0) - dstress_dp(1)) * (_stress(0) - _stress(1)) +
264  (dstress_dp(1) - dstress_dp(2)) * (_stress(1) - _stress(2)) +
265  (dstress_dp(2) - dstress_dp(0)) * (_stress(2) - _stress(0))) +
266  6.0 * (dstress_dp(3) * _stress(3)+
267  dstress_dp(4) * _stress(4)+
268  dstress_dp(5) * _stress(5))) * 0.5 * pow(p, -0.5);
269 
270  return dp;
271 }
272 
273 
274 
277 _p_norm_stress (2.),
278 _p_norm_weight (1),
279 _rho (1.),
280 _sigma0 (0.),
281 _exp_arg_lim (1.e2),
283 _JxW_val (0.),
284 _sigma_vm_int (0.),
285 _sigma_vm_p_norm (0.),
286 _if_stress_plot_mode (false) {
287 
288 }
289 
290 
291 
292 
294 
295  this->clear();
296 }
297 
298 
299 
300 
301 void
303 
304  _JxW_val = 0.;
305  _sigma_vm_int = 0.;
306  _sigma_vm_p_norm = 0.;
307 }
308 
309 
310 
311 void
313 
314  // nothign to be done here.
315 }
316 
317 
318 void
320 
321  // make sure that this has not been initialized ana calculated for all elems
322  libmesh_assert(_physics_elem);
323  libmesh_assert(!_primal_data_initialized);
324 
326  // ask for the values
327  dynamic_cast<MAST::StructuralElementBase*>
328  (_physics_elem)->calculate_stress(false,
329  nullptr,
330  *this);
331 }
332 
333 
334 
335 void
337 
338  // the primal data should have been calculated
339  libmesh_assert(_physics_elem);
341  libmesh_assert(_primal_data_initialized);
342 
344 
345  // ask for the values
346  dynamic_cast<MAST::StructuralElementBase*>
347  (_physics_elem)->calculate_stress(false,
348  &f,
349  *this);
350  }
351 }
352 
353 
354 
355 void
358 
359  // the primal data should have been calculated
360  libmesh_assert(_physics_elem);
361  libmesh_assert(f.is_topology_parameter());
363  libmesh_assert(_primal_data_initialized);
364 
365  // sensitivity only exists at the boundary. So, we proceed with calculation
366  // only if this element has an intersection in the interior, or with a side.
367 
369 
370  std::pair<const MAST::FieldFunction<RealVectorX>*, unsigned int>
371  val = this->get_elem_boundary_velocity_data();
372 
373  if (val.first)
374  dynamic_cast<MAST::StructuralElementBase*>
375  (_physics_elem)->calculate_stress_boundary_velocity(f, *this,
376  val.second,
377  *val.first);
378  }
379 }
380 
381 
382 
383 void
387 
388  // the primal data should have been calculated
389  libmesh_assert(_physics_elem);
390  libmesh_assert(f.is_topology_parameter());
392  libmesh_assert(_primal_data_initialized);
393 
395  &elem = dynamic_cast<const MAST::LevelSetIntersectedElem&>(_physics_elem->elem());
396 
397  // sensitivity only exists at the boundary. So, we proceed with calculation
398  // only if this element has an intersection in the interior, or with a side.
399 
400  if (this->if_evaluate_for_element(elem) &&
403 
404  // ask for the values
405  dynamic_cast<MAST::StructuralElementBase*>
406  (_physics_elem)->calculate_stress_boundary_velocity(f, *this,
408  vel);
409  }
410 }
411 
412 
413 
414 Real
416 
417  libmesh_assert(!_if_stress_plot_mode);
418 
419  // if this has not been initialized, then we should do so now
421  this->functional_for_all_elems();
422 
423  return _sigma_vm_p_norm;
424 }
425 
426 
427 Real
429 
430  libmesh_assert(!_if_stress_plot_mode);
431  libmesh_assert(_primal_data_initialized);
432 
433  Real val = 0.;
434 
436  (p, _physics_elem->elem().get_quadrature_elem().id(), val);
437 
438  return val;
439 }
440 
441 
442 
443 Real
445 
446  libmesh_assert(!_if_stress_plot_mode);
447  libmesh_assert(_primal_data_initialized);
448 
449  Real
450  val = 0.,
451  val_b = 0.;
452 
454  if (p.is_topology_parameter())
456  return val+val_b;
457 }
458 
459 
460 
461 void
463 
464  libmesh_assert(_physics_elem);
465  libmesh_assert(!_if_stress_plot_mode);
466  libmesh_assert(_primal_data_initialized);
467 
469 
470  dq_dX.setZero();
471 
472  dynamic_cast<MAST::StructuralElementBase*>
473  (_physics_elem)->calculate_stress(true,
474  nullptr,
475  *this);
476 
478  (_physics_elem->elem().get_quadrature_elem().id(), dq_dX);
479  }
480 }
481 
482 
483 
484 void
486 set_elem_data(unsigned int dim,
487  const libMesh::Elem& ref_elem,
488  MAST::GeomElem& elem) const {
489 
490  libmesh_assert(!_physics_elem);
491 
492  if (dim == 1) {
493 
494  const MAST::ElementPropertyCard1D& p =
495  dynamic_cast<const MAST::ElementPropertyCard1D&>(_discipline->get_property_card(ref_elem));
496 
497  elem.set_local_y_vector(p.y_vector());
498  }
499 }
500 
501 
502 void
504 
505  libmesh_assert(!_physics_elem);
506  libmesh_assert(_assembly);
507  libmesh_assert(_system);
508 
510  dynamic_cast<const MAST::ElementPropertyCardBase&>(_discipline->get_property_card(elem));
511 
512  _physics_elem =
513  MAST::build_structural_element(*_system, elem, p).release();
514 }
515 
516 
517 
518 void
520 
521  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::iterator
522  map_it = _stress_data.begin(),
523  map_end = _stress_data.end();
524 
525  for ( ; map_it != map_end; map_it++) {
526 
527  // iterate over all the data and delete them
528  std::vector<MAST::StressStrainOutputBase::Data*>::iterator
529  it = map_it->second.begin(),
530  end = map_it->second.end();
531 
532  for ( ; it != end; it++)
533  delete *it;
534 
535  map_it->second.clear();
536  }
537 
538  _stress_data.clear();
539 
540 
541  map_it = _boundary_stress_data.begin();
542  map_end = _boundary_stress_data.end();
543 
544  for ( ; map_it != map_end; map_it++) {
545 
546  // iterate over all the data and delete them
547  std::vector<MAST::StressStrainOutputBase::Data*>::iterator
548  it = map_it->second.begin(),
549  end = map_it->second.end();
550 
551  for ( ; it != end; it++)
552  delete *it;
553 
554  map_it->second.clear();
555  }
556 
557  _boundary_stress_data.clear();
558 
559  this->clear_elem();
560 
561  _primal_data_initialized = false;
562  _JxW_val = 0.;
563  _sigma_vm_int = 0.;
564  _sigma_vm_p_norm = 0.;
565  _if_stress_plot_mode = false;
566 }
567 
568 
569 
570 
571 void
573 
574  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::iterator
575  map_it = _stress_data.begin(),
576  map_end = _stress_data.end();
577 
578  for ( ; map_it != map_end; map_it++) {
579 
580  // iterate over all the data and delete them
581  std::vector<MAST::StressStrainOutputBase::Data*>::iterator
582  it = map_it->second.begin(),
583  end = map_it->second.end();
584 
585  for ( ; it != end; it++)
586  (*it)->clear_sensitivity_data();
587  }
588 
589 
590  map_it = _boundary_stress_data.begin();
591  map_end = _boundary_stress_data.end();
592 
593  for ( ; map_it != map_end; map_it++) {
594 
595  // iterate over all the data and delete them
596  std::vector<MAST::StressStrainOutputBase::Data*>::iterator
597  it = map_it->second.begin(),
598  end = map_it->second.end();
599 
600  for ( ; it != end; it++)
601  delete *it;
602  }
603  _boundary_stress_data.clear();
604 }
605 
606 
607 
608 
609 
610 
614  const unsigned int qp,
615  const libMesh::Point& quadrature_pt,
616  const libMesh::Point& physical_pt,
617  const RealVectorX& stress,
618  const RealVectorX& strain,
619  Real JxW) {
620 
621  // if the element subset has been provided, then make sure that this
622  // element exists in the subdomain.
623  if (_elem_subset.size())
624  libmesh_assert(_elem_subset.count(&e.get_reference_elem()));
625 
626 
629  strain,
630  quadrature_pt,
631  physical_pt,
632  JxW);
633 
634 
635  // check if the specified element exists in the map. If not, add it
636  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::iterator
637  it = _stress_data.find(e.get_quadrature_elem().id());
638 
639  // if the element does not exist in the map, add it to the map.
640  if (it == _stress_data.end())
641  it =
642  _stress_data.insert(std::pair<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >
643  (e.get_quadrature_elem().id(),
644  std::vector<MAST::StressStrainOutputBase::Data*>())).first;
645  else
646  // this assumes that the previous qp data is provided and
647  // therefore, this qp number should be == size of the vector.
648  libmesh_assert_equal_to(qp, it->second.size());
649 
650  it->second.push_back(d);
651 
652  return *d;
653 }
654 
655 
656 
657 
661  const unsigned int s,
662  const unsigned int qp,
663  const libMesh::Point& quadrature_pt,
664  const libMesh::Point& physical_pt,
665  const RealVectorX& stress,
666  const RealVectorX& strain,
667  Real JxW_Vn) {
668 
669  // if the element subset has been provided, then make sure that this
670  // element exists in the subdomain.
671  if (_elem_subset.size())
672  libmesh_assert(_elem_subset.count(&e.get_reference_elem()));
673 
674 
677  strain,
678  quadrature_pt,
679  physical_pt,
680  JxW_Vn);
681 
682 
683  // check if the specified element exists in the map. If not, add it
684  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::iterator
685  it = _boundary_stress_data.find(e.get_quadrature_elem().id());
686 
687  // if the element does not exist in the map, add it to the map.
688  if (it == _boundary_stress_data.end())
689  it =
690  _boundary_stress_data.insert
691  (std::pair<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >
692  (e.get_quadrature_elem().id(),
693  std::vector<MAST::StressStrainOutputBase::Data*>())).first;
694  else
695  // this assumes that the previous qp data is provided and
696  // therefore, this qp number should be == size of the vector.
697  libmesh_assert_equal_to(qp, it->second.size());
698 
699  it->second.push_back(d);
700 
701  return *d;
702 }
703 
704 
705 
706 
707 const std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >&
709 
710  return _stress_data;
711 }
712 
713 
714 
715 Real
717 
718  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*>>::const_iterator
719  it = _stress_data.begin(),
720  end = _stress_data.end();
721 
722  Real
723  vm = 0.,
724  max_vm = 0.;
725 
726  for ( ; it != end; it++) {
727 
728  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
729  s_it = it->second.begin(),
730  s_end = it->second.end();
731 
732  for ( ; s_it != s_end; s_it++) {
733  vm = (*s_it)->von_Mises_stress();
734  max_vm = vm>max_vm?vm:max_vm;
735  }
736  }
737 
738  // now, identify the max stress on all ranks.
739  _system->system().comm().max(max_vm);
740 
741  return max_vm;
742 }
743 
744 
745 
746 unsigned int
749 
750  unsigned int n = 0;
751 
752  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
753  it = _stress_data.find(e.get_quadrature_elem().id());
754 
755  if ( it != _stress_data.end())
756  n = (unsigned int)it->second.size();
757 
758  return n;
759 }
760 
761 
762 
763 unsigned int
766 
767  unsigned int n = 0;
768 
769  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
770  it = _boundary_stress_data.find(e.get_quadrature_elem().id());
771 
772  if ( it != _boundary_stress_data.end())
773  n = (unsigned int)it->second.size();
774 
775  return n;
776 }
777 
778 
779 
780 const std::vector<MAST::StressStrainOutputBase::Data*>&
783 
784  // check if the specified element exists in the map. If not, add it
785  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
786  it = _stress_data.find(e.get_quadrature_elem().id());
787 
788  // make sure that the specified elem exists in the map
789  libmesh_assert(it != _stress_data.end());
790 
791  return it->second;
792 }
793 
794 
795 
799  const unsigned int qp) {
800 
801 
802  // check if the specified element exists in the map. If not, add it
803  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
804  it = _stress_data.find(e.get_quadrature_elem().id());
805 
806  // make sure that the specified elem exists in the map
807  libmesh_assert(it != _stress_data.end());
808 
809  libmesh_assert_less(qp, it->second.size());
810 
811  return *(it->second[qp]);
812 }
813 
814 
815 
818 
819  MAST::BoundaryConditionBase *rval = nullptr;
820 
821  // this should only be called if the user has specified evaluation of
822  // stress for this
823  libmesh_assert(this->if_evaluate_for_element(elem));
824 
825 
827  vol_loads = _discipline->volume_loads();
828 
829  std::pair<std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator,
830  std::multimap<libMesh::subdomain_id_type, MAST::BoundaryConditionBase*>::const_iterator> it;
831 
832  it = vol_loads.equal_range(elem.get_reference_elem().subdomain_id());
833 
834  // FIXME: that this assumes that only one temperature boundary condition
835  // is applied for an element.
836  for ( ; it.first != it.second; it.first++)
837  if (it.first->second->type() == MAST::TEMPERATURE) {
838 
839  // make sure that only one thermal load exists for an element
840  libmesh_assert(!rval);
841 
842  rval = it.first->second;
843  }
844 
845  return rval;
846 }
847 
848 
849 
850 
851 void
853 
854  libmesh_assert(!_if_stress_plot_mode);
855  libmesh_assert(!_primal_data_initialized);
856  libmesh_assert_greater(_sigma0, 0.);
857 
858  Real
859  sp = 0.,
860  exp_sp = 0.,
861  e_val = 0.,
862  JxW = 0.;
863 
864  _JxW_val = 0.;
865  _sigma_vm_int = 0.;
866  _sigma_vm_p_norm = 0.;
867 
868  // first find the data with the maximum value, to be used for scaling
869 
870  // iterate over all element data
871  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
872  map_it = _stress_data.begin(),
873  map_end = _stress_data.end();
874 
875  for ( ; map_it != map_end; map_it++) {
876 
877  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
878  vec_it = map_it->second.begin(),
879  vec_end = map_it->second.end();
880 
881  for ( ; vec_it != vec_end; vec_it++) {
882 
883  // ask this data point for the von Mises stress value
884  e_val = (*vec_it)->von_Mises_stress();
885  JxW = (*vec_it)->quadrature_point_JxW();
886 
887  // we do not use absolute value here, since von Mises stress
888  // is >= 0.
889  sp = pow((e_val-_sigma0)/_sigma0, _p_norm_weight);
890  if (_rho * sp > _exp_arg_lim)
891  exp_sp = exp(_exp_arg_lim);
892  else
893  exp_sp = exp(_rho * sp);
894  _sigma_vm_int += pow(e_val/_sigma0, _p_norm_stress) * exp_sp * JxW;
895  _JxW_val += exp_sp * JxW;
896  }
897  }
898 
899  // sum over all processors, since part of the mesh will exist on the
900  // other processors.
901  if (!_skip_comm_sum) {
902 
903  _system->system().comm().sum(_sigma_vm_int);
904  _system->system().comm().sum(_JxW_val);
905  }
906 
909 }
910 
911 
912 
913 void
916  Real& dsigma_vm_val_df) const {
917 
918  libmesh_assert(!_if_stress_plot_mode);
919  libmesh_assert(_primal_data_initialized);
920 
921  Real
922  val = 0.;
923 
924  dsigma_vm_val_df = 0.;
925 
926  // iterate over all element data
927  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
928  map_it = _stress_data.begin(),
929  map_end = _stress_data.end();
930 
931  for ( ; map_it != map_end; map_it++) {
932 
933  this->functional_sensitivity_for_elem(f, map_it->first, val);
934  dsigma_vm_val_df += val;
935  }
936 
937  // sum over all processors, since part of the mesh will exist on the
938  // other processors
939  if (!_skip_comm_sum)
940  _system->system().comm().sum(dsigma_vm_val_df);
941 }
942 
943 
944 
945 
946 void
949  Real& dsigma_vm_val_df) const {
950 
951  libmesh_assert(!_if_stress_plot_mode);
952  libmesh_assert(_primal_data_initialized);
953 
954  Real
955  val = 0.;
956 
957  dsigma_vm_val_df = 0.;
958 
959  // iterate over all element data
960  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
961  map_it = _boundary_stress_data.begin(),
962  map_end = _boundary_stress_data.end();
963 
964  for ( ; map_it != map_end; map_it++) {
965 
966  this->functional_boundary_sensitivity_for_elem(f, map_it->first, val);
967  dsigma_vm_val_df += val;
968  }
969 
970  // sum over all processors, since part of the mesh will exist on the
971  // other processors
972  if (!_skip_comm_sum)
973  _system->system().comm().sum(dsigma_vm_val_df);
974 }
975 
976 
977 
978 void
981  const libMesh::dof_id_type e_id,
982  Real& dsigma_vm_val_df) const {
983 
984  libmesh_assert(!_if_stress_plot_mode);
985  libmesh_assert(_primal_data_initialized);
986  libmesh_assert_greater(_sigma0, 0.);
987 
988  Real
989  sp_stress = 0.,
990  sp1_stress = 0.,
991  sp_weight = 0.,
992  sp1_weight = 0.,
993  exp_sp = 0.,
994  e_val = 0.,
995  de_val = 0.,
996  num_sens = 0.,
997  denom_sens = 0.,
998  JxW = 0.;
999 
1000  dsigma_vm_val_df = 0.;
1001 
1002  // iterate over all element data
1003  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
1004  map_it = _stress_data.find(e_id),
1005  map_end = _stress_data.end();
1006 
1007  libmesh_assert(map_it != map_end);
1008 
1009  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
1010  vec_it = map_it->second.begin(),
1011  vec_end = map_it->second.end();
1012 
1013  for ( ; vec_it != vec_end; vec_it++) {
1014 
1015  // ask this data point for the von Mises stress value
1016  e_val = (*vec_it)->von_Mises_stress();
1017  de_val = (*vec_it)->dvon_Mises_stress_dp(f);
1018  JxW = (*vec_it)->quadrature_point_JxW();
1019 
1020  // we do not use absolute value here, since von Mises stress
1021  // is >= 0.
1022  sp_stress = pow(e_val/_sigma0, _p_norm_stress);
1023  sp1_stress = pow(e_val/_sigma0, _p_norm_stress-1.);
1024  sp_weight = pow((e_val-_sigma0)/_sigma0, _p_norm_weight);
1025  sp1_weight = pow((e_val-_sigma0)/_sigma0, _p_norm_weight-1.);
1026  if (_rho*sp_weight > _exp_arg_lim) {
1027  exp_sp = exp(_exp_arg_lim);
1028  denom_sens += 0.;
1029  num_sens += _p_norm_stress * sp1_stress * exp_sp * de_val/_sigma0 * JxW;
1030  }
1031  else {
1032  exp_sp = exp(_rho * sp_weight);
1033  denom_sens += exp_sp * _rho * _p_norm_weight * sp1_weight * de_val/_sigma0 * JxW;
1034  num_sens += (de_val/_sigma0 * JxW * exp_sp *
1035  (_p_norm_stress * sp1_stress +
1036  sp_stress * _rho * _p_norm_weight * sp1_weight));
1037  }
1038 
1039  }
1040 
1041  dsigma_vm_val_df = _sigma0/_p_norm_stress * pow(_sigma_vm_int/_JxW_val, 1./_p_norm_stress - 1.) *
1042  (num_sens / _JxW_val - _sigma_vm_int / pow(_JxW_val, 2.) * denom_sens);
1043 }
1044 
1045 
1046 
1047 
1048 
1049 void
1052  const libMesh::dof_id_type e_id,
1053  Real& dsigma_vm_val_df) const {
1054 
1055  libmesh_assert(!_if_stress_plot_mode);
1056  libmesh_assert(_primal_data_initialized);
1057  libmesh_assert_greater(_sigma0, 0.);
1058 
1059  Real
1060  sp = 0.,
1061  exp_sp = 0.,
1062  e_val = 0.,
1063  JxW_Vn = 0.,
1064  num_sens = 0.,
1065  denom_sens = 0.;
1066 
1067  dsigma_vm_val_df = 0.;
1068 
1069  // iterate over all element data
1070  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
1071  map_it = _boundary_stress_data.find(e_id),
1072  map_end = _boundary_stress_data.end();
1073 
1074  libmesh_assert(map_it != map_end);
1075 
1076  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
1077  vec_it = map_it->second.begin(),
1078  vec_end = map_it->second.end();
1079 
1080  for ( ; vec_it != vec_end; vec_it++) {
1081 
1082  // ask this data point for the von Mises stress value
1083  e_val = (*vec_it)->von_Mises_stress();
1084  JxW_Vn = (*vec_it)->quadrature_point_JxW();
1085 
1086  // we do not use absolute value here, since von Mises stress
1087  // is >= 0.
1088  sp = pow((e_val-_sigma0)/_sigma0, _p_norm_weight);
1089  if (_rho*sp > _exp_arg_lim)
1090  exp_sp = exp(_exp_arg_lim);
1091  else
1092  exp_sp = exp(_rho * sp);
1093  denom_sens += exp_sp * JxW_Vn;
1094  num_sens += pow(e_val/_sigma0, _p_norm_stress) * exp_sp * JxW_Vn;
1095  }
1096 
1097  dsigma_vm_val_df = _sigma0/_p_norm_stress * pow(_sigma_vm_int/_JxW_val, 1./_p_norm_stress - 1.) *
1098  (num_sens / _JxW_val - _sigma_vm_int / pow(_JxW_val, 2.) * denom_sens);
1099 }
1100 
1101 
1102 
1103 
1104 void
1106  RealVectorX& dq_dX) const {
1107  libmesh_assert(!_if_stress_plot_mode);
1108  libmesh_assert(_primal_data_initialized);
1109  libmesh_assert_greater(_sigma0, 0.);
1110 
1111  Real
1112  sp_stress = 0.,
1113  sp1_stress = 0.,
1114  sp_weight = 0.,
1115  sp1_weight = 0.,
1116  exp_sp = 0.,
1117  e_val = 0.,
1118  JxW = 0.;
1119 
1120  RealVectorX
1121  denom_sens = RealVectorX::Zero(dq_dX.size()),
1122  num_sens = RealVectorX::Zero(dq_dX.size()),
1123  de_val = RealVectorX::Zero(dq_dX.size());
1124  dq_dX.setZero();
1125 
1126  // first find the data with the maximum value, to be used for scaling
1127 
1128  // iterate over all element data
1129  std::map<const libMesh::dof_id_type, std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
1130  map_it = _stress_data.find(e_id),
1131  map_end = _stress_data.end();
1132 
1133  // make sure that the data exists
1134  libmesh_assert(map_it != map_end);
1135 
1136  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
1137  vec_it = map_it->second.begin(),
1138  vec_end = map_it->second.end();
1139 
1140 
1141  for ( ; vec_it != vec_end; vec_it++) {
1142 
1143  // ask this data point for the von Mises stress value
1144  e_val = (*vec_it)->von_Mises_stress();
1145  de_val = (*vec_it)->dvon_Mises_stress_dX();
1146  JxW = (*vec_it)->quadrature_point_JxW();
1147 
1148  // we do not use absolute value here, since von Mises stress
1149  // is >= 0.
1150  sp_stress = pow(e_val/_sigma0, _p_norm_stress);
1151  sp1_stress = pow(e_val/_sigma0, _p_norm_stress-1.);
1152  sp_weight = pow((e_val-_sigma0)/_sigma0, _p_norm_weight);
1153  sp1_weight = pow((e_val-_sigma0)/_sigma0, _p_norm_weight-1.);
1154  if (_rho*sp_weight > _exp_arg_lim) {
1155 
1156  exp_sp = exp(_exp_arg_lim);
1157  denom_sens += 0. * de_val;
1158  num_sens += 1. * _p_norm_stress * sp1_stress * exp_sp/_sigma0 * JxW * de_val;
1159  }
1160  else {
1161 
1162  exp_sp = exp(_rho * sp_weight);
1163  denom_sens += exp_sp * _rho * _p_norm_weight * sp1_weight/_sigma0 * JxW * de_val;
1164  num_sens += (de_val/_sigma0 * JxW * exp_sp *
1165  (_p_norm_stress * sp1_stress +
1166  sp_stress * _rho * _p_norm_weight * sp1_weight));
1167  }
1168  }
1169 
1170  dq_dX = _sigma0/_p_norm_stress * pow(_sigma_vm_int/_JxW_val, 1./_p_norm_stress - 1.) *
1171  (num_sens / _JxW_val - _sigma_vm_int / pow(_JxW_val, 2.) * denom_sens);
1172 }
1173 
1174 
1175 
1176 
virtual Real output_sensitivity_for_elem(const MAST::FunctionBase &p)
virtual void functional_boundary_sensitivity_for_all_elems(const MAST::FunctionBase &f, Real &dsigma_vm_val_df) const
calculates and returns the sensitivity of von Mises p-norm functional for all the elements that this ...
Data(const RealVectorX &stress, const RealVectorX &strain, const libMesh::Point &qp, const libMesh::Point &xyz, Real JxW)
MAST::NonlinearSystem & system()
virtual void evaluate_sensitivity(const MAST::FunctionBase &f)
this evaluates all relevant stress sensitivity components on the element to evaluate the p-averaged q...
std::map< const MAST::FunctionBase *, RealVectorX > _stress_sensitivity
map of sensitivity of the stress with respect to a parameter
std::multimap< libMesh::subdomain_id_type, MAST::BoundaryConditionBase * > VolumeBCMapType
libMesh::Point _qp
quadrature point location in element coordinates
const MAST::ElementPropertyCardBase & get_property_card(const libMesh::Elem &elem) const
get property card for the specified element
virtual const libMesh::Elem & get_reference_elem() const
Definition: geom_elem.cpp:54
RealMatrixX _dstress_dX
derivative of stress wrt state vector
virtual bool if_evaluate_for_element(const MAST::GeomElem &elem) const
checks to see if the object has been told about the subset of elements and if the specified element i...
virtual void functional_for_all_elems()
calculates and returns the von Mises p-norm functional for all the elements that this object currentl...
const RealMatrixX & get_dstress_dX() const
Real dvon_Mises_stress_dp(const MAST::FunctionBase &f) const
void clear()
clears the data structure of any stored values so that it can be used for another element...
std::map< const libMesh::dof_id_type, std::vector< MAST::StressStrainOutputBase::Data * > > _boundary_stress_data
vector of stress with the associated location details
RealVectorX & y_vector()
returns value of the property val.
This provides the base class for definitin of element level contribution of output quantity in an ana...
void set_local_y_vector(const RealVectorX &y_vec)
for 1D elements the transformed coordinate system attached to the element defines the local x-axis al...
Definition: geom_elem.cpp:119
Real _sigma0
reference stress value used in scaling volume.
virtual void zero_for_sensitivity()
zeroes the output quantity values stored inside this object so that assembly process can begin...
virtual const std::vector< MAST::StressStrainOutputBase::Data * > & get_stress_strain_data_for_elem(const MAST::GeomElem &e) const
libMesh::Real Real
MAST::PhysicsDisciplineBase * _discipline
Real _rho
exponent used in scaling volume based on stress value.
virtual void functional_state_derivartive_for_elem(const libMesh::dof_id_type e_id, RealVectorX &dq_dX) const
calculates and returns the derivative of von Mises p-norm functional wrt state vector for the specifi...
virtual void functional_sensitivity_for_all_elems(const MAST::FunctionBase &f, Real &dsigma_vm_val_df) const
calculates and returns the sensitivity of von Mises p-norm functional for all the elements that this ...
virtual std::pair< const MAST::FieldFunction< RealVectorX > *, unsigned int > get_elem_boundary_velocity_data()
searches through the side load data and populates the data with the boundary id and velocity function...
bool _primal_data_initialized
primal data, needed for sensitivity and adjoints
const RealVectorX & get_strain_sensitivity(const MAST::FunctionBase &f) const
@ returns the sensitivity of the data with respect to a function
virtual bool is_topology_parameter() const
Definition: function_base.h:97
Real _p_norm_stress
norm to be used for calculation of output stress function.
virtual Real output_sensitivity_total(const MAST::FunctionBase &p)
const RealVectorX & get_stress_sensitivity(const MAST::FunctionBase &f) const
@ returns the sensitivity of the data with respect to a function
virtual const std::map< const libMesh::dof_id_type, std::vector< MAST::StressStrainOutputBase::Data * > > & get_stress_strain_data() const
bool _skip_comm_sum
If an output has contrinutions only from local processor then the user can request that the global co...
std::map< const libMesh::dof_id_type, std::vector< MAST::StressStrainOutputBase::Data * > > _stress_data
vector of stress with the associated location details
RealMatrixX _dstrain_dX
derivative of strain data wrt state vector
Matrix< Real, Dynamic, Dynamic > RealMatrixX
virtual void output_derivative_for_elem(RealVectorX &dq_dX)
calculates the derivative of p-norm von Mises stress for the norm identified using set_p_val()...
virtual void evaluate_topology_sensitivity(const MAST::FunctionBase &f)
this evaluates all relevant topological sensitivity components on the element.
bool has_stress_sensitivity(const MAST::FunctionBase &f) const
@ returns true if sensitivity data is available for function f .
MAST::BoundaryConditionBase * get_thermal_load_for_elem(const MAST::GeomElem &elem)
virtual void functional_boundary_sensitivity_for_elem(const MAST::FunctionBase &f, const libMesh::dof_id_type e_id, Real &dsigma_vm_val_df) const
calculates and returns the boundary sensitivity of von Mises p-norm functional for the element e...
virtual void set_elem_data(unsigned int dim, const libMesh::Elem &ref_elem, MAST::GeomElem &elem) const
sets the structural element y-vector if 1D element is used.
const libMesh::Point & point_location_in_element_coordinate() const
This class inherits from MAST::GeomElem and provides an interface to initialize FE objects on sub-ele...
unsigned int n_stress_strain_data_for_elem(const MAST::GeomElem &e) const
virtual void init(const MAST::GeomElem &elem)
initialize for the element.
Matrix< Real, Dynamic, 1 > RealVectorX
virtual void zero_for_analysis()
zeroes the output quantity values stored inside this object so that assembly process can begin...
unsigned int n_boundary_stress_strain_data_for_elem(const GeomElem &e) const
std::unique_ptr< MAST::StructuralElementBase > build_structural_element(MAST::SystemInitialization &sys, const MAST::GeomElem &elem, const MAST::ElementPropertyCardBase &p)
builds the structural element for the specified element type
virtual void clear_sensitivity_data()
clears the data stored for sensitivity analysis.
This class provides a mechanism to store stress/strain values, their derivatives and sensitivity valu...
This class acts as a wrapper around libMesh::Elem for the purpose of providing a uniform interface fo...
Definition: geom_elem.h:59
const RealVectorX & strain() const
const MAST::VolumeBCMapType & volume_loads() const
StressStrainOutputBase()
default constructor
const MAST::GeomElem & elem() const
Definition: elem_base.h:109
virtual const libMesh::Elem & get_quadrature_elem() const
Definition: geom_elem.cpp:72
const RealMatrixX & get_dstrain_dX() const
Real _JxW
quadrature point JxW (product of transformation Jacobian and quadrature weight) for use in definition...
void set_derivatives(const RealMatrixX &dstress_dX, const RealMatrixX &dstrain_dX)
adds the derivative data
virtual void evaluate()
this evaluates all relevant stress components on the element to evaluate the p-averaged quantity...
std::map< const MAST::FunctionBase *, RealVectorX > _strain_sensitivity
map of sensitivity of the strain with respect to a parameter
virtual MAST::StressStrainOutputBase::Data & get_stress_strain_data_for_elem_at_qp(const MAST::GeomElem &e, const unsigned int qp)
virtual void clear_elem()
clears the element initialization
virtual void functional_sensitivity_for_elem(const MAST::FunctionBase &f, const libMesh::dof_id_type e_id, Real &dsigma_vm_val_df) const
calculates and returns the sensitivity of von Mises p-norm functional for the element e...
bool _if_stress_plot_mode
identifies the mode in which evaluation is peformed.
virtual MAST::StressStrainOutputBase::Data & add_stress_strain_at_qp_location(const MAST::GeomElem &e, const unsigned int qp, const libMesh::Point &quadrature_pt, const libMesh::Point &physical_pt, const RealVectorX &stress, const RealVectorX &strain, Real JxW)
add the stress tensor associated with the qp.
std::set< const libMesh::Elem * > _elem_subset
set of elements for which the data will be stored.
const RealVectorX & stress() const
void set_sensitivity(const MAST::FunctionBase &f, const RealVectorX &dstress_df, const RealVectorX &dstrain_df)
sets the sensitivity of the data with respect to a function
virtual MAST::StressStrainOutputBase::Data & add_stress_strain_at_boundary_qp_location(const MAST::GeomElem &e, const unsigned int s, const unsigned int qp, const libMesh::Point &quadrature_pt, const libMesh::Point &physical_pt, const RealVectorX &stress, const RealVectorX &strain, Real JxW_Vn)
add the stress tensor associated with the qp on side s of element e.
MAST::SystemInitialization * _system