diff --git a/cpppetsc/src/include/ae108/cpppetsc/Mesh.h b/cpppetsc/src/include/ae108/cpppetsc/Mesh.h index c177ecbc901de195feab8db67286fc1f9cc48083..df317804539890e0e5a78db577b8dd0d6f9f6c80 100644 --- a/cpppetsc/src/include/ae108/cpppetsc/Mesh.h +++ b/cpppetsc/src/include/ae108/cpppetsc/Mesh.h @@ -15,7 +15,6 @@ #pragma once -#include "ae108/cpppetsc/InvalidParametersException.h" #include "ae108/cpppetsc/IteratorRange.h" #include "ae108/cpppetsc/LocalElementIterator.h" #include "ae108/cpppetsc/LocalElementView.h" @@ -84,17 +83,6 @@ public: Mesh cloneWithDofs(const size_type dofPerVertex, const size_type dofPerElement) const; - /** - * @brief Set the coordinates of the vertices of the mesh. - * - * @param coordinates A vector with dimension number of degrees of freedom per - * vertex. - * - * @throw InvalidParametersException The vector was not created from a mesh - * describing its layout. - */ - void setCoordinates(distributed<vector_type> coordinates); - /** * @brief Makes it possible to iterate over (views of) the local elements. */ @@ -495,23 +483,6 @@ template <class Policy> UniqueEntity<DM> Mesh<Policy>::createDM() { return makeUniqueEntity<Policy>(dm); } -template <class Policy> -void Mesh<Policy>::setCoordinates(distributed<vector_type> coordinates) { - const auto coordinateDM = [&]() { - auto dm = DM{}; - Policy::handleError(VecGetDM(coordinates.unwrap().data(), &dm)); - return dm; - }(); - - if (!coordinateDM) { - throw InvalidParametersException(); - } - - Policy::handleError(DMSetCoordinateDM(_mesh.get(), coordinateDM)); - Policy::handleError( - DMSetCoordinates(_mesh.get(), coordinates.unwrap().data())); -} - template <class Policy> typename Mesh<Policy>::size_type Mesh<Policy>::totalNumberOfVertices() const { return _totalNumberOfVertices; diff --git a/cpppetsc/src/include/ae108/cpppetsc/writeToViewer.h b/cpppetsc/src/include/ae108/cpppetsc/writeToViewer.h index 10e4e82a860ea3961e4c42ef466a4930f85d168a..6ad9f0d1bd73e4d69b6bccb60b3013e5fdf08ff0 100644 --- a/cpppetsc/src/include/ae108/cpppetsc/writeToViewer.h +++ b/cpppetsc/src/include/ae108/cpppetsc/writeToViewer.h @@ -15,7 +15,6 @@ #pragma once -#include "ae108/cpppetsc/InvalidParametersException.h" #include "ae108/cpppetsc/Mesh_fwd.h" #include "ae108/cpppetsc/ParallelComputePolicy_fwd.h" #include "ae108/cpppetsc/SequentialComputePolicy_fwd.h" @@ -29,32 +28,35 @@ namespace cpppetsc { /** * @brief Writes a mesh to a Viewer. - * - * @throw InvalidParametersException if the coordinates of `mesh` are not set. */ template <class Policy> -void writeToViewer(const Mesh<Policy> &mesh, const Viewer<Policy> &viewer); +void writeToViewer(const Mesh<Policy> &mesh, + const distributed<Vector<Policy>> &coordinates, + const Viewer<Policy> &viewer); /** - * @brief Writes a vector to a Viewer. - * - * @throw InvalidParametersException if the `data` vector has no associated mesh - * or if the coordinates of this mesh are not set. + * @brief Writes a vector to a Viewer. The concrete format depends on the file + * extension (vtk/vtu). */ template <class Policy> void writeToViewer(const distributed<Vector<Policy>> &data, + const distributed<Vector<Policy>> &coordinates, const Viewer<Policy> &viewer); -extern template void -writeToViewer<SequentialComputePolicy>(const Mesh<SequentialComputePolicy> &, - const Viewer<SequentialComputePolicy> &); -extern template void -writeToViewer<ParallelComputePolicy>(const Mesh<ParallelComputePolicy> &, - const Viewer<ParallelComputePolicy> &); extern template void writeToViewer<SequentialComputePolicy>( + const Mesh<SequentialComputePolicy> &, + const distributed<Vector<SequentialComputePolicy>> &, + const Viewer<SequentialComputePolicy> &); +extern template void writeToViewer<ParallelComputePolicy>( + const Mesh<ParallelComputePolicy> &, + const distributed<Vector<ParallelComputePolicy>> &, + const Viewer<ParallelComputePolicy> &); +extern template void writeToViewer<SequentialComputePolicy>( + const distributed<Vector<SequentialComputePolicy>> &, const distributed<Vector<SequentialComputePolicy>> &, const Viewer<SequentialComputePolicy> &); extern template void writeToViewer<ParallelComputePolicy>( + const distributed<Vector<ParallelComputePolicy>> &, const distributed<Vector<ParallelComputePolicy>> &, const Viewer<ParallelComputePolicy> &); @@ -66,47 +68,71 @@ extern template void writeToViewer<ParallelComputePolicy>( namespace ae108 { namespace cpppetsc { -namespace detail { -template <class Policy> void throwIfNoCoordinateDM(const DM dm) { - auto coordinateDM = DM{}; - Policy::handleError(DMGetCoordinateDM(dm, &coordinateDM)); - if (!coordinateDM) { - throw InvalidParametersException(); - } -} - -template <class Policy> void throwIfNoCoordinates(const DM dm) { - auto coordinates = Vec{}; - Policy::handleError(DMGetCoordinates(dm, &coordinates)); - if (!coordinates) { - throw InvalidParametersException(); - } -} -} // namespace detail template <class Policy> -void writeToViewer(const Mesh<Policy> &mesh, const Viewer<Policy> &viewer) { - detail::throwIfNoCoordinateDM<Policy>(mesh.data()); - detail::throwIfNoCoordinates<Policy>(mesh.data()); - Policy::handleError(DMView(mesh.data(), viewer.data())); +void writeToViewer(const Mesh<Policy> &mesh, + const distributed<Vector<Policy>> &coordinates, + const Viewer<Policy> &viewer) { + const auto coordinateDM = [&]() { + auto dm = DM{}; + Policy::handleError(VecGetDM(coordinates.unwrap().data(), &dm)); + assert(dm); + return UniqueEntity<DM>(dm, [](DM) {}); + }(); + + // copy the DM to be able to set the coordinate DM, which is + // required by DMView + auto dm = [&]() { + auto dm = DM{}; + Policy::handleError(DMClone(mesh.data(), &dm)); + return makeUniqueEntity<Policy>(dm); + }(); + Policy::handleError(DMSetCoordinateDM(dm.get(), coordinateDM.get())); + Policy::handleError(DMSetCoordinates(dm.get(), coordinates.unwrap().data())); + + Policy::handleError(DMView(dm.get(), viewer.data())); } template <class Policy> void writeToViewer(const distributed<Vector<Policy>> &data, + const distributed<Vector<Policy>> &coordinates, const Viewer<Policy> &viewer) { + const auto getDM = [](const Vector<Policy> &x) { + auto dm = DM{}; + Policy::handleError(VecGetDM(x.data(), &dm)); + assert(dm); + return UniqueEntity<DM>(dm, [](DM) {}); + }; + + // clone DM that defines the layout of the data vector + // to be able to set the coordinate DM const auto dm = [&]() { auto dm = DM{}; - Policy::handleError(VecGetDM(data.unwrap().data(), &dm)); - return dm; + const auto reference = getDM(data).get(); + Policy::handleError(DMClone(reference, &dm)); + return makeUniqueEntity<Policy>(dm); }(); - if (!dm) { - throw InvalidParametersException(); - } - detail::throwIfNoCoordinateDM<Policy>(dm); - detail::throwIfNoCoordinates<Policy>(dm); + // configure the default section to be able to create + // a copy of the data vector + auto section = PetscSection{}; + Policy::handleError(DMGetDefaultSection(getDM(data).get(), §ion)); + Policy::handleError(DMSetDefaultSection(dm.get(), section)); + + // set the coordinate DM which is required by VecView + const auto coordinateDM = getDM(coordinates); + Policy::handleError(DMSetCoordinateDM(dm.get(), coordinateDM.get())); + Policy::handleError(DMSetCoordinates(dm.get(), coordinates.unwrap().data())); + + // copy the data to the vector with the correct DM + const auto vec = [&]() { + auto vec = Vec{}; + Policy::handleError(DMCreateGlobalVector(dm.get(), &vec)); + return makeUniqueEntity<Policy>(vec); + }(); + Policy::handleError(VecCopy(data.unwrap().data(), vec.get())); - Policy::handleError(VecView(data.unwrap().data(), viewer.data())); + Policy::handleError(VecView(vec.get(), viewer.data())); } } // namespace cpppetsc diff --git a/cpppetsc/src/writeToViewer.cc b/cpppetsc/src/writeToViewer.cc index 54df94b4836f139721cac6f0609f3969d6179b08..4ba82311aca2d0bdb9fbe724ff09f1a1e5fb5589 100644 --- a/cpppetsc/src/writeToViewer.cc +++ b/cpppetsc/src/writeToViewer.cc @@ -20,16 +20,20 @@ namespace ae108 { namespace cpppetsc { -template void -writeToViewer<SequentialComputePolicy>(const Mesh<SequentialComputePolicy> &, - const Viewer<SequentialComputePolicy> &); -template void -writeToViewer<ParallelComputePolicy>(const Mesh<ParallelComputePolicy> &, - const Viewer<ParallelComputePolicy> &); template void writeToViewer<SequentialComputePolicy>( + const Mesh<SequentialComputePolicy> &, const distributed<Vector<SequentialComputePolicy>> &, const Viewer<SequentialComputePolicy> &); template void writeToViewer<ParallelComputePolicy>( + const Mesh<ParallelComputePolicy> &, + const distributed<Vector<ParallelComputePolicy>> &, + const Viewer<ParallelComputePolicy> &); +template void writeToViewer<SequentialComputePolicy>( + const distributed<Vector<SequentialComputePolicy>> &, + const distributed<Vector<SequentialComputePolicy>> &, + const Viewer<SequentialComputePolicy> &); +template void writeToViewer<ParallelComputePolicy>( + const distributed<Vector<ParallelComputePolicy>> &, const distributed<Vector<ParallelComputePolicy>> &, const Viewer<ParallelComputePolicy> &); diff --git a/cpppetsc/test/Mesh_Test.cc b/cpppetsc/test/Mesh_Test.cc index b49925b3d7c38bdb31c7daee6489563ee5565598..06d4d64695a3837c083229fcdb766dcb39c25516 100644 --- a/cpppetsc/test/Mesh_Test.cc +++ b/cpppetsc/test/Mesh_Test.cc @@ -113,9 +113,9 @@ template <typename T> struct Mesh_Test : Test { using Connectivity = std::vector<std::array<size_type, verticesPerElement>>; const Connectivity connectivity = {{0, 2}, {1, 2}, {0, 2}}; - mesh_type mesh = mesh_type::fromConnectivity(dimension, connectivity, - totalNumberOfVertices, - dofPerVertex, dofPerElement); + const mesh_type mesh = mesh_type::fromConnectivity( + dimension, connectivity, totalNumberOfVertices, dofPerVertex, + dofPerElement); }; template <class Policy, int VertexDof, int ElementDof> struct TestCase { @@ -139,28 +139,6 @@ TYPED_TEST(Mesh_Test, from_connectivity_generates_correct_number_of_entities) { Eq(this->totalNumberOfVertices)); } -TYPED_TEST(Mesh_Test, coordinates_can_be_set) { - using size_type = typename TestFixture::size_type; - using vector_type = typename TestFixture::vector_type; - - const auto coordinateMesh = - this->mesh.cloneWithDofs(this->dimension, size_type{0}); - auto coordinates = vector_type::fromGlobalMesh(coordinateMesh); - - EXPECT_NO_THROW(this->mesh.setCoordinates(std::move(coordinates))); -} - -TYPED_TEST(Mesh_Test, setting_coordinates_throws_if_not_associated_with_mesh) { - using size_type = typename TestFixture::size_type; - using vector_type = typename TestFixture::vector_type; - - auto coordinates = tag<DistributedTag>( - vector_type(this->totalNumberOfVertices * this->dofPerVertex)); - - EXPECT_THROW(this->mesh.setCoordinates(std::move(coordinates)), - InvalidParametersException); -} - TYPED_TEST(Mesh_Test, cloned_mesh_has_correct_number_of_entities) { using size_type = typename TestFixture::size_type;