QuadraticBasisFunction.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include <boost/numeric/ublas/matrix.hpp>
00030 #include <boost/numeric/ublas/matrix_proxy.hpp>
00031 
00032 #include "QuadraticBasisFunction.hpp"
00033 #include "Exception.hpp"
00034 
00044 double QuadraticBasisFunction<0>::ComputeBasisFunction(const ChastePoint<0>& rPoint, unsigned basisIndex)
00045 {
00046     assert(basisIndex == 0);
00047     return 1.0;
00048 }
00049 
00057 void QuadraticBasisFunction<0>::ComputeBasisFunctions(const ChastePoint<0>& rPoint,
00058                                                       c_vector<double, 1>& rReturnValue)
00059 {
00060     rReturnValue(0) = ComputeBasisFunction(rPoint, 0);
00061 }
00062 
00072 template <unsigned ELEMENT_DIM>
00073 double QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunction(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00074 {
00075     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00076     double x, y, z;
00077     switch (ELEMENT_DIM)
00078     {
00079     case 0:
00080         assert(basisIndex == 0);
00081         return 1.0;
00082         break;
00083 
00084     case 1:
00085         x = rPoint[0];
00086         switch (basisIndex)
00087         {
00088             case 0:
00089                 return 2.0*(x-1.0)*(x-0.5);
00090                 break;
00091             case 1:
00092                 return 2.0*x*(x-0.5);
00093                 break;
00094             case 2:
00095                 return 4.0*x*(1.0-x);
00096                 break;
00097             default:
00098                 NEVER_REACHED;
00099         }
00100         break;
00101 
00102     case 2:
00103         x = rPoint[0];
00104         y = rPoint[1];
00105         switch (basisIndex)
00106         {
00107             case 0: // the node at (0,0)
00108                 return 2.0 * (1.0 - x - y) * (0.5 - x - y);
00109                 break;
00110             case 1: // the node at (1,0)
00111                 return 2.0*x*(x-0.5);
00112                 break;
00113             case 2: // the node at (0,1)
00114                 return 2.0*y*(y-0.5);
00115                 break;
00116             case 3: // the node opposite 0, which is (1/2,1/2)
00117                 return 4.0 * y * x;
00118                 break;
00119             case 4: // the node opposite 1, which is (0,1/2)
00120                 return 4.0 * (1.0 - x - y) * y;
00121                 break;
00122             case 5: // the node opposite 2, which is (1/2,0)
00123                 return 4.0 * (1.0 - x - y) * x;
00124                 break;
00125             default:
00126                 NEVER_REACHED;
00127         }
00128         break;
00129 
00130     case 3:
00131         x = rPoint[0];
00132         y = rPoint[1];
00133         z = rPoint[2];
00134         switch (basisIndex)
00135         {
00136             case 0: // the node at (0,0,0)
00137                 return 2.0 * (1.0 - x - y - z) * (0.5 - x - y - z);
00138                 break;
00139             case 1: // the node at (1,0,0)
00140                 return 2.0*x*(x-0.5);
00141                 break;
00142             case 2: // the node at (0,1,0)
00143                 return 2.0*y*(y-0.5);
00144                 break;
00145             case 3: // the node at (0,0,1)
00146                 return 2.0*z*(z-0.5);
00147                 break;
00148             case 4: // our (tetgen convention), node4 is between nodes 0 and 1, (1/2,0,0)
00149                 return 4.0 * (1.0 - x - y - z) * x;
00150                 break;
00151             case 5: // our (tetgen convention), node5 is between nodes 1 and 2, (1/2,1/2,0)
00152                 return 4 * x * y;
00153                 break;
00154             case 6: // our (tetgen convention), node6 is between nodes 0 and 2, (0,1/2,0)
00155                 return 4.0 * (1.0 - x - y - z) * y;
00156                 break;
00157             case 7: // our (tetgen convention), node7 is between nodes 0 and 3, (0,0,1/2)
00158                 return 4.0 * (1.0 - x - y - z) * z;
00159                 break;
00160             case 8: // our (tetgen convention), node8 is between nodes 1 and 3, (1/2,0,1/2)
00161                 return 4.0 * x * z;
00162                 break;
00163             case 9: // our (tetgen convention), node9 is between nodes 2 and 3, (0,1/2,1/2)
00164                 return 4.0 * y * z;
00165                 break;
00166             default:
00167                 NEVER_REACHED;
00168         }
00169         break;
00170     }
00171     return 0.0; // Avoid compiler warning
00172 }
00173 
00184 template <unsigned ELEMENT_DIM>
00185 c_vector<double, ELEMENT_DIM> QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivative(const ChastePoint<ELEMENT_DIM>& rPoint, unsigned basisIndex)
00186 {
00187     c_vector<double, ELEMENT_DIM> gradN;
00188     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00189 
00190     double x, y, z;
00191     switch (ELEMENT_DIM)
00192     {
00193     case 1:
00194         x = rPoint[0];
00195         switch (basisIndex)
00196         {
00197             case 0:
00198                 gradN(0) = 4.0*x-3.0;
00199                 break;
00200             case 1:
00201                 gradN(0) = 4.0*x-1.0;
00202                 break;
00203             case 2:
00204                 gradN(0) = 4.0-8.0*x;
00205                 break;
00206             default:
00207                 NEVER_REACHED;
00208         }
00209         break;
00210 
00211     case 2:
00212         x = rPoint[0];
00213         y = rPoint[1];
00214         switch (basisIndex)
00215         {
00216             case 0:
00217                 gradN(0) = -3.0 + 4.0*x + 4.0*y;
00218                 gradN(1) = -3.0 + 4.0*x + 4.0*y;
00219                 break;
00220             case 1:
00221                 gradN(0) = 4.0*x - 1.0;
00222                 gradN(1) = 0.0;
00223                 break;
00224             case 2:
00225                 gradN(0) = 0.0;
00226                 gradN(1) = 4.0*y - 1.0;
00227                 break;
00228             case 3:
00229                 gradN(0) = 4.0*y;
00230                 gradN(1) = 4.0*x;
00231                 break;
00232             case 4:
00233                 gradN(0) = -4.0*y;
00234                 gradN(1) = 4.0-4.0*x-8.0*y;
00235                 break;
00236             case 5:
00237                 gradN(0) = 4.0-8.0*x-4.0*y;
00238                 gradN(1) = -4.0*x;
00239                 break;
00240             default:
00241                 NEVER_REACHED;
00242         }
00243         break;
00244 
00245     case 3:
00246         x = rPoint[0];
00247         y = rPoint[1];
00248         z = rPoint[2];
00249         switch (basisIndex)
00250         {
00251             case 0:
00252                 gradN(0) = -3.0 + 4.0*(x+y+z);
00253                 gradN(1) = -3.0 + 4.0*(x+y+z);
00254                 gradN(2) = -3.0 + 4.0*(x+y+z);
00255                 break;
00256             case 1:
00257                 gradN(0) =  4.0*x-1.0;
00258                 gradN(1) =  0;
00259                 gradN(2) =  0;
00260                 break;
00261             case 2:
00262                 gradN(0) =  0;
00263                 gradN(1) =  4.0*y-1.0;
00264                 gradN(2) =  0;
00265                 break;
00266             case 3:
00267                 gradN(0) =  0;
00268                 gradN(1) =  0;
00269                 gradN(2) =  4.0*z-1.0;
00270                 break;
00271             case 4:
00272                 gradN(0) =  4.0-8.0*x-4.0*y-4.0*z;
00273                 gradN(1) =  -4.0*x;
00274                 gradN(2) =  -4.0*x;
00275                 break;
00276             case 5:
00277                 gradN(0) =  4.0*y;
00278                 gradN(1) =  4.0*x;
00279                 gradN(2) =  0.0;
00280                 break;
00281             case 6:
00282                 gradN(0) =  -4.0*y;
00283                 gradN(1) =  4.0-4.0*x-8.0*y-4.0*z;
00284                 gradN(2) =  -4.0*y;
00285                 break;
00286             case 7:
00287                 gradN(0) =  -4.0*z;
00288                 gradN(1) =  -4.0*z;
00289                 gradN(2) =  4.0-4.0*x-4.0*y-8.0*z;
00290                 break;
00291             case 8:
00292                 gradN(0) =  4.0*z;
00293                 gradN(1) =  0;
00294                 gradN(2) =  4.0*x;
00295                 break;
00296             case 9:
00297                 gradN(0) =  0;
00298                 gradN(1) =  4.0*z;
00299                 gradN(2) =  4.0*y;
00300                 break;
00301             default:
00302                 NEVER_REACHED;
00303         }
00304         break;
00305     }
00306     return gradN;
00307 }
00308 
00316 template <unsigned ELEMENT_DIM>
00317 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctions(const ChastePoint<ELEMENT_DIM>& rPoint,
00318                                                              c_vector<double, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00319 {
00320     assert(ELEMENT_DIM < 4 && ELEMENT_DIM >= 0);
00321 
00322     for (unsigned i=0; i<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; i++)
00323     {
00324         rReturnValue(i) = ComputeBasisFunction(rPoint, i);
00325     }
00326 }
00327 
00337 template <unsigned ELEMENT_DIM>
00338 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00339                                                                     c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00340 {
00341     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00342 
00343     for (unsigned j=0; j<(ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2; j++)
00344     {
00345         matrix_column<c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2> > column(rReturnValue, j);
00346         column = ComputeBasisFunctionDerivative(rPoint, j);
00347     }
00348 }
00349 
00363 template <unsigned ELEMENT_DIM>
00364 void QuadraticBasisFunction<ELEMENT_DIM>::ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEMENT_DIM>& rPoint,
00365                                                                                   const c_matrix<double, ELEMENT_DIM, ELEMENT_DIM>& rInverseJacobian,
00366                                                                                   c_matrix<double, ELEMENT_DIM, (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2>& rReturnValue)
00367 {
00368     assert(ELEMENT_DIM < 4 && ELEMENT_DIM > 0);
00369 
00370     ComputeBasisFunctionDerivatives(rPoint, rReturnValue);
00371     rReturnValue = prod(trans(rInverseJacobian), rReturnValue);
00372 }
00373 
00375 // Explicit instantiation
00377 
00378 template class QuadraticBasisFunction<1>;
00379 template class QuadraticBasisFunction<2>;
00380 template class QuadraticBasisFunction<3>;
Generated on Thu Dec 22 13:00:17 2011 for Chaste by  doxygen 1.6.3