AbstractPerElementWriter.hpp

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 #ifndef ABSTRACTPERELEMENTWRITER_HPP_
00036 #define ABSTRACTPERELEMENTWRITER_HPP_
00037 
00038 #include "AbstractTetrahedralMesh.hpp"
00039 #include "UblasCustomFunctions.hpp"
00040 #include "OutputFileHandler.hpp"
00041 #include "Version.hpp"
00042 
00048 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned DATA_SIZE>
00049 class AbstractPerElementWriter
00050 {
00051 private:
00052     bool mFileIsBinary;  
00054 protected:
00058     AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* mpMesh;
00059 
00064     out_stream mpMasterFile;
00065 
00074     virtual void Visit(Element<ELEMENT_DIM, SPACE_DIM>* pElement,
00075                        unsigned localElementIndex,
00076                        c_vector<double, DATA_SIZE>& rData)=0;
00077 
00085     virtual void WriteElementOnMaster(const c_vector<double, DATA_SIZE>& rData)
00086     {
00087         if (mFileIsBinary)
00088         {
00089             //The binary file is row-major
00090             mpMasterFile->write((char*)&rData[0], DATA_SIZE*sizeof(double));
00091         }
00092         else
00093         {
00094             for (unsigned i=0; i<DATA_SIZE; i++)
00095             {
00096                 (*mpMasterFile) << rData[i] << "\t";
00097             }
00098             (*mpMasterFile)<<"\n";
00099         }
00100     }
00101 
00109     virtual void WriteHeaderOnMaster()
00110     {
00111     }
00112 
00119     virtual void PreWriteCalculations(OutputFileHandler& rOutputDirectory)
00120     {
00121     }
00122 
00123 public:
00124 
00130     AbstractPerElementWriter(AbstractTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>* pMesh)
00131      : mFileIsBinary(false),
00132        mpMesh(pMesh),
00133        mpMasterFile(NULL)
00134     {
00135 
00136     }
00137 
00149     void WriteData(OutputFileHandler& rHandler, const std::string& rFileName)
00150     {
00151         PreWriteCalculations(rHandler);
00152 
00153         c_vector<double, DATA_SIZE> data;
00154         if (PetscTools::AmMaster())
00155         {
00156             mpMasterFile = rHandler.OpenOutputFile(rFileName);
00157             MPI_Status status;
00158             status.MPI_ERROR = MPI_SUCCESS; //For MPICH2
00159             WriteHeaderOnMaster();
00160             // say whether the fibres are binary in the header line (not ended yet!)
00161             if (mFileIsBinary)
00162             {
00163                 *mpMasterFile << "\tBIN\n";
00164             }
00165             else
00166             {
00167                 *mpMasterFile << "\n";
00168             }
00169             // The master process needs to keep track of both the global element list
00170             // (so that all elements are concentrated) and the local element list (so that
00171             // a local element index can be applied
00172             unsigned local_element_index=0u; //Data invariant associates iter with local_element_index
00173             typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator iter = mpMesh->GetElementIteratorBegin();
00174 
00175             for (unsigned global_element_index=0; global_element_index<mpMesh->GetNumElements(); global_element_index++)
00176             {
00177                 if (mpMesh->CalculateDesignatedOwnershipOfElement(global_element_index))
00178                 {
00179                     Element<ELEMENT_DIM,SPACE_DIM>* p_elem = mpMesh->GetElement(global_element_index);
00180                     //Spool forward in the local vector of elements
00181                     while (&(*iter) != p_elem)
00182                     {
00183                         ++iter;
00184                         local_element_index++;
00185                         assert(iter != mpMesh->GetElementIteratorEnd());
00186                     }
00187                     //Master owns this process and can write it directly
00188                     Visit(p_elem, local_element_index, data);
00189                 }
00190                 else
00191                 {
00192                     //Data must come from a remote process
00193                     MPI_Recv(&data[0], DATA_SIZE, MPI_DOUBLE, MPI_ANY_SOURCE, global_element_index, PETSC_COMM_WORLD, &status);
00194                 }
00195                 WriteElementOnMaster(data);
00196             }
00197             *mpMasterFile << "# "<<ChasteBuildInfo::GetProvenanceString();
00198             mpMasterFile->close();
00199         }
00200         else
00201         {
00202             //Not master process
00203             unsigned previous_index = 0u; //Used to check that the indices are monotone
00204             unsigned local_index = 0u;
00205             for (typename AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>::ElementIterator iter = mpMesh->GetElementIteratorBegin();
00206                           iter != mpMesh->GetElementIteratorEnd();
00207                           ++iter, local_index++)
00208             {
00209                 unsigned element_index = iter->GetIndex();
00210                 //Check monotonicity
00211                 if (previous_index>0u)
00212                 {
00213                     assert(element_index > previous_index);
00214                 }
00215                 previous_index = element_index;
00216                 if (mpMesh->CalculateDesignatedOwnershipOfElement(element_index))
00217                 {
00218                     // The master needs to know about this one.
00219                     Visit(&(*iter), local_index, data);
00221                     MPI_Ssend(&data[0], DATA_SIZE, MPI_DOUBLE, 0, element_index, PETSC_COMM_WORLD);//Tag with element_index
00222                 }
00223             }
00224 
00225         }
00226     }
00227 
00235      void SetWriteFileAsBinary(bool binary=true)
00236      {
00237          mFileIsBinary = binary;
00238      }
00239 
00243     virtual ~AbstractPerElementWriter()
00244     {
00245     }
00246 };
00247 
00248 
00249 #endif /*ABSTRACTPERELEMENTWRITER_HPP_*/

Generated by  doxygen 1.6.2