diff --git a/AMDiS/CMakeLists.txt b/AMDiS/CMakeLists.txt index 971e990c48dd39670478afae58ae88f26b9f3953..4c77ee6a2e57fbe6a6582a4f70871b3706020207 100644 --- a/AMDiS/CMakeLists.txt +++ b/AMDiS/CMakeLists.txt @@ -162,6 +162,7 @@ SET(AMDIS_SRC ${SOURCE_DIR}/AdaptBase.cc ${SOURCE_DIR}/io/PngReader.cc ${SOURCE_DIR}/io/PngWriter.cc ${SOURCE_DIR}/io/PovrayWriter.cc + ${SOURCE_DIR}/io/Spreadsheet.cc ${SOURCE_DIR}/io/ValueReader.cc ${SOURCE_DIR}/io/ValueWriter.cc ${SOURCE_DIR}/io/VtkWriter.cc diff --git a/AMDiS/src/AMDiS.h b/AMDiS/src/AMDiS.h index dc878e1d8f5786a0ce08a25d9ba9390743a19575..2df55bcdca8dd2f8fb20d8f163f62c73a0b51305 100644 --- a/AMDiS/src/AMDiS.h +++ b/AMDiS/src/AMDiS.h @@ -122,6 +122,7 @@ #include "io/MacroWriter.h" #include "io/PngWriter.h" #include "io/PovrayWriter.h" +#include "io/Spreadsheet.h" #include "io/ValueReader.h" #include "io/ValueWriter.h" #include "io/VtkWriter.h" diff --git a/AMDiS/src/io/DofWriter.cc b/AMDiS/src/io/DofWriter.cc index 788165cde1b218fd32bb5ffa8dc5e53218edfb6e..02b6593734960314b761d9524e18bffb5b8741e7 100644 --- a/AMDiS/src/io/DofWriter.cc +++ b/AMDiS/src/io/DofWriter.cc @@ -16,7 +16,9 @@ namespace AMDiS { - void DofWriter::writeFile(std::string filename, std::vector<DOFVector<double>*> &vec) + using namespace std; + + void DofWriter::writeFile(string filename, vector<DOFVector<double>*> &vec) { FUNCNAME("DofWriter::writeFile()"); @@ -25,13 +27,14 @@ namespace AMDiS { Mesh *mesh = feSpace->getMesh(); const BasisFunction* basFcts = feSpace->getBasisFcts(); int nBasFcts = basFcts->getNumber(); - std::vector<DegreeOfFreedom> dofVec(nBasFcts); + vector<DegreeOfFreedom> dofVec(nBasFcts); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS); while (elInfo) { - basFcts->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), dofVec); + basFcts->getLocalIndices(elInfo->getElement(), + feSpace->getAdmin(), dofVec); for (int i = 0; i < nBasFcts; i++) { DimVec<double> *baryCoords = basFcts->getCoords(i); elInfo->coordToWorld(*baryCoords, coordDof[dofVec[i]]); @@ -40,7 +43,7 @@ namespace AMDiS { elInfo = stack.traverseNext(elInfo); } - std::ofstream outfile; + ofstream outfile; outfile.open(filename.c_str()); outfile.precision(10); @@ -53,7 +56,7 @@ namespace AMDiS { for (unsigned int i = 0; i < vec.size(); i++) outfile << (*(vec[i]))[it.getDOFIndex()] << " "; - outfile << std::endl; + outfile << endl; } outfile.close(); diff --git a/AMDiS/src/io/Spreadsheet.cc b/AMDiS/src/io/Spreadsheet.cc new file mode 100644 index 0000000000000000000000000000000000000000..5cb39df11ceebf3a60061c0b99107a179b80c1f7 --- /dev/null +++ b/AMDiS/src/io/Spreadsheet.cc @@ -0,0 +1,88 @@ +// +// Software License for AMDiS +// +// Copyright (c) 2010 Dresden University of Technology +// All rights reserved. +// Authors: Simon Vey, Thomas Witkowski et al. +// +// This file is part of AMDiS +// +// See also license.opensource.txt in the distribution. + + +#include <algorithm> +#include <fstream> +#include <boost/algorithm/string.hpp> +#include <boost/lexical_cast.hpp> +#include "Spreadsheet.h" +#include "Global.h" + +namespace AMDiS { + + using namespace std; + using namespace boost; + + using boost::lexical_cast; + + void Spreadsheet::write(string filename) + { + int nRows = static_cast<int>(data.size()); + int maxDataLength = 0; + + for (int i = 0; i < nRows; i++) + maxDataLength = std::max(maxDataLength, static_cast<int>(data[i].size())); + + for (int i = 0; i < nRows; i++) + data[i].resize(maxDataLength, 0.0); + + ofstream file; + file.open(filename.c_str()); + + for (int i = 0; i < nRows; i++) { + for (int j = 0; j < maxDataLength; j++) { + file << data[i][j]; + if (j + 1 < maxDataLength) + file << " "; + else + file << "\n"; + } + } + + file.close(); + } + + + void Spreadsheet::read(string filename) + { + data.clear(); + + string line; + vector<string> lineSplit; + + ifstream file; + file.open(filename.c_str()); + + while (!file.eof()) { + getline(file, line); + split(lineSplit, line, is_any_of(" ,")); + + if (lineSplit.size() == 0) + continue; + + if ((lineSplit.size() == 1) && (lineSplit[0] == "")) + continue; + + if (lineSplit[0].find("#") == 0) + continue; + + vector<double> lineData(lineSplit.size()); + for (unsigned int i = 0; i < lineSplit.size(); i++) + lineData[i] = lexical_cast<double>(lineSplit[i]); + + data.push_back(lineData); + } + + file.close(); + } + +} diff --git a/AMDiS/src/io/Spreadsheet.h b/AMDiS/src/io/Spreadsheet.h new file mode 100644 index 0000000000000000000000000000000000000000..795c6bd9a8059d87ed9c9c76d14c836015a5507d --- /dev/null +++ b/AMDiS/src/io/Spreadsheet.h @@ -0,0 +1,77 @@ +// ============================================================================ +// == == +// == Amdis - Adaptive multidimensional simulations == +// == == +// == http://www.amdis-fem.org == +// == == +// ============================================================================ +// +// Software License for AMDiS +// +// Copyright (c) 2010 Dresden University of Technology +// All rights reserved. +// Authors: Simon Vey, Thomas Witkowski et al. +// +// This file is part of AMDiS +// +// See also license.opensource.txt in the distribution. + + + +/** \file Spreadsheet.h */ + +#ifndef AMDIS_SPREADSHEET_H +#define AMDIS_SPREADSHEET_H + +#include <vector> +#include <string> + +namespace AMDiS { + + using namespace std; + + /** + * \brief + * Implements basic support to read and write tables of data (all are + * assumed to be of type double. The files are written in ASCII mode and + * allow to use comments (lines that start with #). + */ + class Spreadsheet + { + public: + typedef vector<vector<double> > DataType; + + Spreadsheet() + : data(0) + {} + + void addData(vector<double> &d) + { + data.push_back(d); + } + + void addData(DataType &d) + { + data.insert(data.end(), d.begin(), d.end()); + } + + void setData(DataType &d) + { + data = d; + } + + DataType& getData() + { + return data; + } + + void write(string filename); + + void read(string filename); + + protected: + DataType data; + }; +} + +#endif diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index 29be59ba6d154a4cdf3a52a108974e4a4ccc1a90..27be4794c97d38598f0716d9f9711e896ef96d20 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -168,26 +168,11 @@ namespace AMDiS { return feSpaces; } - /** \brief - * Returns the number of DOFs in rank's domain for a given FE space. - * - * \param[in] feSpace If the FE space is defined, the function returns - * the number of DOFs for this FE space. If this - * parameter is not specified, the function assumes - * that there is only one FE space and returns the - * number of DOFs for this one. - */ - inline int getNumberRankDofs(const FiniteElemSpace *feSpace = NULL) + /// Returns the number of DOFs in rank's domain for a given FE space. + inline int getNumberRankDofs(const FiniteElemSpace *feSpace) { FUNCNAME("MeshDistributor::getNumberRankDofs()"); - if (feSpace == NULL) { - TEST_EXIT_DBG(dofFeData.size() == 1) - ("More than one FE space defined!\n"); - - return dofFeData.begin()->second.nRankDofs; - } - TEST_EXIT_DBG(dofFeData.count(feSpace))("Should not happen!\n"); return dofFeData[feSpace].nRankDofs; @@ -232,26 +217,11 @@ namespace AMDiS { return result; } - /** \brief - * Returns the global number of DOFs for a given FE space. - * - * \param[in] feSpace If the FE space is defined, the function returns - * the number of DOFs for this FE space. If this - * parameter is not specified, the function assumes - * that there is only one FE space and returns the - * number of DOFs for this one. - */ - inline int getNumberOverallDofs(const FiniteElemSpace *feSpace = NULL) + /// Returns the global number of DOFs for a given FE space. + inline int getNumberOverallDofs(const FiniteElemSpace *feSpace) { FUNCNAME("MeshDistributor::getNumberOverallDofs()"); - if (feSpace == NULL) { - TEST_EXIT_DBG(dofFeData.size() == 1) - ("More than one FE space defined!\n"); - - return dofFeData.begin()->second.nOverallDofs; - } - TEST_EXIT_DBG(dofFeData.count(feSpace))("Should not happen!\n"); return dofFeData[feSpace].nOverallDofs; diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index 6918f7c5dc64ace0c7d0e791dd660875ca5eb1cf..e0ab38be8ab1c088b39391ce79383c8081cceece 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -228,8 +228,19 @@ namespace AMDiS { TEST_EXIT_DBG(meshLevel + 1 == meshDistributor->getMeshLevelData().getLevelNumber()) ("Mesh hierarchy does not contain %d levels!\n", meshLevel + 1); - if (subDomainSolver == NULL) - subDomainSolver = new SubDomainSolver(meshDistributor, mpiComm, mpiSelfComm); + if (subDomainSolver == NULL) { + if (meshLevel == 0) { + subDomainSolver = + new SubDomainSolver(meshDistributor, mpiComm, mpiSelfComm); + } else { + MeshLevelData& levelData = meshDistributor->getMeshLevelData(); + + subDomainSolver = + new SubDomainSolver(meshDistributor, + levelData.getMpiComm(meshLevel - 1), + levelData.getMpiComm(meshLevel)); + } + } primalDofMap.init(mpiComm, feSpaces, meshDistributor->getFeSpaces(), true, true); @@ -375,10 +386,8 @@ namespace AMDiS { for (DofComm::Iterator it(meshDistributor->getSendDofs(), meshLevel, feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) - if (!isPrimal(feSpace, it.getDofIndex())) { - MSG("SEND TO RANK %d\n", it.getRank()); + if (!isPrimal(feSpace, it.getDofIndex())) stdMpi.getSendData(it.getRank()).push_back(boundaryDofRanks[feSpace][it.getDofIndex()]); - } stdMpi.updateSendDataSize(); @@ -388,7 +397,6 @@ namespace AMDiS { for (; !it.endDofIter(); it.nextDof()) { if (!isPrimal(feSpace, it.getDofIndex())) { recvFromRank = true; - MSG("RECV FROM RANK %d\n", it.getRank()); break; } } diff --git a/AMDiS/src/parallel/PetscSolverFeti.h b/AMDiS/src/parallel/PetscSolverFeti.h index 38de4e8e1414ac22663efe0b327578c13a1ebef6..4853314d19cda5ac4af864d2fe8e4f4b02f4c6c7 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.h +++ b/AMDiS/src/parallel/PetscSolverFeti.h @@ -83,11 +83,21 @@ namespace AMDiS { return primalDofMap.getOverallDofs(); } + int getNumberOfRankPrimals() + { + return primalDofMap.getRankDofs(); + } + int getNumberOfDuals() { return dualDofMap.getOverallDofs(); } + int getNumberOfRankDuals() + { + return dualDofMap.getRankDofs(); + } + protected: /// Defines which boundary nodes are primal. Creates global index of /// the primal variables. diff --git a/test/mpi/src/test0002.cc b/test/mpi/src/test0002.cc index fe62ba2684d7780deae7a5a6c83462ef7f0d3e79..c8135eb350b43fe51be22987f2624103272066bb 100644 --- a/test/mpi/src/test0002.cc +++ b/test/mpi/src/test0002.cc @@ -36,6 +36,41 @@ BOOST_AUTO_TEST_CASE(amdis_mpi_feti) BOOST_REQUIRE(feti.getNumberOfPrimals() == 21); BOOST_REQUIRE(feti.getNumberOfDuals() == 48); + + + + Spreadsheet sheet; + sheet.read("data/data0002a"); + vector<double> data = sheet.getData()[MPI::COMM_WORLD.Get_rank()]; + + const FiniteElemSpace *feSpace = ellipt.getFeSpace(0); + vector<double> testData; + testData.push_back(feti.getNumberOfRankPrimals()); + testData.push_back(feti.getNumberOfRankDuals()); + testData.push_back(meshDist->getNumberRankDofs(feSpace)); + testData.push_back(meshDist->getStartDofs(feSpace)); + testData.push_back(meshDist->getNumberOverallDofs(feSpace)); + + BOOST_REQUIRE(data.size() - 1 == testData.size()); + BOOST_REQUIRE(equal(data.begin() + 1, data.end(), testData.begin())); + + ellipt.getRefinementManager()->globalRefine(mesh, 6); + meshDist->checkMeshChange(); + feti.createFetiData(); + + + + sheet.read("data/data0002b"); + data = sheet.getData()[MPI::COMM_WORLD.Get_rank()]; + testData.clear(); + testData.push_back(feti.getNumberOfRankPrimals()); + testData.push_back(feti.getNumberOfRankDuals()); + testData.push_back(meshDist->getNumberRankDofs(feSpace)); + testData.push_back(meshDist->getStartDofs(feSpace)); + testData.push_back(meshDist->getNumberOverallDofs(feSpace)); + + BOOST_REQUIRE(data.size() - 1 == testData.size()); + BOOST_REQUIRE(equal(data.begin() + 1, data.end(), testData.begin())); }