Chaste Release::3.1
QuadraticBasisFunction.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 <boost/numeric/ublas/matrix.hpp>
00037 #include <boost/numeric/ublas/matrix_proxy.hpp>
00038 
00039 #include "QuadraticBasisFunction.hpp"
00040 #include "Exception.hpp"
00041 
00051 double QuadraticBasisFunction<0>::ComputeBasisFunction(const ChastePoint<0>& rPoint, unsigned basisIndex)
00052 {
00053     assert(basisIndex == 0);
00054     return 1.0;
00055 }
00056 
00064 void QuadraticBasisFunction<0>::ComputeBasisFunctions(const ChastePoint<0>& rPoint,
00065                                                       c_vector<double, 1>& rReturnValue)
00066 {
00067     rReturnValue(0) = ComputeBasisFunction(rPoint, 0);
00068 }
00069 
00079 template <unsigned ELEMENT_DIM>
00080 double QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunction(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00081 {
00082     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00083     double x, y, z;
00084     switch (ELEMENT_DIM)
00085     {
00086     case 0:
00087         assert(basisIndex == 0);
00088         return 1.0;
00089         break;
00090 
00091     case 1:
00092         x = rPoint[0];
00093         switch (basisIndex)
00094         {
00095             case 0:
00096                 return 2.0*(x-1.0)*(x-0.5);
00097                 break;
00098             case 1:
00099                 return 2.0*x*(x-0.5);
00100                 break;
00101             case 2:
00102                 return 4.0*x*(1.0-x);
00103                 break;
00104             default:
00105                 NEVER_REACHED;
00106         }
00107         break;
00108 
00109     case 2:
00110         x = rPoint[0];
00111         y = rPoint[1];
00112         switch (basisIndex)
00113         {
00114             case 0: // the node at (0,0)
00115                 return 2.0 * (1.0 - x - y) * (0.5 - x - y);
00116                 break;
00117             case 1: // the node at (1,0)
00118                 return 2.0*x*(x-0.5);
00119                 break;
00120             case 2: // the node at (0,1)
00121                 return 2.0*y*(y-0.5);
00122                 break;
00123             case 3: // the node opposite 0, which is (1/2,1/2)
00124                 return 4.0 * y * x;
00125                 break;
00126             case 4: // the node opposite 1, which is (0,1/2)
00127                 return 4.0 * (1.0 - x - y) * y;
00128                 break;
00129             case 5: // the node opposite 2, which is (1/2,0)
00130                 return 4.0 * (1.0 - x - y) * x;
00131                 break;
00132             default:
00133                 NEVER_REACHED;
00134         }
00135         break;
00136 
00137     case 3:
00138         x = rPoint[0];
00139         y = rPoint[1];
00140         z = rPoint[2];
00141         switch (basisIndex)
00142         {
00143             case 0: // the node at (0,0,0)
00144                 return 2.0 * (1.0 - x - y - z) * (0.5 - x - y - z);
00145                 break;
00146             case 1: // the node at (1,0,0)
00147                 return 2.0*x*(x-0.5);
00148                 break;
00149             case 2: // the node at (0,1,0)
00150                 return 2.0*y*(y-0.5);
00151                 break;
00152             case 3: // the node at (0,0,1)
00153                 return 2.0*z*(z-0.5);
00154                 break;
00155             case 4: // our (tetgen convention), node4 is between nodes 0 and 1, (1/2,0,0)
00156                 return 4.0 * (1.0 - x - y - z) * x;
00157                 break;
00158             case 5: // our (tetgen convention), node5 is between nodes 1 and 2, (1/2,1/2,0)
00159                 return 4 * x * y;
00160                 break;
00161             case 6: // our (tetgen convention), node6 is between nodes 0 and 2, (0,1/2,0)
00162                 return 4.0 * (1.0 - x - y - z) * y;
00163                 break;
00164             case 7: // our (tetgen convention), node7 is between nodes 0 and 3, (0,0,1/2)
00165                 return 4.0 * (1.0 - x - y - z) * z;
00166                 break;
00167             case 8: // our (tetgen convention), node8 is between nodes 1 and 3, (1/2,0,1/2)
00168                 return 4.0 * x * z;
00169                 break;
00170             case 9: // our (tetgen convention), node9 is between nodes 2 and 3, (0,1/2,1/2)
00171                 return 4.0 * y * z;
00172                 break;
00173             default:
00174                 NEVER_REACHED;
00175         }
00176         break;
00177     }
00178     return 0.0; // Avoid compiler warning
00179 }
00180 
00191 template <unsigned ELEMENT_DIM>
00192 c_vector<double, ELEMENT_DIM> QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivative(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00193 {
00194     c_vector<double, ELEMENT_DIM> gradN;
00195     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00196 
00197     double x, y, z;
00198     switch (ELEMENT_DIM)
00199     {
00200     case 1:
00201         x = rPoint[0];
00202         switch (basisIndex)
00203         {
00204             case 0:
00205                 gradN(0) = 4.0*x-3.0;
00206                 break;
00207             case 1:
00208                 gradN(0) = 4.0*x-1.0;
00209                 break;
00210             case 2:
00211                 gradN(0) = 4.0-8.0*x;
00212                 break;
00213             default:
00214                 NEVER_REACHED;
00215         }
00216         break;
00217 
00218     case 2:
00219         x = rPoint[0];
00220         y = rPoint[1];
00221         switch (basisIndex)
00222         {
00223             case 0:
00224                 gradN(0) = -3.0 + 4.0*x + 4.0*y;
00225                 gradN(1) = -3.0 + 4.0*x + 4.0*y;
00226                 break;
00227             case 1:
00228                 gradN(0) = 4.0*x - 1.0;
00229                 gradN(1) = 0.0;
00230                 break;
00231             case 2:
00232                 gradN(0) = 0.0;
00233                 gradN(1) = 4.0*y - 1.0;
00234                 break;
00235             case 3:
00236                 gradN(0) = 4.0*y;
00237                 gradN(1) = 4.0*x;
00238                 break;
00239             case 4:
00240                 gradN(0) = -4.0*y;
00241                 gradN(1) = 4.0-4.0*x-8.0*y;
00242                 break;
00243             case 5:
00244                 gradN(0) = 4.0-8.0*x-4.0*y;
00245                 gradN(1) = -4.0*x;
00246                 break;
00247             default:
00248                 NEVER_REACHED;
00249         }
00250         break;
00251 
00252     case 3:
00253         x = rPoint[0];
00254         y = rPoint[1];
00255         z = rPoint[2];
00256         switch (basisIndex)
00257         {
00258             case 0:
00259                 gradN(0) = -3.0 + 4.0*(x+y+z);
00260                 gradN(1) = -3.0 + 4.0*(x+y+z);
00261                 gradN(2) = -3.0 + 4.0*(x+y+z);
00262                 break;
00263             case 1:
00264                 gradN(0) =  4.0*x-1.0;
00265                 gradN(1) =  0;
00266                 gradN(2) =  0;
00267                 break;
00268             case 2:
00269                 gradN(0) =  0;
00270                 gradN(1) =  4.0*y-1.0;
00271                 gradN(2) =  0;
00272                 break;
00273             case 3:
00274                 gradN(0) =  0;
00275                 gradN(1) =  0;
00276                 gradN(2) =  4.0*z-1.0;
00277                 break;
00278             case 4:
00279                 gradN(0) =  4.0-8.0*x-4.0*y-4.0*z;
00280                 gradN(1) =  -4.0*x;
00281                 gradN(2) =  -4.0*x;
00282                 break;
00283             case 5:
00284                 gradN(0) =  4.0*y;
00285                 gradN(1) =  4.0*x;
00286                 gradN(2) =  0.0;
00287                 break;
00288             case 6:
00289                 gradN(0) =  -4.0*y;
00290                 gradN(1) =  4.0-4.0*x-8.0*y-4.0*z;
00291                 gradN(2) =  -4.0*y;
00292                 break;
00293             case 7:
00294                 gradN(0) =  -4.0*z;
00295                 gradN(1) =  -4.0*z;
00296                 gradN(2) =  4.0-4.0*x-4.0*y-8.0*z;
00297                 break;
00298             case 8:
00299                 gradN(0) =  4.0*z;
00300                 gradN(1) =  0;
00301                 gradN(2) =  4.0*x;
00302                 break;
00303             case 9:
00304                 gradN(0) =  0;
00305                 gradN(1) =  4.0*z;
00306                 gradN(2) =  4.0*y;
00307                 break;
00308             default:
00309                 NEVER_REACHED;
00310         }
00311         break;
00312     }
00313     return gradN;
00314 }
00315 
00323 template <unsigned ELEMENT_DIM>
00324 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(const ChastePoint<ELEMENT_DIM>& rPoint,
00325                                                              c_vector<double, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00326 {
00327     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00328 
00329     for (unsigned i=0; i<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; i++)
00330     {
00331         rReturnValue(i) = ComputeBasisFunction(rPoint, i);
00332     }
00333 }
00334 
00344 template <unsigned ELEMENT_DIM>
00345 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00346                                                                     c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00347 {
00348     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00349 
00350     for (unsigned j=0; j<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; j++)
00351     {
00352         matrix_column<c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2> > column(rReturnValue, j);
00353         column = ComputeBasisFunctionDerivative(rPoint, j);
00354     }
00355 }
00356 
00370 template <unsigned ELEMENT_DIM>
00371 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00372                                                                                   const c_matrix<double, ELEMENT_DIM, ELEMENT_DIM>& rInverseJacobian,
00373                                                                                   c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00374 {
00375     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00376 
00377     ComputeBasisFunctionDerivatives(rPoint, rReturnValue);
00378     rReturnValue = prod(trans(rInverseJacobian), rReturnValue);
00379 }
00380 
00382 // Explicit instantiation
00384 
00385 template class QuadraticBasisFunction<1>;
00386 template class QuadraticBasisFunction<2>;
00387 template class QuadraticBasisFunction<3>;