GRINS-0.6.0
Public Types | Public Member Functions | Protected Member Functions | List of all members
GRINS::PhysicsFactory Class Reference

Object for constructing list of physics for simulation. More...

#include <physics_factory.h>

Public Types

typedef std::tr1::shared_ptr< PhysicsPhysicsPtr
 
typedef std::pair< std::string, PhysicsPtrPhysicsPair
 

Public Member Functions

 PhysicsFactory ()
 
virtual ~PhysicsFactory ()
 Destructor does not need to delete std::tr1::shared_ptr's. More...
 
GRINS::PhysicsList build (const GetPot &input)
 Builds PhysicsList. This is the primary function of this class. More...
 

Protected Member Functions

virtual void add_physics (const GetPot &input, const std::string &physics_to_add, GRINS::PhysicsList &physics_list)
 Figures out which GRINS::Physics pointer to create. More...
 
virtual void check_physics_consistency (const GRINS::PhysicsList &physics_list)
 Make sure the requested GRINS::Physics classes are consistent. More...
 
void physics_consistency_error (const std::string physics_checked, const std::string physics_required) const
 Utility function. More...
 

Detailed Description

Object for constructing list of physics for simulation.

PhysicsFactory will construct the appropriate GRINS::PhysicsList to be handed to the GRINS::MultiphysicsSystem class. The list of GRINS::Physics objects constructed is set at run time.

Definition at line 45 of file physics_factory.h.

Member Typedef Documentation

typedef std::pair< std::string, PhysicsPtr > GRINS::PhysicsFactory::PhysicsPair

Definition at line 58 of file physics_factory.h.

typedef std::tr1::shared_ptr<Physics> GRINS::PhysicsFactory::PhysicsPtr

Definition at line 57 of file physics_factory.h.

Constructor & Destructor Documentation

GRINS::PhysicsFactory::PhysicsFactory ( )

Definition at line 385 of file physics_factory.C.

386  {
387  return;
388  }
GRINS::PhysicsFactory::~PhysicsFactory ( )
virtual

Destructor does not need to delete std::tr1::shared_ptr's.

Definition at line 390 of file physics_factory.C.

391  {
392  return;
393  }

Member Function Documentation

void GRINS::PhysicsFactory::add_physics ( const GetPot &  input,
const std::string &  physics_to_add,
GRINS::PhysicsList physics_list 
)
protectedvirtual

Figures out which GRINS::Physics pointer to create.

This is the primary method to override if the user wants to extend the physics capabilities. The strategy is to conditionally add the physics you want, then call the parent PhysicsFactory::add_physics function.

Definition at line 441 of file physics_factory.C.

References GRINS::averaged_fan, GRINS::averaged_fan_adjoint_stab, GRINS::averaged_turbine, GRINS::axisymmetric_boussinesq_buoyancy, GRINS::axisymmetric_heat_transfer, GRINS::boussinesq_buoyancy, GRINS::boussinesq_buoyancy_adjoint_stab, GRINS::boussinesq_buoyancy_spgsm_stab, GRINS::constant_source_term, GRINS::elastic_cable, GRINS::elastic_cable_constant_gravity, GRINS::elastic_membrane, GRINS::elastic_membrane_constant_pressure, GRINS::heat_transfer, GRINS::heat_transfer_adjoint_stab, GRINS::heat_transfer_source, GRINS::heat_transfer_spgsm_stab, GRINS::incompressible_navier_stokes, GRINS::incompressible_navier_stokes_adjoint_stab, GRINS::incompressible_navier_stokes_spgsm_stab, GRINS::low_mach_navier_stokes, GRINS::low_mach_navier_stokes_braack_stab, GRINS::low_mach_navier_stokes_spgsm_stab, GRINS::low_mach_navier_stokes_vms_stab, GRINS::new_mu_class< SpalartAllmaras >(), GRINS::parsed_source_term, GRINS::parsed_velocity_source, GRINS::parsed_velocity_source_adjoint_stab, GRINS::reacting_low_mach_navier_stokes, GRINS::scalar_ode, GRINS::spalart_allmaras, GRINS::spalart_allmaras_spgsm_stab, GRINS::stokes, GRINS::velocity_drag, GRINS::velocity_drag_adjoint_stab, GRINS::velocity_penalty, GRINS::velocity_penalty2, GRINS::velocity_penalty2_adjoint_stab, GRINS::velocity_penalty3, GRINS::velocity_penalty3_adjoint_stab, and GRINS::velocity_penalty_adjoint_stab.

