Skip to content
Snippets Groups Projects
Commit efb0355e authored by podlesny's avatar podlesny
Browse files

multi threading steps in adaptivetimestepper

parent b660cb8d
No related branches found
No related tags found
No related merge requests found
...@@ -10,6 +10,8 @@ add_custom_target(tectonic_dune_time-stepping SOURCES ...@@ -10,6 +10,8 @@ add_custom_target(tectonic_dune_time-stepping SOURCES
rate.cc rate.cc
state.hh state.hh
state.cc state.cc
step.hh
stepbase.hh
updaters.hh updaters.hh
) )
...@@ -19,5 +21,7 @@ install(FILES ...@@ -19,5 +21,7 @@ install(FILES
coupledtimestepper.hh coupledtimestepper.hh
rate.hh rate.hh
state.hh state.hh
step.hh
stepbase.hh
updaters.hh updaters.hh
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/tectonic) DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/tectonic)
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
#include "config.h" #include "config.h"
#endif #endif
#include <future>
#include <thread> #include <thread>
#include <chrono>
#include <dune/solvers/norms/energynorm.hh> #include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/iterationsteps/multigridstep.hh> #include <dune/solvers/iterationsteps/multigridstep.hh>
...@@ -14,80 +16,10 @@ ...@@ -14,80 +16,10 @@
#include <dune/tectonic/utils/reductionfactors.hh> #include <dune/tectonic/utils/reductionfactors.hh>
#include "adaptivetimestepper.hh" #include "adaptivetimestepper.hh"
#include "step.hh"
const unsigned int N_THREADS = std::thread::hardware_concurrency(); const unsigned int N_THREADS = std::thread::hardware_concurrency();
template<class IterationStepType, class NormType, class ReductionFactorContainer>
Dune::Solvers::Criterion reductionFactorCriterion(
IterationStepType& iterationStep,
const NormType& norm,
ReductionFactorContainer& reductionFactors)
{
double normOfOldCorrection = 1;
auto lastIterate = std::make_shared<typename IterationStepType::Vector>(*iterationStep.getIterate());
return Dune::Solvers::Criterion(
[&, lastIterate, normOfOldCorrection] () mutable {
double normOfCorrection = norm.diff(*lastIterate, *iterationStep.getIterate());
double convRate = (normOfOldCorrection > 0) ? normOfCorrection / normOfOldCorrection : 0.0;
if (convRate>1.0)
std::cout << "Solver convergence rate of " << convRate << std::endl;
normOfOldCorrection = normOfCorrection;
*lastIterate = *iterationStep.getIterate();
reductionFactors.push_back(convRate);
return std::make_tuple(convRate < 0, Dune::formatString(" % '.5f", convRate));
},
" reductionFactor");
}
template<class IterationStepType, class Functional, class ReductionFactorContainer>
Dune::Solvers::Criterion energyCriterion(
const IterationStepType& iterationStep,
const Functional& f,
ReductionFactorContainer& reductionFactors)
{
double normOfOldCorrection = 1;
auto lastIterate = std::make_shared<typename IterationStepType::Vector>(*iterationStep.getIterate());
return Dune::Solvers::Criterion(
[&, lastIterate, normOfOldCorrection] () mutable {
double normOfCorrection = std::abs(f(*lastIterate) - f(*iterationStep.getIterate())); //norm.diff(*lastIterate, *iterationStep.getIterate());
double convRate = (normOfOldCorrection != 0.0) ? 1.0 - (normOfCorrection / normOfOldCorrection) : 0.0;
if (convRate>1.0)
std::cout << "Solver convergence rate of " << convRate << std::endl;
normOfOldCorrection = normOfCorrection;
*lastIterate = *iterationStep.getIterate();
reductionFactors.push_back(convRate);
return std::make_tuple(convRate < 0, Dune::formatString(" % '.5f", convRate));
},
" reductionFactor");
}
template <class ReductionFactorContainer>
void updateReductionFactors(ReductionFactorContainer& reductionFactors) {
const size_t s = reductionFactors.size();
//print(reductionFactors, "reduction factors: ");
if (s>allReductionFactors.size()) {
allReductionFactors.resize(s);
}
for (size_t i=0; i<reductionFactors.size(); i++) {
allReductionFactors[i].push_back(reductionFactors[i]);
}
reductionFactors.clear();
}
void IterationRegister::registerCount(FixedPointIterationCounter count) { void IterationRegister::registerCount(FixedPointIterationCounter count) {
totalCount += count; totalCount += count;
} }
...@@ -101,239 +33,284 @@ void IterationRegister::reset() { ...@@ -101,239 +33,284 @@ void IterationRegister::reset() {
finalCount = FixedPointIterationCounter(); finalCount = FixedPointIterationCounter();
} }
/*
* Implementation: AdaptiveTimeStepper
*/
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms> template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::AdaptiveTimeStepper( AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::AdaptiveTimeStepper(
Dune::ParameterTree const &parset, const StepBase& stepBase,
ContactNetwork& contactNetwork, ContactNetwork& contactNetwork,
const IgnoreVector& ignoreNodes,
GlobalFriction& globalFriction,
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries,
Updaters &current, Updaters &current,
double relativeTime, double relativeTime,
double relativeTau, double relativeTau,
ExternalForces& externalForces,
const ErrorNorms& errorNorms,
std::function<bool(Updaters &, Updaters &)> mustRefine) std::function<bool(Updaters &, Updaters &)> mustRefine)
: relativeTime_(relativeTime), : relativeTime_(relativeTime),
relativeTau_(relativeTau), relativeTau_(relativeTau),
finalTime_(parset.get<double>("problem.finalTime")), stepBase_(stepBase),
parset_(parset),
contactNetwork_(contactNetwork), contactNetwork_(contactNetwork),
ignoreNodes_(ignoreNodes),
globalFriction_(globalFriction),
bodywiseNonmortarBoundaries_(bodywiseNonmortarBoundaries),
current_(current), current_(current),
R1_(), R1_(),
externalForces_(externalForces), mustRefine_(mustRefine) {}
mustRefine_(mustRefine),
errorNorms_(errorNorms) {}
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms> template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
bool AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::reachedEnd() { bool AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::reachedEnd() {
return relativeTime_ >= 1.0; return relativeTime_ >= 1.0;
} }
// compute C and R2 in parallel
// returns number of coarsenings done
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms> template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
auto AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::makeLinearSolver() const { int AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::coarsen() {
// make linear solver for linear correction in TNNMGStep using Step = Step<Factory, ContactNetwork, Updaters, ErrorNorms>;
using Norm = EnergyNorm<Matrix, Vector>;
using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;
const auto& preconditionerParset = parset_.sub("solver.tnnmg.linear.preconditioner"); int coarseCount = 1; // one coarsening step was already done in determineStrategy()
Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true); UpdatersWithCount C;
Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels); UpdatersWithCount R2;
preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
preconditioner.build();
auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>(); const auto& currentNBodyAssembler = contactNetwork_.nBodyAssembler();
cgStep->setPreconditioner(preconditioner);
Norm norm(*cgStep); while (relativeTime_ + relativeTau_ <= 1.0) {
std::cout << "tau: " << relativeTau_ << std::endl;
return std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.linear.tolerance"), norm, Solver::QUIET); setDeformation(current_);
} auto C_Step = Step(stepBase_, current_, currentNBodyAssembler, relativeTime_, 2 * relativeTau_, iterationRegister_);
C_Step.run(Step::Mode::newThread); //newThread
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms> //updateReductionFactors(reductionFactors);
IterationRegister AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::advance() { std::cout << "AdaptiveTimeStepper C computed!" << std::endl << std::endl;
/*
| C | We check here if making the step R1 of size tau is a
| R1 | R2 | good idea. To check if we can coarsen, we compare
|F1|F2| | the result of (R1+R2) with C, i.e. two steps of size
tau with one of size 2*tau. To check if we need to
refine, we compare the result of (F1+F2) with R1, i.e. two steps
of size tau/2 with one of size tau. The method makes multiple
coarsening/refining attempts, with coarsening coming first. */
//std::cout << "AdaptiveTimeStepper::advance()" << std::endl; /*using ScalarVector = typename Updaters::StateUpdater::ScalarVector;
std::vector<ScalarVector> cAlpha(contactNetwork_.nBodies());
C.updaters.state_->extractAlpha(cAlpha);
print(cAlpha, "cAlpha: ");*/
// patch preconditioner only needs to be computed once per advance() setDeformation(R1_.updaters);
// make linear solver for linear correction in TNNMGStep //auto R2_linearSolver = makeLinearSolver();
using Norm = EnergyNorm<Matrix, Vector>; auto&& nBodyAssembler = step(currentNBodyAssembler);
using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>; auto R2_Step = Step(stepBase_, R1_.updaters, nBodyAssembler, relativeTime_ + relativeTau_, relativeTau_, iterationRegister_);
using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>; R2_Step.run(Step::Mode::newThread); //newThread
/*const auto& preconditionerParset = parset_.sub("solver.tnnmg.preconditioner"); //updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper R2 computed!" << std::endl << std::endl;
Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true); C = C_Step.get();
Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels); R2 = R2_Step.get();
preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
preconditioner.build();
auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>(); /*std::vector<ScalarVector> rAlpha(contactNetwork_.nBodies());
cgStep->setPreconditioner(preconditioner); R2.updaters.state_->extractAlpha(rAlpha);
print(rAlpha, "rAlpha: ");*/
Norm norm(*cgStep); if (mustRefine_(C.updaters, R2.updaters))
break;
auto linearSolver = std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET); relativeTau_ *= 2;
*/ R1_ = C;
// set multigrid solver coarseCount++;
auto smoother = TruncatedBlockGSStep<Matrix, Vector>(); }
using TransferOperator = NBodyContactTransfer<ContactNetwork, Vector>; current_ = R1_.updaters;
using TransferOperators = std::vector<std::shared_ptr<TransferOperator>>; R1_ = R2;
TransferOperators transfer(contactNetwork_.nLevels()-1); return coarseCount;
for (size_t i=0; i<transfer.size(); i++) { }
transfer[i] = std::make_shared<TransferOperator>();
transfer[i]->setup(contactNetwork_, i, i+1);
}
// Remove any recompute filed so that initially the full transferoperator is assembled // compute F1 and F2 sequentially
for (size_t i=0; i<transfer.size(); i++) // returns number of refinements done
std::dynamic_pointer_cast<TruncatedMGTransfer<Vector> >(transfer[i])->setRecomputeBitField(nullptr); template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
int AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::refine(UpdatersWithCount& R2) {
using Step = Step<Factory, ContactNetwork, Updaters, ErrorNorms>;
auto linearMultigridStep = std::make_shared<Dune::Solvers::MultigridStep<Matrix, Vector> >(); int refineCount = 1; // one refinement step was already done in determineStrategy()
linearMultigridStep->setMGType(1, 3, 3);
linearMultigridStep->setSmoother(smoother);
linearMultigridStep->setTransferOperators(transfer);
Norm norm(*linearMultigridStep); UpdatersWithCount F1;
UpdatersWithCount F2;
auto linearSolver = std::make_shared<LinearSolver>(linearMultigridStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET); const auto& currentNBodyAssembler = contactNetwork_.nBodyAssembler();
Vector x; while (true) {
x.resize(contactNetwork_.nBodyAssembler().totalHasObstacle_.size()); setDeformation(current_);
x = 0; //auto F1_linearSolver = makeLinearSolver();
dynamic_cast<Dune::Solvers::IterationStep<Vector>*>(linearMultigridStep.get())->setProblem(x); auto F1_Step = Step(stepBase_, current_, currentNBodyAssembler, relativeTime_, relativeTau_ / 2.0, iterationRegister_);
//dynamic_cast<Dune::Solvers::IterationStep<Vector>*>(cgStep.get())->setProblem(x); F1_Step.run(Step::Mode::sameThread);
F1 = F1_Step.get();
//updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper F1 computed!" << std::endl << std::endl;
setDeformation(F1.updaters);
//auto F2_linearSolver = makeLinearSolver();
auto&& nBodyAssembler = step(currentNBodyAssembler);
auto F2_Step = Step(stepBase_, F1.updaters, nBodyAssembler, relativeTime_ + relativeTau_ / 2.0,
relativeTau_ / 2.0, iterationRegister_);
F2_Step.run(Step::Mode::sameThread);
F2 = F2_Step.get();
//updateReductionFactors(reductionFactors);
if (!mustRefine_(R1_.updaters, F2.updaters)) {
std::cout << "Sufficiently refined!" << std::endl;
break;
}
relativeTau_ /= 2.0;
R1_ = F1;
R2 = F2;
refineCount++;
}
const auto& currentNBodyAssembler = contactNetwork_.nBodyAssembler(); current_ = R1_.updaters;
R1_ = R2;
std::vector<double> reductionFactors; return refineCount;
linearSolver->addCriterion(reductionFactorCriterion(*linearMultigridStep, norm, reductionFactors)); }
//linearSolver->addCriterion(reductionFactorCriterion(*cgStep, norm, reductionFactors));
auto refine = [&](UpdatersWithCount& F1, UpdatersWithCount& F2){
setDeformation(current_);
F1 = step(current_, currentNBodyAssembler, linearSolver, relativeTime_, relativeTau_ / 2.0);
updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper F1 computed!" << std::endl << std::endl;
setDeformation(F1.updaters); /*
auto&& nBodyAssembler = step(currentNBodyAssembler); * determines how to adapt time step, returns
F2 = step(F1.updaters, nBodyAssembler, linearSolver, relativeTime_ + relativeTau_ / 2.0, * -1: coarsen
relativeTau_ / 2.0); * 0: keep
updateReductionFactors(reductionFactors); * 1: refine
}; */
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
int AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::determineStrategy(UpdatersWithCount& R2) {
using Step = Step<Factory, ContactNetwork, Updaters, ErrorNorms>;
auto coarsen = [&](UpdatersWithCount& C, UpdatersWithCount& R2){ int strategy = 0;
setDeformation(current_);
C = step(current_, currentNBodyAssembler, linearSolver, relativeTime_, 2 * relativeTau_).get();
updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper C computed!" << std::endl << std::endl;
/*using ScalarVector = typename Updaters::StateUpdater::ScalarVector; const auto& currentNBodyAssembler = contactNetwork_.nBodyAssembler();
std::vector<ScalarVector> cAlpha(contactNetwork_.nBodies());
C.updaters.state_->extractAlpha(cAlpha);
print(cAlpha, "cAlpha: ");*/
setDeformation(R1_.updaters); UpdatersWithCount C;
auto&& nBodyAssembler = step(currentNBodyAssembler); UpdatersWithCount F1;
R2 = step(R1_.updaters, nBodyAssembler, linearSolver, relativeTime_ + relativeTau_, relativeTau_).get(); UpdatersWithCount F2;
updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper R2 computed!" << std::endl << std::endl;
};
auto canCoarsen = [&]{ //if (relativeTime_ + relativeTau_ > 1.0) {
std::cout << N_THREADS << " concurrent threads are supported." << std::endl; // return false;
//}
if (R1_.updaters == Updaters()) { setDeformation(current_);
//setDeformation(current_); //auto C_linearSolver = makeLinearSolver();
R1_ = step(current_, currentNBodyAssembler, linearSolver, relativeTime_, relativeTau_); auto C_Step = Step(stepBase_, current_, currentNBodyAssembler, relativeTime_, 2 * relativeTau_, iterationRegister_);
updateReductionFactors(reductionFactors); C_Step.run(Step::Mode::newThread); // newThread
} //updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper C computed!" << std::endl << std::endl;
if (N_THREADS<3) { setDeformation(R1_.updaters);
//auto R2_linearSolver = makeLinearSolver();
auto&& nBodyAssembler = step(currentNBodyAssembler);
auto R2_Step = Step(stepBase_, R1_.updaters, nBodyAssembler, relativeTime_ + relativeTau_, relativeTau_, iterationRegister_);
R2_Step.run(Step::Mode::newThread); //newThread
} else { //updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper R2 computed!" << std::endl << std::endl;
if (N_THREADS < 3) {
C = C_Step.get();
R2 = R2_Step.get();
if (!mustRefine_(C.updaters, R2.updaters)) {
strategy = -1;
}
} }
return ; if (strategy>-1) {
}; setDeformation(current_);
//auto F1_linearSolver = makeLinearSolver();
auto F1_Step = Step(stepBase_, current_, currentNBodyAssembler, relativeTime_, relativeTau_ / 2.0, iterationRegister_);
F1_Step.run(Step::Mode::newThread); //newThread
//updateReductionFactors(reductionFactors);
std::cout << "AdaptiveTimeStepper F1 computed!" << std::endl << std::endl;
if (N_THREADS > 2) {
C = C_Step.get();
R2 = R2_Step.get();
if (!mustRefine_(C.updaters, R2.updaters)) {
strategy = -1;
}
}
F1 = F1_Step.get();
if (strategy>-1) {
setDeformation(F1.updaters);
//auto F2_linearSolver = makeLinearSolver();
auto&& nBodyAssembler = step(currentNBodyAssembler);
auto F2_Step = Step(stepBase_, F1.updaters, nBodyAssembler, relativeTime_ + relativeTau_ / 2.0,
relativeTau_ / 2.0, iterationRegister_);
F2_Step.run(Step::Mode::sameThread);
F2 = F2_Step.get();
//updateReductionFactors(reductionFactors);
if (mustRefine_(R1_.updaters, F2.updaters)) {
strategy = 1;
}
}
}
//std::cout << "AdaptiveTimeStepper Step 1" << std::endl; switch (strategy) {
case -1:
relativeTau_ *= 2;
R1_ = C;
break;
case 0:
current_ = R1_.updaters;
R1_ = R2;
break;
case 1:
relativeTau_ /= 2.0;
R1_ = F1;
R2 = F2;
break;
}
size_t coarseningCount = 0; return strategy;
size_t refineCount = 0; }
bool didCoarsen = false; template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
iterationRegister_.reset(); IterationRegister AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::advance() {
UpdatersWithCount R2; /*
UpdatersWithCount C; | C | We check here if making the step R1 of size tau is a
| R1 | R2 | good idea. To check if we can coarsen, we compare
|F1|F2| | the result of (R1+R2) with C, i.e. two steps of size
tau with one of size 2*tau. To check if we need to
refine, we compare the result of (F1+F2) with R1, i.e. two steps
of size tau/2 with one of size tau. The method makes multiple
coarsening/refining attempts, with coarsening coming first. */
while (relativeTime_ + relativeTau_ <= 1.0) { //std::cout << "AdaptiveTimeStepper::advance()" << std::endl;
std::cout << "tau: " << relativeTau_ << std::endl;
coarsen(C, R2); using Step = Step<Factory, ContactNetwork, Updaters, ErrorNorms>;
/*std::vector<ScalarVector> rAlpha(contactNetwork_.nBodies()); std::cout << N_THREADS << " concurrent threads are supported." << std::endl;
R2.updaters.state_->extractAlpha(rAlpha);
print(rAlpha, "rAlpha: ");*/
if (mustRefine_(C.updaters, R2.updaters)) if (R1_.updaters == Updaters()) {
break; //setDeformation(current_);
//auto R1_linearSolver = makeLinearSolver();
auto R1_Step = Step(stepBase_, current_, contactNetwork_.nBodyAssembler(), relativeTime_, relativeTau_, iterationRegister_);
R1_Step.run(Step::Mode::sameThread);
R1_ = R1_Step.get();
}
didCoarsen = true; iterationRegister_.reset();
relativeTau_ *= 2; UpdatersWithCount R2;
R1_ = C; int strat = determineStrategy(R2);
coarseningCount++; // coarsen
if (strat<0) {
int coarseningCount = coarsen();
std::cout << " done with coarseningCount: " << coarseningCount << std::endl;
} }
UpdatersWithCount F1; // refine
UpdatersWithCount F2; if (strat>0) {
if (!didCoarsen) { int refineCount = refine(R2);
while (true) { std::cout << " done with refineCount: " << refineCount << std::endl;
refine(F1, F2);
if (!mustRefine_(R1_.updaters, F2.updaters)) {
std::cout << "Sufficiently refined!" << std::endl;
break;
}
relativeTau_ /= 2.0;
R1_ = F1;
R2 = F2;
refineCount++;
}
} }
std::cout << "AdaptiveTimeStepper::advance() ...";
iterationRegister_.registerFinalCount(R1_.count); iterationRegister_.registerFinalCount(R1_.count);
relativeTime_ += relativeTau_; relativeTime_ += relativeTau_;
current_ = R1_.updaters;
//UpdatersWithCount emptyR1;
//R1_ = emptyR1;
R1_ = R2;
std::cout << " done with coarseningCount: " << coarseningCount << " and refineCount: " << refineCount << std::endl;
return iterationRegister_; return iterationRegister_;
} }
...@@ -362,32 +339,4 @@ AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::step(const N ...@@ -362,32 +339,4 @@ AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::step(const N
return nBodyAssembler; return nBodyAssembler;
} }
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
template <class LinearSolver>
typename AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::UpdatersWithCount
AdaptiveTimeStepper<Factory, ContactNetwork, Updaters, ErrorNorms>::step(
const Updaters& oldUpdaters, const NBodyAssembler& nBodyAssembler, std::shared_ptr<LinearSolver>& linearSolver, double rTime, double rTau) {
auto doStep = [&]{
UpdatersWithCount newUpdatersAndCount = {oldUpdaters.clone(), {}};
MyCoupledTimeStepper coupledTimeStepper(finalTime_, parset_, nBodyAssembler,
ignoreNodes_, globalFriction_, bodywiseNonmortarBoundaries_,
newUpdatersAndCount.updaters, errorNorms_, externalForces_);
newUpdatersAndCount.count = coupledTimeStepper.step(linearSolver, rTime, rTau);
iterationRegister_.registerCount(newUpdatersAndCount.count);
return newUpdatersAndCount;
};
return doStep();
/*using ScalarVector = typename Updaters::StateUpdater::ScalarVector;
std::vector<ScalarVector> alpha(contactNetwork_.nBodies());
newUpdatersAndCount.updaters.state_->extractAlpha(alpha);
print(alpha, "step alpha: ");
*/
}
#include "adaptivetimestepper_tmpl.cc" #include "adaptivetimestepper_tmpl.cc"
...@@ -2,9 +2,14 @@ ...@@ -2,9 +2,14 @@
#define SRC_TIME_STEPPING_ADAPTIVETIMESTEPPER_HH #define SRC_TIME_STEPPING_ADAPTIVETIMESTEPPER_HH
#include <fstream> #include <fstream>
#include <future>
#include <thread>
//#include "../multi-threading/task.hh" //#include "../multi-threading/task.hh"
#include "../spatial-solving/contact/nbodycontacttransfer.hh"
#include "coupledtimestepper.hh" #include "coupledtimestepper.hh"
#include "stepbase.hh"
struct IterationRegister { struct IterationRegister {
void registerCount(FixedPointIterationCounter count); void registerCount(FixedPointIterationCounter count);
...@@ -16,20 +21,23 @@ struct IterationRegister { ...@@ -16,20 +21,23 @@ struct IterationRegister {
FixedPointIterationCounter finalCount; FixedPointIterationCounter finalCount;
}; };
template <class Updaters>
struct UpdatersWithCount {
Updaters updaters;
FixedPointIterationCounter count;
};
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms> template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
class AdaptiveTimeStepper { class AdaptiveTimeStepper {
struct UpdatersWithCount { using UpdatersWithCount = UpdatersWithCount<Updaters>;
Updaters updaters;
FixedPointIterationCounter count;
};
using StepBase = StepBase<Factory, ContactNetwork, Updaters, ErrorNorms>;
using NBodyAssembler = typename ContactNetwork::NBodyAssembler;
using Vector = typename Factory::Vector; using Vector = typename Factory::Vector;
using Matrix = typename Factory::Matrix; using Matrix = typename Factory::Matrix;
using IgnoreVector = typename Factory::BitVector;
//using ConvexProblem = typename Factory::ConvexProblem;
//using Nonlinearity = typename Factory::Nonlinearity;
using NBodyAssembler = typename ContactNetwork::NBodyAssembler; using IgnoreVector = typename Factory::BitVector;
using MyCoupledTimeStepper = CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorms>; using MyCoupledTimeStepper = CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorms>;
...@@ -38,23 +46,15 @@ class AdaptiveTimeStepper { ...@@ -38,23 +46,15 @@ class AdaptiveTimeStepper {
using ExternalForces = typename MyCoupledTimeStepper::ExternalForces; using ExternalForces = typename MyCoupledTimeStepper::ExternalForces;
public: public:
AdaptiveTimeStepper( AdaptiveTimeStepper(const StepBase& stepBase,
Dune::ParameterTree const &parset,
ContactNetwork& contactNetwork, ContactNetwork& contactNetwork,
const IgnoreVector& ignoreNodes,
GlobalFriction& globalFriction,
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries,
Updaters &current, Updaters &current,
double relativeTime, double relativeTime,
double relativeTau, double relativeTau,
ExternalForces& externalForces,
const ErrorNorms& errorNorms,
std::function<bool(Updaters &, Updaters &)> mustRefine); std::function<bool(Updaters &, Updaters &)> mustRefine);
bool reachedEnd(); bool reachedEnd();
auto makeLinearSolver() const;
IterationRegister advance(); IterationRegister advance();
double relativeTime_; double relativeTime_;
...@@ -65,25 +65,19 @@ class AdaptiveTimeStepper { ...@@ -65,25 +65,19 @@ class AdaptiveTimeStepper {
NBodyAssembler step(const NBodyAssembler& oldNBodyAssembler) const; NBodyAssembler step(const NBodyAssembler& oldNBodyAssembler) const;
int refine(UpdatersWithCount& R2);
template <class LinearSolver> int coarsen();
UpdatersWithCount step(const Updaters& oldUpdaters, const NBodyAssembler& nBodyAssembler,
std::shared_ptr<LinearSolver>& linearSolver,
double rTime, double rTau);
double finalTime_; int determineStrategy(UpdatersWithCount& R2);
Dune::ParameterTree const &parset_;
ContactNetwork& contactNetwork_;
const IgnoreVector& ignoreNodes_;
GlobalFriction& globalFriction_; const StepBase& stepBase_;
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries_; ContactNetwork& contactNetwork_;
Updaters &current_; Updaters &current_;
UpdatersWithCount R1_; UpdatersWithCount R1_;
ExternalForces& externalForces_;
std::function<bool(Updaters &, Updaters &)> mustRefine_; std::function<bool(Updaters &, Updaters &)> mustRefine_;
const ErrorNorms& errorNorms_;
IterationRegister iterationRegister_; IterationRegister iterationRegister_;
}; };
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#error MY_DIM unset #error MY_DIM unset
#endif #endif
#include <future>
#include <thread>
#include "../explicitgrid.hh" #include "../explicitgrid.hh"
#include "../explicitvectors.hh" #include "../explicitvectors.hh"
...@@ -37,6 +40,7 @@ using MySolverFactory = SolverFactory<MyFunctional, BitVector>; ...@@ -37,6 +40,7 @@ using MySolverFactory = SolverFactory<MyFunctional, BitVector>;
template class AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>; template class AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>;
template typename AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>::UpdatersWithCount /*
template std::packaged_task<typename AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>::UpdatersWithCount()>
AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>::step<LinearSolver>( AdaptiveTimeStepper<MySolverFactory, MyContactNetwork, MyUpdaters, ErrorNorms>::step<LinearSolver>(
const MyUpdaters&, const MyNBodyAssembler&, std::shared_ptr<LinearSolver>&, double, double); const MyUpdaters&, const MyNBodyAssembler&, std::shared_ptr<LinearSolver>&, double, double); */
#ifndef DUNE_TECTONIC_TIME_STEPPING_STEP_HH
#define DUNE_TECTONIC_TIME_STEPPING_STEP_HH
#include <future>
#include <thread>
#include <chrono>
#include <functional>
#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/iterationsteps/multigridstep.hh>
#include <dune/solvers/iterationsteps/cgstep.hh>
#include <dune/solvers/solvers/loopsolver.hh>
#include "../spatial-solving/preconditioners/multilevelpatchpreconditioner.hh"
#include <dune/tectonic/utils/reductionfactors.hh>
#include "stepbase.hh"
#include "adaptivetimestepper.hh"
template<class IterationStepType, class NormType, class ReductionFactorContainer>
Dune::Solvers::Criterion reductionFactorCriterion(
IterationStepType& iterationStep,
const NormType& norm,
ReductionFactorContainer& reductionFactors)
{
double normOfOldCorrection = 1;
auto lastIterate = std::make_shared<typename IterationStepType::Vector>(*iterationStep.getIterate());
return Dune::Solvers::Criterion(
[&, lastIterate, normOfOldCorrection] () mutable {
double normOfCorrection = norm.diff(*lastIterate, *iterationStep.getIterate());
double convRate = (normOfOldCorrection > 0) ? normOfCorrection / normOfOldCorrection : 0.0;
if (convRate>1.0)
std::cout << "Solver convergence rate of " << convRate << std::endl;
normOfOldCorrection = normOfCorrection;
*lastIterate = *iterationStep.getIterate();
reductionFactors.push_back(convRate);
return std::make_tuple(convRate < 0, Dune::formatString(" % '.5f", convRate));
},
" reductionFactor");
}
template<class IterationStepType, class Functional, class ReductionFactorContainer>
Dune::Solvers::Criterion energyCriterion(
const IterationStepType& iterationStep,
const Functional& f,
ReductionFactorContainer& reductionFactors)
{
double normOfOldCorrection = 1;
auto lastIterate = std::make_shared<typename IterationStepType::Vector>(*iterationStep.getIterate());
return Dune::Solvers::Criterion(
[&, lastIterate, normOfOldCorrection] () mutable {
double normOfCorrection = std::abs(f(*lastIterate) - f(*iterationStep.getIterate())); //norm.diff(*lastIterate, *iterationStep.getIterate());
double convRate = (normOfOldCorrection != 0.0) ? 1.0 - (normOfCorrection / normOfOldCorrection) : 0.0;
if (convRate>1.0)
std::cout << "Solver convergence rate of " << convRate << std::endl;
normOfOldCorrection = normOfCorrection;
*lastIterate = *iterationStep.getIterate();
reductionFactors.push_back(convRate);
return std::make_tuple(convRate < 0, Dune::formatString(" % '.5f", convRate));
},
" reductionFactor");
}
template <class ReductionFactorContainer>
void updateReductionFactors(ReductionFactorContainer& reductionFactors) {
const size_t s = reductionFactors.size();
//print(reductionFactors, "reduction factors: ");
if (s>allReductionFactors.size()) {
allReductionFactors.resize(s);
}
for (size_t i=0; i<reductionFactors.size(); i++) {
allReductionFactors[i].push_back(reductionFactors[i]);
}
reductionFactors.clear();
}
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
class Step : protected StepBase<Factory, ContactNetwork, Updaters, ErrorNorms> {
public:
enum Mode { sameThread, newThread };
private:
using Base = StepBase<Factory, ContactNetwork, Updaters, ErrorNorms>;
using NBodyAssembler = typename ContactNetwork::NBodyAssembler;
using UpdatersWithCount = UpdatersWithCount<Updaters>;
const Updaters& oldUpdaters_;
const NBodyAssembler& nBodyAssembler_;
double relativeTime_;
double relativeTau_;
IterationRegister& iterationRegister_;
std::packaged_task<UpdatersWithCount()> task_;
std::future<UpdatersWithCount> future_;
std::thread thread_;
Mode mode_;
public:
Step(const Base& stepFactory, const Updaters& oldUpdaters, const NBodyAssembler& nBodyAssembler, double rTime, double rTau, IterationRegister& iterationRegister) :
Base(stepFactory.parset_, stepFactory.contactNetwork_, stepFactory.ignoreNodes_, stepFactory.globalFriction_,
stepFactory.bodywiseNonmortarBoundaries_, stepFactory.externalForces_, stepFactory.errorNorms_),
oldUpdaters_(oldUpdaters),
nBodyAssembler_(nBodyAssembler),
relativeTime_(rTime),
relativeTau_(rTau),
iterationRegister_(iterationRegister) {}
UpdatersWithCount doStep() {
// make linear solver for linear correction in TNNMGStep
using Vector = typename Factory::Vector;
using Matrix = typename Factory::Matrix;
/* old, pre multi threading, was unused
using Norm = EnergyNorm<Matrix, Vector>;
using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;
const auto& preconditionerParset = parset_.sub("solver.tnnmg.linear.preconditioner");
Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true);
Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels);
preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
preconditioner.build();
auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>();
cgStep->setPreconditioner(preconditioner);
Norm norm(*cgStep);
return std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.linear.tolerance"), norm, Solver::QUIET);
*/
// patch preconditioner only needs to be computed once per advance()
// make linear solver for linear correction in TNNMGStep
using Norm = EnergyNorm<Matrix, Vector>;
using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;
/*const auto& preconditionerParset = parset_.sub("solver.tnnmg.preconditioner");
Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true);
Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels);
preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
preconditioner.build();
auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>();
cgStep->setPreconditioner(preconditioner);
Norm norm(*cgStep);
auto linearSolver = std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET);
*/
// set multigrid solver
auto smoother = TruncatedBlockGSStep<Matrix, Vector>();
// transfer operators need to be recomputed on change due to setDeformation()
using TransferOperator = NBodyContactTransfer<ContactNetwork, Vector>;
using TransferOperators = std::vector<std::shared_ptr<TransferOperator>>;
TransferOperators transfer(this->contactNetwork_.nLevels()-1);
for (size_t i=0; i<transfer.size(); i++) {
transfer[i] = std::make_shared<TransferOperator>();
transfer[i]->setup(this->contactNetwork_, i, i+1);
}
// Remove any recompute filed so that initially the full transferoperator is assembled
for (size_t i=0; i<transfer.size(); i++)
std::dynamic_pointer_cast<TruncatedMGTransfer<Vector> >(transfer[i])->setRecomputeBitField(nullptr);
auto linearMultigridStep = std::make_shared<Dune::Solvers::MultigridStep<Matrix, Vector> >();
linearMultigridStep->setMGType(1, 3, 3);
linearMultigridStep->setSmoother(smoother);
linearMultigridStep->setTransferOperators(transfer);
Norm norm(*linearMultigridStep);
auto linearSolver = std::make_shared<LinearSolver>(linearMultigridStep, this->parset_.template get<int>("solver.tnnmg.main.multi"), this->parset_.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET);
Vector x;
x.resize(nBodyAssembler_.totalHasObstacle_.size());
x = 0;
linearSolver->getIterationStep().setProblem(x);
//dynamic_cast<Dune::Solvers::IterationStep<Vector>*>(linearMultigridStep.get())->setProblem(x);
//dynamic_cast<Dune::Solvers::IterationStep<Vector>*>(cgStep.get())->setProblem(x);
//std::vector<double> reductionFactors;
//linearSolver->addCriterion(reductionFactorCriterion(linearSolver->getIterationStep(), linearSolver->getErrorNorm(), reductionFactors));
//linearSolver->addCriterion(reductionFactorCriterion(*cgStep, norm, reductionFactors));
UpdatersWithCount newUpdatersAndCount = {oldUpdaters_.clone(), {}};
typename Base::MyCoupledTimeStepper coupledTimeStepper(
this->finalTime_, this->parset_, nBodyAssembler_,
this->ignoreNodes_, this->globalFriction_, this->bodywiseNonmortarBoundaries_,
newUpdatersAndCount.updaters, this->errorNorms_, this->externalForces_);
newUpdatersAndCount.count = coupledTimeStepper.step(linearSolver, relativeTime_, relativeTau_);
iterationRegister_.registerCount(newUpdatersAndCount.count);
//updateReductionFactors(reductionFactors);
return newUpdatersAndCount;
}
/* auto simple = [&]{
std::cout << "starting task... " << std::endl;
UpdatersWithCount newUpdatersAndCount = {oldUpdaters.clone(), {}};
std::this_thread::sleep_for(std::chrono::milliseconds(10000));
std::cout << "finishing task... " << std::endl;
return newUpdatersAndCount;
}*/
void run(Mode mode = sameThread) {
mode_ = mode;
task_ = std::packaged_task<UpdatersWithCount()>( [this]{ return doStep(); });
future_ = task_.get_future();
if (mode == Mode::sameThread) {
task_();
} else {
thread_ = std::thread(std::move(task_));
}
}
auto get() {
std::cout << "Step::get() called" << std::endl;
if (thread_.joinable()) {
thread_.join();
std::cout << "Thread joined " << std::endl;
}
return future_.get();
}
~Step() {
if (thread_.joinable()) {
thread_.join();
std::cout << "Destructor:: Thread joined " << std::endl;
}
}
};
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
Step<Factory, ContactNetwork, Updaters, ErrorNorms>
buildStep(const StepBase<Factory, ContactNetwork, Updaters, ErrorNorms>& base,
const Updaters& oldUpdaters,
const typename ContactNetwork::NBodyAssembler& nBodyAssembler,
double rTime, double rTau) {
return Step(base, oldUpdaters, nBodyAssembler, rTime, rTau);
}
#endif
#ifndef DUNE_TECTONIC_TIME_STEPPING_STEPBASE_HH
#define DUNE_TECTONIC_TIME_STEPPING_STEPBASE_HH
#include "coupledtimestepper.hh"
template <class Factory, class ContactNetwork, class Updaters, class ErrorNorms>
class StepBase {
protected:
using NBodyAssembler = typename ContactNetwork::NBodyAssembler;
using IgnoreVector = typename Factory::BitVector;
using MyCoupledTimeStepper = CoupledTimeStepper<Factory, NBodyAssembler, Updaters, ErrorNorms>;
using GlobalFriction = typename MyCoupledTimeStepper::GlobalFriction;
using BitVector = typename MyCoupledTimeStepper::BitVector;
using ExternalForces = typename MyCoupledTimeStepper::ExternalForces;
public:
StepBase(
Dune::ParameterTree const &parset,
ContactNetwork& contactNetwork,
const IgnoreVector& ignoreNodes,
GlobalFriction& globalFriction,
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries,
ExternalForces& externalForces,
const ErrorNorms& errorNorms) :
parset_(parset),
finalTime_(parset_.get<double>("problem.finalTime")),
contactNetwork_(contactNetwork),
ignoreNodes_(ignoreNodes),
globalFriction_(globalFriction),
bodywiseNonmortarBoundaries_(bodywiseNonmortarBoundaries),
externalForces_(externalForces),
errorNorms_(errorNorms) {}
Dune::ParameterTree const &parset_;
double finalTime_;
ContactNetwork& contactNetwork_;
const IgnoreVector& ignoreNodes_;
GlobalFriction& globalFriction_;
const std::vector<const BitVector*>& bodywiseNonmortarBoundaries_;
ExternalForces& externalForces_;
const ErrorNorms& errorNorms_;
};
#endif
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
#include <dune/tectonic/time-stepping/adaptivetimestepper.hh> #include <dune/tectonic/time-stepping/adaptivetimestepper.hh>
#include <dune/tectonic/time-stepping/rate.hh> #include <dune/tectonic/time-stepping/rate.hh>
#include <dune/tectonic/time-stepping/state.hh> #include <dune/tectonic/time-stepping/state.hh>
#include <dune/tectonic/time-stepping/stepbase.hh>
#include <dune/tectonic/time-stepping/updaters.hh> #include <dune/tectonic/time-stepping/updaters.hh>
#include <dune/tectonic/utils/debugutils.hh> #include <dune/tectonic/utils/debugutils.hh>
...@@ -341,10 +342,14 @@ int main(int argc, char *argv[]) { ...@@ -341,10 +342,14 @@ int main(int argc, char *argv[]) {
typename ContactNetwork::ExternalForces externalForces; typename ContactNetwork::ExternalForces externalForces;
contactNetwork.externalForces(externalForces); contactNetwork.externalForces(externalForces);
StepBase<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
stepBase(parset, contactNetwork, totalDirichletNodes, globalFriction, frictionNodes,
externalForces, stateEnergyNorms);
AdaptiveTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>> AdaptiveTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
adaptiveTimeStepper(parset, contactNetwork, totalDirichletNodes, globalFriction, frictionNodes, current, adaptiveTimeStepper(stepBase, contactNetwork, current,
programState.relativeTime, programState.relativeTau, programState.relativeTime, programState.relativeTau,
externalForces, stateEnergyNorms, mustRefine); mustRefine);
size_t timeSteps = parset.get<size_t>("timeSteps.timeSteps"); size_t timeSteps = parset.get<size_t>("timeSteps.timeSteps");
......
# -*- mode:conf -*- # -*- mode:conf -*-
[body0] [body0]
smallestDiameter = 0.05 # 2e-3 [m] smallestDiameter = 0.02 # 2e-3 [m]
[body1] [body1]
smallestDiameter = 0.05 # 2e-3 [m] smallestDiameter = 0.02 # 2e-3 [m]
[timeSteps] [timeSteps]
refinementTolerance = 5e-6 # 1e-5 refinementTolerance = 5e-6 # 1e-5
......
...@@ -56,6 +56,8 @@ ...@@ -56,6 +56,8 @@
#include <dune/tectonic/factories/strikeslipfactory.hh> #include <dune/tectonic/factories/strikeslipfactory.hh>
#include <dune/tectonic/io/io-handler.hh>
#include <dune/tectonic/io/hdf5-writer.hh> #include <dune/tectonic/io/hdf5-writer.hh>
#include <dune/tectonic/io/hdf5/restart-io.hh> #include <dune/tectonic/io/hdf5/restart-io.hh>
#include <dune/tectonic/io/vtk.hh> #include <dune/tectonic/io/vtk.hh>
...@@ -167,29 +169,13 @@ int main(int argc, char *argv[]) { ...@@ -167,29 +169,13 @@ int main(int argc, char *argv[]) {
using MyProgramState = ProgramState<Vector, ScalarVector>; using MyProgramState = ProgramState<Vector, ScalarVector>;
MyProgramState programState(nVertices); MyProgramState programState(nVertices);
auto const firstRestart = parset.get<size_t>("io.restarts.first");
auto const restartSpacing = parset.get<size_t>("io.restarts.spacing"); IOHandler<Assembler, ContactNetwork> ioHandler(parset.sub("io"), contactNetwork);
auto const writeRestarts = parset.get<bool>("io.restarts.write");
auto const writeData = parset.get<bool>("io.data.write"); bool restartRead = ioHandler.read(programState);
bool const handleRestarts = writeRestarts or firstRestart > 0; if (!restartRead) {
programState.setupInitialConditions(parset, contactNetwork);
auto restartFile = handleRestarts }
? std::make_unique<HDF5::File>(
"restarts.h5",
writeRestarts ? HDF5::Access::READWRITE
: HDF5::Access::READONLY)
: nullptr;
auto restartIO = handleRestarts
? std::make_unique<RestartIO<MyProgramState>>(
*restartFile, nVertices)
: nullptr;
if (firstRestart > 0) // automatically adjusts the time and timestep
restartIO->read(firstRestart, programState);
else
programState.setupInitialConditions(parset, contactNetwork);
auto& nBodyAssembler = contactNetwork.nBodyAssembler(); auto& nBodyAssembler = contactNetwork.nBodyAssembler();
for (size_t i=0; i<bodyCount; i++) { for (size_t i=0; i<bodyCount; i++) {
...@@ -206,90 +192,9 @@ int main(int argc, char *argv[]) { ...@@ -206,90 +192,9 @@ int main(int argc, char *argv[]) {
auto& globalFriction = contactNetwork.globalFriction(); auto& globalFriction = contactNetwork.globalFriction();
globalFriction.updateAlpha(programState.alpha); globalFriction.updateAlpha(programState.alpha);
using MyVertexBasis = typename Assembler::VertexBasis;
using MyCellBasis = typename Assembler::CellBasis;
std::vector<Vector> vertexCoordinates(bodyCount);
std::vector<const MyVertexBasis* > vertexBases(bodyCount);
std::vector<const MyCellBasis* > cellBases(bodyCount);
auto& wPatches = blocksFactory.weakPatches();
std::vector<std::vector<const ConvexPolyhedron<LocalVector>*>> weakPatches(bodyCount);
for (size_t i=0; i<bodyCount; i++) {
const auto& body = contactNetwork.body(i);
vertexBases[i] = &(body->assembler()->vertexBasis);
cellBases[i] = &(body->assembler()->cellBasis);
weakPatches[i].resize(1);
weakPatches[i][0] = wPatches[i].get();
auto& vertexCoords = vertexCoordinates[i];
vertexCoords.resize(nVertices[i]);
auto hostLeafView = body->grid()->hostGrid().leafGridView();
Dune::MultipleCodimMultipleGeomTypeMapper<
LeafGridView, Dune::MCMGVertexLayout> const vertexMapper(hostLeafView, Dune::mcmgVertexLayout());
for (auto &&v : vertices(hostLeafView))
vertexCoords[vertexMapper.index(v)] = geoToPoint(v.geometry());
}
typename ContactNetwork::BoundaryPatches frictionBoundaries;
contactNetwork.boundaryPatches("friction", frictionBoundaries);
std::vector<const typename ContactNetwork::BoundaryPatch*> frictionPatches;
contactNetwork.frictionPatches(frictionPatches);
IterationRegister iterationCount; IterationRegister iterationCount;
auto const report = [&](bool initial = false) { ioHandler.write(programState, contactNetwork, globalFriction, iterationCount, true);
auto dataFile =
writeData ? std::make_unique<HDF5::File>("output.h5") : nullptr;
auto dataWriter =
writeData ? std::make_unique<
HDF5Writer<MyProgramState, MyVertexBasis, DefLeafGridView>>(
*dataFile, vertexCoordinates, vertexBases,
frictionPatches, weakPatches)
: nullptr;
if (writeData) {
dataWriter->reportSolution(programState, contactNetwork, globalFriction);
if (!initial)
dataWriter->reportIterations(programState, iterationCount);
dataFile->flush();
}
if (writeRestarts and !initial and
programState.timeStep % restartSpacing == 0) {
restartIO->write(programState);
restartFile->flush();
}
if (parset.get<bool>("io.printProgress"))
std::cout << "timeStep = " << std::setw(6) << programState.timeStep
<< ", time = " << std::setw(12) << programState.relativeTime
<< ", tau = " << std::setw(12) << programState.relativeTau
<< std::endl;
if (parset.get<bool>("io.vtk.write")) {
std::vector<ScalarVector> stress(bodyCount);
for (size_t i=0; i<bodyCount; i++) {
const auto& body = contactNetwork.body(i);
body->assembler()->assembleVonMisesStress(body->data()->getYoungModulus(),
body->data()->getPoissonRatio(),
programState.u[i], stress[i]);
}
const MyVTKWriter<MyVertexBasis, MyCellBasis> vtkWriter(cellBases, vertexBases, "../debug_print/vtk/");
vtkWriter.write(programState.timeStep, programState.u, programState.v,
programState.alpha, stress);
}
};
report(true);
// ------------------- // -------------------
// Set up TNNMG solver // Set up TNNMG solver
...@@ -428,10 +333,14 @@ int main(int argc, char *argv[]) { ...@@ -428,10 +333,14 @@ int main(int argc, char *argv[]) {
typename ContactNetwork::ExternalForces externalForces; typename ContactNetwork::ExternalForces externalForces;
contactNetwork.externalForces(externalForces); contactNetwork.externalForces(externalForces);
StepBase<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
stepBase(parset, contactNetwork, totalDirichletNodes, globalFriction, frictionNodes,
externalForces, stateEnergyNorms);
AdaptiveTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>> AdaptiveTimeStepper<NonlinearFactory, std::decay_t<decltype(contactNetwork)>, Updaters, std::decay_t<decltype(stateEnergyNorms)>>
adaptiveTimeStepper(parset, contactNetwork, totalDirichletNodes, globalFriction, frictionNodes, current, adaptiveTimeStepper(stepBase, contactNetwork, current,
programState.relativeTime, programState.relativeTau, programState.relativeTime, programState.relativeTau,
externalForces, stateEnergyNorms, mustRefine); mustRefine);
size_t timeSteps = parset.get<size_t>("timeSteps.timeSteps"); size_t timeSteps = parset.get<size_t>("timeSteps.timeSteps");
...@@ -456,7 +365,7 @@ int main(int argc, char *argv[]) { ...@@ -456,7 +365,7 @@ int main(int argc, char *argv[]) {
contactNetwork.setDeformation(programState.u); contactNetwork.setDeformation(programState.u);
report(); ioHandler.write(programState, contactNetwork, globalFriction, iterationCount, false);
if (programState.timeStep==timeSteps) { if (programState.timeStep==timeSteps) {
std::cout << "limit of timeSteps reached!" << std::endl; std::cout << "limit of timeSteps reached!" << std::endl;
......
...@@ -55,11 +55,11 @@ sigmaN = 200.0 # [Pa] ...@@ -55,11 +55,11 @@ sigmaN = 200.0 # [Pa]
finalVelocity = 1e-4 # [m/s] finalVelocity = 1e-4 # [m/s]
[io] [io]
data.write = true data.write = false
printProgress = true printProgress = true
restarts.first = 0 restarts.first = 0
restarts.spacing= 20 restarts.spacing= 1
restarts.write = false #true restarts.write = true #true
vtk.write = true vtk.write = true
[problem] [problem]
...@@ -73,7 +73,7 @@ relativeTau = 2e-4 # 1e-6 ...@@ -73,7 +73,7 @@ relativeTau = 2e-4 # 1e-6
[timeSteps] [timeSteps]
scheme = newmark scheme = newmark
timeSteps = 5000 timeSteps = 5
[u0.solver] [u0.solver]
maximumIterations = 100 maximumIterations = 100
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment