From 3e38e65de64d79a185bbadc709ec376c6b13d594 Mon Sep 17 00:00:00 2001 From: Nicolas Marsic <nicolas.marsic@gmail.com> Date: Mon, 7 Apr 2014 13:30:35 +0000 Subject: [PATCH] Bug in ReferenceSpace::getJacobian -- Has to take sign of determinant into account when flipping elements ! + FunctionSpaceVector::interpolateDerivative + Mapper::hDiv -- do not use fabs in mapping --- FunctionSpace/BasisHierarchical0Form.cpp | 11 +++++ FunctionSpace/BasisHierarchical1Form.cpp | 25 +++++++++- FunctionSpace/FunctionSpaceScalar.h | 1 + FunctionSpace/FunctionSpaceVector.cpp | 34 ++++++++++++++ FunctionSpace/FunctionSpaceVector.h | 60 ++++++++++++++++++++++++ FunctionSpace/ReferenceSpace.cpp | 22 ++++++--- 6 files changed, 145 insertions(+), 8 deletions(-) diff --git a/FunctionSpace/BasisHierarchical0Form.cpp b/FunctionSpace/BasisHierarchical0Form.cpp index df97eebade..0405beb5fe 100644 --- a/FunctionSpace/BasisHierarchical0Form.cpp +++ b/FunctionSpace/BasisHierarchical0Form.cpp @@ -82,10 +82,21 @@ getFunctions(fullMatrix<double>& retValues, void BasisHierarchical0Form::getDerivative(fullMatrix<double>& retValues, const MElement& element, double u, double v, double w) const{ + + const size_t nOrientation = ReferenceSpaceManager::getNOrientation(getType()); + // Get Grad // if(!hasGrad) getGrad(); + // Delete if older // + if(preEvaluatedGrad){ + for(size_t i = 0; i < nOrientation; i++) + delete preEvaluatedGradFunction[i]; + + delete[] preEvaluatedGradFunction; + } + // Define Orientation // const size_t orientation = ReferenceSpaceManager::getOrientation(element); diff --git a/FunctionSpace/BasisHierarchical1Form.cpp b/FunctionSpace/BasisHierarchical1Form.cpp index 06b51302b2..bd53fa7904 100644 --- a/FunctionSpace/BasisHierarchical1Form.cpp +++ b/FunctionSpace/BasisHierarchical1Form.cpp @@ -92,7 +92,30 @@ getFunctions(fullMatrix<double>& retValues, void BasisHierarchical1Form::getDerivative(fullMatrix<double>& retValues, const MElement& element, double u, double v, double w) const{ - throw Exception("Not Implemented"); + + const size_t nOrientation = ReferenceSpaceManager::getNOrientation(getType()); + + // Build Curl // + if(!hasCurl) + getCurl(); + + // Delete if older // + if(preEvaluatedCurl){ + for(size_t i = 0; i < nOrientation; i++) + delete preEvaluatedCurlFunction[i]; + + delete[] preEvaluatedCurlFunction; + } + + // Define Orientation // + const size_t orientation = ReferenceSpaceManager::getOrientation(element); + + // Fill Matrix // + for(size_t i = 0; i < nFunction; i++){ + retValues(i, 0) = curl[orientation][i]->at(0).at(u, v, w); + retValues(i, 1) = curl[orientation][i]->at(1).at(u, v, w); + retValues(i, 2) = curl[orientation][i]->at(2).at(u, v, w); + } } void BasisHierarchical1Form:: diff --git a/FunctionSpace/FunctionSpaceScalar.h b/FunctionSpace/FunctionSpaceScalar.h index 42428d8f0c..0cae40d3ba 100644 --- a/FunctionSpace/FunctionSpaceScalar.h +++ b/FunctionSpace/FunctionSpaceScalar.h @@ -98,6 +98,7 @@ class FunctionSpaceScalar : public FunctionSpace{ If the given coordinate are not in the given element @em Bad @em Things may happend + ** @fn FunctionSpaceScalar::interpolateDerivative @param element The MElement to interpolate on diff --git a/FunctionSpace/FunctionSpaceVector.cpp b/FunctionSpace/FunctionSpaceVector.cpp index 1fb78e7d39..3303886db1 100644 --- a/FunctionSpace/FunctionSpaceVector.cpp +++ b/FunctionSpace/FunctionSpaceVector.cpp @@ -57,3 +57,37 @@ interpolateInABC(const MElement& element, Mapper::hCurl(val, 0, 0, invJac, map); return map; } + +fullVector<double> FunctionSpaceVector:: +interpolateDerivativeInABC(const MElement& element, + const std::vector<double>& coef, + double abc[3]) const{ + // Get Jacobian // + fullMatrix<double> jac(3, 3); + double det = + ReferenceSpaceManager::getJacobian(element, abc[0], abc[1], abc[2], jac); + + // Get Basis Functions // + const Basis& basis = getBasis(element); + const size_t nFun = basis.getNFunction(); + fullMatrix<double> fun(nFun, 3); + + basis.getDerivative(fun, element, abc[0], abc[1], abc[2]); + + // Interpolate (in Reference Place) // + fullMatrix<double> val(1, 3); + val(0, 0) = 0; + val(0, 1) = 0; + val(0, 2) = 0; + + for(size_t i = 0; i < nFun; i++){ + val(0, 0) += fun(i, 0) * coef[i]; + val(0, 1) += fun(i, 1) * coef[i]; + val(0, 2) += fun(i, 2) * coef[i]; + } + + // Return Interpolated Value // + fullVector<double> map(3); + Mapper::hDiv(val, 0, 0, jac, det, map); + return map; +} diff --git a/FunctionSpace/FunctionSpaceVector.h b/FunctionSpace/FunctionSpaceVector.h index 7bdaff6a73..5f2a027760 100644 --- a/FunctionSpace/FunctionSpaceVector.h +++ b/FunctionSpace/FunctionSpaceVector.h @@ -33,11 +33,25 @@ class FunctionSpaceVector : public FunctionSpace{ const std::vector<double>& coef, const fullVector<double>& uvw) const; + fullVector<double> + interpolateDerivative(const MElement& element, + const std::vector<double>& coef, + const fullVector<double>& xyz) const; + + fullVector<double> + interpolateDerivativeInRefSpace(const MElement& element, + const std::vector<double>& coef, + const fullVector<double>& uvw) const; private: fullVector<double> interpolateInABC(const MElement& element, const std::vector<double>& coef, double abc[3]) const; + + fullVector<double> + interpolateDerivativeInABC(const MElement& element, + const std::vector<double>& coef, + double abc[3]) const; }; @@ -91,6 +105,26 @@ class FunctionSpaceVector : public FunctionSpace{ If the given coordinate are not in the given element @em Bad @em Things may happend + ** + + @fn FunctionSpaceVector::interpolateDerivative + @param element The MElement to interpolate on + @param coef The coefficients of the interpolation + @param xyz The coordinate (of a point inside the given element) + of the interpolation in the @em physical space + + Same as FunctionSpaceVector::interpolate(element, coef, xyz), + but this method iterpolates the derivative. + ** + + @fn FunctionSpaceVector::interpolateDerivativeInRefSpace + @param element The MElement to interpolate on + @param coef The coefficients of the interpolation + @param uvw The coordinate (of a point inside the given element) + of the interpolation in the @em reference space + + Same as FunctionSpaceVector::interpolateInRefSpace(element, coef, uvw), + but this method iterpolates the derivative. */ @@ -124,4 +158,30 @@ interpolateInRefSpace(const MElement& element, return interpolateInABC(element, coef, abc); } +inline fullVector<double> FunctionSpaceVector:: +interpolateDerivative(const MElement& element, + const std::vector<double>& coef, + const fullVector<double>& xyz) const{ + + // Get ABC Space coordinate // + double abc[3]; + ReferenceSpaceManager::mapFromXYZtoABC(element, xyz(0), xyz(1), xyz(2), abc); + + // Interpolate in ABC // + return interpolateDerivativeInABC(element, coef, abc); +} + +inline fullVector<double> FunctionSpaceVector:: +interpolateDerivativeInRefSpace(const MElement& element, + const std::vector<double>& coef, + const fullVector<double>& uvw) const{ + + // Get ABC Space coordinate // + double abc[3]; + ReferenceSpaceManager::mapFromUVWtoABC(element, uvw(0), uvw(1), uvw(2), abc); + + // Interpolate in ABC // + return interpolateDerivativeInABC(element, coef, abc); +} + #endif diff --git a/FunctionSpace/ReferenceSpace.cpp b/FunctionSpace/ReferenceSpace.cpp index 63f1912097..bdd10dc17e 100644 --- a/FunctionSpace/ReferenceSpace.cpp +++ b/FunctionSpace/ReferenceSpace.cpp @@ -244,8 +244,8 @@ isCyclicPermutation(const vector<size_t>& pTest, // Test if we have the same connectivity bool isSameConnectivity = isSameEdge(pTest, pRef); - if(isCyclic && isSameConnectivity){ - //if(isSameConnectivity){ + //if(isCyclic && isSameConnectivity){ + if(isSameConnectivity){ tri.first = true; tri.second = getRefIndexPermutation(pRef, pTest); tri.third = getReverseIndexPermutation(pRef, pTest); @@ -779,17 +779,25 @@ double ReferenceSpace::getJacobian(const MElement& element, double uvw[3]; mapFromABCtoUVW(element, a, b, c, uvw); - // UVW to XYZ Jacobian + Determinant // - // NB: Volume is not modified when we go from ABC to UVW // - // --> Determinant unchanged // + // UVW to XYZ Jacobian // fullMatrix<double> jacUVWtoXYZ(3, 3); - double det = element.getJacobian(uvw[0], uvw[1], uvw[2], jacUVWtoXYZ); + element.getJacobian(uvw[0], uvw[1], uvw[2], jacUVWtoXYZ); // Product of the two Jacobians & Return // // Do a naive gemm, so that we do not encounter nested threads // (limitation of OpenBLAS) jac.gemm_naive(jacABCtoUVW, jacUVWtoXYZ, 1, 0); - return det; + + // New Jacobian determinant (same as jacUVWtoXYZ with maybe a SIGN CHANGE) // + // ---> Has to be recomputed! + return + jac(0, 0) * jac(1, 1) * jac(2, 2) + + jac(0, 1) * jac(1, 2) * jac(2, 0) + + jac(0, 2) * jac(1, 0) * jac(2, 1) - + + jac(0, 2) * jac(1, 1) * jac(2, 0) - + jac(0, 1) * jac(1, 0) * jac(2, 2) - + jac(0, 0) * jac(1, 2) * jac(2, 1); } void ReferenceSpace::regularize(size_t dim, fullMatrix<double>& jac){ -- GitLab