MAST
Multidisciplinary-design Adaptation and Sensitivity Toolkit (MAST)
stress_assembly.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
25 #include "base/nonlinear_system.h"
26 #include "mesh/geom_elem.h"
27 
28 // libMesh includes
29 #include "libmesh/system.h"
30 #include "libmesh/dof_map.h"
31 #include "libmesh/numeric_vector.h"
32 
34 MAST::AssemblyBase() {
35 
36 }
37 
38 
40 
41 }
42 
43 
44 
45 void
46 get_max_stress_strain_values(const std::vector<MAST::StressStrainOutputBase::Data*>& data,
47  RealVectorX& max_strain,
48  RealVectorX& max_stress,
49  Real& max_vm,
50  const MAST::FunctionBase* p) {
51 
52  max_strain = RealVectorX::Zero(6);
53  max_stress = RealVectorX::Zero(6);
54  max_vm = 0.;
55 
56  // if there is only one data point, then simply copy the value to the output
57  // routines
58  if (data.size() == 1) {
59  if (p == nullptr) {
60  max_strain = data[0]->strain();
61  max_stress = data[0]->stress();
62  max_vm = data[0]->von_Mises_stress();
63  }
64  else {
65  max_strain = data[0]->get_strain_sensitivity(*p);
66  max_stress = data[0]->get_stress_sensitivity(*p);
67  max_vm = data[0]->dvon_Mises_stress_dp (*p);
68  }
69 
70  return;
71  }
72 
73  // if multiple values are provided for an element, then we need to compare
74  std::vector<MAST::StressStrainOutputBase::Data*>::const_iterator
75  it = data.begin(),
76  end = data.end();
77 
78  Real
79  vm = 0.;
80 
81  for ( ; it != end; it++) {
82 
83  // get the strain value at this point
84  const RealVectorX& strain = (*it)->strain();
85  const RealVectorX& stress = (*it)->stress();
86  vm = (*it)->von_Mises_stress();
87 
88  // now compare
89  if (vm > max_vm) max_vm = vm;
90 
91  for ( unsigned int i=0; i<6; i++) {
92  if (fabs(strain(i)) > fabs(max_strain(i))) max_strain(i) = strain(i);
93  if (fabs(stress(i)) > fabs(max_stress(i))) max_stress(i) = stress(i);
94  }
95  }
96 }
97 
98 
99 
100 
103  const libMesh::NumericVector<Real>& X) {
104 
105  // make sure it has been initialized
106  libmesh_assert(_system);
107  libmesh_assert(_discipline);
108  libmesh_assert(!_elem_ops);
109 
110  this->set_elem_operation_object(ops);
111 
112  RealVectorX sol;
113 
114  const MAST::NonlinearSystem&
115  structural_sys = _system->system();
116 
117  libMesh::System&
118  stress_sys = dynamic_cast<MAST::StructuralSystemInitialization*>(_system)->get_stress_sys();
119  const std::vector<unsigned int>&
120  stress_vars = dynamic_cast<MAST::StructuralSystemInitialization*>(_system)->get_stress_var_ids();
121 
122  stress_sys.solution->zero();
123 
124  std::vector<libMesh::dof_id_type> dof_indices;
125  const libMesh::DofMap& dof_map = structural_sys.get_dof_map();
126 
127  std::unique_ptr<libMesh::NumericVector<Real> > localized_solution;
128  localized_solution.reset(this->build_localized_vector(structural_sys,
129  X).release());
130 
131 
132  libMesh::MeshBase::const_element_iterator el =
133  structural_sys.get_mesh().active_local_elements_begin();
134  const libMesh::MeshBase::const_element_iterator end_el =
135  structural_sys.get_mesh().active_local_elements_end();
136 
137  libMesh::dof_id_type
138  dof_id = 0;
139 
140  unsigned int
141  sys_num = stress_sys.number();
142 
144  max_strain_vals = RealVectorX::Zero(6),
145  max_stress_vals = RealVectorX::Zero(6);
146 
147  Real
148  max_vm_stress = 0.;
149 
150  for ( ; el != end_el; el++) {
151 
152  const libMesh::Elem* elem = *el;
153 
154  // clear before calculating the data
155  ops.clear();
156  MAST::GeomElem geom_elem;
157  ops.set_elem_data(elem->dim(), *elem, geom_elem);
158  geom_elem.init(*elem, *_system);
159 
160  if (!ops.if_evaluate_for_element(geom_elem)) continue;
161 
162  dof_map.dof_indices (elem, dof_indices);
163 
164  unsigned int ndofs = (unsigned int)dof_indices.size();
165  sol.setZero(ndofs);
166 
167  for (unsigned int i=0; i<dof_indices.size(); i++)
168  sol(i) = (*localized_solution)(dof_indices[i]);
169 
170  ops.init(geom_elem);
171  ops.set_elem_solution(sol);
172  ops.evaluate();
173  ops.clear_elem();
174 
175  // get the stress-strain data map from the object
176  const std::map<const libMesh::dof_id_type,
177  std::vector<MAST::StressStrainOutputBase::Data*> >& output_map =
179 
180  // make sure that only one element has been added to this data,
181  // and that the element id is the same as the one being computed
182  libmesh_assert_equal_to(output_map.size(), 1);
183  libmesh_assert_equal_to(output_map.begin()->first, elem->id());
184 
185  // now iterate over all the elements and set the value in the
186  // new system used for output
187  std::map<const libMesh::dof_id_type,
188  std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
189  e_it = output_map.begin(),
190  e_end = output_map.end();
191 
192  for ( ; e_it != e_end; e_it++) {
193 
194  get_max_stress_strain_values(e_it->second,
195  max_strain_vals,
196  max_stress_vals,
197  max_vm_stress,
198  nullptr);
199 
200  // set the values in the system
201  // stress value
202  dof_id = elem->dof_number(sys_num, stress_vars[12], 0);
203  stress_sys.solution->set(dof_id, max_vm_stress);
204 
205  for (unsigned int i=0; i<6; i++) {
206  // strain value
207  dof_id = elem->dof_number(sys_num, stress_vars[i], 0);
208  stress_sys.solution->set(dof_id, max_strain_vals(i));
209 
210  // stress value
211  dof_id = elem->dof_number(sys_num, stress_vars[i+6], 0);
212  stress_sys.solution->set(dof_id, max_stress_vals(i));
213  }
214  }
215  }
216 
217  stress_sys.solution->close();
219 }
220 
221 
222 
223 
224 
227  const libMesh::NumericVector<Real>& X,
228  const libMesh::NumericVector<Real>& dXdp,
229  const MAST::FunctionBase& p,
230  libMesh::NumericVector<Real>& dsigmadp) {
231 
232  // make sure it has been initialized
233  libmesh_assert(_system);
234  libmesh_assert(_discipline);
235  libmesh_assert(!_elem_ops);
236 
237  this->set_elem_operation_object(ops);
238 
240  sol,
241  dsol;
242 
243  const MAST::NonlinearSystem&
244  structural_sys = _system->system();
245 
246  libMesh::System&
247  stress_sys = dynamic_cast<MAST::StructuralSystemInitialization*>(_system)->get_stress_sys();
248  const std::vector<unsigned int>&
249  stress_vars = dynamic_cast<MAST::StructuralSystemInitialization*>(_system)->get_stress_var_ids();
250 
251  dsigmadp.zero();
252 
253  std::vector<libMesh::dof_id_type> dof_indices;
254  const libMesh::DofMap& dof_map = structural_sys.get_dof_map();
255 
256  std::unique_ptr<libMesh::NumericVector<Real> >
257  localized_solution,
258  localized_solution_sens;
259  localized_solution.reset(this->build_localized_vector(structural_sys,
260  X).release());
261  localized_solution_sens.reset(this->build_localized_vector(structural_sys,
262  dXdp).release());
263 
264 
265  libMesh::MeshBase::const_element_iterator el =
266  structural_sys.get_mesh().active_local_elements_begin();
267  const libMesh::MeshBase::const_element_iterator end_el =
268  structural_sys.get_mesh().active_local_elements_end();
269 
270  libMesh::dof_id_type
271  dof_id = 0;
272 
273  unsigned int
274  sys_num = stress_sys.number();
275 
277  max_strain_vals = RealVectorX::Zero(6),
278  max_stress_vals = RealVectorX::Zero(6);
279 
280  Real
281  max_vm_stress = 0.;
282 
283  for ( ; el != end_el; el++) {
284 
285  const libMesh::Elem* elem = *el;
286 
287  // clear before calculating the data. We have to calculate the stress
288  // before calculating sensitivity since the sensitivity assumes the
289  // presence of stress data, which is cleared after each element.
290  ops.clear();
291  MAST::GeomElem geom_elem;
292  ops.set_elem_data(elem->dim(), *elem, geom_elem);
293  geom_elem.init(*elem, *_system);
294 
295  if (!ops.if_evaluate_for_element(geom_elem)) continue;
296 
297  dof_map.dof_indices (elem, dof_indices);
298 
299  unsigned int ndofs = (unsigned int)dof_indices.size();
300  sol.setZero(ndofs);
301  dsol.setZero(ndofs);
302 
303  for (unsigned int i=0; i<dof_indices.size(); i++) {
304  sol (i) = (*localized_solution) (dof_indices[i]);
305  dsol(i) = (*localized_solution_sens)(dof_indices[i]);
306  }
307 
308  ops.init(geom_elem);
309  ops.set_stress_plot_mode(true);
310  ops.set_elem_solution(sol);
312  ops.evaluate();
313  ops.evaluate_sensitivity(p);
314  ops.clear_elem();
315 
316  // get the stress-strain data map from the object
317  const std::map<const libMesh::dof_id_type,
318  std::vector<MAST::StressStrainOutputBase::Data*> >& output_map =
320 
321  // make sure that only one element has been added to this data,
322  // and that the element id is the same as the one being computed
323  libmesh_assert_equal_to(output_map.size(), 1);
324  libmesh_assert_equal_to(output_map.begin()->first, elem->id());
325 
326  // now iterate over all the elements and set the value in the
327  // new system used for output
328  std::map<const libMesh::dof_id_type,
329  std::vector<MAST::StressStrainOutputBase::Data*> >::const_iterator
330  e_it = output_map.begin(),
331  e_end = output_map.end();
332 
333  for ( ; e_it != e_end; e_it++) {
334 
335  get_max_stress_strain_values(e_it->second,
336  max_strain_vals,
337  max_stress_vals,
338  max_vm_stress,
339  &p);
340 
341  // set the values in the system
342  // stress value
343  dof_id = elem->dof_number(sys_num, stress_vars[12], 0);
344  dsigmadp.set(dof_id, max_vm_stress);
345 
346  for (unsigned int i=0; i<6; i++) {
347  // strain value
348  dof_id = elem->dof_number(sys_num, stress_vars[i], 0);
349  dsigmadp.set(dof_id, max_strain_vals(i));
350 
351  // stress value
352  dof_id = elem->dof_number(sys_num, stress_vars[i+6], 0);
353  dsigmadp.set(dof_id, max_stress_vals(i));
354  }
355  }
356  }
357 
358  dsigmadp.close();
359  ops.set_stress_plot_mode(false);
361 }
362 
363 
364 
MAST::AssemblyElemOperations * _elem_ops
provides assembly elem operations for use by this class
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...
StressAssembly()
constructor associates this assembly object with the system
Data structure provides the mechanism to store stress and strain output from a structural analysis...
virtual ~StressAssembly()
destructor resets the association of this assembly object with the system
This class implements a system for solution of nonlinear systems.
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 clear_elem_operation_object()
clears the association of this object with the assembly element operation object. ...
void get_max_stress_strain_values(const std::vector< MAST::StressStrainOutputBase::Data *> &data, RealVectorX &max_strain, RealVectorX &max_stress, Real &max_vm, const MAST::FunctionBase *p)
void clear()
clears the data structure of any stored values so that it can be used for another element...
virtual void set_elem_solution_sensitivity(const RealVectorX &sol)
sets the element solution sensitivity
void set_stress_plot_mode(bool f)
tells the object that the calculation is for stress to be output for plotting.
virtual void set_elem_operation_object(MAST::AssemblyElemOperations &elem_ops)
attaches a element operation to this object, and associated this with the element operation object...
virtual void set_elem_solution(const RealVectorX &sol)
sets the element solution
libMesh::Real Real
MAST::SystemInitialization * _system
System for which this assembly is performed.
virtual void update_stress_strain_data(MAST::StressStrainOutputBase &ops, const libMesh::NumericVector< Real > &X)
updates the stresses and strains for the specified solution vector X.
MAST::PhysicsDisciplineBase * _discipline
PhysicsDisciplineBase object for which this class is assembling.
virtual const std::map< const libMesh::dof_id_type, std::vector< MAST::StressStrainOutputBase::Data * > > & get_stress_strain_data() const
std::unique_ptr< libMesh::NumericVector< Real > > build_localized_vector(const libMesh::System &sys, const libMesh::NumericVector< Real > &global) const
localizes the parallel vector so that the local copy stores all values necessary for calculation of t...
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.
virtual void init(const MAST::GeomElem &elem)
initialize for the element.
Matrix< Real, Dynamic, 1 > RealVectorX
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 evaluate()
this evaluates all relevant stress components on the element to evaluate the p-averaged quantity...
virtual void clear_elem()
clears the element initialization
virtual void update_stress_strain_sensitivity_data(MAST::StressStrainOutputBase &ops, const libMesh::NumericVector< Real > &X, const libMesh::NumericVector< Real > &dXdp, const MAST::FunctionBase &p, libMesh::NumericVector< Real > &dsigmadp)
updates the sensitivity of stresses and strains for the specified solution vector X and its sensitivi...
virtual void init(const libMesh::Elem &elem, const MAST::SystemInitialization &sys_init)
initialize the object for the specified reference elem.
Definition: geom_elem.cpp:134