13#ifndef HERMITE_INTERPOLATION_3D_HH
14#define HERMITE_INTERPOLATION_3D_HH
50 template<
class Scalar_,
class Gr
idView,
class InterpolationPolicy>
51 class HIPImpl<Scalar_, GridView, InterpolationPolicy, 3> :
public HIPBase<Scalar_,3>
54 typedef HIPBase<Scalar_,3> Base;
55 static int const dim = 3;
56 typedef typename Base::Scalar Scalar;
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;
75 HIPImpl(
int numberOfShapeFunctions) : Base(numberOfShapeFunctions), origin(0) {}
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)
91 init(entity, gridView, shapeFunctionSet, container, policy);
102 template <
class ShapeFunctionSet>
103 void init(Entity
const& entity, GridView
const& gridView, ShapeFunctionSet
const& shapeFunctionSet, Container
const& container, InterpolationPolicy
const& policy)
105 initSamplingPointValuesOnEdges(entity, gridView, shapeFunctionSet, container, policy);
106 initSamplingPointValuesOnFaces(entity, gridView, shapeFunctionSet, container, policy);
111 template <
class ShapeFunctionSet>
112 void initSamplingPointValuesOnEdges(Entity
const& entity, GridView
const &gridView, ShapeFunctionSet
const& shapeFunctionSet, Container
const& container, InterpolationPolicy
const& policy){
116 Scalar tissue = round(policy.phaseId( entity ));
119 std::vector<Vector> entityVertexNormals(dim+1,
Vector());
122 LocalFaceIterator fend = gridView.iend(entity);
123 for(LocalFaceIterator face = gridView.ibegin(entity); face!=fend; ++face){
125 Scalar tissueNeighbour = -1;
127 if( face->neighbor() )
128 tissueNeighbour = round(policy.phaseId( *face->outside() ));
132 if(fabs(tissue-tissueNeighbour) < 1e-9)
continue;
134 if( policy.ignoreOuterBoundary(*face) )
continue;
137 int faceId = face->indexInInside();
140 for(
int edgeIdInFace = 0; edgeIdInFace < dim; ++edgeIdInFace){
143 int edgeIdInEntity = ReferenceTetrahedron::simplex().subEntity(faceId,1,edgeIdInFace,dim-1);
148 int globalEdgeId = gridView.indexSet().subIndex(entity, edgeIdInEntity, dim-1);
151 if( !container.edgeNormals[globalEdgeId].isRelevant )
continue;
154 Vector edgeDirection = entity.geometry().corner(edgeVertexIdsInEntity[1]) - entity.geometry().corner(edgeVertexIdsInEntity[0]);
160 Vector edgeNormal = getEdgeNormal(globalEdgeId, tissue, container.edgeNormals);
164 std::vector<Vector> projectedVertexNormals(2), desiredGradientDirections(2,
Vector(1e-301));
166 std::vector<int> shapeFunctionIds(2);
167 for(
int vertexIdInEdge=0; vertexIdInEdge<2; ++vertexIdInEdge){
169 shapeFunctionIds[vertexIdInEdge] = 4 + edgeIdInEntity + vertexIdInEdge*6;
172 if( !container.vertexNormals[ globalVertexIds[ edgeVertexIdsInEntity[vertexIdInEdge] ] ].isRelevant ){
173 desiredGradients[vertexIdInEdge] = 0;
178 projectedVertexNormals[vertexIdInEdge] = entityVertexNormals[edgeVertexIdsInEntity[vertexIdInEdge]];
181 GeomTools::crossProduct(planeNormal, projectedVertexNormals[vertexIdInEdge], desiredGradientDirections[vertexIdInEdge]);
185 if(container.vertexNormals[globalVertexIds[ edgeVertexIdsInEntity[vertexIdInEdge] ] ].isRelevant){
186 desiredGradients[vertexIdInEdge] = (edgeNormal * desiredGradientDirections[vertexIdInEdge])
187 /(edgeDirection * desiredGradientDirections[vertexIdInEdge]);
188 policy.applyGradientThreshold(desiredGradients[vertexIdInEdge]);
192 desiredGradients[vertexIdInEdge] = 0;
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];
203 jacobian.mv(sf_grad, sf_grad_chain);
204 A[vertexIdInEdge][sfId] = sf_grad_chain * edgeDirection;
210 A.solve(coefficients, desiredGradients);
213 for(
int sfId=0; sfId<2; ++sfId)
214 this->insertEntry(coefficients[sfId], edgeNormal, shapeFunctionIds[sfId]);
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)
229 Scalar tissue = round(policy.phaseId(entity));
232 LocalFaceIterator fend = gridView.iend(entity);
233 for(LocalFaceIterator face = gridView.ibegin(entity); face!=fend; ++face){
236 int faceId = face->indexInInside();
238 Scalar tissueNeighbour = -1;
240 if( face->neighbor() )
241 tissueNeighbour = round(policy.phaseId( *face->outside() ));
244 if( fabs(tissue-tissueNeighbour) < 1e-9 )
continue;
246 if( policy.ignoreOuterBoundary(*face) )
continue;
249 std::vector<Vector> iNodes(dim);
256 std::vector<int> edgeIdInEntity(dim,0), globalEdgeIds(dim,0), shapeFunctionIds(6,0);
257 std::vector<std::vector<int> > edgeVertexIdsInEntity(dim);
258 std::vector<Vector> edgeNormal(dim,origin),
259 planeNormal(dim,origin),
260 projectedPlaneNormal(dim,origin),
261 deformedProjectedPlaneNormal(dim,origin),
262 deformedFaceNormal(dim,origin);
264 Vector faceNormal = face->centerUnitOuterNormal();
266 if(tissueNeighbour+1e-9 < tissue && tissueNeighbour > 1e-9)
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];
279 for(
int edgeIdInFace = 0; edgeIdInFace<dim; ++edgeIdInFace){
282 iNodes[edgeIdInFace] = entity.geometry().local( 0.5 * ( entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][0]) + entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][1]) ) );
285 Vector edgeDirection = entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][0]) - entity.geometry().corner(edgeVertexIdsInEntity[edgeIdInFace][1]);
290 if(container.edgeNormals[ globalEdgeIds[edgeIdInFace ] ].isRelevant)
293 edgeNormal[edgeIdInFace] = getEdgeNormal(globalEdgeIds[edgeIdInFace], tissue, container.edgeNormals);
297 projectedPlaneNormal[edgeIdInFace] = planeNormal[edgeIdInFace];
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;
309 deformationGradient.mtv(projectedPlaneNormal[edgeIdInFace], deformedProjectedPlaneNormal[edgeIdInFace]);
311 deformationGradient.mtv(faceNormal, deformedFaceNormal[edgeIdInFace]);
316 int remainingVertexId = edgeVertexIdsInEntity[edgeIdInFace][2];
317 deformedProjectedPlaneNormal[edgeIdInFace] = entity.geometry().corner(remainingVertexId);
318 deformedProjectedPlaneNormal[edgeIdInFace]-= entity.geometry().global(iNodes[edgeIdInFace]);
331 for(
int edgeIdInFace=0; edgeIdInFace<dim; ++edgeIdInFace)
332 for(
int sfID=0; sfID<dim; ++sfID){
334 Vector grad = shapeFunctionSet[16 + faceId*dim + sfID].evaluateDerivative(iNodes[edgeIdInFace])[0];
336 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialInverseDeformationGradient(iNodes[edgeIdInFace], entity, shapeFunctionIds, shapeFunctionSet);
339 jacobian.mv(grad, chainRuleTmp);
341 inverseDeformationGradient.mv(chainRuleTmp,grad);
344 A[edgeIdInFace][sfID] = grad * deformedProjectedPlaneNormal[edgeIdInFace];
353 for(
int iNode = 0; iNode<dim; ++iNode){
355 if(container.edgeNormals[ globalEdgeIds[iNode] ].isRelevant){
356 desiredGradients[iNode] = (planeNormal[iNode] * deformedFaceNormal[iNode]) / (planeNormal[iNode] * deformedProjectedPlaneNormal[iNode]);
357 policy.applyGradientThreshold(desiredGradients[iNode]);
360 desiredGradients[iNode] = 0;
366 for(
int iNode = 0; iNode<dim; ++iNode){
368 for(
int edgeIdInFace = 0; edgeIdInFace < dim; ++edgeIdInFace){
373 Vector grad = shapeFunctionSet[ shapeFunctionIds[edgeIdInFace] ].evaluateDerivative(iNodes[iNode])[0];
375 jacobian.mv(grad,chainRuleTmp);
376 inverseDeformationGradient.mv(chainRuleTmp,grad);
378 desiredGradients[iNode] -= grad * deformedProjectedPlaneNormal[iNode] * this->values[ shapeFunctionIds[edgeIdInFace] ];
381 grad = shapeFunctionSet[ shapeFunctionIds[edgeIdInFace+dim]].evaluateDerivative(iNodes[iNode])[0];
383 jacobian.mv(grad,chainRuleTmp);
384 inverseDeformationGradient.mv(chainRuleTmp,grad);
386 desiredGradients[iNode] -= grad * deformedProjectedPlaneNormal[iNode] * this->values[ shapeFunctionIds[edgeIdInFace+dim] ];
392 A.solve(coefficients, desiredGradients);
393 if(!(coefficients==coefficients))
395 for(
int edgeIdInFace=0; edgeIdInFace<dim; ++edgeIdInFace)
396 for(
int sfID=0; sfID<dim; ++sfID){
398 Vector grad = shapeFunctionSet[16 + faceId*dim + sfID].evaluateDerivative(iNodes[edgeIdInFace])[0];
400 Dune::FieldMatrix<Scalar,dim,dim> inverseDeformationGradient = getPartialInverseDeformationGradient(iNodes[edgeIdInFace], entity, shapeFunctionIds, shapeFunctionSet);
403 jacobian.mv(grad, chainRuleTmp);
407 inverseDeformationGradient.mv(chainRuleTmp,grad);
409 std::cout << grad <<
" * " << deformedProjectedPlaneNormal[edgeIdInFace] << std::endl << std::endl;
413 std::cout << desiredGradients <<
" -> " << coefficients << std::endl << std::endl;
419 for(
int sfId=0; sfId<dim; ++sfId)
420 this->insertEntry(coefficients[sfId], faceNormal, 16 + dim*faceId + sfId);
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);
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;
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 {
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){
472 Vector grad = shapeFunctionSet[ shapeFunctionIds[k] ].evaluateDerivative( iNode )[0];
475 jacobian.mv(grad,chain);
476 deformationGradient[j][i] += this->values[ shapeFunctionIds[k] ] * chain[j] * this->directions[ shapeFunctionIds[k] ][i];
480 deformationGradient[i][i] += 1;
482 return deformationGradient;
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 {
497 inverseDeformationGradient.invert();
498 return inverseDeformationGradient;
typename GridView::Intersection Face
The type of faces in the grid view.
Dune::FieldVector< Scalar, dim > Vector