GRINS-0.8.0
multiphysics_sys.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // GRINS - General Reacting Incompressible Navier-Stokes
5 //
6 // Copyright (C) 2014-2017 Paul T. Bauman, Roy H. Stogner
7 // Copyright (C) 2010-2013 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA 02110-1301 USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 
26 // This class
27 #include "grins/multiphysics_sys.h"
28 
29 // GRINS
30 #include "grins/assembly_context.h"
33 #include "grins/bc_builder.h"
35 #include "grins/composite_qoi.h"
36 
37 // libMesh
38 #include "libmesh/composite_function.h"
39 #include "libmesh/getpot.h"
40 #include "libmesh/parameter_multiaccessor.h"
41 
42 namespace GRINS
43 {
44 
45  MultiphysicsSystem::MultiphysicsSystem( libMesh::EquationSystems& es,
46  const std::string& name,
47  const unsigned int number )
48  : FEMSystem(es, name, number),
49  _use_numerical_jacobians_only(false)
50  {}
51 
53  {
54  _physics_list = physics_list;
55  }
56 
57  void MultiphysicsSystem::read_input_options( const GetPot& input )
58  {
59  // Cache this for building boundary condition later
60  _input = &input;
61 
62  // Read options for MultiphysicsSystem first
63  this->verify_analytic_jacobians = input("linear-nonlinear-solver/verify_analytic_jacobians", 0.0 );
64  this->print_solution_norms = input("screen-options/print_solution_norms", false );
65  this->print_solutions = input("screen-options/print_solutions", false );
66  this->print_residual_norms = input("screen-options/print_residual_norms", false );
67 
68  // backwards compatibility with old config files.
70  this->print_residuals = input("screen-options/print_residual", false );
71  if (this->print_residuals)
72  libmesh_deprecated();
73 
74  this->print_residuals = input("screen-options/print_residuals", this->print_residuals );
75  this->print_jacobian_norms = input("screen-options/print_jacobian_norms", false );
76  this->print_jacobians = input("screen-options/print_jacobians", false );
77  this->print_element_solutions = input("screen-options/print_element_solutions", false );
78  this->print_element_residuals = input("screen-options/print_element_residuals", false );
79  this->print_element_jacobians = input("screen-options/print_element_jacobians", false );
80 
81  _use_numerical_jacobians_only = input("linear-nonlinear-solver/use_numerical_jacobians_only", false );
82 
83  numerical_jacobian_h =
84  input("linear-nonlinear-solver/numerical_jacobian_h",
85  numerical_jacobian_h);
86 
87  const unsigned int n_numerical_jacobian_h_values =
88  input.vector_variable_size
89  ("linear-nonlinear-solver/numerical_jacobian_h_values");
90 
91  if (n_numerical_jacobian_h_values !=
92  input.vector_variable_size
93  ("linear-nonlinear-solver/numerical_jacobian_h_variables"))
94  {
95  std::cerr << "Error: found " << n_numerical_jacobian_h_values
96  << " numerical_jacobian_h_values" << std::endl;
97  std::cerr << " but "
98  << input.vector_variable_size
99  ("linear-nonlinear-solver/numerical_jacobian_h_variables")
100  << " numerical_jacobian_h_variables" << std::endl;
101  libmesh_error();
102  }
103 
104  _numerical_jacobian_h_variables.resize(n_numerical_jacobian_h_values);
105  _numerical_jacobian_h_values.resize(n_numerical_jacobian_h_values);
106  for (unsigned int i=0; i != n_numerical_jacobian_h_values; ++i)
107  {
109  input("linear-nonlinear-solver/numerical_jacobian_h_variables",
110  "", i);
112  input("linear-nonlinear-solver/numerical_jacobian_h_values",
113  libMesh::Real(0), i);
114  }
115  }
116 
118  {
119  // Need this to be true because of our overloading of the
120  // mass_residual function.
121  // This is data in FEMSystem. MUST be set before FEMSystem::init_data.
122  use_fixed_solution = true;
123 
124  // Initalize all the variables. We pass this pointer for the system.
125  /* NOTE: We CANNOT fuse this loop with the others. This loop
126  MUST complete first. */
129  for( PhysicsListIter physics_iter = _physics_list.begin();
130  physics_iter != _physics_list.end();
131  physics_iter++ )
132  {
133  (physics_iter->second)->init_variables( this );
134  }
135 
136  libmesh_assert(_input);
138 
139  this->_constraint =
141 
142  this->attach_constraint_object(*this->_constraint);
143 
144  // If any variables need custom numerical_jacobian_h, we can set those
145  // values now that variable names are all registered with the System
146  for (unsigned int i=0; i != _numerical_jacobian_h_values.size(); ++i)
147  {
148  unsigned int var_num =
149  this->variable_number(_numerical_jacobian_h_variables[i]);
150  this->set_numerical_jacobian_h_for_var
151  (var_num, _numerical_jacobian_h_values[i]);
152  }
153 
154  // Now set time_evolving variables
155  for( PhysicsListIter physics_iter = _physics_list.begin();
156  physics_iter != _physics_list.end();
157  physics_iter++ )
158  {
159  (physics_iter->second)->set_time_evolving_vars( this );
160  }
161 
162  // Set whether the problem we're solving is steady or not
163  // Since the variable is static, just call one Physics class
164  {
165  (_physics_list.begin()->second)->set_is_steady((this->time_solver)->is_steady());
166  }
167 
168  // Next, call parent init_data function to intialize everything.
169  libMesh::FEMSystem::init_data();
170 
171  // After solution has been initialized we can project initial
172  // conditions to it
174  for( PhysicsListIter physics_iter = _physics_list.begin();
175  physics_iter != _physics_list.end();
176  physics_iter++ )
177  {
178  // Initialize builtin IC's for each physics
179  (physics_iter->second)->init_ics( this, ic_function );
180  }
181 
182  if (ic_function.n_subfunctions())
183  {
184  this->project_solution(&ic_function);
185  }
186 
187  // Now do any auxillary initialization required by each Physics
188  for( PhysicsListIter physics_iter = _physics_list.begin();
189  physics_iter != _physics_list.end();
190  physics_iter++ )
191  {
192  (physics_iter->second)->auxiliary_init( *this );
193  }
194 
195  return;
196  }
197 
198  libMesh::UniquePtr<libMesh::DiffContext> MultiphysicsSystem::build_context()
199  {
200  AssemblyContext* context = new AssemblyContext(*this);
201 
202  libMesh::UniquePtr<libMesh::DiffContext> ap(context);
203 
204  libMesh::DifferentiablePhysics* phys = libMesh::FEMSystem::get_physics();
205 
206  libmesh_assert(phys);
207 
208  // If we are solving a moving mesh problem, tell that to the Context
209  context->set_mesh_system(phys->get_mesh_system());
210  context->set_mesh_x_var(phys->get_mesh_x_var());
211  context->set_mesh_y_var(phys->get_mesh_y_var());
212  context->set_mesh_z_var(phys->get_mesh_z_var());
213 
214  ap->set_deltat_pointer( &deltat );
215 
216  // If we are solving the adjoint problem, tell that to the Context
217  ap->is_adjoint() = this->get_time_solver().is_adjoint();
218 
219  return ap;
220  }
221 
224  {
225  for( PhysicsListIter physics_iter = _physics_list.begin();
226  physics_iter != _physics_list.end();
227  physics_iter++ )
228  {
229  (physics_iter->second)->register_postprocessing_vars( input, postprocessing );
230  }
231 
232  return;
233  }
234 
236  ( const std::string & param_name,
238  {
239  //Loop over each physics to ask each for the requested parameter
240  for( PhysicsListIter physics_iter = _physics_list.begin();
241  physics_iter != _physics_list.end();
242  physics_iter++ )
243  {
244  (physics_iter->second)->register_parameter( param_name,
245  param_pointer );
246  }
247 
248  for (unsigned int bc=0; bc<_neumann_bcs.size(); bc++)
249  _neumann_bcs[bc]->get_func()->register_parameter(param_name, param_pointer);
250  }
251 
252 
253 
254  void MultiphysicsSystem::init_context( libMesh::DiffContext& context )
255  {
256  AssemblyContext& c = libMesh::cast_ref<AssemblyContext&>(context);
257 
258  //Loop over each physics to initialize relevant variable structures for assembling system
259  for( PhysicsListIter physics_iter = _physics_list.begin();
260  physics_iter != _physics_list.end();
261  physics_iter++ )
262  {
263  (physics_iter->second)->init_context( c );
264  }
265 
266  return;
267  }
268 
269  void MultiphysicsSystem::assembly( bool get_residual,
270  bool get_jacobian,
271  bool apply_heterogeneous_constraints,
272  bool apply_no_constraints )
273  {
274  // First do any preassembly that the Physics requires (which by default is none)
275  for( PhysicsListIter physics_iter = _physics_list.begin();
276  physics_iter != _physics_list.end();
277  physics_iter++ )
278  (physics_iter->second)->preassembly(*this);
279 
280  // Now do the assembly
281  libMesh::FEMSystem::assembly(get_residual,get_jacobian,
282  apply_heterogeneous_constraints,
283  apply_no_constraints);
284  }
285 
287  {
288  // First call Parent
289  FEMSystem::reinit();
290 
291  // Now do per Physics reinit (which by default is none)
292  for( PhysicsListIter physics_iter = _physics_list.begin();
293  physics_iter != _physics_list.end();
294  physics_iter++ )
295  (physics_iter->second)->reinit(*this);
296 
297  // And now reinit the QoI
298  if (this->qoi.size() > 0)
299  {
300  libMesh::DifferentiableQoI* diff_qoi = this->get_qoi();
301  CompositeQoI* qoi = libMesh::cast_ptr<CompositeQoI*>(diff_qoi);
302  qoi->reinit(*this);
303  }
304  }
305 
306  bool MultiphysicsSystem::_general_residual( bool request_jacobian,
307  libMesh::DiffContext& context,
308  ResFuncType resfunc,
309  CacheFuncType cachefunc)
310  {
311  AssemblyContext& c = libMesh::cast_ref<AssemblyContext&>(context);
312 
313  bool compute_jacobian = true;
314  if( !request_jacobian || _use_numerical_jacobians_only ) compute_jacobian = false;
315 
316  CachedValues & cache = c.get_cached_values();
317 
318  // Now compute cache for this element
319  for( PhysicsListIter physics_iter = _physics_list.begin();
320  physics_iter != _physics_list.end();
321  physics_iter++ )
322  {
323  // shared_ptr gets confused by operator->*
324  ((*(physics_iter->second)).*cachefunc)( c );
325  }
326 
327  // Loop over each physics and compute their contributions
328  for( PhysicsListIter physics_iter = _physics_list.begin();
329  physics_iter != _physics_list.end();
330  physics_iter++ )
331  {
332  if(c.has_elem())
333  {
334  if( (physics_iter->second)->enabled_on_elem( &c.get_elem() ) )
335  {
336  ((*(physics_iter->second)).*resfunc)( compute_jacobian, c );
337  }
338  }
339  else
340  {
341  ((*(physics_iter->second)).*resfunc)( compute_jacobian, c );
342  }
343  }
344 
345  // We need to clear out the cache when we're done so we don't interfere
346  // with other residual functions
347  cache.clear();
348 
349  // TODO: Need to think about the implications of this because there might be some
350  // TODO: jacobian terms we don't want to compute for efficiency reasons
351  return compute_jacobian;
352  }
353 
354  bool MultiphysicsSystem::element_time_derivative( bool request_jacobian,
355  libMesh::DiffContext& context )
356  {
357  return this->_general_residual
358  (request_jacobian,
359  context,
362  }
363 
364  bool MultiphysicsSystem::side_time_derivative( bool request_jacobian,
365  libMesh::DiffContext& context )
366  {
367  bool jacobian_computed = this->apply_neumann_bcs(request_jacobian,
368  context);
369 
370  jacobian_computed = jacobian_computed &&
371  this->_general_residual
372  (request_jacobian,
373  context,
376 
377  return jacobian_computed;
378  }
379 
380  bool MultiphysicsSystem::nonlocal_time_derivative( bool request_jacobian,
381  libMesh::DiffContext& context )
382  {
383  return this->_general_residual
384  (request_jacobian,
385  context,
388  }
389 
390  bool MultiphysicsSystem::element_constraint( bool request_jacobian,
391  libMesh::DiffContext& context )
392  {
393  return this->_general_residual
394  (request_jacobian,
395  context,
398  }
399 
400  bool MultiphysicsSystem::side_constraint( bool request_jacobian,
401  libMesh::DiffContext& context )
402  {
403  return this->_general_residual
404  (request_jacobian,
405  context,
408  }
409 
410  bool MultiphysicsSystem::nonlocal_constraint( bool request_jacobian,
411  libMesh::DiffContext& context )
412  {
413  return this->_general_residual
414  (request_jacobian,
415  context,
418  }
419 
420  bool MultiphysicsSystem::damping_residual( bool request_jacobian,
421  libMesh::DiffContext& context )
422  {
423  return this->_general_residual
424  (request_jacobian,
425  context,
428  }
429 
430  bool MultiphysicsSystem::mass_residual( bool request_jacobian,
431  libMesh::DiffContext& context )
432  {
433  return this->_general_residual
434  (request_jacobian,
435  context,
438  }
439 
440  bool MultiphysicsSystem::nonlocal_mass_residual( bool request_jacobian,
441  libMesh::DiffContext& context )
442  {
443  return this->_general_residual
444  (request_jacobian,
445  context,
448  }
449 
450  SharedPtr<Physics> MultiphysicsSystem::get_physics( const std::string physics_name )
451  {
452  if( _physics_list.find( physics_name ) == _physics_list.end() )
453  {
454  std::cerr << "Error: Could not find physics " << physics_name << std::endl;
455  libmesh_error();
456  }
457 
458  return _physics_list[physics_name];
459  }
460 
461  bool MultiphysicsSystem::has_physics( const std::string physics_name ) const
462  {
463  bool has_physics = false;
464 
465  if( _physics_list.find(physics_name) != _physics_list.end() )
466  has_physics = true;
467 
468  return has_physics;
469  }
470 
471  void MultiphysicsSystem::compute_postprocessed_quantity( unsigned int quantity_index,
472  const AssemblyContext& context,
473  const libMesh::Point& point,
474  libMesh::Real& value )
475  {
476  for( PhysicsListIter physics_iter = _physics_list.begin();
477  physics_iter != _physics_list.end();
478  physics_iter++ )
479  {
480  // Only compute if physics is active on current subdomain or globally
481  if( (physics_iter->second)->enabled_on_elem( &context.get_elem() ) )
482  {
483  (physics_iter->second)->compute_postprocessed_quantity( quantity_index, context, point, value );
484  }
485  }
486  return;
487  }
488 
490  const std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs,
491  std::vector<SharedPtr<NeumannBCContainer> >& active_neumann_bcs )
492  {
493  // Manually writing the loop since std::copy_if is C++11 only
494  for( std::vector<SharedPtr<NeumannBCContainer> >::const_iterator it = neumann_bcs.begin();
495  it < neumann_bcs.end(); ++it )
496  if( (*it)->has_bc_id( bc_id ) )
497  active_neumann_bcs.push_back( *it );
498  }
499 
500  bool MultiphysicsSystem::apply_neumann_bcs( bool request_jacobian,
501  libMesh::DiffContext& context )
502  {
503  AssemblyContext& assembly_context =
504  libMesh::cast_ref<AssemblyContext&>( context );
505 
506  std::vector<BoundaryID> ids;
507  assembly_context.side_boundary_ids(ids);
508 
509  bool compute_jacobian = request_jacobian;
510  if( !request_jacobian || _use_numerical_jacobians_only ) compute_jacobian = false;
511 
512  for( std::vector<BoundaryID>::const_iterator it = ids.begin();
513  it != ids.end(); it++ )
514  {
515  BoundaryID bc_id = *it;
516 
517  libmesh_assert_not_equal_to(bc_id, libMesh::BoundaryInfo::invalid_id);
518 
519  // Retreive the NeumannBCContainers that are active on the current bc_id
520  std::vector<SharedPtr<NeumannBCContainer> > active_neumann_bcs;
521  this->get_active_neumann_bcs( bc_id, _neumann_bcs, active_neumann_bcs );
522 
523  if( !active_neumann_bcs.empty() )
524  {
525  typedef std::vector<SharedPtr<NeumannBCContainer> >::iterator BCIt;
526 
527  for( BCIt container = active_neumann_bcs.begin(); container < active_neumann_bcs.end(); ++container )
528  {
529  SharedPtr<NeumannBCAbstract>& func = (*container)->get_func();
530 
531  const FEVariablesBase& var = (*container)->get_fe_var();
532 
533  func->eval_flux( compute_jacobian, assembly_context,
535  }
536  }
537  } // end loop over boundary ids
538 
539  return compute_jacobian;
540  }
541 
542 } // namespace GRINS
virtual void compute_element_constraint_cache(AssemblyContext &)
Definition: physics.h:218
static bool is_axisymmetric()
Definition: physics.h:132
CachedValues & get_cached_values()
virtual void compute_mass_residual_cache(AssemblyContext &)
Definition: physics.h:226
bool has_physics(const std::string physics_name) const
Query to check if a particular physics has been enabled.
static void build_boundary_conditions(const GetPot &input, MultiphysicsSystem &system, std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs)
Definition: bc_builder.C:41
void attach_physics_list(PhysicsList physics_list)
PhysicsList gets built by GRINS::PhysicsFactory and attached here.
std::vector< std::string > _numerical_jacobian_h_variables
std::vector< SharedPtr< NeumannBCContainer > > _neumann_bcs
Neumann boundary conditions.
virtual void compute_element_time_derivative_cache(AssemblyContext &)
Definition: physics.h:212
virtual void init_data()
System initialization. Calls each physics implementation of init_variables()
virtual void compute_damping_residual_cache(AssemblyContext &)
Definition: physics.h:224
void register_postprocessing_vars(const GetPot &input, PostProcessedQuantities< libMesh::Real > &postprocessing)
Each Physics will register their postprocessed quantities with this call.
virtual void side_time_derivative(bool, AssemblyContext &)
Time dependent part(s) of physics for boundaries of elements on the domain boundary.
Definition: physics.h:178
virtual bool side_constraint(bool request_jacobian, libMesh::DiffContext &context)
Boundary contributions to which do not have time varying components.
libMesh::boundary_id_type BoundaryID
More descriptive name of the type used for boundary ids.
Definition: var_typedefs.h:56
virtual bool damping_residual(bool request_jacobian, libMesh::DiffContext &context)
Contributions to .
virtual void element_time_derivative(bool, AssemblyContext &)
Time dependent part(s) of physics for element interiors.
Definition: physics.h:174
SharedPtr< GRINS::Physics > get_physics(const std::string physics_name)
libMesh::UniquePtr< libMesh::System::Constraint > _constraint
Constraint application object.
PhysicsList _physics_list
Container of pointers to GRINS::Physics classes requested at runtime.
virtual void nonlocal_constraint(bool, AssemblyContext &)
Constraint part(s) of physics for scalar variables.
Definition: physics.h:194
virtual bool nonlocal_time_derivative(bool request_jacobian, libMesh::DiffContext &context)
Contributions to on SCALAR variables which have time varying components.
virtual void compute_side_constraint_cache(AssemblyContext &)
Definition: physics.h:220
virtual void compute_postprocessed_quantity(unsigned int quantity_index, const AssemblyContext &context, const libMesh::Point &point, libMesh::Real &value)
GRINS namespace.
virtual void nonlocal_mass_residual(bool, AssemblyContext &)
Mass matrix part(s) for scalar variables.
Definition: physics.h:206
libMesh::Real neumann_bc_sign() const
void register_parameter(const std::string &param_name, libMesh::ParameterMultiAccessor< libMesh::Number > &param_pointer)
Each Physics will register its copy(s) of an independent variable.
virtual void side_constraint(bool, AssemblyContext &)
Constraint part(s) of physics for boundaries of elements on the domain boundary.
Definition: physics.h:190
virtual bool nonlocal_mass_residual(bool request_jacobian, libMesh::DiffContext &context)
Contributions to on SCALAR variables.
virtual bool element_time_derivative(bool request_jacobian, libMesh::DiffContext &context)
Element interior contributions to which have time varying components.
virtual void reinit()
Override FEMSystem::reinit.
virtual libMesh::UniquePtr< libMesh::DiffContext > build_context()
Override FEMSystem::build_context in order to use our own AssemblyContext.
virtual bool nonlocal_constraint(bool request_jacobian, libMesh::DiffContext &context)
Contributions to on SCALAR variables which do not have time varying components.
virtual void element_constraint(bool, AssemblyContext &)
Constraint part(s) of physics for element interiors.
Definition: physics.h:186
virtual void compute_nonlocal_time_derivative_cache(AssemblyContext &)
Definition: physics.h:216
virtual void mass_residual(bool, AssemblyContext &)
Mass matrix part(s) for element interiors. All boundary terms lie within the time_derivative part...
Definition: physics.h:202
virtual void compute_nonlocal_constraint_cache(AssemblyContext &)
Definition: physics.h:222
void get_active_neumann_bcs(BoundaryID bc_id, const std::vector< SharedPtr< NeumannBCContainer > > &neumann_bcs, std::vector< SharedPtr< NeumannBCContainer > > &active_neumann_bcs)
Extract the bcs from neumann_bcs that are active on bc_id and return them in active_neumann_bcs.
static libMesh::UniquePtr< libMesh::System::Constraint > build_constraint_object(const GetPot &input, MultiphysicsSystem &system)
std::map< std::string, SharedPtr< GRINS::Physics > > PhysicsList
Container for GRINS::Physics object pointers.
Definition: var_typedefs.h:59
std::vector< libMesh::Real > _numerical_jacobian_h_values
virtual void assembly(bool get_residual, bool get_jacobian, bool apply_heterogeneous_constraints=false, bool apply_no_constraints=false)
Override FEMSystem::assembly.
virtual void compute_nonlocal_mass_residual_cache(AssemblyContext &)
Definition: physics.h:228
bool _general_residual(bool request_jacobian, libMesh::DiffContext &context, ResFuncType resfunc, CacheFuncType cachefunc)
virtual bool element_constraint(bool request_jacobian, libMesh::DiffContext &context)
virtual void compute_side_time_derivative_cache(AssemblyContext &)
Definition: physics.h:214
virtual bool mass_residual(bool request_jacobian, libMesh::DiffContext &context)
Contributions to .
virtual void damping_residual(bool, AssemblyContext &)
Damping matrix part(s) for element interiors. All boundary terms lie within the time_derivative part...
Definition: physics.h:198
bool apply_neumann_bcs(bool request_jacobian, libMesh::DiffContext &context)
Applies the subset of _neumann_bcs that are active on the current element side.
virtual void nonlocal_time_derivative(bool, AssemblyContext &)
Time dependent part(s) of physics for scalar variables.
Definition: physics.h:182
MultiphysicsSystem(libMesh::EquationSystems &es, const std::string &name, const unsigned int number)
Constructor. Will be called by libMesh only.
virtual bool side_time_derivative(bool request_jacobian, libMesh::DiffContext &context)
Boundary contributions to which have time varying components.
std::map< std::string, SharedPtr< GRINS::Physics > >::const_iterator PhysicsListIter
Iterator for PhysicsList.
Definition: var_typedefs.h:62
virtual void init_context(libMesh::DiffContext &context)
Context initialization. Calls each physics implementation of init_context()
virtual void read_input_options(const GetPot &input)
Reads input options for this class and all physics that are enabled.
virtual void reinit(MultiphysicsSystem &system)
Reinitialize qoi.
const GetPot * _input
Cached for helping build boundary conditions.

Generated on Tue Dec 19 2017 12:47:28 for GRINS-0.8.0 by  doxygen 1.8.9.1