Electrodes.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 "Electrodes.hpp"
00030 
00031 template<unsigned DIM>
00032 Electrodes<DIM>::Electrodes(AbstractTetrahedralMesh<DIM,DIM>& rMesh,
00033                        bool groundSecondElectrode,
00034                        unsigned index,
00035                        double lowerValue,
00036                        double upperValue,
00037                        double magnitude,
00038                        double duration)
00039 {
00040     DistributedVectorFactory factory(rMesh.GetDistributedVectorFactory()->GetProblemSize(), 
00041                                      rMesh.GetDistributedVectorFactory()->GetLocalOwnership());
00042     assert(index < DIM);
00043     mGroundSecondElectrode = groundSecondElectrode;
00044     assert(duration > 0);
00045     mEndTime = 0.0 + duration; // currently start time = 0 is hardcoded here
00046     mAreActive = true; // switch electrodes on!
00047 
00048     // check min x_i = a and max x_i = b, where i = index
00049     double local_min = DBL_MAX;
00050     double local_max = -DBL_MAX;
00051     
00052     for (typename AbstractTetrahedralMesh<DIM,DIM>::NodeIterator iter=rMesh.GetNodeIteratorBegin();
00053          iter != rMesh.GetNodeIteratorEnd();
00054          ++iter)
00055     {
00056         double value = (*iter).rGetLocation()[index];
00057         if(value < local_min)
00058         {
00059             local_min = value;
00060         }
00061         if(value > local_max)
00062         {
00063            local_max = value;
00064         }        
00065     }    
00066 
00067     double global_min;
00068     double global_max;
00069 
00070     int mpi_ret = MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, PETSC_COMM_WORLD);
00071     assert(mpi_ret == MPI_SUCCESS);
00072     mpi_ret = MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, PETSC_COMM_WORLD);
00073     assert(mpi_ret == MPI_SUCCESS);
00074 
00075     if( fabs(global_min - lowerValue) > 1e-6 )
00076     {
00077         EXCEPTION("Minimum value of coordinate is not the value given");
00078     }
00079     if( fabs(global_max - upperValue) > 1e-6 )
00080     {
00081         EXCEPTION("Maximum value of coordinate is not the value given");
00082     }
00083 
00084     mpBoundaryConditionsContainer = new BoundaryConditionsContainer<DIM,DIM,2>;
00085 
00086     ConstBoundaryCondition<DIM>* p_bc_flux_in = new ConstBoundaryCondition<DIM>(magnitude);
00087     ConstBoundaryCondition<DIM>* p_bc_flux_out = new ConstBoundaryCondition<DIM>(-magnitude);
00088 
00089     // loop over boundary elements and add a non-zero phi_e boundary condition (ie extracellular
00090     // stimulus) if (assuming index=0, etc) x=lowerValue (where x is the x-value of the centroid)
00091     for (typename AbstractTetrahedralMesh<DIM,DIM>::BoundaryElementIterator iter
00092             = rMesh.GetBoundaryElementIteratorBegin();
00093        iter != rMesh.GetBoundaryElementIteratorEnd();
00094        iter++)
00095     {
00096         if ( fabs((*iter)->CalculateCentroid()[index] - lowerValue) < 1e-6 )
00097         {
00098             mpBoundaryConditionsContainer->AddNeumannBoundaryCondition(*iter, p_bc_flux_in,  1);
00099         }
00100 
00101         if (!mGroundSecondElectrode)
00102         {
00103             if ( fabs((*iter)->CalculateCentroid()[index] - upperValue) < 1e-6 )
00104             {
00105                 mpBoundaryConditionsContainer->AddNeumannBoundaryCondition(*iter, p_bc_flux_out, 1);
00106             }
00107         }
00108     }
00109 
00110     // set up mGroundedNodes using opposite surface is second electrode is
00111     // grounded
00112     if (mGroundSecondElectrode)
00113     {
00114         ConstBoundaryCondition<DIM>* p_zero_bc = new ConstBoundaryCondition<DIM>(0.0);
00115 
00116         for (typename AbstractTetrahedralMesh<DIM,DIM>::NodeIterator iter=rMesh.GetNodeIteratorBegin();
00117              iter != rMesh.GetNodeIteratorEnd();
00118              ++iter)
00119         {
00120             if (fabs((*iter).rGetLocation()[index]-upperValue)<1e-6)
00121             {
00122                 mpBoundaryConditionsContainer->AddDirichletBoundaryCondition(&(*iter), p_zero_bc, 1);
00123             }
00124         }
00125 
00126         //Unused boundary conditions will not be deleted by the b.c. container
00127         delete p_bc_flux_out;
00128     }
00129 }
00130 
00132 // Explicit instantiation
00134 
00135 template class Electrodes<1>;
00136 template class Electrodes<2>;
00137 template class Electrodes<3>;

Generated on Tue Aug 4 16:10:22 2009 for Chaste by  doxygen 1.5.5