12 #ifdef LIBMESH_HAVE_PETSC
13 #if !PETSC_VERSION_LESS_THAN(3, 6, 0)
14 #include "FEProblem.h"
15 #include "DisplacedProblem.h"
16 #include "NonlinearSystem.h"
17 #include "GeometricSearchData.h"
18 #include "PenetrationLocator.h"
20 #include "libmesh/petsc_nonlinear_solver.h"
21 #include "libmesh/petsc_solver_exception.h"
22 #include "libmesh/petsc_vector.h"
31 return validParams<LineSearch>();
35 : LineSearch(parameters), _nl(_fe_problem.getNonlinearSystemBase())
37 _solver =
dynamic_cast<PetscNonlinearSolver<Real> *
>(
38 _fe_problem.getNonlinearSystem().nonlinearSolver());
41 "This line search operates only with Petsc, so Petsc must be your nonlinear solver.");
49 mooseError(
"This line search only makes sense in a displaced context");
55 PetscBool changed_y = PETSC_FALSE;
58 SNESLineSearch line_search;
59 PetscReal fnorm, xnorm, ynorm;
60 PetscBool domainerror;
63 ierr = SNESGetLineSearch(snes, &line_search);
65 ierr = SNESLineSearchGetVecs(line_search, &X, &F, &Y, &W, &G);
67 ierr = SNESLineSearchGetNorms(line_search, &xnorm, &fnorm, &ynorm);
69 ierr = SNESLineSearchSetReason(line_search, SNES_LINESEARCH_SUCCEEDED);
72 ierr = SNESLineSearchPreCheck(line_search, X, Y, &changed_y);
76 ierr = VecWAXPY(W, -1., Y, X);
80 PetscVector<Number> solution(W, this->comm());
82 _nl.setSolution(solution);
97 std::set<dof_id_type> nodes_displaced;
99 std::vector<unsigned int> disp_nums;
103 disp_nums.push_back(
_nl.system().variable_number(disp_name));
105 for (
const auto & pen_loc : pen_locs)
106 for (
const auto & pinfo_pair : pen_loc.second->_penetration_info)
108 auto node_id = pinfo_pair.first;
109 auto pen_info = pinfo_pair.second;
112 if (pen_info->_distance > 0)
117 auto pair = nodes_displaced.insert(node_id);
118 mooseAssert(pair.second,
"Node id " << node_id <<
" has already been displaced");
121 const auto & node = mesh.node_ref(node_id);
124 if (node.processor_id() != this->processor_id())
128 auto required_solution_change = pen_info->_distance * pen_info->_normal;
131 std::vector<PetscInt> indices;
132 std::vector<PetscScalar> values;
133 for (
auto disp_num : disp_nums)
135 auto dof_number = node.dof_number(0, disp_num, 0);
136 indices.push_back(static_cast<PetscInt>(dof_number));
137 values.push_back(static_cast<PetscScalar>(required_solution_change(
component++)));
140 W, static_cast<PetscInt>(indices.size()), indices.data(), values.data(), ADD_VALUES);
141 LIBMESH_CHKERR(ierr);
145 ierr = VecAssemblyBegin(W);
146 LIBMESH_CHKERR(ierr);
147 ierr = VecAssemblyEnd(W);
148 LIBMESH_CHKERR(ierr);
150 ierr = SNESComputeFunction(snes, W, F);
151 LIBMESH_CHKERR(ierr);
152 ierr = SNESGetFunctionDomainError(snes, &domainerror);
153 LIBMESH_CHKERR(ierr);
156 ierr = SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_DOMAIN);
157 LIBMESH_CHKERR(ierr);
159 ierr = VecNorm(F, NORM_2, &fnorm);
160 LIBMESH_CHKERR(ierr);
162 ierr = VecCopy(W, X);
163 LIBMESH_CHKERR(ierr);
165 ierr = SNESLineSearchComputeNorms(line_search);
166 LIBMESH_CHKERR(ierr);
169 #endif // !PETSC_VERSION_LESS_THAN(3, 3, 0)
170 #endif // LIBMESH_HAVE_PETSC