MAST
first_order_newmark_transient_solver.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
23 #include "base/elem_base.h"
25 #include "base/nonlinear_system.h"
26 
27 
28 // libMesh includes
29 #include "libmesh/numeric_vector.h"
30 
31 
32 MAST::FirstOrderNewmarkTransientSolver::FirstOrderNewmarkTransientSolver():
33 MAST::TransientSolverBase(1, 2),
34 beta(0.5)
35 { }
36 
37 
38 MAST::FirstOrderNewmarkTransientSolver::~FirstOrderNewmarkTransientSolver()
39 { }
40 
41 
42 
43 void
44 MAST::FirstOrderNewmarkTransientSolver::
45 set_element_data(const std::vector<libMesh::dof_id_type>& dof_indices,
46  const std::vector<libMesh::NumericVector<Real>*>& sols) {
47 
48  libmesh_assert_equal_to(sols.size(), 2);
49 
50  const unsigned int n_dofs = (unsigned int)dof_indices.size();
51 
52  // get the current state and velocity estimates
53  // also get the current discrete velocity replacement
55  sol = RealVectorX::Zero(n_dofs),
56  vel = RealVectorX::Zero(n_dofs);
57 
58 
59  const libMesh::NumericVector<Real>
60  &sol_global = *sols[0],
61  &vel_global = *sols[1];
62 
63  // get the references to current and previous sol and velocity
64 
65  for (unsigned int i=0; i<n_dofs; i++) {
66 
67  sol(i) = sol_global(dof_indices[i]);
68  vel(i) = vel_global(dof_indices[i]);
69  }
70 
71  _assembly_ops->set_elem_solution(sol);
72  _assembly_ops->set_elem_velocity(vel);
73 }
74 
75 
76 
77 void
78 MAST::FirstOrderNewmarkTransientSolver::
79 extract_element_sensitivity_data(const std::vector<libMesh::dof_id_type>& dof_indices,
80  const std::vector<libMesh::NumericVector<Real>*>& sols,
81  std::vector<RealVectorX>& local_sols) {
82 
83  libmesh_assert_equal_to(sols.size(), 2);
84 
85  const unsigned int n_dofs = (unsigned int)dof_indices.size();
86 
87  local_sols.resize(2);
88 
90  &sol = local_sols[0],
91  &vel = local_sols[1];
92 
93  sol = RealVectorX::Zero(n_dofs);
94  vel = RealVectorX::Zero(n_dofs);
95 
96  const libMesh::NumericVector<Real>
97  &sol_global = *sols[0],
98  &vel_global = *sols[1];
99 
100  // get the references to current and previous sol and velocity
101 
102  for (unsigned int i=0; i<n_dofs; i++) {
103 
104  sol(i) = sol_global(dof_indices[i]);
105  vel(i) = vel_global(dof_indices[i]);
106  }
107 
108 }
109 
110 
111 
112 void
113 MAST::FirstOrderNewmarkTransientSolver::
114 set_element_perturbed_data(const std::vector<libMesh::dof_id_type>& dof_indices,
115  const std::vector<libMesh::NumericVector<Real>*>& sols){
116 
117  libmesh_assert_equal_to(sols.size(), 2);
118 
119  const unsigned int n_dofs = (unsigned int)dof_indices.size();
120 
121  // get the current state and velocity estimates
122  // also get the current discrete velocity replacement
124  sol = RealVectorX::Zero(n_dofs),
125  vel = RealVectorX::Zero(n_dofs);
126 
127 
128  const libMesh::NumericVector<Real>
129  &sol_global = *sols[0],
130  &vel_global = *sols[1];
131 
132  // get the references to current and previous sol and velocity
133 
134  for (unsigned int i=0; i<n_dofs; i++) {
135 
136  sol(i) = sol_global(dof_indices[i]);
137  vel(i) = vel_global(dof_indices[i]);
138  }
139 
140  _assembly_ops->set_elem_perturbed_solution(sol);
141  _assembly_ops->set_elem_perturbed_velocity(vel);
142 }
143 
144 
145 
146 
147 
148 void
149 MAST::FirstOrderNewmarkTransientSolver::
150 update_velocity(libMesh::NumericVector<Real>& vec,
151  const libMesh::NumericVector<Real>& sol) {
152 
153  const libMesh::NumericVector<Real>
154  &prev_sol = this->solution(1),
155  &prev_vel = this->velocity(1);
156 
157  vec.zero();
158  vec.add( 1., sol);
159  vec.add(-1., prev_sol);
160  vec.scale(1./beta/dt);
161  vec.close();
162  vec.add(-(1.-beta)/beta, prev_vel);
163 
164  vec.close();
165 }
166 
167 
168 
169 void
170 MAST::FirstOrderNewmarkTransientSolver::
171 update_sensitivity_velocity(libMesh::NumericVector<Real>& vec,
172  const libMesh::NumericVector<Real>& sol) {
173 
174  const libMesh::NumericVector<Real>
175  &prev_sol = this->solution_sensitivity(1),
176  &prev_vel = this->velocity_sensitivity(1);
177 
178  vec.zero();
179  vec.add( 1., sol);
180  vec.add(-1., prev_sol);
181  vec.scale(1./beta/dt);
182  vec.close();
183  vec.add(-(1.-beta)/beta, prev_vel);
184 
185  vec.close();
186 }
187 
188 
189 
190 void
191 MAST::FirstOrderNewmarkTransientSolver::
192 update_delta_velocity(libMesh::NumericVector<Real>& vec,
193  const libMesh::NumericVector<Real>& sol) {
194 
195  vec.zero();
196  vec.add( 1./beta/dt, sol);
197  vec.close();
198 }
199 
200 
201 
202 
203 
204 void
205 MAST::FirstOrderNewmarkTransientSolver::
206 elem_calculations(bool if_jac,
207  RealVectorX& vec,
208  RealMatrixX& mat) {
209  // make sure that the assembly object is provided
210  libmesh_assert(_assembly_ops);
211  unsigned int n_dofs = (unsigned int)vec.size();
212 
214  f_x = RealVectorX::Zero(n_dofs),
215  f_m = RealVectorX::Zero(n_dofs);
216 
218  f_m_jac_xdot = RealMatrixX::Zero(n_dofs, n_dofs),
219  f_m_jac = RealMatrixX::Zero(n_dofs, n_dofs),
220  f_x_jac = RealMatrixX::Zero(n_dofs, n_dofs);
221 
222  // perform the element assembly
223  _assembly_ops->elem_calculations(if_jac,
224  f_m, // mass vector
225  f_x, // forcing vector
226  f_m_jac_xdot, // Jac of mass wrt x_dot
227  f_m_jac, // Jac of mass wrt x
228  f_x_jac); // Jac of forcing vector wrt x
229 
230  if (_if_highest_derivative_solution) {
231 
232  //
233  // The residual here is modeled as
234  // r(x, xdot) = f_m(x, xdot) + f_x(x, xdot)= 0
235  //
236  // then, given x = x0, the residual can be used to evaluate xdot0 at
237  // the same time step as
238  //
239  // r(x0, xdot) + dr/dxdot dxdot = 0
240  //
241 
242  // system residual
243  vec = (f_m + f_x);
244 
245  // system Jacobian
246  if (if_jac)
247  mat = f_m_jac_xdot;
248  }
249  else {
250  //
251  // The residual here is modeled as
252  // r = (f_m + f_x )= 0
253  // where, (for example)
254  // f_m = int_Omega phi u_dot [typical mass vector in conduction, for example]
255  // f_x = int_Omega phi_i u_i - int_Gamma phi q_n [typical conductance and heat flux combination, for example]
256  //
257  // This method assumes
258  // x = x0 + (1-beta) dt x0_dot + beta dt x_dot
259  // or, x_dot = (x-x0)/beta/dt - (1-beta)/beta x0_dot
260  //
261  // Both f_m and f_x can be functions of x_dot and x. Then, the
262  // Jacobian is
263  // dr/dx =[df_m/dx + df_x/dx +
264  // df_m/dx_dot dx_dot/dx + df_x/dx_dot dx_dot/dx]
265  // = [(df_m/dx + df_x/dx) +
266  // (df_m/dx_dot + df_x/dx_dot) (1/beta/dt)]
267  // = (df_m/dx + df_x/dx) +
268  // 1/(beta*dt)(df_m/dx_dot + df_x/dx_dot)
269  // Note that this form of equations makes it a good candidate for
270  // use as implicit solver, ie, for a nonzero beta.
271  //
272 
273 
274  // system residual
275  vec = (f_m + f_x);
276 
277  // system Jacobian
278  if (if_jac)
279  mat = (1./beta/dt)*f_m_jac_xdot + (f_m_jac + f_x_jac);
280  }
281 }
282 
283 
284 
285 void
288 
289  // make sure that the assembly object is provided
290  libmesh_assert(_assembly_ops);
291 
292  // perform the element assembly
293  _assembly_ops->linearized_jacobian_solution_product(vec);
294 }
295 
296 
297 
298 
299 void
302  RealVectorX& vec) {
303 
304  // make sure that the assembly object is provided
305  libmesh_assert(_assembly_ops);
306  unsigned int n_dofs = (unsigned int)vec.size();
307 
309  f_x = RealVectorX::Zero(n_dofs),
310  f_m = RealVectorX::Zero(n_dofs);
311 
312  // perform the element assembly
313  _assembly_ops->elem_sensitivity_calculations(f,
314  f_m, // mass vector
315  f_x); // forcing vector
316 
317  // sensitivity of system residual involving mass and internal force term
318  vec = (f_m + f_x);
319 }
320 
321 
322 
323 void
325 elem_sensitivity_contribution_previous_timestep(const std::vector<RealVectorX>& prev_sols,
326  RealVectorX& vec) {
327 
328  // make sure that the assembly object is provided
329  libmesh_assert(_assembly_ops);
330  libmesh_assert_equal_to(prev_sols.size(), 2);
331 
332  unsigned int n_dofs = (unsigned int)vec.size();
333 
334  const RealVectorX
335  &sol = prev_sols[0],
336  &vel = prev_sols[1];
338  dummy_vec = RealVectorX::Zero(n_dofs);
339 
341  f_m_jac_xdot = RealMatrixX::Zero(n_dofs, n_dofs),
342  dummy_mat = RealMatrixX::Zero(n_dofs, n_dofs);
343 
344  // perform the element assembly
345  _assembly_ops->elem_calculations(true,
346  dummy_vec, // mass vector
347  dummy_vec, // forcing vector
348  f_m_jac_xdot, // Jac of mass wrt x_dot
349  dummy_mat, // Jac of mass wrt x
350  dummy_mat); // Jac of forcing vector wrt x
351 
352  vec = -1.*(f_m_jac_xdot * ( (1./beta/dt)*sol + (1.-beta)/beta * vel));
353 }
354 
355 
356 
357 void
360  RealVectorX& vec) {
361 
362  libmesh_assert(false); // to be implemented
363 }
364 
365 
366 
367 void
371  RealVectorX& vec) {
372  libmesh_assert(false); // to be implemented
373 }
374 
375 
376 
virtual void elem_sensitivity_calculations(const MAST::FunctionBase &f, RealVectorX &vec)
performs the element sensitivity calculations over elem, and returns the element residual sensitivity...
virtual void elem_topology_sensitivity_calculations(const MAST::FunctionBase &f, const MAST::FieldFunction< RealVectorX > &vel, RealVectorX &vec)
performs the element topology sensitivity calculations over elem, and returns the element residual se...
virtual void elem_sensitivity_contribution_previous_timestep(const std::vector< RealVectorX > &prev_sols, RealVectorX &vec)
computes the contribution for this element from previous time step
Matrix< Real, Dynamic, Dynamic > RealMatrixX
Matrix< Real, Dynamic, 1 > RealVectorX
virtual void elem_linearized_jacobian_solution_product(RealVectorX &vec)
This class implements the Newmark solver for solution of a first-order ODE.
virtual void elem_shape_sensitivity_calculations(const MAST::FunctionBase &f, RealVectorX &vec)
performs the element shape sensitivity calculations over elem, and returns the element residual sensi...