-
Sander, Oliver authored
This removes one use of the CosseratEnergyLocalStiffness class, which is scheduled for complete removal.
Sander, Oliver authoredThis removes one use of the CosseratEnergyLocalStiffness class, which is scheduled for complete removal.
localadolcstiffnesstest.cc 8.52 KiB
#include <config.h>
#include <fenv.h>
#include <array>
//#define MULTIPRECISION
#ifdef MULTIPRECISION
#include <boost/multiprecision/mpfr.hpp>
#endif
#ifdef MULTIPRECISION
typedef boost::multiprecision::mpfr_float_50 FDType;
#else
typedef double FDType;
#endif
// Includes for the ADOL-C automatic differentiation library
// Need to come before (almost) all others.
#include <adolc/adouble.h>
#include <adolc/drivers/drivers.h> // use of "Easy to Use" drivers
#include <adolc/taping.h>
#include <dune/fufem/utilities/adolcnamespaceinjections.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/fmatrix.hh>
#include <dune/geometry/quadraturerules.hh>
#include <dune/grid/yaspgrid.hh>
#include <dune/istl/io.hh>
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/functions/functionspacebases/interpolate.hh>
#include <dune/functions/functionspacebases/powerbasis.hh>
#include <dune/gfe/localgeodesicfefunction.hh>
#include <dune/gfe/assemblers/localintegralenergy.hh>
#include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh>
#include <dune/gfe/assemblers/localgeodesicfefdstiffness.hh>
#include <dune/gfe/densities/planarcosseratshelldensity.hh>
#include <dune/gfe/spaces/productmanifold.hh>
#include <dune/gfe/spaces/realtuple.hh>
#include <dune/gfe/spaces/rotation.hh>
using namespace Dune;
// grid dimension
const int dim = 2;
// Image space of the geodesic fe functions
using TargetSpace = GFE::ProductManifold<RealTuple<double,3>,Rotation<double,3> >;
// Compare two matrices
void compareMatrices(const Matrix<double>& matrixA, std::string nameA,
const Matrix<double>& matrixB, std::string nameB)
{
double maxAbsDifference = -1;
double maxRelDifference = -1;
for(size_t i=0; i<matrixA.N(); i++) {
for (size_t j=0; j<matrixA.M(); j++ ) {
const double valueA = matrixA[i][j];
const double valueB = matrixB[i][j];
double absDifference = valueA - valueB;
double relDifference = std::abs(absDifference) / std::abs(valueA);
maxAbsDifference = std::max(maxAbsDifference, std::abs(absDifference));
if (not std::isinf(relDifference))
maxRelDifference = std::max(maxRelDifference, relDifference);
if (relDifference > 1)
std::cout << i << ", " << j << " , "
<< nameA << ": " << valueA << ", " << nameB << ": " << valueB << std::endl;
}
}
std::cout << nameA << " vs. " << nameB << " -- max absolute / relative difference is " << maxAbsDifference << " / " << maxRelDifference << std::endl;
}
int main (int argc, char *argv[]) try
{
MPIHelper::instance(argc, argv);
typedef std::vector<TargetSpace> SolutionType;
constexpr static int blocksize = TargetSpace::TangentVector::dimension;
// ///////////////////////////////////////
// Create the grid
// ///////////////////////////////////////
typedef YaspGrid<dim> GridType;
FieldVector<double,dim> upper = {{0.38, 0.128}};
std::array<int,dim> elements = {{5, 5}};
GridType grid(upper, elements);
typedef GridType::LeafGridView GridView;
GridView gridView = grid.leafGridView();
///////////////////////////////////////////////
// Construct the basis for the tangent spaces
///////////////////////////////////////////////
typedef Functions::LagrangeBasis<GridView,1> FEBasis;
FEBasis feBasis(gridView);
using namespace Functions::BasisFactory;
const int dimRotation = Rotation<double,3>::TangentVector::dimension;
auto tangentBasis = makeBasis(
gridView,
power<3+dimRotation>(
lagrange<1>()
)
);
using TangentBasis = decltype(tangentBasis);
// //////////////////////////
// Initial iterate
// //////////////////////////
SolutionType x(feBasis.size());
//////////////////////////////////////////7
// Read initial iterate from file
//////////////////////////////////////////7
#if 0
Dune::BlockVector<FieldVector<double,7> > xEmbedded(x.size());
std::ifstream file("dangerous_iterate", std::ios::in|std::ios::binary);
if (not (file))
DUNE_THROW(SolverError, "Couldn't open file 'dangerous_iterate' for reading");
GenericVector::readBinary(file, xEmbedded);
file.close();
for (int ii=0; ii<x.size(); ii++)
x[ii] = xEmbedded[ii];
#else
auto identity = [](const FieldVector<double,2>& x) -> FieldVector<double,3> {
return {x[0], x[1], 0};
};
std::vector<FieldVector<double,3> > v;
auto powerBasis = makeBasis(
gridView,
power<3>(
lagrange<1>(),
blockedInterleaved()
));
Functions::interpolate(powerBasis, v, identity);
for (size_t i=0; i<x.size(); i++)
x[i][Indices::_0] = v[i];
#endif
// ////////////////////////////////////////////////////////////
// Create an assembler for the energy functional
// ////////////////////////////////////////////////////////////
ParameterTree materialParameters;
materialParameters["thickness"] = "1";
materialParameters["mu"] = "1";
materialParameters["lambda"] = "1";
materialParameters["mu_c"] = "1";
materialParameters["L_c"] = "1";
materialParameters["q"] = "2";
materialParameters["kappa"] = "1";
//////////////////////////////////////////////////////
// Assembler using ADOL-C
//////////////////////////////////////////////////////
// The 'active' target spaces, i.e., the number type is replaced by adouble
using ATargetSpace = typename TargetSpace::template rebind<adouble>::other;
// Select geometric finite element interpolation method
using AInterpolationRule = LocalGeodesicFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, ATargetSpace>;
auto activeDensity = std::make_shared<GFE::PlanarCosseratShellDensity<GridType::Codim<0>::Entity::Geometry::LocalCoordinate, adouble> >(materialParameters);
auto activeCosseratLocalEnergy = std::make_shared<GFE::LocalIntegralEnergy<TangentBasis,AInterpolationRule,ATargetSpace> >(activeDensity);
// The actual assembler
LocalGeodesicFEADOLCStiffness<TangentBasis,
TargetSpace> localGFEADOLCStiffness(activeCosseratLocalEnergy);
//////////////////////////////////////////////////////
// Assembler using finite differences
//////////////////////////////////////////////////////
// Select geometric finite element interpolation method
using InterpolationRule = LocalGeodesicFEFunction<dim, double, FEBasis::LocalView::Tree::FiniteElement, TargetSpace>;
auto cosseratDensity = std::make_shared<GFE::PlanarCosseratShellDensity<GridType::Codim<0>::Entity::Geometry::LocalCoordinate, double> >(materialParameters);
auto cosseratLocalEnergy = std::make_shared<GFE::LocalIntegralEnergy<TangentBasis,InterpolationRule,TargetSpace> >(cosseratDensity);
// The actual assembler
LocalGeodesicFEFDStiffness<TangentBasis,
TargetSpace,
FDType> localGFEFDStiffness(cosseratLocalEnergy.get());
////////////////////////////////////////////////////////
// Compute and compare tangent matrices
////////////////////////////////////////////////////////
for (const auto& element : Dune::elements(gridView))
{
std::cout << " ++++ element " << gridView.indexSet().index(element) << " ++++" << std::endl;
auto localView = feBasis.localView();
localView.bind(element);
auto tangentLocalView = tangentBasis.localView();
tangentLocalView.bind(element);
const int numOfBaseFct = localView.size();
// Extract local configuration
std::vector<TargetSpace> localSolution(numOfBaseFct);
for (int i=0; i<numOfBaseFct; i++)
localSolution[i] = x[localView.index(i)];
// Assemble Riemannian derivatives
std::vector<double> localRiemannianADGradient(numOfBaseFct*blocksize);
std::vector<double> localRiemannianFDGradient(numOfBaseFct*blocksize);
Matrix<double> localRiemannianADHessian;
Matrix<double> localRiemannianFDHessian;
localGFEADOLCStiffness.assembleGradientAndHessian(tangentLocalView,
localSolution,
localRiemannianADGradient,
localRiemannianADHessian);
localGFEFDStiffness.assembleGradientAndHessian(tangentLocalView,
localSolution,
localRiemannianFDGradient,
localRiemannianFDHessian);
// compare
compareMatrices(localRiemannianADHessian, "Riemannian AD", localRiemannianFDHessian, "Riemannian FD");
}
return 0;
}
catch (Exception& e)
{
std::cout << e.what() << std::endl;
return 1;
}