unsteady_solver.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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_solver.h" 00020 #include "libmesh/diff_system.h" 00021 #include "libmesh/dof_map.h" 00022 #include "libmesh/numeric_vector.h" 00023 #include "libmesh/unsteady_solver.h" 00024 00025 namespace libMesh 00026 { 00027 00028 00029 00030 UnsteadySolver::UnsteadySolver (sys_type& s) 00031 : TimeSolver(s), 00032 old_local_nonlinear_solution (NumericVector<Number>::build()), 00033 first_solve (true), 00034 first_adjoint_step (true) 00035 { 00036 } 00037 00038 00039 00040 UnsteadySolver::~UnsteadySolver () 00041 { 00042 } 00043 00044 00045 00046 void UnsteadySolver::init () 00047 { 00048 TimeSolver::init(); 00049 00050 _system.add_vector("_old_nonlinear_solution"); 00051 } 00052 00053 00054 00055 void UnsteadySolver::init_data() 00056 { 00057 #ifdef LIBMESH_ENABLE_GHOSTED 00058 old_local_nonlinear_solution->init (_system.n_dofs(), _system.n_local_dofs(), 00059 _system.get_dof_map().get_send_list(), false, 00060 GHOSTED); 00061 #else 00062 old_local_nonlinear_solution->init (_system.n_dofs(), false, SERIAL); 00063 #endif 00064 } 00065 00066 00067 00068 void UnsteadySolver::reinit () 00069 { 00070 TimeSolver::reinit(); 00071 00072 #ifdef LIBMESH_ENABLE_GHOSTED 00073 old_local_nonlinear_solution->init (_system.n_dofs(), _system.n_local_dofs(), 00074 _system.get_dof_map().get_send_list(), false, 00075 GHOSTED); 00076 #else 00077 old_local_nonlinear_solution->init (_system.n_dofs(), false, SERIAL); 00078 #endif 00079 00080 } 00081 00082 00083 00084 void UnsteadySolver::solve () 00085 { 00086 if (first_solve) 00087 { 00088 advance_timestep(); 00089 first_solve = false; 00090 } 00091 00092 unsigned int solve_result = _diff_solver->solve(); 00093 00094 // If we requested the UnsteadySolver to attempt reducing dt after a 00095 // failed DiffSolver solve, check the results of the solve now. 00096 if (reduce_deltat_on_diffsolver_failure) 00097 { 00098 bool backtracking_failed = 00099 solve_result & DiffSolver::DIVERGED_BACKTRACKING_FAILURE; 00100 00101 bool max_iterations = 00102 solve_result & DiffSolver::DIVERGED_MAX_NONLINEAR_ITERATIONS; 00103 00104 if (backtracking_failed || max_iterations) 00105 { 00106 // Cut timestep in half 00107 for (unsigned int nr=0; nr<reduce_deltat_on_diffsolver_failure; ++nr) 00108 { 00109 _system.deltat *= 0.5; 00110 libMesh::out << "Newton backtracking failed. Trying with smaller timestep, dt=" 00111 << _system.deltat << std::endl; 00112 00113 solve_result = _diff_solver->solve(); 00114 00115 // Check solve results with reduced timestep 00116 bool backtracking_still_failed = 00117 solve_result & DiffSolver::DIVERGED_BACKTRACKING_FAILURE; 00118 00119 bool backtracking_max_iterations = 00120 solve_result & DiffSolver::DIVERGED_MAX_NONLINEAR_ITERATIONS; 00121 00122 if (!backtracking_still_failed && !backtracking_max_iterations) 00123 { 00124 if (!quiet) 00125 libMesh::out << "Reduced dt solve succeeded." << std::endl; 00126 return; 00127 } 00128 } 00129 00130 // If we made it here, we still couldn't converge the solve after 00131 // reducing deltat 00132 libMesh::out << "DiffSolver::solve() did not succeed after " 00133 << reduce_deltat_on_diffsolver_failure 00134 << " attempts." << std::endl; 00135 libmesh_convergence_failure(); 00136 00137 } // end if (backtracking_failed || max_iterations) 00138 } // end if (reduce_deltat_on_diffsolver_failure) 00139 } 00140 00141 00142 00143 void UnsteadySolver::advance_timestep () 00144 { 00145 if (!first_solve) 00146 { 00147 // Store the solution, does nothing by default 00148 // User has to attach appropriate solution_history object for this to 00149 // actually store anything anywhere 00150 solution_history->store(); 00151 00152 _system.time += _system.deltat; 00153 } 00154 00155 NumericVector<Number> &old_nonlinear_soln = 00156 _system.get_vector("_old_nonlinear_solution"); 00157 NumericVector<Number> &nonlinear_solution = 00158 *(_system.solution); 00159 00160 old_nonlinear_soln = nonlinear_solution; 00161 00162 old_nonlinear_soln.localize 00163 (*old_local_nonlinear_solution, 00164 _system.get_dof_map().get_send_list()); 00165 } 00166 00167 00168 00169 void UnsteadySolver::adjoint_advance_timestep () 00170 { 00171 // On the first call of this function, we dont save the adjoint solution or 00172 // decrement the time, we just call the retrieve function below 00173 if(!first_adjoint_step) 00174 { 00175 // Call the store function to store the last adjoint before decrementing the time 00176 solution_history->store(); 00177 // Decrement the system time 00178 _system.time -= _system.deltat; 00179 } 00180 else 00181 { 00182 first_adjoint_step = false; 00183 } 00184 00185 // Retrieve the primal solution vectors at this time using the 00186 // solution_history object 00187 solution_history->retrieve(); 00188 00189 // Dont forget to localize the old_nonlinear_solution ! 00190 _system.get_vector("_old_nonlinear_solution").localize 00191 (*old_local_nonlinear_solution, 00192 _system.get_dof_map().get_send_list()); 00193 } 00194 00195 void UnsteadySolver::retrieve_timestep() 00196 { 00197 // Retrieve all the stored vectors at the current time 00198 solution_history->retrieve(); 00199 00200 // Dont forget to localize the old_nonlinear_solution ! 00201 _system.get_vector("_old_nonlinear_solution").localize 00202 (*old_local_nonlinear_solution, 00203 _system.get_dof_map().get_send_list()); 00204 } 00205 00206 00207 Number UnsteadySolver::old_nonlinear_solution(const dof_id_type global_dof_number) 00208 const 00209 { 00210 libmesh_assert_less (global_dof_number, _system.get_dof_map().n_dofs()); 00211 libmesh_assert_less (global_dof_number, old_local_nonlinear_solution->size()); 00212 00213 return (*old_local_nonlinear_solution)(global_dof_number); 00214 } 00215 00216 00217 00218 Real UnsteadySolver::du(const SystemNorm &norm) const 00219 { 00220 00221 AutoPtr<NumericVector<Number> > solution_copy = 00222 _system.solution->clone(); 00223 00224 solution_copy->add(-1., _system.get_vector("_old_nonlinear_solution")); 00225 00226 solution_copy->close(); 00227 00228 return _system.calculate_norm(*solution_copy, norm); 00229 } 00230 00231 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:49 UTC
Hosted By: