KASKADE 7 development version
hermite3D.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2011 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef HERMITE_INTERPOLATION_3D_HH
14#define HERMITE_INTERPOLATION_3D_HH
15
18
27namespace Kaskade
28{
30 /*
31 * Hermite interpolation on a simplicial grid. It is assumed that the function values
32 * of the vertices are zero. Moreover the tangent planes at each vertex and each edge
33 * are given through its outer normals. Note that the deformation can only act in
34 * normal direction. On the faces this is clear. On the edges the normal direction is
35 * determined by the normals of the two adjacent faces.
36 * The interpolation is split into two independant parts:
37 * - First use cubic hermite interpolation at the edges in order to achieve tangent
38 * plane continuity at the vertices. This approach also minimizes the second derivative
39 * of the curves parametrization over [0,1] in L2.
40 * - Second adjust the remaining shape functions. Note that with the chosen "3rd" order
41 * hierarchic shape functions it is not possible to guarantee tangent plane continuity
42 * over the edges. Thus tangent plane continuity is only required at the edge's center.
43 *
44 * \param RT floating point type
45 * \param GridView GridView
46 * \param ShapeFunctionSet type of the shape function set of the codim 0 reference element
47 * \param InterpolationPolicy class specifying the interpolation details
48 * \param Container container class storing vertex and edge normals
49 */
50 template<class Scalar_, class GridView, class InterpolationPolicy>
51 class HIPImpl<Scalar_, GridView, InterpolationPolicy, 3> : public HIPBase<Scalar_,3>
52 {
53 public:
54 typedef HIPBase<Scalar_,3> Base;
55 static int const dim = 3;
56 typedef typename Base::Scalar Scalar;
57 typedef typename Base::Vector Vector;
58 typedef typename GridView::template Codim<0>::Iterator CellIterator;
59 typedef typename CellIterator::Entity Entity;
60 typedef InterpolationTools::NormalContainer<Scalar,dim> Container;
61 typedef typename Container::CollectionType NormalCollection;
62 typedef typename GridView::IntersectionIterator LocalFaceIterator;
63 typedef typename LocalFaceIterator::Intersection Face;
64 typedef typename GridView::Grid Grid;
65 typedef Dune::GenericReferenceElements<Scalar,dim> ReferenceTetrahedron;
66 typedef Dune::GenericReferenceElements<Scalar,dim-1> ReferenceTriangle;
67
68
70
75 HIPImpl(int numberOfShapeFunctions) : Base(numberOfShapeFunctions), origin(0) {}
76
78 /*
79 * \param entity entity on which the polynomial is defined
80 * \param gridView grid view
81 * \param container container holding vertex normals and edge normals in container.vertexNormals/container.edgeNormals
82 * \param shapefunctionset shape function set of the reference codim 0 element
83 * \param policy policy object specifiying interpolation details
84 */
85 template <class ShapeFunctionSet>
86 HIPImpl(Entity const& entity, GridView const& gridView,
87 ShapeFunctionSet const& shapeFunctionSet, Container const& container,
88 InterpolationPolicy const& policy) :
89 Base(shapeFunctionSet.size()), origin(0)
90 {
91 init(entity, gridView, shapeFunctionSet, container, policy);
92 }
93
95
102 template <class ShapeFunctionSet>
103 void init(Entity const& entity, GridView const& gridView, ShapeFunctionSet const& shapeFunctionSet, Container const& container, InterpolationPolicy const& policy)
104 {
105 initSamplingPointValuesOnEdges(entity, gridView, shapeFunctionSet, container, policy);
106 initSamplingPointValuesOnFaces(entity, gridView, shapeFunctionSet, container, policy);
107 }
108
109 private:
111 template <class ShapeFunctionSet>
112 void initSamplingPointValuesOnEdges(Entity const& entity, GridView const &gridView, ShapeFunctionSet const& shapeFunctionSet, Container const& container, InterpolationPolicy const& policy){
113 // get global vertex ids
114 std::vector<int> globalVertexIds = InterpolationTools::getGlobalVertexIds(entity, gridView);
115 // get tissue id of the current cell
116 Scalar tissue = round(policy.phaseId( entity ));
117
118 // get "normal" vectors associated with the vertices
119 std::vector<Vector> entityVertexNormals(dim+1, Vector());
120 InterpolationTools::getVertexNormals(globalVertexIds, container.vertexNormals, entityVertexNormals, tissue);
121
122 LocalFaceIterator fend = gridView.iend(entity);
123 for(LocalFaceIterator face = gridView.ibegin(entity); face!=fend; ++face){
124
125 Scalar tissueNeighbour = -1;
126 // get neighbouring tissue id if neighbour exists and material information is provided
127 if( face->neighbor() )
128 tissueNeighbour = round(policy.phaseId( *face->outside() ));
129
130 // criteria for skipping calculation
131 // if no inner boundary exists (no intersection with cells associated with other materials) continue
132 if(fabs(tissue-tissueNeighbour) < 1e-9) continue;
133
134 if( policy.ignoreOuterBoundary(*face) ) continue;
135
136 // id of face in cell
137 int faceId = face->indexInInside();
138
139 // iterate over edges
140 for(int edgeIdInFace = 0; edgeIdInFace < dim; ++edgeIdInFace){
141
142 // get corner and edge ids
143 int edgeIdInEntity = ReferenceTetrahedron::simplex().subEntity(faceId,1,edgeIdInFace,dim-1);
144 std::vector<int> edgeVertexIdsInEntity = InterpolationTools::getEdgeCornerIdsInEntity(entity, edgeIdInEntity);
145
146 // local id of the edge in the cell
147 // global edge id
148 int globalEdgeId = gridView.indexSet().subIndex(entity, edgeIdInEntity, dim-1);
149
150 // if edge has been marked as not relevant skip it
151 if( !container.edgeNormals[globalEdgeId].isRelevant ) continue;
152
153 // create normalized vector in edge direction
154 Vector edgeDirection = entity.geometry().corner(edgeVertexIdsInEntity[1]) - entity.geometry().corner(edgeVertexIdsInEntity[0]);
155 GeomTools::normalize(edgeDirection);
156
157 // get normal vector of the plane spanned the edge direction and the edge "normal"
158 Vector planeNormal;
159
160 Vector edgeNormal = getEdgeNormal(globalEdgeId, tissue, container.edgeNormals);
161
162 GeomTools::crossProduct(edgeNormal, edgeDirection, planeNormal);
163
164 std::vector<Vector> projectedVertexNormals(2), desiredGradientDirections(2,Vector(1e-301));
165 Dune::FieldVector<Scalar,2> desiredGradients;
166 std::vector<int> shapeFunctionIds(2);
167 for(int vertexIdInEdge=0; vertexIdInEdge<2; ++vertexIdInEdge){
168 // ids of 2nd and 3rd order shape functions associated with the considered edge
169 shapeFunctionIds[vertexIdInEdge] = 4 + edgeIdInEntity + vertexIdInEdge*6;
170
171 // skip calculation of rhs values
172 if( !container.vertexNormals[ globalVertexIds[ edgeVertexIdsInEntity[vertexIdInEdge] ] ].isRelevant ){
173 desiredGradients[vertexIdInEdge] = 0;
174 continue;
175 }
176
177 // get convenient coordinate system
178 projectedVertexNormals[vertexIdInEdge] = entityVertexNormals[edgeVertexIdsInEntity[vertexIdInEdge]];
179 GeomTools::projectOnPlane(projectedVertexNormals[vertexIdInEdge], planeNormal);
180 GeomTools::normalize(projectedVertexNormals[vertexIdInEdge]);
181 GeomTools::crossProduct(planeNormal, projectedVertexNormals[vertexIdInEdge], desiredGradientDirections[vertexIdInEdge]);
182
183 // first determine the desired gradients at the (deformed) edges and apply threshold
184 // set the gradient = 0 if on the corresponding edge no smoothing is desired
185 if(container.vertexNormals[globalVertexIds[ edgeVertexIdsInEntity[vertexIdInEdge] ] ].isRelevant){
186 desiredGradients[vertexIdInEdge] = (edgeNormal * desiredGradientDirections[vertexIdInEdge])
187 /(edgeDirection * desiredGradientDirections[vertexIdInEdge]);
188 policy.applyGradientThreshold(desiredGradients[vertexIdInEdge]);
189 }
190 else
191 {
192 desiredGradients[vertexIdInEdge] = 0;
193 }
194 }
195
196 // evaluate derivatives of shape functions at the edge's corners
198 for(int vertexIdInEdge=0; vertexIdInEdge<2; ++vertexIdInEdge){
199 for(int sfId = 0; sfId<2; ++sfId){
200 Dune::FieldMatrix<Scalar,dim,dim> jacobian = entity.geometry().jacobianInverseTransposed(entity.geometry().local(entity.geometry().corner(edgeVertexIdsInEntity[vertexIdInEdge])));
201 Vector sf_grad = shapeFunctionSet[shapeFunctionIds[sfId]].evaluateDerivative( entity.geometry().local( entity.geometry().corner(edgeVertexIdsInEntity[vertexIdInEdge]) ) )[0];
202 Vector sf_grad_chain;
203 jacobian.mv(sf_grad, sf_grad_chain);
204 A[vertexIdInEdge][sfId] = sf_grad_chain * edgeDirection;
205 }
206 }
207
208 // determine coefficients of the hierarchic ansatz functions associated with this edge
209 Dune::FieldVector<Scalar,2> coefficients;
210 A.solve(coefficients, desiredGradients);
211
212 // store calculated coefficients
213 for(int sfId=0; sfId<2; ++sfId)
214 this->insertEntry(coefficients[sfId], edgeNormal, shapeFunctionIds[sfId]);
215 }
216 }
217 }
218
219
221 template <class ShapeFunctionSet>
222 void initSamplingPointValuesOnFaces(Entity const& entity,
223 GridView const &gridView,
224 ShapeFunctionSet const& shapeFunctionSet,
225 Container const& container,
226 InterpolationPolicy const& policy)
227 {
228 // get tissue id of the current cell
229 Scalar tissue = round(policy.phaseId(entity));
230
231 // iterate over faces
232 LocalFaceIterator fend = gridView.iend(entity);
233 for(LocalFaceIterator face = gridView.ibegin(entity); face!=fend; ++face){
234
235 // id of face in cell
236 int faceId = face->indexInInside();
237
238 Scalar tissueNeighbour = -1;
239 // get neighbouring tissue id if neighbour exists and material information is provided
240 if( face->neighbor() )
241 tissueNeighbour = round(policy.phaseId( *face->outside() ));
242
243 // if no inner boundary exists (no intersection with cells associated with other materials) continue
244 if( fabs(tissue-tissueNeighbour) < 1e-9 ) continue;
245 // continue if policy decides to skip face
246 if( policy.ignoreOuterBoundary(*face) ) continue;
247
248 // interpolation points in local coordinates
249 std::vector<Vector> iNodes(dim);
250
251 // affine coordinate mapping -> jacobian is constant on each entity
252 Dune::FieldMatrix<Scalar,dim,dim> jacobian = entity.geometry().jacobianInverseTransposed(origin);
253
254 // initialize variables
255 Vector desiredGradients; // right hand side vector
256 std::vector<int> edgeIdInEntity(dim,0), globalEdgeIds(dim,0), shapeFunctionIds(6,0); // store used indices
257 std::vector<std::vector<int> > edgeVertexIdsInEntity(dim); // more indices
258 std::vector<Vector> edgeNormal(dim,origin),
259 planeNormal(dim,origin), // note that plane denotes the plane spanned by the edge and the "real" surface normal
260 projectedPlaneNormal(dim,origin),
261 deformedProjectedPlaneNormal(dim,origin),
262 deformedFaceNormal(dim,origin); // store used vectors
263
264 Vector faceNormal = face->centerUnitOuterNormal();
265 // adjust orientation such that a unique normal direction is associated with every face
266 if(tissueNeighbour+1e-9 < tissue && tissueNeighbour > 1e-9)
267 faceNormal *= -1;
268
269 // get ids
270 for(int edgeIdInFace = 0; edgeIdInFace<dim; ++edgeIdInFace){
271 edgeIdInEntity[edgeIdInFace] = ReferenceTetrahedron::simplex().subEntity(faceId,1,edgeIdInFace,dim-1);
272 globalEdgeIds[edgeIdInFace] = gridView.indexSet().subIndex(entity, edgeIdInEntity[edgeIdInFace], dim-1);
273 edgeVertexIdsInEntity[edgeIdInFace] = getExtendedEdgeVertexIds(edgeIdInFace, faceId);
274 shapeFunctionIds[edgeIdInFace] = 4 + edgeIdInEntity[edgeIdInFace];
275 shapeFunctionIds[edgeIdInFace+dim] = 10 + edgeIdInEntity[edgeIdInFace];
276 }
277
278 // iterate over edges and collect directions and interpolation nodes
279 for(int edgeIdInFace = 0; edgeIdInFace<dim; ++edgeIdInFace){
280
281 // get interpolation points
282 iNodes[edgeIdInFace] = entity.geometry().local( 0.5 * ( entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][0]) + entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][1]) ) );
283
284 // get normalized edge vector
285 Vector edgeDirection = entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][0]) - entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][1]);
286 GeomTools::normalize(edgeDirection);
287
288 // check if edge is relevant and if this is the case get associated edge normal
289 // and compute the associated tangential directions in the necessary coordinate systems
290 if(container.edgeNormals[ globalEdgeIds[edgeIdInFace ] ].isRelevant)
291 {
292 // get edge normal
293 edgeNormal[edgeIdInFace] = getEdgeNormal(globalEdgeIds[edgeIdInFace], tissue, container.edgeNormals);
294 // get tangential direction
295 GeomTools::crossProduct(edgeNormal[edgeIdInFace], edgeDirection, planeNormal[edgeIdInFace]);
296 // and project it on triangle
297 projectedPlaneNormal[edgeIdInFace] = planeNormal[edgeIdInFace];
298 GeomTools::projectOnPlane(projectedPlaneNormal[edgeIdInFace], faceNormal);
299 GeomTools::normalize(projectedPlaneNormal[edgeIdInFace]);
300 // correct orientation such that projectedPlaneNormal points into the face
301 int remainingVertexId = edgeVertexIdsInEntity[edgeIdInFace][2];
302 Vector anotherEdgeDirection = entity.geometry().corner(remainingVertexId) - entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][0]);
303 if(anotherEdgeDirection * projectedPlaneNormal[edgeIdInFace] < 0)
304 projectedPlaneNormal[edgeIdInFace] *= -1;
305
306 // project projected tangential direction on deformed surface and normalize
307 Dune::FieldMatrix<Scalar,dim,dim> deformationGradient = getPartialDeformationGradient(iNodes[edgeIdInFace], entity, shapeFunctionIds, shapeFunctionSet);
308 // use derivative, not gradient for the transformation of directions
309 deformationGradient.mtv(projectedPlaneNormal[edgeIdInFace], deformedProjectedPlaneNormal[edgeIdInFace]);
310 GeomTools::normalize(deformedProjectedPlaneNormal[edgeIdInFace]);
311 deformationGradient.mtv(faceNormal, deformedFaceNormal[edgeIdInFace]);
312 // ??? GeomTools::normalize(deformedFaceNormal[edgeIdInFace]);
313 }
314 else
315 {
316 int remainingVertexId = edgeVertexIdsInEntity[edgeIdInFace][2];
317 deformedProjectedPlaneNormal[edgeIdInFace] = entity.geometry().corner(remainingVertexId);
318 deformedProjectedPlaneNormal[edgeIdInFace]-= entity.geometry().global(iNodes[edgeIdInFace]);
319 GeomTools::normalize(deformedProjectedPlaneNormal[edgeIdInFace]);
320 }
321 // else deformedProjectedPlaneNormal[edgeIdInFace] = origin (initial value)
322 }
323
324 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
325 /* fill Matrix */
326 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
327 // interpolate coefficients for the hierarchic shape functions associated with the face
328 // shape functions associated with the vertices vanish -> consider 2nd and 3rd order terms only.
330
331 for(int edgeIdInFace=0; edgeIdInFace<dim; ++edgeIdInFace)
332 for(int sfID=0; sfID<dim; ++sfID){
333 // get gradients on reference tetrahedron
334 Vector grad = shapeFunctionSet[16 + faceId*dim + sfID].evaluateDerivative(iNodes[edgeIdInFace])[0];
335
336 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialInverseDeformationGradient(iNodes[edgeIdInFace], entity, shapeFunctionIds, shapeFunctionSet);
337 Vector chainRuleTmp(0);
338 // apply chain rule -> gradient on the actual tetrahedron
339 jacobian.mv(grad, chainRuleTmp);
340 // apply chain rule -> gradient on the deformed tetrahedron
341 inverseDeformationGradient.mv(chainRuleTmp,grad);
342
343 // evaluate directional derivative in deformed surface
344 A[edgeIdInFace][sfID] = grad * deformedProjectedPlaneNormal[edgeIdInFace];
345 }
346
347
348 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
349 /* fill right hand side */
350 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
351 // first determine the desired gradients at the (deformed) edges and apply threshold
352 // set the gradient = 0 if on the corresponding edge no smoothing is desired
353 for(int iNode = 0; iNode<dim; ++iNode){
354 // desired normal
355 if(container.edgeNormals[ globalEdgeIds[iNode] ].isRelevant){
356 desiredGradients[iNode] = (planeNormal[iNode] * deformedFaceNormal[iNode]) / (planeNormal[iNode] * deformedProjectedPlaneNormal[iNode]);
357 policy.applyGradientThreshold(desiredGradients[iNode]);
358 }
359 else
360 desiredGradients[iNode] = 0;
361 }
362
363 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
364 /* then subtract contributions from other shape functions */
365 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
366 for(int iNode = 0; iNode<dim; ++iNode){
367 // subtract contributions from other shape functions
368 for(int edgeIdInFace = 0; edgeIdInFace < dim; ++edgeIdInFace){
369 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialInverseDeformationGradient(iNodes[iNode], entity, shapeFunctionIds, shapeFunctionSet);
370 Vector chainRuleTmp(0);
371
372 // second order shape function
373 Vector grad = shapeFunctionSet[ shapeFunctionIds[edgeIdInFace] ].evaluateDerivative(iNodes[iNode])[0];
374
375 jacobian.mv(grad,chainRuleTmp);
376 inverseDeformationGradient.mv(chainRuleTmp,grad);
377
378 desiredGradients[iNode] -= grad * deformedProjectedPlaneNormal[iNode] * this->values[ shapeFunctionIds[edgeIdInFace] ];
379
380 // third order shape function
381 grad = shapeFunctionSet[ shapeFunctionIds[edgeIdInFace+dim]].evaluateDerivative(iNodes[iNode])[0];
382
383 jacobian.mv(grad,chainRuleTmp);
384 inverseDeformationGradient.mv(chainRuleTmp,grad);
385
386 desiredGradients[iNode] -= grad * deformedProjectedPlaneNormal[iNode] * this->values[ shapeFunctionIds[edgeIdInFace+dim] ];
387 }
388 }
389
390 // solve LSE
391 Vector coefficients;
392 A.solve(coefficients, desiredGradients);
393 if(!(coefficients==coefficients))
394 {
395 for(int edgeIdInFace=0; edgeIdInFace<dim; ++edgeIdInFace)
396 for(int sfID=0; sfID<dim; ++sfID){
397 // get gradients on reference tetrahedron
398 Vector grad = shapeFunctionSet[16 + faceId*dim + sfID].evaluateDerivative(iNodes[edgeIdInFace])[0];
399
400 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialInverseDeformationGradient(iNodes[edgeIdInFace], entity, shapeFunctionIds, shapeFunctionSet);
401 Vector chainRuleTmp(0);
402 // apply chain rule -> gradient on the actual tetrahedron
403 jacobian.mv(grad, chainRuleTmp);
404
405
406 // apply chain rule -> gradient on the deformed tetrahedron
407 inverseDeformationGradient.mv(chainRuleTmp,grad);
408
409 std::cout << grad << " * " << deformedProjectedPlaneNormal[edgeIdInFace] << std::endl << std::endl;
410
411 }
412 std::cout << A;
413 std::cout << desiredGradients << " -> " << coefficients << std::endl << std::endl;
414 coefficients = 0.0;
415
416 }
417
418
419 for(int sfId=0; sfId<dim; ++sfId)
420 this->insertEntry(coefficients[sfId], faceNormal, 16 + dim*faceId + sfId);
421 }
422 }
423
425 /* The first two ids are the edge ids wrt. the entity. The last is the remaining vertex id wrt. the entity.
426 *
427 * \param edgeIdInFace id of the edge wrt. the face.
428 * \return vector containing the local vertex ids of the edges vertices and additionally in the last entry the id of the remaining vertex of the face.
429 */
430 std::vector<int> getExtendedEdgeVertexIds(int edgeIdInFace, int faceId) const {
431 std::vector<int> result(dim);
432 result[0] = ReferenceTriangle::simplex().subEntity(edgeIdInFace,1,0,dim-1);
433 result[1] = ReferenceTriangle::simplex().subEntity(edgeIdInFace,1,1,dim-1);
434 result[2] = dim - result[1] - result[0];
435 result[0] = ReferenceTetrahedron::simplex().subEntity(faceId,1, result[0], dim);
436 result[1] = ReferenceTetrahedron::simplex().subEntity(faceId,1, result[1], dim);
437 result[2] = ReferenceTetrahedron::simplex().subEntity(faceId,1, result[2], dim);
438 return result;
439 }
440
442 /*
443 * \param eid global id of the edge
444 * \param tissueId material id
445 * \result edge normal of edge eid associated with tissueId
446 */
447 Vector getEdgeNormal(int eid, Scalar tissueId, NormalCollection const& edgeNormals){
448 for(int i=0; i<edgeNormals[eid].phaseIds.size(); ++i)
449 if(fabs(edgeNormals[eid].phaseIds[i] - round(tissueId)) < 1e-9)
450 return edgeNormals[eid].normals[i];
451 std::cout << "Warning: No edge normal found! " << std::endl;
452 return origin;
453 }
454
456 /*
457 * \param iNode evaluation point
458 * \param entity entity containing the evaluation point
459 * \param shapeFunctionIds ids of the used shape functions
460 * \param shapeFunctionSet shape function set
461 *
462 * \return deformation gradient
463 */
464 template <class ShapeFunctionSet>
465 Dune::FieldMatrix<Scalar,dim,dim> getPartialDeformationGradient(Vector const& iNode, Entity const& entity, std::vector<int> const& shapeFunctionIds, ShapeFunctionSet const& shapeFunctionSet) const {
466 Dune::FieldMatrix<Scalar,dim,dim> deformationGradient(0);
467 Dune::FieldMatrix<Scalar,dim,dim> jacobian = entity.geometry().jacobianInverseTransposed(Vector(0));
468 for(int i=0;i<dim; ++i){
469 for(int j=0; j<dim; ++j){
470 for(int k=0; k<shapeFunctionIds.size(); ++k){
471 // evaluation on reference element
472 Vector grad = shapeFunctionSet[ shapeFunctionIds[k] ].evaluateDerivative( iNode )[0];
473 Vector chain(0);
474 // chain rule -> derivative on actual element
475 jacobian.mv(grad,chain);
476 deformationGradient[j][i] += this->values[ shapeFunctionIds[k] ] * chain[j] * this->directions[ shapeFunctionIds[k] ][i];
477 }
478 }
479 // add identity
480 deformationGradient[i][i] += 1;
481 }
482 return deformationGradient;
483 }
484
486 /*
487 * \param iNode evaluation point
488 * \param entity entity containing the evaluation point
489 * \param shapeFunctionIds ids of the used shape functions
490 * \param shapeFunctionSet shape function set
491 *
492 * \return inverse of deformation gradient
493 */
494 template <class ShapeFunctionSet>
495 Dune::FieldMatrix<Scalar,dim,dim> getPartialInverseDeformationGradient(Vector const& iNode, Entity const& entity, std::vector<int> const& shapeFunctionIds, ShapeFunctionSet const& shapeFunctionSet) const {
496 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialDeformationGradient(iNode, entity, shapeFunctionIds, shapeFunctionSet);
497 inverseDeformationGradient.invert();
498 return inverseDeformationGradient;
499 }
500
501 Vector const origin;
502 };
503} // namespace Kaskade
507#endif // HERMITE_INTERPOLATION_3D_HH
Some simple tools for geometric calculations. Please extend.
typename GridView::Intersection Face
The type of faces in the grid view.
Definition: gridBasics.hh:42
Dune::FieldVector< Scalar, 3 > crossProduct(Dune::FieldVector< Scalar, 3 > const &v1, Dune::FieldVector< Scalar, 3 > const &v2)
DEPRECATED: use vectorProduct instead.
Definition: geomtools.hh:30
void projectOnPlane(Vector &vec, Vector const &planeNormal)
Project Vector vec on plane given through planeNormal. No translation is performed.
Definition: geomtools.hh:78
Vector normalize(Vector &vector)
Normalize vector.
Definition: geomtools.hh:48
void getVertexNormals(std::vector< int > const &vid, NormalCollection const &vertexNormals, std::vector< Vector > &localNormals, typename Vector::field_type const tissueId)
Get the normals assoicated to the global vertex indices in vid.
Definition: tools.hh:731
std::vector< int > getEdgeCornerIdsInEntity(Entity const &entity, int edgeId)
Get local coordinates of the edges vertices in the codim<0> entity.
Definition: tools.hh:697
std::vector< int > getGlobalVertexIds(Entity const &entity, GridView const &gridView)
Get global vertex ids of the entities corners.
Definition: tools.hh:682
Dune::FieldVector< Scalar, dim > Vector