Referenced by build().

444  {
445  if( physics_to_add == incompressible_navier_stokes )
446  {
447  physics_list[physics_to_add] =
448  new_mu_class<IncompressibleNavierStokes>
449  (physics_to_add, input);
450  }
451  else if( physics_to_add == stokes )
452  {
453  physics_list[physics_to_add] =
454  new_mu_class<Stokes>
455  (physics_to_add, input);
456  }
457  else if( physics_to_add == incompressible_navier_stokes_adjoint_stab )
458  {
459  physics_list[physics_to_add] =
460  new_mu_class<IncompressibleNavierStokesAdjointStabilization>
461  (physics_to_add, input);
462  }
463  else if( physics_to_add == incompressible_navier_stokes_spgsm_stab )
464  {
465  physics_list[physics_to_add] =
466  new_mu_class<IncompressibleNavierStokesSPGSMStabilization>
467  (physics_to_add, input);
468  }
469  else if( physics_to_add == velocity_drag )
470  {
471  physics_list[physics_to_add] =
472  new_mu_class<VelocityDrag>
473  (physics_to_add, input);
474  }
475  else if( physics_to_add == velocity_drag_adjoint_stab )
476  {
477  physics_list[physics_to_add] =
478  new_mu_class<VelocityDragAdjointStabilization>
479  (physics_to_add, input);
480  }
481  else if( physics_to_add == velocity_penalty ||
482  physics_to_add == velocity_penalty2 ||
483  physics_to_add == velocity_penalty3)
484  {
485  physics_list[physics_to_add] =
486  new_mu_class<VelocityPenalty>
487  (physics_to_add, input);
488  }
489  else if( physics_to_add == velocity_penalty_adjoint_stab ||
490  physics_to_add == velocity_penalty2_adjoint_stab ||
491  physics_to_add == velocity_penalty3_adjoint_stab )
492  {
493  physics_list[physics_to_add] =
494  new_mu_class<VelocityPenaltyAdjointStabilization>
495  (physics_to_add, input);
496  }
497  else if( physics_to_add == parsed_velocity_source )
498  {
499  physics_list[physics_to_add] =
500  new_mu_class<ParsedVelocitySource>
501  (physics_to_add, input);
502  }
503  else if( physics_to_add == parsed_velocity_source_adjoint_stab )
504  {
505  physics_list[physics_to_add] =
506  new_mu_class<ParsedVelocitySourceAdjointStabilization>
507  (physics_to_add, input);
508  }
509  else if( physics_to_add == averaged_fan )
510  {
511  physics_list[physics_to_add] =
512  new_mu_class<AveragedFan>
513  (physics_to_add, input);
514  }
515  else if( physics_to_add == averaged_fan_adjoint_stab )
516  {
517  physics_list[physics_to_add] =
518  new_mu_class<AveragedFanAdjointStabilization>
519  (physics_to_add, input);
520  }
521  else if( physics_to_add == averaged_turbine )
522  {
523  physics_list[physics_to_add] =
524  new_mu_class<AveragedTurbine>
525  (physics_to_add, input);
526  }
527  else if( physics_to_add == spalart_allmaras )
528  {
529  physics_list[physics_to_add] =
531  (physics_to_add, input);
532  }
533  else if( physics_to_add == spalart_allmaras_spgsm_stab )
534  {
535  physics_list[physics_to_add] =
536  new_turb_mu_class<SpalartAllmarasSPGSMStabilization>
537  (physics_to_add, input);
538  }
539  else if( physics_to_add == scalar_ode )
540  {
541  physics_list[physics_to_add] =
542  PhysicsPtr(new ScalarODE(physics_to_add,input));
543  }
544  else if( physics_to_add == heat_transfer )
545  {
546  physics_list[physics_to_add] =
547  new_k_class<HeatTransfer>
548  (physics_to_add, input);
549  }
550  else if( physics_to_add == heat_transfer_adjoint_stab )
551  {
552  physics_list[physics_to_add] =
553  new_k_class<HeatTransferAdjointStabilization>
554  (physics_to_add, input);
555  }
556  else if( physics_to_add == heat_transfer_spgsm_stab )
557  {
558  physics_list[physics_to_add] =
559  new_k_class<HeatTransferSPGSMStabilization>
560  (physics_to_add, input);
561  }
562  else if( physics_to_add == heat_transfer_source )
563  {
564  std::string source_function = input( "Physics/"+physics_to_add+"/source_function", "constant" );
565  if( source_function == "constant")
566  {
567  physics_list[physics_to_add] =
568  PhysicsPtr(new HeatTransferSource<ConstantSourceFunction>(physics_to_add,input));
569  }
570  else
571  {
572  std::cerr << "================================================================" << std::endl
573  << "Invalid combination of models for " << physics_to_add << std::endl
574  << "Source function = " << source_function << std::endl
575  << "================================================================" << std::endl;
576  libmesh_error();
577  }
578  }
579  else if( physics_to_add == axisymmetric_heat_transfer )
580  {
581  physics_list[physics_to_add] =
582  new_k_class<AxisymmetricHeatTransfer>
583  (physics_to_add, input);
584  }
585  else if( physics_to_add == boussinesq_buoyancy )
586  {
587  physics_list[physics_to_add] =
588  PhysicsPtr(new BoussinesqBuoyancy(physics_to_add,input));
589  }
590  else if( physics_to_add == boussinesq_buoyancy_adjoint_stab )
591  {
592  physics_list[physics_to_add] =
593  new_mu_class<BoussinesqBuoyancyAdjointStabilization>
594  (physics_to_add, input);
595  }
596  else if( physics_to_add == boussinesq_buoyancy_spgsm_stab )
597  {
598  physics_list[physics_to_add] =
599  new_mu_class<BoussinesqBuoyancySPGSMStabilization>
600  (physics_to_add, input);
601  }
602  else if( physics_to_add == axisymmetric_boussinesq_buoyancy)
603  {
604  physics_list[physics_to_add] =
605  PhysicsPtr(new AxisymmetricBoussinesqBuoyancy(physics_to_add,input));
606  }
607  else if( physics_to_add == "HeatConduction" )
608  {
609  physics_list[physics_to_add] =
610  new_k_class<HeatConduction>
611  (physics_to_add, input);
612  }
613  else if( physics_to_add == low_mach_navier_stokes )
614  {
615  physics_list[physics_to_add] =
616  new_mu_cp_k_class<LowMachNavierStokes>
617  (physics_to_add, input);
618  }
619  else if( physics_to_add == low_mach_navier_stokes_spgsm_stab )
620  {
621  physics_list[physics_to_add] =
622  new_mu_cp_k_class<LowMachNavierStokesSPGSMStabilization>
623  (physics_to_add, input);
624  }
625  else if( physics_to_add == low_mach_navier_stokes_vms_stab )
626  {
627  physics_list[physics_to_add] =
628  new_mu_cp_k_class<LowMachNavierStokesVMSStabilization>
629  (physics_to_add, input);
630  }
631  else if( physics_to_add == low_mach_navier_stokes_braack_stab )
632  {
633  physics_list[physics_to_add] =
634  new_mu_cp_k_class<LowMachNavierStokesBraackStabilization>
635  (physics_to_add, input);
636  }
637  else if( physics_to_add == reacting_low_mach_navier_stokes )
638  {
639  physics_list[physics_to_add] =
640  new_reacting_low_mach_class<ReactingLowMachNavierStokes>
641  (physics_to_add, input);
642  }
643  else if( physics_to_add == elastic_membrane )
644  {
645  std::string elasticity_model = input("Physics/"+elastic_membrane+"/elasticity_model", "HookesLaw" );
646 
647  if( elasticity_model == std::string("HookesLaw") )
648  {
649  physics_list[physics_to_add] =
650  PhysicsPtr(new ElasticMembrane<HookesLaw>(physics_to_add,input,false /*is_compressible*/));
651  }
652  else if( elasticity_model == std::string("MooneyRivlin") )
653  {
654  physics_list[physics_to_add] =
655  // \lambda determined from incompressiblity
656  PhysicsPtr(new ElasticMembrane<IncompressiblePlaneStressHyperelasticity<MooneyRivlin> >(physics_to_add,input,false /*is_compressible*/));
657  }
658  else
659  {
660  std::cerr << "Error: Invalid elasticity_model: " << elasticity_model << std::endl
661  << " Valid selections are: Hookean" << std::endl;
662  libmesh_error();
663  }
664  }
665  else if( physics_to_add == elastic_membrane_constant_pressure )
666  {
667  physics_list[physics_to_add] =
668  PhysicsPtr(new ElasticMembraneConstantPressure(physics_to_add,input));
669  }
670  else if( physics_to_add == elastic_cable )
671  {
672  std::string elasticity_model = input("Physics/"+elastic_cable+"/elasticity_model", "HookesLaw" );
673 
674  if( elasticity_model == std::string("HookesLaw") )
675  {
676  physics_list[physics_to_add] =
677  PhysicsPtr(new ElasticCable<HookesLaw1D>(physics_to_add,input,false /*is_compressible*/));
678  }
679  else
680  {
681  std::cerr << "Error: Invalid elasticity_model: " << elasticity_model << std::endl
682  << " Valid selections are: Hookean" << std::endl;
683  libmesh_error();
684  }
685  }
686  else if( physics_to_add == elastic_cable_constant_gravity )
687  {
688  physics_list[physics_to_add] =
689  PhysicsPtr(new ElasticCableConstantGravity(physics_to_add,input));
690  }
691  else if( physics_to_add == constant_source_term )
692  {
693  physics_list[physics_to_add] =
694  PhysicsPtr(new ConstantSourceTerm(physics_to_add,input));
695  }
696  else if( physics_to_add == parsed_source_term )
697  {
698  physics_list[physics_to_add] =
699  PhysicsPtr(new ParsedSourceTerm(physics_to_add,input));
700  }
701  else
702  {
703  std::cerr << "Error: Invalid physics name " << physics_to_add << std::endl;
704  libmesh_error();
705  }
706 
707  return;
708  }
const PhysicsName parsed_velocity_source_adjoint_stab
const PhysicsName incompressible_navier_stokes_spgsm_stab
const PhysicsName incompressible_navier_stokes
const PhysicsName parsed_source_term
const PhysicsName elastic_cable_constant_gravity
const PhysicsName incompressible_navier_stokes_adjoint_stab
const PhysicsName axisymmetric_heat_transfer
const PhysicsName boussinesq_buoyancy_adjoint_stab
PhysicsPtr new_mu_class< SpalartAllmaras >(const std::string &physics_to_add, const GetPot &input)
const PhysicsName velocity_drag_adjoint_stab
const PhysicsName averaged_turbine
const PhysicsName spalart_allmaras
const PhysicsName spalart_allmaras_spgsm_stab
const PhysicsName averaged_fan_adjoint_stab
const PhysicsName heat_transfer_spgsm_stab
const PhysicsName elastic_membrane
const PhysicsName velocity_penalty2_adjoint_stab
const PhysicsName elastic_cable
const PhysicsName velocity_penalty_adjoint_stab
const PhysicsName scalar_ode
const PhysicsName boussinesq_buoyancy_spgsm_stab
const PhysicsName heat_transfer_source
const PhysicsName elastic_membrane_constant_pressure
const PhysicsName stokes
const PhysicsName parsed_velocity_source
const PhysicsName velocity_penalty3
const PhysicsName velocity_penalty2
const PhysicsName low_mach_navier_stokes
const PhysicsName heat_transfer
const PhysicsName low_mach_navier_stokes_braack_stab
std::tr1::shared_ptr< Physics > PhysicsPtr
const PhysicsName reacting_low_mach_navier_stokes
const PhysicsName boussinesq_buoyancy
const PhysicsName low_mach_navier_stokes_vms_stab
const PhysicsName heat_transfer_adjoint_stab
const PhysicsName axisymmetric_boussinesq_buoyancy
const PhysicsName velocity_penalty3_adjoint_stab
const PhysicsName low_mach_navier_stokes_spgsm_stab
const PhysicsName averaged_fan
const PhysicsName velocity_penalty
const PhysicsName velocity_drag
const PhysicsName constant_source_term
PhysicsList GRINS::PhysicsFactory::build ( const GetPot &  input)

