-
Elias Pipping authored
This reverts commit 3c2fc4080e8af5ed4b17512914e6a7db866a11e6. Conflicts: src/one-body-sample.org
Elias Pipping authoredThis reverts commit 3c2fc4080e8af5ed4b17512914e6a7db866a11e6. Conflicts: src/one-body-sample.org
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
one-body-sample.org 17.96 KiB
Setup
{
MassAssembler
<GridType, P1Basis::LocalFiniteElement,
P1Basis::LocalFiniteElement> const localMass;
OperatorAssembler<P1Basis,P1Basis>(p1Basis, p1Basis)
.assemble(localMass, massMatrix);
massMatrix *= density;
}
{
double volume = 1.0;
for (int i=0; i<dim; ++i)
volume *= (upperRight[i] - lowerLeft[i]);
double area = 1.0;
for (int i=0; i<dim; ++i)
if (i != 1)
area *= (upperRight[i] - lowerLeft[i]);
// volume * gravity * density / area = normal stress
// V * g * rho / A = sigma_n
// m^d * N/kg * kg/m^d / m^(d-1) = N/m^(d-1)
normalStress = volume * gravity * density / area;
}
{
SmallVector weightedGravitationalDirection(0);
weightedGravitationalDirection[1] = - density * gravity;
ConstantFunction<SmallVector,SmallVector> const gravityFunction
(weightedGravitationalDirection);
L2FunctionalAssembler<GridType, SmallVector> gravityFunctionalAssembler
(gravityFunction);
FunctionalAssembler<P1Basis>(p1Basis)
.assemble(gravityFunctionalAssembler, gravityFunctional, true);
}
{
StVenantKirchhoffAssembler
<GridType, P1Basis::LocalFiniteElement,
P1Basis::LocalFiniteElement> const localStiffness(E, nu);
OperatorAssembler<P1Basis,P1Basis>(p1Basis, p1Basis)
.assemble(localStiffness, stiffnessMatrix);
}
{
typedef typename GridView::template Codim<dim>::Iterator VertexLeafIterator;
Dune::MultipleCodimMultipleGeomTypeMapper
<GridView, Dune::MCMGVertexLayout> const myVertexMapper(leafView);
for (auto it = leafView.template begin<dim>();
it != leafView.template end<dim>();
++it) {
assert(it->geometry().corners() == 1);
Dune::FieldVector<double, dim> const coordinates = it->geometry().corner(0);
size_t const id = myVertexMapper.map(*it);
// Find the center of the lower face
switch (dim) {
case 3:
if (coordinates[2] != lowerLeft[2])
break;
// fallthrough
case 2:
if (coordinates[1] == lowerLeft[1]
&& std::abs(coordinates[0] - lowerLeft[0]) < 1e-8)
specialNode = id;
break;
default:
assert(false);
}
// lower face
if (coordinates[1] == lowerLeft[1]) {
frictionalNodes[id] = true;
ignoreNodes[id][1] = true;
}
// upper face
else if (coordinates[1] == upperRight[1])
ignoreNodes[id] = true;
// right face (except for both corners)
else if (coordinates[0] == upperRight[0])
;
// left face (except for both corners)
else if (coordinates[0] == lowerLeft[0])
;
}
// Make sure that specialNode was set and points to a frictional node
assert(specialNode != finestSize);
assert(frictionalNodes[specialNode][0]);
}
Writers
std::fstream state_writer("state", std::fstream::out);
std::fstream displacement_writer("displacement", std::fstream::out);
std::fstream velocity_writer("velocity", std::fstream::out);
std::fstream coefficient_writer("coefficient", std::fstream::out);
state_writer << alpha[specialNode][0] << " " << std::endl;
displacement_writer << u[specialNode][0] << " " << std::endl;
velocity_writer << ud[specialNode][0] << " " << std::endl;
coefficient_writer << mu
+ a * std::log(ud[specialNode].two_norm() / V0)
+ b * (alpha[specialNode] + std::log(V0 / L))
<< " " << std::endl;
state_writer.close();
displacement_writer.close();
velocity_writer.close();
coefficient_writer.close();
if (parset.get<bool>("writeVTK")) {
VonMisesStressAssembler<GridType> localStressAssembler
(E, nu,
Dune::make_shared<BasisGridFunction<P1Basis, VectorType> const>
(p1Basis, u));
FunctionalAssembler<P0Basis>(p0Basis)
.assemble(localStressAssembler, vonMisesStress, true);
writeVtk<P1Basis, P0Basis, VectorType, SingletonVectorType, GridView>
(p1Basis, u, alpha, p0Basis, vonMisesStress, leafView,
(boost::format("obs%d") % run).str());
}
Misc. helpers
if (parset.get<bool>("enableTimer"))
std::cerr << std::endl
<< "Making " << timesteps
<< " time steps took " << timer.elapsed()
<< "s" << std::endl;
if (parset.get<bool>("printProgress")) {
std::cerr << '.';
std::cerr.flush();
}
if (parset.get<bool>("printProgress"))
std::cerr << std::endl;
Functions
template<class VectorType, class MatrixType, class FunctionType, int dim>
Dune::shared_ptr
<TimeSteppingScheme
<VectorType,MatrixType,FunctionType,dim> >
initTimeStepper(Config::scheme scheme,
FunctionType const &dirichletFunction,
Dune::BitSetVector<dim> const &ignoreNodes,
MatrixType const &massMatrix, MatrixType const &stiffnessMatrix,
VectorType const &u_initial,
VectorType const &ud_initial,
VectorType const &udd_initial)
{
switch (scheme) {
case Config::ImplicitTwoStep:
return Dune::make_shared<ImplicitTwoStep<VectorType,MatrixType,
FunctionType,dim> >
(stiffnessMatrix, u_initial, ud_initial, ignoreNodes, dirichletFunction);
case Config::ImplicitEuler:
return Dune::make_shared<ImplicitEuler<VectorType,MatrixType,
FunctionType,dim> >
(stiffnessMatrix, u_initial, ud_initial, ignoreNodes, dirichletFunction);
case Config::Newmark:
return Dune::make_shared <Newmark <VectorType,MatrixType,FunctionType,dim> >
(stiffnessMatrix, massMatrix, u_initial, ud_initial, udd_initial,
ignoreNodes, dirichletFunction);
}
}
template<class SingletonVectorType, class VectorType>
Dune::shared_ptr<StateUpdater<SingletonVectorType, VectorType> >
initStateUpdater(Config::state_model model,
SingletonVectorType const &alpha_initial,
Dune::BitSetVector<1> const &frictionalNodes,
double L)
{
switch (model) {
case Config::Dieterich:
return Dune::make_shared
<DieterichStateUpdater<SingletonVectorType, VectorType> >
(alpha_initial, frictionalNodes, L);
case Config::Ruina:
return Dune::make_shared
<RuinaStateUpdater<SingletonVectorType, VectorType> >
(alpha_initial, frictionalNodes, L);
}
}
template <class FunctionMap>
void
initPython(FunctionMap &functions)
{
Python::start();
Python::run("import sys");
Python::run("sys.path.append('" srcdir "')");
Python::import("one-body-sample")
.get("Functions")
.toC<typename FunctionMap::Base>(functions);
}
try {
Dune::Timer timer;
Dune::ParameterTree parset;
Dune::ParameterTreeParser::readINITree
(srcdir "/one-body-sample.parset", parset);
Dune::ParameterTreeParser::readOptions(argc, argv, parset);
typedef Dune::FieldVector<double, dim> SmallVector;
typedef Dune::FieldMatrix<double, dim, dim> SmallMatrix;
typedef Dune::BCRSMatrix<SmallMatrix> MatrixType;
typedef Dune::BlockVector<SmallVector> VectorType;
typedef Dune::BlockVector<Dune::FieldVector<double,1> > SingletonVectorType;
auto const E = parset.get<double>("body.E");
auto const nu = parset.get<double>("body.nu");
auto const mu = parset.get<double>("boundary.friction.mu");
auto const a = parset.get<double>("boundary.friction.a");
auto const b = parset.get<double>("boundary.friction.b");
auto const V0 = parset.get<double>("boundary.friction.V0");
auto const L = parset.get<double>("boundary.friction.L");
// {{{ Set up grid
typedef Dune::ALUGrid<dim, dim, Dune::simplex, Dune::nonconforming>
GridType;
Dune::FieldVector<typename GridType::ctype, dim> lowerLeft(0);
Dune::FieldVector<typename GridType::ctype, dim> upperRight(1);
upperRight[0] = parset.get<size_t>("body.width");
upperRight[1] = parset.get<size_t>("body.height");
Dune::array<unsigned int, dim> elements;
std::fill(elements.begin(), elements.end(), 1);
elements[0] = parset.get<size_t>("body.width");
elements[1] = parset.get<size_t>("body.height");
auto grid = Dune::StructuredGridFactory<GridType>::createSimplexGrid
(lowerLeft, upperRight, elements);
auto const refinements = parset.get<size_t>("grid.refinements");
grid->globalRefine(refinements);
size_t const finestSize = grid->size(grid->maxLevel(), dim);
typedef GridType::LeafGridView GridView;
GridView const leafView = grid->leafView();
// }}}
// Set up bases
typedef P0Basis<GridView, double> P0Basis;
typedef P1NodalBasis<GridView, double> P1Basis;
P0Basis const p0Basis(leafView);
P1Basis const p1Basis(leafView);
// Set up the boundary
size_t specialNode = finestSize;
Dune::BitSetVector<dim> ignoreNodes(finestSize, false);
Dune::BitSetVector<1> neumannNodes(finestSize, false);
Dune::BitSetVector<1> frictionalNodes(finestSize, false);
<<setupBoundary>>;
// Set up functions for time-dependent boundary conditions
typedef SharedPointerMap
<std::string, Dune::VirtualFunction<double, double> > FunctionMap;
FunctionMap functions;
initPython(functions);
auto const &dirichletFunction = functions.get("dirichletCondition");
auto const &neumannFunction = functions.get("neumannCondition");
// Set up normal stress, mass matrix, and gravity functional
double normalStress;
MatrixType massMatrix;
VectorType gravityFunctional;
{
double const gravity = 9.81;
double const density = parset.get<double>("body.density");
<<assembleMassMatrix>>;
<<computeNormalStress>>;
<<computeGravitationalBodyForce>>;
}
SingletonVectorType surfaceNormalStress(finestSize);
surfaceNormalStress = 0.0;
for (size_t i = 0; i < frictionalNodes.size(); ++i)
if (frictionalNodes[i][0])
surfaceNormalStress[i] = normalStress;
MatrixType stiffnessMatrix;
<<assembleStiffnessMatrix>>;
EnergyNorm<MatrixType, VectorType> energyNorm(stiffnessMatrix);
auto const nodalIntegrals
= assemble_frictional<GridType, GridView, SmallVector, P1Basis>
(leafView, p1Basis, frictionalNodes);
// {{{ Initialise vectors
VectorType u(finestSize); u = 0.0;
VectorType ud(finestSize); ud = 0.0;
VectorType u_initial(finestSize); u_initial = 0.0;
VectorType ud_initial(finestSize); ud_initial = 0.0;
VectorType udd_initial(finestSize); udd_initial = 0.0;
SingletonVectorType alpha_initial(finestSize);
alpha_initial = parset.get<double>("boundary.friction.initial_log_state");
SingletonVectorType alpha(alpha_initial);
SingletonVectorType vonMisesStress;
// }}}
// Set up TNNMG solver
auto const solver_tolerance = parset.get<double>("solver.tolerance");
typedef MyConvexProblem<MatrixType, VectorType> MyConvexProblemType;
typedef MyBlockProblem<MyConvexProblemType> MyBlockProblemType;
MySolver<dim, MatrixType, VectorType, GridType, MyBlockProblemType>
mySolver(parset.sub("solver.tnnmg"), refinements, solver_tolerance,
*grid, ignoreNodes);
Solver::VerbosityMode const verbosity
= parset.get<bool>("verbose") ? Solver::FULL : Solver::QUIET;
<<createWriters>>;
// Set up time steppers that
auto timeSteppingScheme = initTimeStepper
(parset.get<Config::scheme>("timeSteppingScheme"), dirichletFunction,
ignoreNodes, massMatrix, stiffnessMatrix, u_initial, ud_initial,
udd_initial);
auto stateUpdater = initStateUpdater<SingletonVectorType, VectorType>
(parset.get<Config::state_model>("boundary.friction.state_model"),
alpha_initial, frictionalNodes, L);
auto const timesteps = parset.get<size_t>("timeSteps");
auto const tau = parset.get<double>("endOfTime") / timesteps;
auto const state_fpi_max
= parset.get<size_t>("solver.tnnmg.fixed_point_iterations");
for (size_t run = 1; run <= timesteps; ++run) {
stateUpdater->nextTimeStep();
timeSteppingScheme->nextTimeStep();
double const time = tau * run;
VectorType ell(finestSize);
assemble_neumann<GridType, GridView, SmallVector, P1Basis>
(leafView, p1Basis, neumannNodes, ell, neumannFunction, time);
ell += gravityFunctional;
MatrixType problem_A;
VectorType problem_rhs(finestSize);
VectorType problem_iterate(finestSize);
stateUpdater->setup(tau);
timeSteppingScheme->setup(ell, tau, time,
problem_rhs, problem_iterate, problem_A);
// Since the velocity explodes in the quasistatic case, use the
// displacement as a convergence criterion
VectorType u_saved;
for (size_t state_fpi = 1; state_fpi <= state_fpi_max; ++state_fpi) {
{
auto myGlobalNonlinearity
= assemble_nonlinearity<MatrixType, VectorType>
(parset.sub("boundary.friction"), *nodalIntegrals, alpha,
surfaceNormalStress);
MyConvexProblemType const myConvexProblem
(problem_A, *myGlobalNonlinearity, problem_rhs);
MyBlockProblemType myBlockProblem(parset, myConvexProblem);
auto multigridStep = mySolver.getSolver();
multigridStep->setProblem(problem_iterate, myBlockProblem);
LoopSolver<VectorType> overallSolver
(multigridStep, parset.get<size_t>("solver.tnnmg.maxiterations"),
solver_tolerance, &energyNorm, verbosity, false); // absolute error
overallSolver.solve();
}
timeSteppingScheme->postProcess(problem_iterate);
timeSteppingScheme->extractDisplacement(u);
timeSteppingScheme->extractVelocity(ud);
stateUpdater->solve(ud);
stateUpdater->extractState(alpha);
<<printInnerProgress>>;
if (state_fpi > 1 && energyNorm.diff(u_saved, u)
< parset.get<double>("solver.tnnmg.fixed_point_tolerance"))
break;
else
u_saved = u;
if (state_fpi == state_fpi_max)
std::cerr << "[ref = " << refinements
<< "]: FPI did not converge after "
<< state_fpi_max << " iterations" << std::endl;
}
<<printOuterProgress>>;
<<writeData>>;
<<assembleAndWriteStress>>;
}
<<printBenchmarkData>>;
<<closeWriters>>;
Python::stop();
}
catch (Dune::Exception &e) {
Dune::derr << "Dune reported error: " << e << std::endl;
}
catch (std::exception &e) {
std::cerr << "Standard exception: " << e.what() << std::endl;
}
Skeleton
// GENERATED -- DO NOT MODIFY
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_IPOPT
#undef HAVE_IPOPT
#endif
#ifndef srcdir
#error srcdir unset
#endif
#ifndef DIM
#error DIM unset
#endif
#ifndef HAVE_PYTHON
#error Python is required
#endif
#if ! HAVE_ALUGRID
#error ALUGRID is required
#endif
#include <cmath>
#include <exception>
#include <iostream>
#include <boost/format.hpp>
#include <Python.h>
#include <dune/common/bitsetvector.hh>
#include <dune/common/exceptions.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/function.hh>
#include <dune/common/fvector.hh>
#include <dune/common/parametertree.hh>
#include <dune/common/parametertreeparser.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/common/timer.hh>
#include <dune/grid/alugrid.hh>
#include <dune/grid/common/mcmgmapper.hh>
#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/istl/bcrsmatrix.hh>
#include <dune/istl/bvector.hh>
#include <dune/fufem/assemblers/functionalassembler.hh>
#include <dune/fufem/assemblers/localassemblers/l2functionalassembler.hh>
#include <dune/fufem/assemblers/localassemblers/massassembler.hh>
#include <dune/fufem/assemblers/localassemblers/stvenantkirchhoffassembler.hh>
#include <dune/fufem/assemblers/localassemblers/vonmisesstressassembler.hh>
#include <dune/fufem/assemblers/operatorassembler.hh>
#include <dune/fufem/dunepython.hh>
#include <dune/fufem/functions/basisgridfunction.hh>
#include <dune/fufem/functions/constantfunction.hh>
#include <dune/fufem/functionspacebases/p0basis.hh>
#include <dune/fufem/functionspacebases/p1nodalbasis.hh>
#include <dune/fufem/sharedpointermap.hh>
#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/solvers/loopsolver.hh>
#include <dune/solvers/solvers/solver.hh> // Solver::FULL
#include <dune/tectonic/myblockproblem.hh>
#include <dune/tectonic/myconvexproblem.hh>
#include "assemblers.hh"
#include "mysolver.hh"
#include "vtk.hh"
#include "enums.hh"
#include "enum_parser.cc"
#include "enum_state_model.cc"
#include "enum_scheme.cc"
#include "timestepping.hh"
#include "state/stateupdater.hh"
#include "state/ruinastateupdater.hh"
#include "state/dieterichstateupdater.hh"
int const dim = DIM;
<<defineInitTimeStepper>>
<<defineInitStateUpdater>>
<<defineInitPython>>
int
main(int argc, char *argv[])
{
<<mainBody>>
}