Newer
Older

Lisa Julia Nebel
committed
#include <config.h>
#include <array>
// Includes for the ADOL-C automatic differentiation library
// Need to come before (almost) all others.
#include <adolc/adouble.h>
#include <dune/fufem/utilities/adolcnamespaceinjections.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/bitsetvector.hh>

Lisa Julia Nebel
committed
#include <dune/common/tuplevector.hh>

Lisa Julia Nebel
committed
#include <dune/functions/functionspacebases/compositebasis.hh>
#include <dune/functions/functionspacebases/interpolate.hh>
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/functions/functionspacebases/powerbasis.hh>
#include <dune/functions/gridfunctions/discreteglobalbasisfunction.hh>
#include <dune/fufem/boundarypatch.hh>
#include <dune/grid/utility/structuredgridfactory.hh>
#include <dune/grid/uggrid.hh>
#include <dune/gfe/assemblers/cosseratenergystiffness.hh>
#include <dune/gfe/assemblers/geodesicfeassembler.hh>
#include <dune/gfe/assemblers/harmonicenergy.hh>
#include <dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh>

Lisa Julia Nebel
committed
#include <dune/gfe/localprojectedfefunction.hh>
#include <dune/gfe/assemblers/mixedgfeassembler.hh>
#include <dune/gfe/assemblers/mixedlocalgfeadolcstiffness.hh>

Lisa Julia Nebel
committed
#include <dune/gfe/riemanniantrsolver.hh>
#include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>

Lisa Julia Nebel
committed
#include <dune/istl/multitypeblockmatrix.hh>
#include <dune/istl/multitypeblockvector.hh>
// grid dimension
const int gridDim = 2;
// target dimension
const int dim = 3;
//order of the finite element space
const int displacementOrder = 2;
const int rotationOrder = 2;
using namespace Dune;
using namespace Indices;
//differentiation method: ADOL-C
using ValueType = adouble;
//Types for the mixed space
using DisplacementVector = std::vector<RealTuple<double,dim>>;
using RotationVector = std::vector<Rotation<double,dim>>;

Lisa Julia Nebel
committed
using Vector = TupleVector<DisplacementVector, RotationVector>;

