diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 9ed16be..62d9b84 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -9,24 +9,22 @@ on: # '*' is a special character in YAML, so string must be quoted - cron: "0 1 * * *" env: - PETSC_ARCH: linux-gnu-real-32 + PETSC_ARCH: linux-gnu-real64-32 jobs: build: - if: "!(contains(github.event.head_commit.message, '[ci skip]') || contains(github.event.head_commit.message, '[skip ci]'))" runs-on: ubuntu-latest - container: fenicsproject/test-env:nightly-mpich - + container: ghcr.io/fenics/test-env:v0.7.2-mpich steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Get Basix - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./basix repository: FEniCS/basix - ref: main + ref: v0.7.0 - name: Install UFL, Basix, FFCx run: | @@ -34,15 +32,15 @@ jobs: cmake --build build-basix --parallel 3 cmake --install build-basix BUILD_TYPE="Release" pip3 install ./basix/python - python3 -m pip install git+https://github.com/FEniCS/ufl.git - python3 -m pip install git+https://github.com/FEniCS/ffcx.git + python3 -m pip install git+https://github.com/FEniCS/ufl.git@2023.2.0 + python3 -m pip install git+https://github.com/FEniCS/ffcx.git@v0.7.0 - name: Get DOLFINx - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: ./dolfinx repository: FEniCS/dolfinx - ref: main + ref: v0.7.2 - name: Configure C++ (dolfinx) run: | diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9f3331 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +**/*build-dir*/** +__pycache__ +*.egg-info +*.bp \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b094b2f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Joseph P. Dean + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/convergence.py b/convergence.py index f551878..6b4952b 100644 --- a/convergence.py +++ b/convergence.py @@ -13,7 +13,7 @@ # Problem create_problem = problems.create_problem_0 # Characteristic element size -hs = [1 / 4, 1 / 8] +hs = [1 / 2, 1 / 4, 1 / 8] # Polynomial orders ks = [1, 2, 3, 4] # Coefficients diff --git a/cpp/README.md b/cpp/README.md index bbd02b8..39dd9cb 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -2,15 +2,49 @@ ## Muelu Trilinos Demo To compile, first install FEniCS-X dolfinx (real or complex) -and Trilinos (an example build script is in builder.sh) +and [Trilinos](https://github.com/trilinos/Trilinos.git) (an example build script is in builder.sh) +1. Clone trilinos from their github and checkout the correct version: +```bash +git clone https://github.com/trilinos/Trilinos.git +cd Trilinos +git checkout trilinos-release-13-4-1 +``` +2. Buld trilinos +```bash +cmake -G Ninja -B build-dir-trilinos \ + -DTPL_ENABLE_MPI=ON \ + -DMPI_BASE_DIR=/usr/x86_64-linux/ \ + -DTrilinos_ENABLE_COMPLEX_DOUBLE=ON \ + -DTrilinos_ENABLE_MueLu=ON \ + -DTrilinos_ENABLE_TrilinosCouplings=ON \ + -DTrilinos_ENABLE_Teko=OFF \ + -DTpetra_INST_INT_LONG=ON \ + -DTpetra_INST_INT_LONG_LONG=OFF \ + -DBUILD_SHARED_LIBS=ON \ + -DTrilinos_ENABLE_PyTrilinos=OFF \ + -DTPL_ENABLE_Netcdf=OFF \ + . +ninja -j8 -C build-dir-trilinos + +``` + +3. Compile integration kernels For real -`ffcx --scalar_type=double maxwell.ufl` +```bash +python3 -m ffcx --scalar_type=double maxwell.py +``` or for complex -`ffcx --scalar_type="double complex" maxwell.ufl` +```bash +python3 -m ffcx --scalar_type="double complex" maxwell.py +``` + +4. Compile demo -cmake . -make +```bash +cmake -G Ninja -B build-dir -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fmax-errors=1" +ninja -j8 -C build-dir +``` diff --git a/cpp/builder.sh b/cpp/builder.sh index b7057df..9ef6a84 100644 --- a/cpp/builder.sh +++ b/cpp/builder.sh @@ -1,15 +1,16 @@ #!/bin/bash -rm -r build -mkdir -p build -cd build -cmake -DTPL_ENABLE_MPI=ON \ +# Based on trilinos released: trilinos-release-13.4.1 +cmake -B build-dir-trilinos \ + -DTPL_ENABLE_MPI=ON \ -DMPI_BASE_DIR=/usr/x86_64-linux/ \ -DTrilinos_ENABLE_COMPLEX_DOUBLE=ON \ -DTrilinos_ENABLE_MueLu=ON \ -DTrilinos_ENABLE_TrilinosCouplings=ON \ - -DTpetra_INST_INT_LONG_LONG=OFF \ + -DTrilinos_ENABLE_Teko=OFF \ -DTpetra_INST_INT_LONG=ON \ + -DTpetra_INST_INT_LONG_LONG=OFF \ -DBUILD_SHARED_LIBS=ON \ -DTrilinos_ENABLE_PyTrilinos=OFF \ -DTPL_ENABLE_Netcdf=OFF \ -DCMAKE_INSTALL_PREFIX=/home/chris/packages/trilinos .. + . diff --git a/cpp/main.cpp b/cpp/main.cpp index 618fc3e..0caa9f9 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -1,9 +1,7 @@ #include "lumping.h" #include "maxwell.h" -#include "tpetra_util.h" - -#include +#include "tpetra_util.h" #include < MatrixMarket_Tpetra.hpp> #include #include #include @@ -28,7 +26,8 @@ void tpetra_assemble(Teuchos::RCP> A_Tpetra, - const fem::Form &form) { + const fem::Form &form) +{ std::vector global_cols; // temp for columns const std::shared_ptr V = form.function_spaces()[0]; @@ -41,36 +40,42 @@ void tpetra_assemble(Teuchos::RCP data_view(data + i * nc, nc); - if (rows[i] < nlocalrows) { - Teuchos::ArrayView col_view(cols, nc); - int nvalid = - A_Tpetra->sumIntoLocalValues(rows[i], col_view, data_view); - if (nvalid != nc) - throw std::runtime_error("Inserted " + std::to_string(nvalid) + - "/" + std::to_string(nc) + " on row:" + - std::to_string(global_indices[rows[i]])); - } else { - global_cols.resize(nc); - for (int j = 0; j < nc; ++j) - global_cols[j] = global_indices[cols[j]]; - int nvalid = A_Tpetra->sumIntoGlobalValues(global_indices[rows[i]], - global_cols, data_view); - if (nvalid != nc) - throw std::runtime_error("Inserted " + std::to_string(nvalid) + - "/" + std::to_string(nc) + " on row:" + - std::to_string(global_indices[rows[i]])); - } - } - return 0; - }; + const PetscScalar *data) + { + for (std::int32_t i = 0; i < nr; ++i) + { + Teuchos::ArrayView data_view(data + i * nc, nc); + if (rows[i] < nlocalrows) + { + Teuchos::ArrayView col_view(cols, nc); + int nvalid = + A_Tpetra->sumIntoLocalValues(rows[i], col_view, data_view); + if (nvalid != nc) + throw std::runtime_error("Inserted " + std::to_string(nvalid) + + "/" + std::to_string(nc) + " on row:" + + std::to_string(global_indices[rows[i]])); + } + else + { + global_cols.resize(nc); + for (int j = 0; j < nc; ++j) + global_cols[j] = global_indices[cols[j]]; + int nvalid = A_Tpetra->sumIntoGlobalValues(global_indices[rows[i]], + global_cols, data_view); + if (nvalid != nc) + throw std::runtime_error("Inserted " + std::to_string(nvalid) + + "/" + std::to_string(nc) + " on row:" + + std::to_string(global_indices[rows[i]])); + } + } + return 0; + }; fem::assemble_matrix(tpetra_insert, form, {}); } -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ common::subsystem::init_mpi(argc, argv); common::subsystem::init_logging(argc, argv); @@ -121,7 +126,8 @@ int main(int argc, char **argv) { create_tpetra_diagonal_matrix(Q->dofmap()->index_map); std::vector col(1); std::vector val(1); - for (int i = 0; i < Q->dofmap()->index_map->size_local(); ++i) { + for (int i = 0; i < Q->dofmap()->index_map->size_local(); ++i) + { col[0] = i; val[0] = 1.0 / vals[i]; Mg_mat->replaceLocalValues(i, col, val); @@ -135,14 +141,16 @@ int main(int argc, char **argv) { std::function mat_set_dg = [&D0_mat](int nr, const int *rows, int nc, const int *cols, - const PetscScalar *data) { - for (int i = 0; i < nr; ++i) { - Teuchos::ArrayView data_view(data + i * nc, nc); - Teuchos::ArrayView col_view(cols, nc); - D0_mat->replaceLocalValues(rows[i], col_view, data_view); - } - return 0; - }; + const PetscScalar *data) + { + for (int i = 0; i < nr; ++i) + { + Teuchos::ArrayView data_view(data + i * nc, nc); + Teuchos::ArrayView col_view(cols, nc); + D0_mat->replaceLocalValues(rows[i], col_view, data_view); + } + return 0; + }; fem::assemble_discrete_gradient(mat_set_dg, *V, *Q); D0_mat->fillComplete(); @@ -153,10 +161,12 @@ int main(int argc, char **argv) { new Tpetra::MultiVector( Mg_mat->getRowMap(), 3)); fem::Function xcoord(Q); - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { common::Timer time_interpolate("Interpolate x"); xcoord.interpolate( - [&j](const xt::xtensor &x) -> xt::xarray { + [&j](const xt::xtensor &x) -> xt::xarray + { return xt::row(x, j); }); time_interpolate.stop(); @@ -168,7 +178,8 @@ int main(int argc, char **argv) { bool write_files = false; - if (write_files) { + if (write_files) + { common::Timer tw("Tpetra: write files"); Tpetra::MatrixMarket::Writer< Tpetra::CrsMatrix>:: diff --git a/cpp/maxwell.ufl b/cpp/maxwell.py similarity index 52% rename from cpp/maxwell.ufl rename to cpp/maxwell.py index 6c8aac0..ead892b 100644 --- a/cpp/maxwell.ufl +++ b/cpp/maxwell.py @@ -1,3 +1,19 @@ +from ufl import ( + VectorElement, + FiniteElement, + Mesh, + SpatialCoordinate, + as_vector, + TrialFunction, + TestFunction, + inner, + curl, + dx, + FunctionSpace, + tetrahedron, + pi, + cos, +) coord_element = VectorElement("Lagrange", tetrahedron, 1) mesh = Mesh(coord_element) @@ -9,15 +25,15 @@ # T_0 = Coefficient(element) x = SpatialCoordinate(mesh) -T_0 = as_vector((- pi * cos(x[2] * pi) / mu, - - pi * cos(x[0] * pi) / mu, - - pi * cos(x[1] * pi) / mu)) +T_0 = as_vector( + (-pi * cos(x[2] * pi) / mu, -pi * cos(x[0] * pi) / mu, -pi * cos(x[1] * pi) / mu) +) A = TrialFunction(Q) v = TestFunction(Q) -Kc = inner(1 / mu * curl(A), curl(v)) * dx + 1e-8 * inner(A, v)*dx -Mc = inner(A, v)*dx +Kc = inner(1 / mu * curl(A), curl(v)) * dx + 1e-8 * inner(A, v) * dx +Mc = inner(A, v) * dx L = inner(T_0, curl(v)) * dx Hgrad_element = FiniteElement("Lagrange", tetrahedron, 1) @@ -26,4 +42,4 @@ v = TestFunction(V) Mg = inner(u, v) * dx -forms = [Kc, Mc, Mg, L] \ No newline at end of file +forms = [Kc, Mc, Mg, L] diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..78c7144 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,32 @@ +[build-system] # Require setuptool version due to https://github.com/pypa/setuptools/issues/2938 +requires = ["setuptools>=64.4.0", "wheel", "pip>=22.3"] + +[project] +name = "maxwell_problems" +version = "0.7.0" +description = "Implementation for solving Maxwell-problems with DOLFINx" +authors = [ + { name = "Joseph P. Dean", email="jpd62@eng.cam.ac.uk"}, + { name = "Jørgen S. Dokken", email = "dokken@simula.no" }] +license = { file = "LICENSE" } +readme = "README.md" +dependencies = ["fenics-dolfinx>=0.7.0"] + +[tool.setuptools] +packages = [] + +[project.optional-dependencies] +test = ["pytest", "coverage"] +dev = ["pdbpp", "ipython", "mypy", "flake8"] +all = ["adios4dolfinx[test,dev]"] + +[tool.pytest.ini_options] +addopts = ["--import-mode=importlib"] +testpaths = ["tests"] + +[tool.mypy] +ignore_missing_imports = true +# Folders to exclude +exclude = ["build/"] +# Folder to check with mypy +files = ["src", "tests"]