Builds PhysicsList. This is the primary function of this class.

Definition at line 395 of file physics_factory.C.

References add_physics(), and check_physics_consistency().

396  {
397  PhysicsList physics_list;
398 
399  int num_physics = input.vector_variable_size("Physics/enabled_physics");
400 
401  if( num_physics < 1 )
402  {
403  std::cerr << "Error: Must enable at least one physics model" << std::endl;
404  libmesh_error();
405  }
406 
407  std::set<std::string> requested_physics;
408 
409  // Go through and create a physics object for each physics we're enabling
410  for( int i = 0; i < num_physics; i++ )
411  {
412  requested_physics.insert( input("Physics/enabled_physics", "NULL", i ) );
413  }
414 
415  for( std::set<std::string>::const_iterator physics = requested_physics.begin();
416  physics != requested_physics.end();
417  physics++ )
418  {
419  this->add_physics( input, *physics, physics_list );
420  }
421 
422  this->check_physics_consistency( physics_list );
423 
424  if( input( "screen-options/echo_physics", true ) )
425  {
426  std::cout << "==========================================================" << std::endl
427  << "List of Enabled Physics:" << std::endl;
428 
429  for( PhysicsListIter it = physics_list.begin();
430  it != physics_list.end();
431  it++ )
432  {
433  std::cout<< it->first << std::endl;
434  }
435  std::cout << "==========================================================" << std::endl;
436  }
437 
438  return physics_list;
439  }
std::map< std::string, std::tr1::shared_ptr< GRINS::Physics > > PhysicsList
Container for GRINS::Physics object pointers.
Definition: var_typedefs.h:57
std::map< std::string, std::tr1::shared_ptr< GRINS::Physics > >::const_iterator PhysicsListIter
Iterator for PhysicsList.
Definition: var_typedefs.h:60
virtual void check_physics_consistency(const GRINS::PhysicsList &physics_list)
Make sure the requested GRINS::Physics classes are consistent.
virtual void add_physics(const GetPot &input, const std::string &physics_to_add, GRINS::PhysicsList &physics_list)
Figures out which GRINS::Physics pointer to create.
void GRINS::PhysicsFactory::check_physics_consistency ( const GRINS::PhysicsList physics_list)
protectedvirtual

