$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 #include "libmesh/diff_system.h" 00020 #include "libmesh/euler_solver.h" 00021 00022 namespace libMesh 00023 { 00024 00025 00026 00027 EulerSolver::EulerSolver (sys_type& s) 00028 : UnsteadySolver(s), theta(1.) 00029 { 00030 } 00031 00032 00033 00034 EulerSolver::~EulerSolver () 00035 { 00036 } 00037 00038 00039 00040 Real EulerSolver::error_order() const 00041 { 00042 if (theta == 0.5) 00043 return 2.; 00044 return 1.; 00045 } 00046 00047 00048 00049 00050 bool EulerSolver::element_residual (bool request_jacobian, 00051 DiffContext &context) 00052 { 00053 return this->_general_residual(request_jacobian, 00054 context, 00055 &DifferentiablePhysics::mass_residual, 00056 &DifferentiablePhysics::_eulerian_time_deriv, 00057 &DifferentiablePhysics::element_constraint, 00058 &DiffContext::elem_reinit); 00059 } 00060 00061 00062 00063 bool EulerSolver::side_residual (bool request_jacobian, 00064 DiffContext &context) 00065 { 00066 return this->_general_residual(request_jacobian, 00067 context, 00068 &DifferentiablePhysics::side_mass_residual, 00069 &DifferentiablePhysics::side_time_derivative, 00070 &DifferentiablePhysics::side_constraint, 00071 &DiffContext::elem_side_reinit); 00072 } 00073 00074 00075 00076 bool EulerSolver::nonlocal_residual (bool request_jacobian, 00077 DiffContext &context) 00078 { 00079 return this->_general_residual(request_jacobian, 00080 context, 00081 &DifferentiablePhysics::nonlocal_mass_residual, 00082 &DifferentiablePhysics::nonlocal_time_derivative, 00083 &DifferentiablePhysics::nonlocal_constraint, 00084 &DiffContext::nonlocal_reinit); 00085 } 00086 00087 00088 00089 bool EulerSolver::_general_residual (bool request_jacobian, 00090 DiffContext &context, 00091 ResFuncType mass, 00092 ResFuncType time_deriv, 00093 ResFuncType constraint, 00094 ReinitFuncType reinit_func) 00095 { 00096 unsigned int n_dofs = context.get_elem_solution().size(); 00097 00098 // We might need to save the old jacobian in case one of our physics 00099 // terms later is unable to update it analytically. 00100 DenseMatrix<Number> old_elem_jacobian(n_dofs, n_dofs); 00101 if (request_jacobian) 00102 old_elem_jacobian.swap(context.get_elem_jacobian()); 00103 00104 // Local nonlinear solution at old timestep 00105 DenseVector<Number> old_elem_solution(n_dofs); 00106 for (unsigned int i=0; i != n_dofs; ++i) 00107 old_elem_solution(i) = 00108 old_nonlinear_solution(context.get_dof_indices()[i]); 00109 00110 // Local time derivative of solution 00111 context.get_elem_solution_rate() = context.get_elem_solution(); 00112 context.get_elem_solution_rate() -= old_elem_solution; 00113 context.elem_solution_rate_derivative = 1 / _system.deltat; 00114 context.get_elem_solution_rate() *= 00115 context.elem_solution_rate_derivative; 00116 00117 // Local nonlinear solution at time t_theta 00118 DenseVector<Number> theta_solution(context.get_elem_solution()); 00119 theta_solution *= theta; 00120 theta_solution.add(1. - theta, old_elem_solution); 00121 00122 context.elem_solution_derivative = theta; 00123 context.fixed_solution_derivative = theta; 00124 00125 // If a fixed solution is requested, we'll use theta_solution 00126 if (_system.use_fixed_solution) 00127 context.get_elem_fixed_solution() = theta_solution; 00128 00129 // Move theta_->elem_, elem_->theta_ 00130 context.get_elem_solution().swap(theta_solution); 00131 00132 // Move the mesh into place first if necessary 00133 (context.*reinit_func)(theta); 00134 00135 // Get the time derivative at t_theta 00136 bool jacobian_computed = 00137 (_system.*time_deriv)(request_jacobian, context); 00138 00139 jacobian_computed = (_system.*mass)(jacobian_computed, context) && 00140 jacobian_computed; 00141 00142 // Restore the elem position if necessary 00143 (context.*reinit_func)(1); 00144 00145 // Move elem_->elem_, theta_->theta_ 00146 context.get_elem_solution().swap(theta_solution); 00147 context.elem_solution_derivative = 1; 00148 00149 // Add the constraint term 00150 jacobian_computed = (_system.*constraint)(jacobian_computed, context) && 00151 jacobian_computed; 00152 00153 // Add back (or restore) the old jacobian 00154 if (request_jacobian) 00155 { 00156 if (jacobian_computed) 00157 context.get_elem_jacobian() += old_elem_jacobian; 00158 else 00159 context.get_elem_jacobian().swap(old_elem_jacobian); 00160 } 00161 00162 return jacobian_computed; 00163 } 00164 00165 00166 } // namespace libMesh