GRINS-0.7.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-2016 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"
34 
35 // libMesh
36 #include "libmesh/composite_function.h"
37 #include "libmesh/getpot.h"
38 #include "libmesh/parameter_multiaccessor.h"
39 
40 namespace GRINS
41 {
42 
43  MultiphysicsSystem::MultiphysicsSystem( libMesh::EquationSystems& es,
44  const std::string& name,
45  const unsigned int number )
46  : FEMSystem(es, name, number),
47  _use_numerical_jacobians_only(false)
48  {}
49 
51  {
52  _physics_list = physics_list;
53  }
54 
55  void MultiphysicsSystem::read_input_options( const GetPot& input )
56  {
57  // Cache this for building boundary condition later
58  _input = &input;
59 
60  // Read options for MultiphysicsSystem first
61  this->verify_analytic_jacobians = input("linear-nonlinear-solver/verify_analytic_jacobians", 0.0 );
62  this->print_solution_norms = input("screen-options/print_solution_norms", false );
63  this->print_solutions = input("screen-options/print_solutions", false );
64  this->print_residual_norms = input("screen-options/print_residual_norms", false );
65 
66  // backwards compatibility with old config files.
68  this->print_residuals = input("screen-options/print_residual", false );
69  if (this->print_residuals)
70  libmesh_deprecated();
71 
72  this->print_residuals = input("screen-options/print_residuals", this->print_residuals );
73  this->print_jacobian_norms = input("screen-options/print_jacobian_norms", false );
74  this->print_jacobians = input("screen-options/print_jacobians", false );
75  this->print_element_solutions = input("screen-options/print_element_solutions", false );
76  this->print_element_residuals = input("screen-options/print_element_residuals", false );
77  this->print_element_jacobians = input("screen-options/print_element_jacobians", false );
78 
79  _use_numerical_jacobians_only = input("linear-nonlinear-solver/use_numerical_jacobians_only", false );
80 
81  numerical_jacobian_h =
82  input("linear-nonlinear-solver/numerical_jacobian_h",
83  numerical_jacobian_h);
84 
85  const unsigned int n_numerical_jacobian_h_values =
86  input.vector_variable_size
87  ("linear-nonlinear-solver/numerical_jacobian_h_values");
88 
89  if (n_numerical_jacobian_h_values !=
90  input.vector_variable_size
91  ("linear-nonlinear-solver/numerical_jacobian_h_variables"))
92  {
93  std::cerr << "Error: found " << n_numerical_jacobian_h_values
94  << " numerical_jacobian_h_values" << std::endl;
95  std::cerr << " but "
96  << input.vector_variable_size
97  ("linear-nonlinear-solver/numerical_jacobian_h_variables")
98  << " numerical_jacobian_h_variables" << std::endl;
99  libmesh_error();
100  }
101 
102  _numerical_jacobian_h_variables.resize(n_numerical_jacobian_h_values);
103  _numerical_jacobian_h_values.resize(n_numerical_jacobian_h_values);
104  for (unsigned int i=0; i != n_numerical_jacobian_h_values; ++i)
105  {
107  input("linear-nonlinear-solver/numerical_jacobian_h_variables",
108  "", i);
110  input("linear-nonlinear-solver/numerical_jacobian_h_values",
111  libMesh::Real(0), i);
112  }
113  }
114 
116  {
117  // Need this to be true because of our overloading of the
118  // mass_residual function.
119  // This is data in FEMSystem. MUST be set before FEMSystem::init_data.
120  use_fixed_solution = true;
121 
122  // Initalize all the variables. We pass this pointer for the system.
123  /* NOTE: We CANNOT fuse this loop with the others. This loop
124  MUST complete first. */
127  for( PhysicsListIter physics_iter = _physics_list.begin();
128  physics_iter != _physics_list.end();
129  physics_iter++ )
130  {
131  (physics_iter->second)->init_variables( this );
132  }
133 
134  libmesh_assert(_input);
136 
137  // If any variables need custom numerical_jacobian_h, we can set those
138  // values now that variable names are all registered with the System
139  for (unsigned int i=0; i != _numerical_jacobian_h_values.size(); ++i)
140  {
141  unsigned int var_num =
142  this->variable_number(_numerical_jacobian_h_variables[i]);
143  this->set_numerical_jacobian_h_for_var
144  (var_num, _numerical_jacobian_h_values[i]);
145  }
146 
147  // Now set time_evolving variables
148  for( PhysicsListIter physics_iter = _physics_list.begin();
149  physics_iter != _physics_list.end();
150  physics_iter++ )
151  {
152  (physics_iter->second)->set_time_evolving_vars( this );
153  }
154 
155  // Set whether the problem we're solving is steady or not
156  // Since the variable is static, just call one Physics class
157  {
158  (_physics_list.begin()->second)->set_is_steady((this->time_solver)->is_steady());
159  }
160 
161  // Next, call parent init_data function to intialize everything.
162  libMesh::FEMSystem::init_data();
163 
164  // After solution has been initialized we can project initial
165  // conditions to it
167  for( PhysicsListIter physics_iter = _physics_list.begin();
168  physics_iter != _physics_list.end();
169  physics_iter++ )
170  {
171  // Initialize builtin IC's for each physics
172  (physics_iter->second)->init_ics( this, ic_function );
173  }
174 
175  if (ic_function.n_subfunctions())
176  {
177  this->project_solution(&ic_function);
178  }
179 
180  // Now do any auxillary initialization required by each Physics
181  for( PhysicsListIter physics_iter = _physics_list.begin();
182  physics_iter != _physics_list.end();
183  physics_iter++ )
184  {
185  (physics_iter->second)->auxiliary_init( *this );
186  }
187 
188  return;
189  }
190 
191  libMesh::UniquePtr<libMesh::DiffContext> MultiphysicsSystem::build_context()
192  {
193  AssemblyContext* context = new AssemblyContext(*this);
194 
195  libMesh::UniquePtr<libMesh::DiffContext> ap(context);
196 
197  libMesh::DifferentiablePhysics* phys = libMesh::FEMSystem::get_physics();
198 
199  libmesh_assert(phys);
200 
201  // If we are solving a moving mesh problem, tell that to the Context
202  context->set_mesh_system(phys->get_mesh_system());
203  context->set_mesh_x_var(phys->get_mesh_x_var());
204  context->set_mesh_y_var(phys->get_mesh_y_var());
205  context->set_mesh_z_var(phys->get_mesh_z_var());
206 
207  ap->set_deltat_pointer( &deltat );
208 
209  // If we are solving the adjoint problem, tell that to the Context
210  ap->is_adjoint() = this->get_time_solver().is_adjoint();
211 
212  return ap;
213  }
214 
217  {
218  for( PhysicsListIter physics_iter = _physics_list.begin();
219  physics_iter != _physics_list.end();
220  physics_iter++ )
221  {
222  (physics_iter->second)->register_postprocessing_vars( input, postprocessing );
223  }
224 
225  return;
226  }
227 
229  ( const std::string & param_name,
231  {
232  //Loop over each physics to ask each for the requested parameter
233  for( PhysicsListIter physics_iter = _physics_list.begin();
234  physics_iter != _physics_list.end();
235  physics_iter++ )
236  {
237  (physics_iter->second)->register_parameter( param_name,
238  param_pointer );
239  }
240  }
241 
242 
243 
244  void MultiphysicsSystem::init_context( libMesh::DiffContext& context )
245  {
246  AssemblyContext& c = libMesh::libmesh_cast_ref<AssemblyContext&>(context);
247 
248  //Loop over each physics to initialize relevant variable structures for assembling system
249  for( PhysicsListIter physics_iter = _physics_list.begin();
250  physics_iter != _physics_list.end();
251  physics_iter++ )
252  {
253  (physics_iter->second)->init_context( c );
254  }
255 
256  return;
257  }
258 
259 
260  bool MultiphysicsSystem::_general_residual( bool request_jacobian,
261  libMesh::DiffContext& context,
262  ResFuncType resfunc,
263  CacheFuncType cachefunc)
264  {
265  AssemblyContext& c = libMesh::libmesh_cast_ref<AssemblyContext&>(context);
266 
267  bool compute_jacobian = true;
268  if( !request_jacobian || _use_numerical_jacobians_only ) compute_jacobian = false;
269 
270  CachedValues cache;
271 
272  // Now compute cache for this element
273  for( PhysicsListIter physics_iter = _physics_list.begin();
274  physics_iter != _physics_list.end();
275  physics_iter++ )
276  {
277  // shared_ptr gets confused by operator->*
278  ((*(physics_iter->second)).*cachefunc)( c, cache );
279  }
280 
281  // Loop over each physics and compute their contributions
282  for( PhysicsListIter physics_iter = _physics_list.begin();
283  physics_iter != _physics_list.end();
284  physics_iter++ )
285  {
286  if(c.has_elem())
287  {
288  if( (physics_iter->second)->enabled_on_elem( &c.get_elem() ) )
289  {
290  ((*(physics_iter->second)).*resfunc)( compute_jacobian, c, cache );
291  }
292  }
293  else
294  {
295  ((*(physics_iter->second)).*resfunc)( compute_jacobian, c, cache );
296  }
297  }
298 
299  // TODO: Need to think about the implications of this because there might be some
300  // TODO: jacobian terms we don't want to compute for efficiency reasons
301  return compute_jacobian;
302  }
303 
304  bool MultiphysicsSystem::element_time_derivative( bool request_jacobian,
305  libMesh::DiffContext& context )
306  {
307  return this->_general_residual
308  (request_jacobian,
309  context,
312  }
313 
314  bool MultiphysicsSystem::side_time_derivative( bool request_jacobian,
315  libMesh::DiffContext& context )
316  {
317  bool jacobian_computed = this->apply_neumann_bcs(request_jacobian,
318  context);
319 
320  jacobian_computed = jacobian_computed &&
321  this->_general_residual
322  (request_jacobian,
323  context,
326 
327  return jacobian_computed;
328  }
329 
330  bool MultiphysicsSystem::nonlocal_time_derivative( bool request_jacobian,
331  libMesh::DiffContext& context )
332  {
333  return this->_general_residual
334  (request_jacobian,
335  context,
338  }
339 
340  bool MultiphysicsSystem::element_constraint( bool request_jacobian,
341  libMesh::DiffContext& context )
342  {
343  return this->_general_residual
344  (request_jacobian,
345  context,
348  }
349 
350  bool MultiphysicsSystem::side_constraint( bool request_jacobian,
351  libMesh::DiffContext& context )
352  {
353  return this->_general_residual
354  (request_jacobian,
355  context,
358  }
359 
360  bool MultiphysicsSystem::nonlocal_constraint( bool request_jacobian,
361  libMesh::DiffContext& context )
362  {
363  return this->_general_residual
364  (request_jacobian,
365  context,
368  }
369 
370  bool MultiphysicsSystem::damping_residual( bool request_jacobian,
371  libMesh::DiffContext& context )
372  {
373  return this->_general_residual
374  (request_jacobian,
375  context,
378  }
379 
380  bool MultiphysicsSystem::mass_residual( bool request_jacobian,
381  libMesh::DiffContext& context )
382  {
383  return this->_general_residual
384  (request_jacobian,
385  context,
388  }
389 
390  bool MultiphysicsSystem::nonlocal_mass_residual( bool request_jacobian,
391  libMesh::DiffContext& context )
392  {
393  return this->_general_residual
394  (request_jacobian,
395  context,
398  }
399 
400  SharedPtr<Physics> MultiphysicsSystem::get_physics( const std::string physics_name )
401  {
402  if( _physics_list.find( physics_name ) == _physics_list.end() )
403  {
404  std::cerr << "Error: Could not find physics " << physics_name << std::endl;
405  libmesh_error();
406  }
407 
408  return _physics_list[physics_name];
409  }
410 
411  bool MultiphysicsSystem::has_physics( const std::string physics_name ) const
412  {
413  bool has_physics = false;
414 
415  if( _physics_list.find(physics_name) != _physics_list.end() )
416  has_physics = true;
417 
418  return has_physics;
419  }
420 
421  void MultiphysicsSystem::compute_postprocessed_quantity( unsigned int quantity_index,
422  const AssemblyContext& context,
423  const libMesh::Point& point,
424  libMesh::Real& value )
425  {
426  for( PhysicsListIter physics_iter = _physics_list.begin();
427  physics_iter != _physics_list.end();
428  physics_iter++ )
429  {
430  // Only compute if physics is active on current subdomain or globally
431  if( (physics_iter->second)->enabled_on_elem( &context.get_elem() ) )
432  {
433  (physics_iter->second)->compute_postprocessed_quantity( quantity_index, context, point, value );
434  }
435  }
436  return;
437  }
438 
440  const std::vector<SharedPtr<NeumannBCContainer> >& neumann_bcs,
441  std::vector<SharedPtr<NeumannBCContainer> >& active_neumann_bcs )
442  {
443  // Manually writing the loop since std::copy_if is C++11 only
444  for( std::vector<SharedPtr<NeumannBCContainer> >::const_iterator it = neumann_bcs.begin();
445  it < neumann_bcs.end(); ++it )
446  if( (*it)->has_bc_id( bc_id ) )
447  active_neumann_bcs.push_back( *it );
448  }
449 
450  bool MultiphysicsSystem::apply_neumann_bcs( bool request_jacobian,
451  libMesh::DiffContext& context )
452  {
453  AssemblyContext& assembly_context =
454  libMesh::libmesh_cast_ref<AssemblyContext&>( context );
455 
456  std::vector<BoundaryID> ids = assembly_context.side_boundary_ids();
457 
458  bool compute_jacobian = request_jacobian;
459  if( !request_jacobian || _use_numerical_jacobians_only ) compute_jacobian = false;
460 
461  for( std::vector<BoundaryID>::const_iterator it = ids.begin();
462  it != ids.end(); it++ )
463  {
464  BoundaryID bc_id = *it;
465 
466  libmesh_assert_not_equal_to(bc_id, libMesh::BoundaryInfo::invalid_id);
467 
468  // Retreive the NeumannBCContainers that are active on the current bc_id
469  std::vector<SharedPtr<NeumannBCContainer> > active_neumann_bcs;
470  this->get_active_neumann_bcs( bc_id, _neumann_bcs, active_neumann_bcs );
471 
472  if( !active_neumann_bcs.empty() )
473  {
474  typedef std::vector<SharedPtr<NeumannBCContainer> >::iterator BCIt;
475 
476  for( BCIt container = active_neumann_bcs.begin(); container < active_neumann_bcs.end(); ++container )
477  {
478  SharedPtr<NeumannBCAbstract>& func = (*container)->get_func();
479 
480  const FEVariablesBase& var = (*container)->get_fe_var();
481 
482  func->eval_flux( compute_jacobian, assembly_context,
484  }
485  }
486  } // end loop over boundary ids
487 
488  return compute_jacobian;
489  }
490 
491 #ifdef GRINS_USE_GRVY_TIMERS
492  void MultiphysicsSystem::attach_grvy_timer( GRVY::GRVY_Timer_Class* grvy_timer )
493  {
494  _timer = grvy_timer;
495 
496  // Attach timers to each physics
497  for( PhysicsListIter physics_iter = _physics_list.begin();
498  physics_iter != _physics_list.end();
499  physics_iter++ )
500  {
501  (physics_iter->second)->attach_grvy_timer( grvy_timer );
502  }
503 
504  return;
505  }
506 #endif
507 
508 
509 } // namespace GRINS
static bool is_axisymmetric()
Definition: physics.h:133
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 init_data()
System initialization. Calls each physics implementation of init_variables()
void register_postprocessing_vars(const GetPot &input, PostProcessedQuantities< libMesh::Real > &postprocessing)
Each Physics will register their postprocessed quantities with this call.
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 void damping_residual(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Damping matrix part(s) for element interiors. All boundary terms lie within the time_derivative part...
Definition: physics.C:230
virtual bool damping_residual(bool request_jacobian, libMesh::DiffContext &context)
Contributions to .
virtual void nonlocal_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for scalar variables.
Definition: physics.C:202
SharedPtr< GRINS::Physics > get_physics(const std::string physics_name)
PhysicsList _physics_list
Container of pointers to GRINS::Physics classes requested at runtime.
virtual void compute_mass_residual_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:176
virtual void compute_element_time_derivative_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:134
virtual bool nonlocal_time_derivative(bool request_jacobian, libMesh::DiffContext &context)
Contributions to on SCALAR variables which have time varying components.
virtual void element_constraint(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Constraint part(s) of physics for element interiors.
Definition: physics.C:209
virtual void compute_side_constraint_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:158
virtual void compute_postprocessed_quantity(unsigned int quantity_index, const AssemblyContext &context, const libMesh::Point &point, libMesh::Real &value)
GRINS namespace.
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 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 compute_element_constraint_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:152
virtual void compute_side_time_derivative_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:140
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 side_constraint(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Constraint part(s) of physics for boundaries of elements on the domain boundary.
Definition: physics.C:216
virtual void nonlocal_mass_residual(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Mass matrix part(s) for scalar variables.
Definition: physics.C:244
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.
virtual void compute_damping_residual_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:170
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 element_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for element interiors.
Definition: physics.C:188
bool _general_residual(bool request_jacobian, libMesh::DiffContext &context, ResFuncType resfunc, CacheFuncType cachefunc)
virtual void side_time_derivative(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Time dependent part(s) of physics for boundaries of elements on the domain boundary.
Definition: physics.C:195
virtual bool element_constraint(bool request_jacobian, libMesh::DiffContext &context)
virtual bool mass_residual(bool request_jacobian, libMesh::DiffContext &context)
Contributions to .
virtual void compute_nonlocal_mass_residual_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:182
virtual void compute_nonlocal_time_derivative_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:146
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 compute_nonlocal_constraint_cache(const AssemblyContext &context, CachedValues &cache)
Definition: physics.C:164
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 nonlocal_constraint(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Constraint part(s) of physics for scalar variables.
Definition: physics.C:223
virtual void read_input_options(const GetPot &input)
Reads input options for this class and all physics that are enabled.
const GetPot * _input
Cached for helping build boundary conditions.
virtual void mass_residual(bool compute_jacobian, AssemblyContext &context, CachedValues &cache)
Mass matrix part(s) for element interiors. All boundary terms lie within the time_derivative part...
Definition: physics.C:237

Generated on Thu Jun 2 2016 21:52:28 for GRINS-0.7.0 by  doxygen 1.8.10