Forked from
agnumpde / dune-tectonic
155 commits ahead of the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
fixedpointiterator.cc 8.23 KiB
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dune/common/exceptions.hh>
#include <dune/matrix-vector/axpy.hh>
#include <dune/solvers/norms/sumnorm.hh>
#include <dune/tectonic/utils/reductionfactors.hh>
#include "functionalfactory.hh"
#include "nonlinearsolver.hh"
#include "../utils/debugutils.hh"
#include "fixedpointiterator.hh"
void FixedPointIterationCounter::operator+=(
FixedPointIterationCounter const &other) {
iterations += other.iterations;
multigridIterations += other.multigridIterations;
}
template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::FixedPointIterator(
Dune::ParameterTree const &parset,
const NBodyAssembler& nBodyAssembler,
const IgnoreVector& ignoreNodes,
GlobalFriction& globalFriction,
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries,
const ErrorNorms& errorNorms)
: parset_(parset),
nBodyAssembler_(nBodyAssembler),
ignoreNodes_(ignoreNodes),
globalFriction_(globalFriction),
bodywiseNonmortarBoundaries_(bodywiseNonmortarBoundaries),
fixedPointMaxIterations_(parset.get<size_t>("v.fpi.maximumIterations")),
fixedPointTolerance_(parset.get<double>("v.fpi.tolerance")),
lambda_(parset.get<double>("v.fpi.lambda")),
solverParset_(parset.sub("v.solver")),
errorNorms_(errorNorms) {}
template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
bool FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::displacementCriterion(const Updaters& updaters, std::vector<Vector>& last_u) const {
bool criterion = true;
std::vector<Vector> u;
updaters.rate_->extractDisplacement(u);
const auto& mats = updaters.rate_->getMatrices();
for (int i=0; i<u.size(); i++) {
const EnergyNorm<Matrix, Vector> ANorm(*mats.elasticity[i]), MNorm(*mats.mass[i]);
const SumNorm<Vector> AMNorm(1.0, ANorm, 1.0, MNorm);
if (u[i].size()==0 || last_u[i].size()==0)
continue;
if (AMNorm.diff(u[i], last_u[i]) >= fixedPointTolerance_) {
criterion = false;
break;
}
}
last_u = u;
return criterion;
}
template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
bool FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::stateCriterion(const std::vector<ScalarVector>& alpha, const std::vector<ScalarVector>& newAlpha) const {
bool criterion = true;
for (int i=0; i<alpha.size(); i++) {
if (alpha[i].size()==0 || newAlpha[i].size()==0)
continue;
if (errorNorms_[i]->diff(alpha[i], newAlpha[i]) >= fixedPointTolerance_) {
criterion = false;
break;
}
}
return criterion;
}
template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
template <class LinearSolver>
FixedPointIterationCounter
FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::run(
Updaters updaters, std::shared_ptr<LinearSolver>& linearSolver,
const std::vector<Matrix>& velocityMatrices, const std::vector<Vector>& velocityRHSs,
std::vector<Vector>& velocityIterates) {
// debugging
/*const auto& contactCouplings = nBodyAssembler_.getContactCouplings();
for (size_t i=0; i<contactCouplings.size(); i++) {
print(*contactCouplings[i]->nonmortarBoundary().getVertices(), "nonmortarBoundaries:");
}*/
const auto nBodies = nBodyAssembler_.nGrids();
FunctionalFactory<std::decay_t<decltype(nBodyAssembler_)>, decltype(globalFriction_), Matrix, Vector> functionalFactory(nBodyAssembler_, globalFriction_, velocityMatrices, velocityRHSs);
functionalFactory.build();
auto functional = functionalFactory.functional();
NonlinearSolver<std::remove_reference_t<decltype(*functional)>, IgnoreVector> solver(parset_.sub("solver.tnnmg"), linearSolver, functional, ignoreNodes_);
size_t fixedPointIteration;
size_t multigridIterations = 0;
std::vector<Vector> last_u;
updaters.rate_->extractOldDisplacement(last_u);
std::vector<ScalarVector> alpha(nBodies);
updaters.state_->extractAlpha(alpha);
std::vector<Vector> v_o;
updaters.rate_->extractOldVelocity(v_o);
Vector total_v_o;
nBodyAssembler_.nodalToTransformed(v_o, total_v_o);
Vector total_v;
nBodyAssembler_.nodalToTransformed(velocityIterates, total_v);
//print(velocityIterates, "velocityIterates start:");
for (fixedPointIteration = 0; fixedPointIteration < fixedPointMaxIterations_;
++fixedPointIteration) {
// update friction
globalFriction_.updateAlpha(alpha);
// solve rate problem
auto res = solver.solve(solverParset_, total_v);
multigridIterations += res.iterations;
Vector v_m = total_v_o;
v_m *= 1.0 - lambda_;
Dune::MatrixVector::addProduct(v_m, lambda_, total_v);
// extract relative velocities in mortar basis
std::vector<Vector> v_rel;
split(v_m, v_rel);
// solve state problem
updaters.state_->solve(v_rel);
std::vector<ScalarVector> newAlpha(nBodies);
updaters.state_->extractAlpha(newAlpha);
nBodyAssembler_.postprocess(total_v, velocityIterates);
//Rprint(velocityIterates, "velocityIterates loop:");
updaters.rate_->postProcess(velocityIterates);
bool breakCriterion = true; //displacementCriterion(updaters, last_u); //stateCriterion(alpha, newAlpha);
printRegularityTruncation(globalFriction_, total_v);
if (lambda_ < 1e-12 or breakCriterion) {
fixedPointIteration++;
break;
}
if (res.iterations>200) {
std::cout << "FixedPointIterator: TNNMG did not converge, iterations: " << res.iterations << std::endl;
//DUNE_THROW(Dune::Exception, "FixedPointIterator: TNNMG did not converge");
break;
}
alpha = newAlpha;
}
if (fixedPointIteration == fixedPointMaxIterations_)
DUNE_THROW(Dune::Exception, "FPI failed to converge");
nBodyAssembler_.postprocess(total_v, velocityIterates);
updaters.rate_->postProcess(velocityIterates);
//print(velocityIterates, "velocityIterates end:");
// Cannot use return { fixedPointIteration, multigridIterations };
// with gcc 4.9.2, see also http://stackoverflow.com/a/37777814/179927
FixedPointIterationCounter ret;
ret.iterations = fixedPointIteration;
ret.multigridIterations = multigridIterations;
return ret;
}
/*std::ostream &operator<<(std::ostream &stream,
FixedPointIterationCounter const &fpic) {
return stream << "(" << fpic.iterations << "," << fpic.multigridIterations
<< ")";
}*/
template <class Factory, class NBodyAssembler, class Updaters, class ErrorNorms>
void FixedPointIterator<Factory, NBodyAssembler, Updaters, ErrorNorms>::split(
const Vector& v,
std::vector<Vector>& splitV) const {
const size_t nBodies = nBodyAssembler_.nGrids();
size_t globalIdx = 0;
splitV.resize(nBodies);
for (size_t bodyIdx=0; bodyIdx<nBodies; bodyIdx++) {
auto& splitV_ = splitV[bodyIdx];
splitV_.resize(nBodyAssembler_.grids_[bodyIdx]->size(dims));
for (size_t i=0; i<splitV_.size(); i++) {
splitV_[i] = v[globalIdx];
globalIdx++;
}
}
/*
boundaryNodes =
const auto gridView = contactCouplings[couplingIndices[0]]->nonmortarBoundary().gridView();
Dune::MultipleCodimMultipleGeomTypeMapper<
decltype(gridView), Dune::MCMGVertexLayout> const vertexMapper(gridView, Dune::mcmgVertexLayout());
for (auto it = gridView.template begin<block_size>(); it != gridView.template end<block_size>(); ++it) {
const auto i = vertexMapper.index(*it);
for (size_t j=0; j<couplingIndices.size(); j++) {
const auto couplingIdx = couplingIndices[j];
if (not contactCouplings[couplingIdx]->nonmortarBoundary().containsVertex(i))
continue;
localToGlobal_.emplace_back(i);
restrictions_.emplace_back(weights[bodyIdx][i], weightedNormalStress[bodyIdx][i],
couplings[i]->frictionData()(geoToPoint(it->geometry())));
break;
}
globalIdx++;
}
maxIndex_[bodyIdx] = globalIdx;
}*/
}
#include "fixedpointiterator_tmpl.cc"