Lisa Julia Nebel
committed
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
const int dimCR = Rotation<double,dim>::TangentVector::dimension; //dimCorrectionRotation = Dimension of the correction for rotations
using CorrectionType = MultiTypeBlockVector<BlockVector<FieldVector<double,dim> >, BlockVector<FieldVector<double,dimCR>>>;
using MatrixRow0 = MultiTypeBlockVector<BCRSMatrix<FieldMatrix<double,dim,dim>>, BCRSMatrix<FieldMatrix<double,dim,dimCR>>>;
using MatrixRow1 = MultiTypeBlockVector<BCRSMatrix<FieldMatrix<double,dimCR,dim>>, BCRSMatrix<FieldMatrix<double,dimCR,dimCR>>>;
using MatrixType = MultiTypeBlockMatrix<MatrixRow0,MatrixRow1>;
//Types for the Non-mixed space
using RBM = RigidBodyMotion<double, dim>;
const static int blocksize = RBM::TangentVector::dimension;
using CorrectionTypeWrapped = BlockVector<FieldVector<double, blocksize> >;
using MatrixTypeWrapped = BCRSMatrix<FieldMatrix<double, blocksize, blocksize> >;
int main (int argc, char *argv[])
{
MPIHelper::instance(argc, argv);
/////////////////////////////////////////////////////////////////////////
// Create the grid
/////////////////////////////////////////////////////////////////////////
using GridType = UGGrid<gridDim>;
auto grid = StructuredGridFactory<GridType>::createCubeGrid({0,0}, {1,1}, {2,2});
grid->globalRefine(2);
grid->loadBalance();
using GridView = GridType::LeafGridView;
GridView gridView = grid->leafGridView();
std::function<bool(FieldVector<double,gridDim>)> isNeumann = [](FieldVector<double,gridDim> coordinate) {
return coordinate[0] > 0.99;
};
BitSetVector<1> neumannVertices(gridView.size(gridDim), false);
const GridView::IndexSet& indexSet = gridView.indexSet();
for (auto&& vertex : vertices(gridView))
neumannVertices[indexSet.index(vertex)] = isNeumann(vertex.geometry().corner(0));
BoundaryPatch<GridView> neumannBoundary(gridView, neumannVertices);
/////////////////////////////////////////////////////////////////////////
// Create a composite basis
/////////////////////////////////////////////////////////////////////////
using namespace Functions::BasisFactory;
auto compositeBasis = makeBasis(
gridView,
composite(
power<dim>(
lagrange<displacementOrder>()
),
power<dim>(
lagrange<rotationOrder>()
)
));
using CompositeBasis = decltype(compositeBasis);
/////////////////////////////////////////////////////////////////////////
// Create the energy functions with their parameters
/////////////////////////////////////////////////////////////////////////
//Surface-Cosserat-Energy-Parameters
ParameterTree parameters;
parameters["thickness"] = "1";
parameters["mu"] = "2.7191e+4";
parameters["lambda"] = "4.4364e+4";
parameters["mu_c"] = "0";
parameters["L_c"] = "0.01";
parameters["q"] = "2";
parameters["kappa"] = "1";

Lisa Julia Nebel
committed
parameters["b1"] = "1";
parameters["b2"] = "1";
parameters["b3"] = "1";

Lisa Julia Nebel
committed
FieldVector<double,dim> values_ = {3e4,2e4,1e4};
auto neumannFunction = [&](FieldVector<double, gridDim>){
return values_;
};

Lisa Julia Nebel
committed
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
CosseratEnergyLocalStiffness<decltype(compositeBasis), dim,adouble> cosseratEnergy(parameters,
&neumannBoundary,
neumannFunction,
nullptr);
MixedLocalGFEADOLCStiffness<CompositeBasis,
RealTuple<double,dim>,
Rotation<double,dim> > mixedLocalGFEADOLCStiffness(&cosseratEnergy);
MixedGFEAssembler<CompositeBasis,
RealTuple<double,dim>,
Rotation<double,dim> > mixedAssembler(compositeBasis, &mixedLocalGFEADOLCStiffness);
using RBM = RigidBodyMotion<double, dim>;
using DeformationFEBasis = Functions::LagrangeBasis<GridView,displacementOrder>;
DeformationFEBasis deformationFEBasis(gridView);
using GFEAssemblerWrapper = GFE::GeodesicFEAssemblerWrapper<CompositeBasis, DeformationFEBasis, RBM, RealTuple<double, dim>, Rotation<double,dim>>;
GFEAssemblerWrapper assembler(&mixedAssembler, deformationFEBasis);
/////////////////////////////////////////////////////////////////////////
// Prepare the iterate x where we want to assemble - identity in 2D with z = 0
/////////////////////////////////////////////////////////////////////////
auto deformationPowerBasis = makeBasis(
gridView,
power<gridDim>(
lagrange<displacementOrder>()
));
BlockVector<FieldVector<double,gridDim> > identity(compositeBasis.size({0}));
Functions::interpolate(deformationPowerBasis, identity, [](FieldVector<double,gridDim> x){ return x; });
BlockVector<FieldVector<double,dim> > initialDeformation(compositeBasis.size({0}));
initialDeformation = 0;
Vector x;
x[_0].resize(compositeBasis.size({0}));
x[_1].resize(compositeBasis.size({1}));
std::vector<RBM> xRBM(compositeBasis.size({0}));
for (std::size_t i = 0; i < compositeBasis.size({0}); i++) {

Lisa Julia Nebel
committed
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
for (int j = 0; j < gridDim; j++)
initialDeformation[i][j] = identity[i][j];
x[_0][i] = initialDeformation[i];
for (int j = 0; j < dim; j ++) { // Displacement part
xRBM[i].r[j] = x[_0][i][j];
}
xRBM[i].q = x[_1][i]; // Rotation part
}
//////////////////////////////////////////////////////////////////////////////
// Compute the energy, assemble the Gradient and Hessian using
// the GeodesicFEAssemblerWrapper and the MixedGFEAssembler and compare!
//////////////////////////////////////////////////////////////////////////////
CorrectionTypeWrapped gradient;
MatrixTypeWrapped hessianMatrix;
double energy = assembler.computeEnergy(xRBM);
assembler.assembleGradientAndHessian(xRBM, gradient, hessianMatrix, true);
double gradientTwoNorm = gradient.two_norm();
double gradientInfinityNorm = gradient.infinity_norm();
double matrixFrobeniusNorm = hessianMatrix.frobenius_norm();
CorrectionType gradientMixed;
gradientMixed[_0].resize(x[_0].size());
gradientMixed[_1].resize(x[_1].size());
MatrixType hessianMatrixMixed;
double energyMixed = mixedAssembler.computeEnergy(x[_0], x[_1]);
mixedAssembler.assembleGradientAndHessian(x[_0], x[_1], gradientMixed[_0], gradientMixed[_1], hessianMatrixMixed, true);
double gradientMixedTwoNorm = gradientMixed.two_norm();
double gradientMixedInfinityNorm = gradientMixed.infinity_norm();
double matrixMixedFrobeniusNorm = hessianMatrixMixed.frobenius_norm();
if (std::abs(energy - energyMixed)/energyMixed > 1e-8)
{
std::cerr << std::setprecision(9);
std::cerr << "The energy calculated by the GeodesicFEAssemblerWrapper is " << energy << " but "
<< energyMixed << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
return 1;
}
if ( std::abs(gradientTwoNorm - gradientMixedTwoNorm)/gradientMixedTwoNorm > 1e-8 ||
std::abs(gradientInfinityNorm - gradientMixedInfinityNorm)/gradientMixedInfinityNorm > 1e-8)
{
std::cerr << std::setprecision(9);
std::cerr << "The gradient infinity norm calculated by the GeodesicFEAssemblerWrapper is " << gradientInfinityNorm << " but "
<< gradientMixedInfinityNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
std::cerr << "The gradient norm calculated by the GeodesicFEAssemblerWrapper is " << gradientTwoNorm << " but "
<< gradientMixedTwoNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
return 1;
}
if (std::abs(matrixFrobeniusNorm - matrixMixedFrobeniusNorm)/matrixMixedFrobeniusNorm > 1e-8)
{
std::cerr << std::setprecision(9);
std::cerr << "The matrix norm calculated by the GeodesicFEAssemblerWrapper is " << matrixFrobeniusNorm << " but "
<< matrixMixedFrobeniusNorm << " (calculated by the MixedGFEAssembler) was expected!" << std::endl;
return 1;
}
}