Make sure the requested GRINS::Physics classes are consistent.

This is the other method to override (in addition to add_physics) for extending physics capabilities. The strategy is to check on the physics you've added, then call the parent PhysicsFactory::check_physics_consistency.

Todo:
Need to move the internals of the loop to a separate function that we'll make virtual and make this function non-virtual

Definition at line 710 of file physics_factory.C.

References GRINS::axisymmetric_boussinesq_buoyancy, GRINS::axisymmetric_heat_transfer, GRINS::boussinesq_buoyancy, GRINS::boussinesq_buoyancy_adjoint_stab, GRINS::heat_transfer, GRINS::heat_transfer_adjoint_stab, GRINS::heat_transfer_source, GRINS::incompressible_navier_stokes, GRINS::incompressible_navier_stokes_adjoint_stab, GRINS::incompressible_navier_stokes_spgsm_stab, GRINS::low_mach_navier_stokes, physics_consistency_error(), and GRINS::reacting_low_mach_navier_stokes.

Referenced by build().

711  {
714  for( PhysicsListIter physics = physics_list.begin();
715  physics != physics_list.end();
716  physics++ )
717  {
718  // For IncompressibleNavierStokes*Stabilization, we'd better have IncompressibleNavierStokes
719  if( (physics->first == incompressible_navier_stokes_adjoint_stab) ||
720  (physics->first == incompressible_navier_stokes_spgsm_stab) )
721  {
722  if( physics_list.find(incompressible_navier_stokes) == physics_list.end() )
723  {
725  }
726  }
727 
728  // For HeatTransfer, we need IncompressibleNavierStokes
729  if( physics->first == heat_transfer )
730  {
731  if( physics_list.find(incompressible_navier_stokes) == physics_list.end() )
732  {
734  }
735  }
736 
737  // For BoussinesqBuoyancy, we need both HeatTransfer and IncompressibleNavierStokes
738  if( physics->first == boussinesq_buoyancy )
739  {
740  if( physics_list.find(incompressible_navier_stokes) == physics_list.end() )
741  {
743  }
744 
745  if( physics_list.find(heat_transfer) == physics_list.end() )
746  {
748  }
749  }
750 
751  /* For AxisymmetricBoussinesqBuoyancy, we need both AxisymmetricHeatTransfer
752  and AxisymmetricIncompNavierStokes */
753  if( physics->first == axisymmetric_boussinesq_buoyancy )
754  {
755 
756  if( physics_list.find(axisymmetric_heat_transfer) == physics_list.end() )
757  {
760  }
761  }
762 
763  /* For LowMachNavierStokes, there should be nothing else loaded, except
764  for stabilization. */
765  if( physics->first == low_mach_navier_stokes )
766  {
767  if( physics_list.size() > 2 )
768  {
769  std::cerr << "=======================================================" << std::endl
770  << "Error: For physics " << low_mach_navier_stokes << std::endl
771  << "only one stabilization physics is allowed. Detected the" << std::endl
772  << "following:" << std::endl;
773  for( GRINS::PhysicsListIter iter = physics_list.begin();
774  iter != physics_list.end();
775  iter++ )
776  {
777  std::cerr << physics->first << std::endl;
778  }
779  std::cerr << "=======================================================" << std::endl;
780  libmesh_error();
781  }
782  }
783 
784  /* For HeatTransferSource, we'd better have HeatTransfer */
785  if( physics->first == heat_transfer_source )
786  {
787  if( physics_list.find(heat_transfer) == physics_list.end() )
788  {
789  this->physics_consistency_error( physics->first, heat_transfer );
790  }
791  }
792 
793  /* For HeatTransferAdjointStabilization, we'd better have HeatTransfer */
794  if( physics->first == heat_transfer_adjoint_stab )
795  {
796  if( physics_list.find(heat_transfer) == physics_list.end() )
797  {
798  this->physics_consistency_error( physics->first, heat_transfer );
799  }
800  }
801 
802  /* For BoussinesqBuoyancyAdjointStabilization, we'd better have IncompressibleNavierStokes */
803  if( physics->first == boussinesq_buoyancy_adjoint_stab )
804  {
805  if( physics_list.find(incompressible_navier_stokes) == physics_list.end() )
806  {
808  }
809  }
810 
811  /* For ReactingLowMachNavierStokes, there should be nothing else loaded, except
812  for stabilization. */
813  if( physics->first == reacting_low_mach_navier_stokes )
814  {
815  if( physics_list.size() > 2 )
816  {
817  std::cerr << "=======================================================" << std::endl
818  << "Error: For physics " << reacting_low_mach_navier_stokes << std::endl
819  << "only one stabilization physics is allowed. Detected the" << std::endl
820  << "following:" << std::endl;
821  for( GRINS::PhysicsListIter iter = physics_list.begin();
822  iter != physics_list.end();
823  iter++ )
824  {
825  std::cerr << physics->first << std::endl;
826  }
827  std::cerr << "=======================================================" << std::endl;
828  libmesh_error();
829  }
830  }
831  }
832 
833  return;
834  }
const PhysicsName incompressible_navier_stokes_spgsm_stab
const PhysicsName incompressible_navier_stokes
void physics_consistency_error(const std::string physics_checked, const std::string physics_required) const
Utility function.
const PhysicsName incompressible_navier_stokes_adjoint_stab
const PhysicsName axisymmetric_heat_transfer
const PhysicsName boussinesq_buoyancy_adjoint_stab
std::map< std::string, std::tr1::shared_ptr< GRINS::Physics > >::const_iterator PhysicsListIter
Iterator for PhysicsList.
Definition: var_typedefs.h:60
const PhysicsName heat_transfer_source
const PhysicsName low_mach_navier_stokes
const PhysicsName heat_transfer
const PhysicsName reacting_low_mach_navier_stokes
const PhysicsName boussinesq_buoyancy
const PhysicsName heat_transfer_adjoint_stab
const PhysicsName axisymmetric_boussinesq_buoyancy
void GRINS::PhysicsFactory::physics_consistency_error ( const std::string  physics_checked,
const std::string  physics_required 
) const
protected

Utility function.

Definition at line 836 of file physics_factory.C.

Referenced by check_physics_consistency().

838  {
839  std::cerr << "Error: " << physics_checked << " physics class requires using "
840  << physics_required << " physics." << std::endl
841  << physics_required << " not found in list of requested physics."
842  << std::endl;
843 
844  libmesh_error();
845 
846  return;
847  }

The documentation for this class was generated from the following files:

Generated on Mon Jun 22 2015 21:32:24 for GRINS-0.6.0 by  doxygen 1.8.9.1