QuadraticBasisFunction.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
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 
00043 template <unsigned ELEM_DIM>
00044 double QuadraticBasisFunction<ELEM_DIM>::ComputeBasisFunction(const ChastePoint<ELEM_DIM> &rPoint, unsigned basisIndex)
00045 {
00046     assert(ELEM_DIM < 4 && ELEM_DIM >= 0);
00047     double x, y, z;
00048     switch(ELEM_DIM)
00049     {
00050     case 0:
00051         assert(basisIndex == 0);
00052         return 1.0;
00053         break;          
00054 
00055     case 1:
00056         x = rPoint[0];
00057         switch (basisIndex)
00058         {
00059             case 0:
00060                 return 2.0*(x-1.0)*(x-0.5);
00061                 break;
00062             case 1:
00063                 return 2.0*x*(x-0.5);
00064                 break;
00065             case 2:
00066                 return 4.0*x*(1.0-x);
00067                 break;
00068             default:
00069                 NEVER_REACHED;
00070         }
00071         break;
00072         
00073     case 2:
00074         x = rPoint[0];
00075         y = rPoint[1];
00076         switch (basisIndex)
00077         {
00078             case 0: // the node at (0,0)
00079                 return 2.0 * (1.0 - x - y) * (0.5 - x - y);
00080                 break;
00081             case 1: // the node at (1,0)
00082                 return 2.0*x*(x-0.5);
00083                 break;
00084             case 2: // the node at (0,1)
00085                 return 2.0*y*(y-0.5);
00086                 break;
00087             case 3: // the node opposite 0, which is (1/2,1/2)
00088                 return 4.0 * y * x;            
00089                 break;
00090             case 4: // the node opposite 1, which is (0,1/2)
00091                 return 4.0 * (1.0 - x - y) * y;
00092                 break;
00093             case 5: // the node opposite 2, which is (1/2,0)
00094                 return 4.0 * (1.0 - x - y) * x;
00095                 break;
00096             default:
00097                 NEVER_REACHED;
00098         }
00099         break;
00100         
00101     case 3:
00102         x = rPoint[0];
00103         y = rPoint[1];
00104         z = rPoint[2];
00105         switch (basisIndex)
00106         {
00107             case 0: // the node at (0,0,0)
00108                 return 2.0 * (1.0 - x - y - z) * (0.5 - x - y - z);
00109                 break;
00110             case 1: // the node at (1,0,0)
00111                 return 2.0*x*(x-0.5);
00112                 break;
00113             case 2: // the node at (0,1,0)
00114                 return 2.0*y*(y-0.5);
00115                 break;
00116             case 3: // the node at (0,0,1)
00117                 return 2.0*z*(z-0.5);
00118                 break;
00119             case 4: // our (tetgen convention), node4 is between nodes 0 and 1, (1/2,0,0)
00120                 return 4.0 * (1.0 - x - y - z) * x;
00121                 break;
00122             case 5: // our (tetgen convention), node5 is between nodes 1 and 2, (1/2,1/2,0)
00123                 return 4 * x * y;
00124                 break;
00125             case 6: // our (tetgen convention), node6 is between nodes 0 and 2, (0,1/2,0)
00126                 return 4.0 * (1.0 - x - y - z) * y;
00127                 break;
00128             case 7: // our (tetgen convention), node7 is between nodes 0 and 3, (0,0,1/2)
00129                 return 4.0 * (1.0 - x - y - z) * z;
00130                 break;
00131             case 8: // our (tetgen convention), node8 is between nodes 1 and 3, (1/2,0,1/2)
00132                 return 4.0 * x * z;
00133                 break;
00134             case 9: // our (tetgen convention), node9 is between nodes 2 and 3, (0,1/2,1/2)
00135                 return 4.0 * y * z;
00136                 break;
00137             default:
00138                 NEVER_REACHED;
00139         }
00140         break;
00141     }
00142     return 0.0; // Avoid compiler warning
00143 }
00144 
00145 
00146 
00157 template <unsigned ELEM_DIM>
00158 c_vector<double, ELEM_DIM> QuadraticBasisFunction<ELEM_DIM>::ComputeBasisFunctionDerivative(const ChastePoint<ELEM_DIM> &rPoint, unsigned basisIndex)
00159 {
00160     c_vector<double, ELEM_DIM> gradN;
00161     assert(ELEM_DIM < 4 && ELEM_DIM > 0);
00162     
00163     double x, y, z;
00164     switch(ELEM_DIM)
00165     {
00166     case 1:
00167         x=rPoint[0];
00168         switch (basisIndex)
00169         {
00170             case 0:
00171                 gradN(0) =  4.0*x-3.0;
00172                 break;
00173             case 1:
00174                 gradN(0) = 4.0*x-1.0;
00175                 break;
00176             case 2:
00177                 gradN(0) = 4.0-8.0*x;
00178                 break;
00179             default:
00180                 NEVER_REACHED;
00181         }
00182         break;
00183         
00184     case 2:
00185         x = rPoint[0];
00186         y = rPoint[1];
00187         switch (basisIndex)
00188         {
00189             case 0:
00190                 gradN(0) = -3.0 + 4.0*x + 4.0*y;
00191                 gradN(1) = -3.0 + 4.0*x + 4.0*y;
00192                 break;
00193             case 1:
00194                 gradN(0) = 4.0*x - 1.0;
00195                 gradN(1) = 0.0;
00196                 break;
00197             case 2:
00198                 gradN(0) = 0.0;
00199                 gradN(1) = 4.0*y - 1.0;
00200                 break;
00201             case 3:
00202                 gradN(0) = 4.0*y;
00203                 gradN(1) = 4.0*x;            
00204                 break;
00205             case 4:
00206                 gradN(0) = -4.0*y;
00207                 gradN(1) = 4.0-4.0*x-8.0*y;
00208                 break;
00209             case 5:
00210                 gradN(0) = 4.0-8.0*x-4.0*y;
00211                 gradN(1) = -4.0*x;
00212                 break;
00213             default:
00214                 NEVER_REACHED;
00215         }
00216         break;
00217         
00218     case 3:
00219         x = rPoint[0];
00220         y = rPoint[1];
00221         z = rPoint[2];
00222         switch (basisIndex)
00223         {
00224             case 0:
00225                 gradN(0) = -3.0 + 4.0*(x+y+z);
00226                 gradN(1) = -3.0 + 4.0*(x+y+z);
00227                 gradN(2) = -3.0 + 4.0*(x+y+z);
00228                 break;
00229             case 1:
00230                 gradN(0) =  4.0*x-1.0;
00231                 gradN(1) =  0;
00232                 gradN(2) =  0;
00233                 break;
00234             case 2:
00235                 gradN(0) =  0;
00236                 gradN(1) =  4.0*y-1.0;
00237                 gradN(2) =  0;
00238                 break;
00239             case 3:
00240                 gradN(0) =  0;
00241                 gradN(1) =  0;
00242                 gradN(2) =  4.0*z-1.0;
00243                 break;
00244             case 4:
00245                 gradN(0) =  4.0-8.0*x-4.0*y-4.0*z;
00246                 gradN(1) =  -4.0*x;
00247                 gradN(2) =  -4.0*x;
00248                 break;
00249             case 5:
00250                 gradN(0) =  4.0*y;
00251                 gradN(1) =  4.0*x;
00252                 gradN(2) =  0.0;
00253                 break;
00254             case 6: 
00255                 gradN(0) =  -4.0*y;
00256                 gradN(1) =  4.0-4.0*x-8.0*y-4.0*z;
00257                 gradN(2) =  -4.0*y; 
00258                 break;
00259             case 7:
00260                 gradN(0) =  -4.0*z;
00261                 gradN(1) =  -4.0*z;
00262                 gradN(2) =  4.0-4.0*x-4.0*y-8.0*z;
00263                 break;
00264             case 8:   
00265                 gradN(0) =  4.0*z;
00266                 gradN(1) =  0;
00267                 gradN(2) =  4.0*x;
00268                 break;
00269             case 9:
00270                 gradN(0) =  0;
00271                 gradN(1) =  4.0*z;
00272                 gradN(2) =  4.0*y;
00273                 break;
00274             default:
00275                 NEVER_REACHED;   
00276         }
00277         break;
00278     }    
00279     return gradN;
00280 }
00281 
00282 
00290 template <unsigned ELEM_DIM>
00291 void QuadraticBasisFunction<ELEM_DIM>::ComputeBasisFunctions(const ChastePoint<ELEM_DIM> &rPoint, 
00292                                                              c_vector<double, (ELEM_DIM+1)*(ELEM_DIM+2)/2>& rReturnValue)
00293 {
00294     assert(ELEM_DIM < 4 && ELEM_DIM >= 0);
00295 
00296     for(unsigned i=0;i<(ELEM_DIM+1)*(ELEM_DIM+2)/2;i++)
00297     {
00298         rReturnValue(i) = ComputeBasisFunction(rPoint,i);
00299     }
00300 
00301 }
00302 
00303 
00304 
00314 template <unsigned ELEM_DIM>
00315 void QuadraticBasisFunction<ELEM_DIM>::ComputeBasisFunctionDerivatives(const ChastePoint<ELEM_DIM> &rPoint,
00316                                                                     c_matrix<double, ELEM_DIM, (ELEM_DIM+1)*(ELEM_DIM+2)/2>& rReturnValue)
00317 {
00318     assert(ELEM_DIM < 4 && ELEM_DIM > 0);
00319 
00320     for (unsigned j=0;j<(ELEM_DIM+1)*(ELEM_DIM+2)/2;j++)
00321     {
00322         matrix_column<c_matrix<double, ELEM_DIM, (ELEM_DIM+1)*(ELEM_DIM+2)/2> > column(rReturnValue, j);
00323         column = ComputeBasisFunctionDerivative(rPoint, j);
00324     }
00325 }
00326 
00340 template <unsigned ELEM_DIM>
00341 void QuadraticBasisFunction<ELEM_DIM>::ComputeTransformedBasisFunctionDerivatives(const ChastePoint<ELEM_DIM> &rPoint,
00342                                                                                   const c_matrix<double, ELEM_DIM, ELEM_DIM> &rInverseJacobian,
00343                                                                                   c_matrix<double, ELEM_DIM, (ELEM_DIM+1)*(ELEM_DIM+2)/2>& rReturnValue)
00344 {
00345     assert(ELEM_DIM < 4 && ELEM_DIM > 0);
00346     
00347     ComputeBasisFunctionDerivatives(rPoint, rReturnValue);
00348     rReturnValue = prod(trans(rInverseJacobian), rReturnValue);
00349 }
00350 
00351 
00353 // Explicit instantiation
00355 
00356 template class QuadraticBasisFunction<0>;
00357 template class QuadraticBasisFunction<1>;
00358 template class QuadraticBasisFunction<2>;
00359 template class QuadraticBasisFunction<3>;
00360 

Generated on Wed Mar 18 12:51:56 2009 for Chaste by  doxygen 1.5.5