QuadraticBasisFunction.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "QuadraticBasisFunction.hpp"
00037 #include "Exception.hpp"
00038 #include "UblasIncludes.hpp"
00039 
00049 double QuadraticBasisFunction<0>::ComputeBasisFunction(const ChastePoint<0>& rPoint, unsigned basisIndex)
00050 {
00051     assert(basisIndex == 0);
00052     return 1.0;
00053 }
00054 
00062 void QuadraticBasisFunction<0>::ComputeBasisFunctions(const ChastePoint<0>& rPoint,
00063                                                       c_vector<double, 1>& rReturnValue)
00064 {
00065     rReturnValue(0) = ComputeBasisFunction(rPoint, 0);
00066 }
00067 
00077 template <unsigned ELEMENT_DIM>
00078 double QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunction(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00079 {
00080     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00081     double x, y, z;
00082     switch (ELEMENT_DIM)
00083     {
00084     case 0:
00085         assert(basisIndex == 0);
00086         return 1.0;
00087         break;
00088 
00089     case 1:
00090         x = rPoint[0];
00091         switch (basisIndex)
00092         {
00093             case 0:
00094                 return 2.0*(x-1.0)*(x-0.5);
00095                 break;
00096             case 1:
00097                 return 2.0*x*(x-0.5);
00098                 break;
00099             case 2:
00100                 return 4.0*x*(1.0-x);
00101                 break;
00102             default:
00103                 NEVER_REACHED;
00104         }
00105         break;
00106 
00107     case 2:
00108         x = rPoint[0];
00109         y = rPoint[1];
00110         switch (basisIndex)
00111         {
00112             case 0: // the node at (0,0)
00113                 return 2.0 * (1.0 - x - y) * (0.5 - x - y);
00114                 break;
00115             case 1: // the node at (1,0)
00116                 return 2.0*x*(x-0.5);
00117                 break;
00118             case 2: // the node at (0,1)
00119                 return 2.0*y*(y-0.5);
00120                 break;
00121             case 3: // the node opposite 0, which is (1/2,1/2)
00122                 return 4.0 * y * x;
00123                 break;
00124             case 4: // the node opposite 1, which is (0,1/2)
00125                 return 4.0 * (1.0 - x - y) * y;
00126                 break;
00127             case 5: // the node opposite 2, which is (1/2,0)
00128                 return 4.0 * (1.0 - x - y) * x;
00129                 break;
00130             default:
00131                 NEVER_REACHED;
00132         }
00133         break;
00134 
00135     case 3:
00136         x = rPoint[0];
00137         y = rPoint[1];
00138         z = rPoint[2];
00139         switch (basisIndex)
00140         {
00141             case 0: // the node at (0,0,0)
00142                 return 2.0 * (1.0 - x - y - z) * (0.5 - x - y - z);
00143                 break;
00144             case 1: // the node at (1,0,0)
00145                 return 2.0*x*(x-0.5);
00146                 break;
00147             case 2: // the node at (0,1,0)
00148                 return 2.0*y*(y-0.5);
00149                 break;
00150             case 3: // the node at (0,0,1)
00151                 return 2.0*z*(z-0.5);
00152                 break;
00153             case 4: // our (tetgen convention), node4 is between nodes 0 and 1, (1/2,0,0)
00154                 return 4.0 * (1.0 - x - y - z) * x;
00155                 break;
00156             case 5: // our (tetgen convention), node5 is between nodes 1 and 2, (1/2,1/2,0)
00157                 return 4 * x * y;
00158                 break;
00159             case 6: // our (tetgen convention), node6 is between nodes 0 and 2, (0,1/2,0)
00160                 return 4.0 * (1.0 - x - y - z) * y;
00161                 break;
00162             case 7: // our (tetgen convention), node7 is between nodes 0 and 3, (0,0,1/2)
00163                 return 4.0 * (1.0 - x - y - z) * z;
00164                 break;
00165             case 8: // our (tetgen convention), node8 is between nodes 1 and 3, (1/2,0,1/2)
00166                 return 4.0 * x * z;
00167                 break;
00168             case 9: // our (tetgen convention), node9 is between nodes 2 and 3, (0,1/2,1/2)
00169                 return 4.0 * y * z;
00170                 break;
00171             default:
00172                 NEVER_REACHED;
00173         }
00174         break;
00175     }
00176     return 0.0; // Avoid compiler warning
00177 }
00178 
00189 template <unsigned ELEMENT_DIM>
00190 c_vector<double, ELEMENT_DIM> QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivative(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00191 {
00192     c_vector<double, ELEMENT_DIM> gradN;
00193     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00194 
00195     double x, y, z;
00196     switch (ELEMENT_DIM)
00197     {
00198     case 1:
00199         x = rPoint[0];
00200         switch (basisIndex)
00201         {
00202             case 0:
00203                 gradN(0) = 4.0*x-3.0;
00204                 break;
00205             case 1:
00206                 gradN(0) = 4.0*x-1.0;
00207                 break;
00208             case 2:
00209                 gradN(0) = 4.0-8.0*x;
00210                 break;
00211             default:
00212                 NEVER_REACHED;
00213         }
00214         break;
00215 
00216     case 2:
00217         x = rPoint[0];
00218         y = rPoint[1];
00219         switch (basisIndex)
00220         {
00221             case 0:
00222                 gradN(0) = -3.0 + 4.0*x + 4.0*y;
00223                 gradN(1) = -3.0 + 4.0*x + 4.0*y;
00224                 break;
00225             case 1:
00226                 gradN(0) = 4.0*x - 1.0;
00227                 gradN(1) = 0.0;
00228                 break;
00229             case 2:
00230                 gradN(0) = 0.0;
00231                 gradN(1) = 4.0*y - 1.0;
00232                 break;
00233             case 3:
00234                 gradN(0) = 4.0*y;
00235                 gradN(1) = 4.0*x;
00236                 break;
00237             case 4:
00238                 gradN(0) = -4.0*y;
00239                 gradN(1) = 4.0-4.0*x-8.0*y;
00240                 break;
00241             case 5:
00242                 gradN(0) = 4.0-8.0*x-4.0*y;
00243                 gradN(1) = -4.0*x;
00244                 break;
00245             default:
00246                 NEVER_REACHED;
00247         }
00248         break;
00249 
00250     case 3:
00251         x = rPoint[0];
00252         y = rPoint[1];
00253         z = rPoint[2];
00254         switch (basisIndex)
00255         {
00256             case 0:
00257                 gradN(0) = -3.0 + 4.0*(x+y+z);
00258                 gradN(1) = -3.0 + 4.0*(x+y+z);
00259                 gradN(2) = -3.0 + 4.0*(x+y+z);
00260                 break;
00261             case 1:
00262                 gradN(0) =  4.0*x-1.0;
00263                 gradN(1) =  0;
00264                 gradN(2) =  0;
00265                 break;
00266             case 2:
00267                 gradN(0) =  0;
00268                 gradN(1) =  4.0*y-1.0;
00269                 gradN(2) =  0;
00270                 break;
00271             case 3:
00272                 gradN(0) =  0;
00273                 gradN(1) =  0;
00274                 gradN(2) =  4.0*z-1.0;
00275                 break;
00276             case 4:
00277                 gradN(0) =  4.0-8.0*x-4.0*y-4.0*z;
00278                 gradN(1) =  -4.0*x;
00279                 gradN(2) =  -4.0*x;
00280                 break;
00281             case 5:
00282                 gradN(0) =  4.0*y;
00283                 gradN(1) =  4.0*x;
00284                 gradN(2) =  0.0;
00285                 break;
00286             case 6:
00287                 gradN(0) =  -4.0*y;
00288                 gradN(1) =  4.0-4.0*x-8.0*y-4.0*z;
00289                 gradN(2) =  -4.0*y;
00290                 break;
00291             case 7:
00292                 gradN(0) =  -4.0*z;
00293                 gradN(1) =  -4.0*z;
00294                 gradN(2) =  4.0-4.0*x-4.0*y-8.0*z;
00295                 break;
00296             case 8:
00297                 gradN(0) =  4.0*z;
00298                 gradN(1) =  0;
00299                 gradN(2) =  4.0*x;
00300                 break;
00301             case 9:
00302                 gradN(0) =  0;
00303                 gradN(1) =  4.0*z;
00304                 gradN(2) =  4.0*y;
00305                 break;
00306             default:
00307                 NEVER_REACHED;
00308         }
00309         break;
00310     }
00311     return gradN;
00312 }
00313 
00321 template <unsigned ELEMENT_DIM>
00322 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(const ChastePoint<ELEMENT_DIM>& rPoint,
00323                                                              c_vector<double, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00324 {
00325     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00326 
00327     for (unsigned i=0; i<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; i++)
00328     {
00329         rReturnValue(i) = ComputeBasisFunction(rPoint, i);
00330     }
00331 }
00332 
00342 template <unsigned ELEMENT_DIM>
00343 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00344                                                                           c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00345 {
00346     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00347 
00348     for (unsigned j=0; j<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; j++)
00349     {
00350         matrix_column<c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2> > column(rReturnValue, j);
00351         column = ComputeBasisFunctionDerivative(rPoint, j);
00352     }
00353 }
00354 
00368 template <unsigned ELEMENT_DIM>
00369 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00370                                                                                      const c_matrix<double, ELEMENT_DIM, ELEMENT_DIM>& rInverseJacobian,
00371                                                                                      c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00372 {
00373     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00374 
00375     ComputeBasisFunctionDerivatives(rPoint, rReturnValue);
00376     rReturnValue = prod(trans(rInverseJacobian), rReturnValue);
00377 }
00378 
00380 // Explicit instantiation
00382 
00383 template class QuadraticBasisFunction<1>;
00384 template class QuadraticBasisFunction<2>;
00385 template class QuadraticBasisFunction<3>;

Generated by  doxygen 1.6.2