https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PetscProjectSolutionOntoBounds.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "FEProblem.h"
12#include "DisplacedProblem.h"
13#include "NonlinearSystem.h"
14#include "GeometricSearchData.h"
15#include "PenetrationLocator.h"
16
17#include "libmesh/petsc_nonlinear_solver.h"
18#include "libmesh/petsc_solver_exception.h"
19#include "libmesh/petsc_vector.h"
20#include <petscdm.h>
21
23
29
31 : LineSearch(parameters), _nl(_fe_problem.getNonlinearSystemBase(/*nl_sys_num=*/0))
32{
33 _solver = dynamic_cast<PetscNonlinearSolver<Real> *>(
35 if (!_solver)
37 "This line search operates only with Petsc, so Petsc must be your nonlinear solver.");
38}
39
40void
42{
45 mooseError("This line search only makes sense in a displaced context");
46}
47
48void
50{
51 PetscBool changed_y = PETSC_FALSE;
52 Vec X, F, Y, W, G;
53 SNESLineSearch line_search;
54 PetscReal fnorm, xnorm, ynorm;
55 SNES snes = _solver->snes();
56
57 LibmeshPetscCall(SNESGetLineSearch(snes, &line_search));
58 LibmeshPetscCall(SNESLineSearchGetVecs(line_search, &X, &F, &Y, &W, &G));
59 LibmeshPetscCall(SNESLineSearchGetNorms(line_search, &xnorm, &fnorm, &ynorm));
60 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_SUCCEEDED));
61
62 LibmeshPetscCall(SNESLineSearchPreCheck(line_search, X, Y, &changed_y));
63
64 // apply the full newton step
65 LibmeshPetscCall(VecWAXPY(W, -1., Y, X));
66
67 {
68 PetscVector<Number> solution(W, this->comm());
69
70 _nl.setSolution(solution);
71
72 // Displace the mesh and update the displaced geometric search objects
74 }
75
76 // A reference to the displaced MeshBase object
77 const auto & mesh = _displaced_problem->mesh().getMesh();
78
79 const auto & pen_locs = _displaced_problem->geomSearchData().getPenetrationLocators();
80
81 // Keep track of the secondary nodes that we push back onto the primary face. We'll eventually
82 // check to make sure that we didn't have a corner node at the intersection of two secondary faces
83 // that we tried to displace twice. As this stands now this won't cover the case wherethe
84 // intersection happens only across processes
85 std::set<dof_id_type> nodes_displaced;
86
87 std::vector<unsigned int> disp_nums;
88
89 // Generate the displaced variable numbers
90 for (const auto & disp_name : _displaced_problem->getDisplacementVarNames())
91 disp_nums.push_back(_nl.system().variable_number(disp_name));
92
93 for (const auto & pen_loc : pen_locs)
94 for (const auto & pinfo_pair : pen_loc.second->_penetration_info)
95 {
96 auto node_id = pinfo_pair.first;
97 auto pen_info = pinfo_pair.second;
98
99 // We have penetration
100 if (pen_info && pen_info->_distance > 0)
101 {
102// Avoid warning in optimized modes about unused variables
103#ifndef NDEBUG
104 // Make sure we haven't done this node before
105 auto pair = nodes_displaced.insert(node_id);
106 mooseAssert(pair.second, "Node id " << node_id << " has already been displaced");
107#endif
108
109 const auto & node = mesh.node_ref(node_id);
110
111 // If this is not a local node, we will let displacement happen on another process
112 if (node.processor_id() != this->processor_id())
113 continue;
114
115 // The vector that we need to displace by
116 auto required_solution_change = pen_info->_distance * pen_info->_normal;
117
118 unsigned component = 0;
119 std::vector<PetscInt> indices;
120 std::vector<PetscScalar> values;
121 for (auto disp_num : disp_nums)
122 {
123 auto dof_number = node.dof_number(/*sys=*/0, disp_num, /*component=*/0);
124 indices.push_back(static_cast<PetscInt>(dof_number));
125 values.push_back(static_cast<PetscScalar>(required_solution_change(component++)));
126 }
127 LibmeshPetscCall(VecSetValues(
128 W, static_cast<PetscInt>(indices.size()), indices.data(), values.data(), ADD_VALUES));
129 }
130 }
131
132 LibmeshPetscCall(VecAssemblyBegin(W));
133 LibmeshPetscCall(VecAssemblyEnd(W));
134
135 LibmeshPetscCall(SNESComputeFunction(snes, W, F));
136#if PETSC_VERSION_LESS_THAN(3, 25, 0)
137 PetscBool domainerror;
138 LibmeshPetscCall(SNESGetFunctionDomainError(snes, &domainerror));
139 if (domainerror)
140 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_DOMAIN));
141#else
142 SNESConvergedReason reason;
143 LibmeshPetscCall(SNESGetConvergedReason(snes, &reason));
144 if (reason == SNES_DIVERGED_FUNCTION_DOMAIN)
145 LibmeshPetscCall(SNESLineSearchSetReason(line_search, SNES_LINESEARCH_FAILED_FUNCTION_DOMAIN));
146#endif
147
148 LibmeshPetscCall(VecNorm(F, NORM_2, &fnorm));
149
150 LibmeshPetscCall(VecCopy(W, X));
151
152 LibmeshPetscCall(SNESLineSearchComputeNorms(line_search));
153}
std::array< Real, 2 > values
registerMooseObject("ContactApp", PetscProjectSolutionOntoBounds)
virtual GeometricSearchData & geomSearchData() override
virtual void updateMesh(bool mesh_changing=false)
virtual MooseMesh & mesh() override
const std::vector< std::string > & getDisplacementVarNames() const
virtual std::shared_ptr< const DisplacedProblem > getDisplacedProblem() const
virtual NonlinearSystem & getNonlinearSystem(const unsigned int nl_sys_num) override
const std::map< std::pair< BoundaryID, BoundaryID >, PenetrationLocator * > & getPenetrationLocators() const
FEProblem & _fe_problem
static InputParameters validParams()
void mooseError(Args &&... args) const
MeshBase & getMesh()
virtual libMesh::System & system() override
virtual libMesh::NonlinearSolver< Number > * nonlinearSolver() override
Petsc implementation of the contact line search (based on the Petsc LineSearchShell)
PetscProjectSolutionOntoBounds(const InputParameters &parameters)
void setSolution(const NumericVector< Number > &soln)
const Parallel::Communicator & comm() const
SNES snes(const char *name=nullptr)
unsigned int variable_number(std::string_view var) const
MeshBase & mesh