Compare commits

...
Author SHA1 Message Date
Tucker Babcock cf8b8bc74e update removeinternalboundariesnotadjacentto 2020-11-21 17:29:02 -05:00
Tucker Babcock c0fbd3a2e3 added method to remove internal boundaries except for those adjacent to specified regions 2020-11-19 14:22:00 -05:00
Tucker Babcock 31a7a4a71f added new method to remove mesh internal boundaries except for those in a array of boundary attributes to keep 2020-11-19 13:37:58 -05:00
Veselin Dobrev ffc0a9ee7d Merge pull request #1873 from mfem/QuadratureFunction_size-fix
Quadrature function size fix
2020-11-18 13:15:43 -08:00
Tzanio Kolev 7083d53dd7 Merge pull request #1862 from mfem/new-umpire-fix
Fix for newer versions of Umpire [new-umpire-fix]
2020-11-18 13:06:45 -08:00
Tzanio Kolev 1b8fd5466e Merge pull request #1872 from mfem/cross-cross-dev
Implementing a missed c'tor in CrossCrossCoefficient [cross-cross-dev]
2020-11-18 12:59:49 -08:00
Tzanio Kolev 4e81be2155 Merge pull request #1878 from mfem/omp-deterministic-dot
Add a deterministic way of computing the dot product with OpenMP
2020-11-18 12:55:15 -08:00
Veselin Dobrev 95adb0d115 Merge pull request #1804 from mfem/jump-error
DG Jump Error Scaling
2020-11-18 12:53:43 -08:00
Stowell, Mark L 336ee95d26 Removing unimplemented method name 2020-11-17 11:52:10 -08:00
Veselin DobrevandTzanio Kolev ea01d71fb0 Update linalg/vector.cpp
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-11-16 15:09:58 -08:00
Veselin DobrevandTzanio Kolev 1b91c0c678 Update linalg/vector.cpp
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-11-16 15:09:51 -08:00
Veselin Dobrev 65f2add11d Add a deterministic way of computing the dot product with OpenMP 2020-11-15 21:18:31 -08:00
Tzanio Kolev 3bb3974bcb Merge pull request #1828 from mfem/cygwin-fixes
Cygwin fixes
2020-11-15 13:22:40 -08:00
Veselin Dobrev 1d1bacf965 Run 'make style' 2020-11-10 17:05:18 -08:00
Veselin Dobrev 0239bd42c0 Merge branch 'master' into jump-error 2020-11-10 16:53:37 -08:00
Gauthier Folzan 343e45e749 Update the doxygen documentation 2020-11-10 23:33:58 +01:00
Stowell, Mark L 81bbf1c998 Implementing a missed c'tor in CrossCrossCoefficient 2020-11-10 11:47:02 -08:00
Gauthier Folzan a12bc35350 Fix the size in the assertion 2020-11-10 15:51:33 +01:00
Tzanio Kolev 4645f97f0f Merge pull request #1864 from mfem/conduitdc-time-cycle-fix
Write time and cycle to conduit data collection root file [conduitdc-time-cycle-fix]
2020-11-08 13:32:32 -08:00
Tzanio Kolev 8ec9a6deda Merge pull request #1856 from mfem/mesh-bdrpoint-fix
Point Boundary for 1D Meshes
2020-11-08 13:31:46 -08:00
Tzanio 4c8c8bea49 Fix a merge 2020-11-03 13:18:27 -08:00
Tzanio Kolev 9345635954 Merge branch 'master' into cygwin-fixes 2020-11-03 12:45:20 -08:00
Tzanio Kolev 7cd6686e42 Merge pull request #1805 from mfem/navier-filter
Implementation of a filter method for Navier
2020-11-03 12:39:54 -08:00
Tzanio 4101b62099 Merge branch 'master' into navier-filter 2020-11-03 12:37:38 -08:00
Julian Andrej eb0df95218 changelog entry 2020-11-03 12:35:56 -08:00
Veselin Dobrev a828dbb5fe Merge pull request #1788 from mfem/mumps-solver
Interface with the distributed MUMPS solver
2020-11-03 10:38:51 -08:00
Veselin Dobrev 538ac3a6ab Merge branch 'master' into mumps-solver 2020-11-03 08:19:30 -08:00
Tzanio Kolev 3c0d346d0d Merge pull request #964 from mfem/RK_solvers
Added three ESDIRK schemes [RK_solvers]
2020-11-03 07:39:13 -08:00
Tzanio 4914e93d0f Merge branch 'master' into navier-filter 2020-11-03 07:38:47 -08:00
Tzanio 6e63b81c94 Mentioned #964 in CHANGELOG 2020-11-03 07:37:55 -08:00
Tzanio edbaa5b3fd Merge branch 'master' into RK_solvers 2020-11-03 07:36:07 -08:00
Tzanio Kolev eb1cf52ebd Merge pull request #1835 from mfem/scaled-jacobian-plot-dev
Scaled Jacobian plot and locations of bad elements [scaled-jacobian-plot-dev]
2020-11-03 07:31:57 -08:00
Tzanio Kolev 03aa166858 Merge branch 'master' into scaled-jacobian-plot-dev 2020-11-03 07:31:20 -08:00
Veselin Dobrev 1de94adf90 Fix for newer versions of Umpire. 2020-11-02 23:52:05 -08:00
Patrick Greene 7b8ef12161 Added time, time step, and cycle to conduit data collection root file 2020-11-02 15:11:44 -08:00
Tzanio Kolev 37efde9e55 Merge pull request #1855 from mfem/catch-v2.13.2
Upgrade from Catch v2.13.0 to v2.13.2
2020-11-01 13:37:18 -08:00
Tzanio a17a1f1a2d Updated CHANGELOG 2020-11-01 13:32:02 -08:00
Tzanio 0640727b77 Merge branch 'master' into mumps-solver 2020-11-01 13:31:21 -08:00
Tzanio 01c0f4af68 Updated CHANGELOG 2020-11-01 13:29:51 -08:00
Tzanio 8de1d37871 Merge branch 'master' into scaled-jacobian-plot-dev 2020-11-01 13:27:11 -08:00
Tzanio 0359c410a9 Merge branch 'master' into RK_solvers 2020-11-01 13:26:02 -08:00
Tzanio d3028ea057 Merge branch 'master' into navier-filter 2020-11-01 13:24:39 -08:00
Tzanio 9f8e2f8bc7 Updated CHANGELOG 2020-11-01 13:22:53 -08:00
Tzanio 2436fa67ca Merge branch 'master' into catch-v2.13.2 2020-11-01 13:20:54 -08:00
Tzanio Kolev b4ba111505 Merge pull request #1857 from mfem/new-dev-version-4.2.1
Update version numbers to 4.2.1 -- a new development version [new-dev-version-4.2.1]
2020-11-01 13:20:07 -08:00
Veselin Dobrev 7bf942176e Merge branch 'master' into mumps-solver 2020-11-01 03:10:08 -08:00
Veselin Dobrev 4149fbc0d6 Update version numbers to 4.2.1 -- a new development version. 2020-11-01 02:18:15 -08:00
termi-official 111357a964 Added missing AddBdrPoint method for 1D meshes.. 2020-10-30 21:53:29 +01:00
Will Pazner 949d43f80e Upgrade from Catch v2.13.0 to v2.13.2
Adds a workaround for internal NVCC compiler error:

   nvcc segfaults when encountering a call to __builtin_constant_p with an
   argument that involves a new-expression trying to invoke a user-provided
   constructor

We would encounter this problem with complex REQUIRE statements (e.g. in
test_ode.cpp).
2020-10-30 09:42:10 -07:00
Tzanio 6be78c57e1 Added comments and a refinement for the scaled Jacobian option in mesh explorer. 2020-10-24 14:46:22 -07:00
Walter I. Nissen ca37dc2e67 Fixed brace style 2020-10-23 15:25:49 -07:00
Walter I. Nissen eb7833533f Slight comments 2020-10-23 15:04:39 -07:00
Walter I. Nissen 9d0a7ac938 Tweak to output to use mfem-style Print function and summary of elements not printed. 2020-10-23 15:04:39 -07:00
Walter I. Nissen f34b48335a Add scaled jacobians with the 'j' key 2020-10-23 15:04:39 -07:00
Walter I. Nissen 4e570ad11c Thanks to Tzanio for telling me where to put this. 2020-10-23 15:04:39 -07:00
psocratis 4b09bc532f moving macros to .cpp file 2020-10-22 12:06:11 -07:00
Veselin Dobrev 3ab4dd4194 Some formatting edits. 2020-10-22 11:54:40 -07:00
Will Pazner 514a0bae58 Add jump error scaling option to rates and prates 2020-10-22 11:51:40 -07:00
psocratis ca3f53b37b fixed version in changelog 2020-10-22 11:04:10 -07:00
psocratis 799069babc renaming info and icntl to avoid conflicts with catch. INFO->MUMPS_INFO, ICNTL->MUMPS_ICNTL 2020-10-21 16:18:01 -07:00
psocratis a14b018692 adding check for HYPRE_BIGINT 2020-10-21 13:49:42 -07:00
Veselin Dobrev 4079f31447 More fixes for Cygwin. 2020-10-20 00:49:13 -07:00
Veselin Dobrev 90ce59a56b Some edits to fix building under Cygwin with gcc.
Use 'std::to_string' from C++11 instead of own implementation.
2020-10-19 22:17:20 -07:00
Julian Andrej c10ede8fba clarify docs 2020-10-19 16:33:42 -07:00
Julian Andrej 81dcca3e12 reference formatting 2020-10-19 11:28:45 -07:00
Julian Andrej bdd237c7ea spelling 2020-10-19 11:27:41 -07:00
Julian Andrej cacc93d8dc mention filter algorithm reference 2020-10-19 11:27:00 -07:00
psocratis 3b9c4b28ad style 2020-10-18 15:43:19 -07:00
psocratis 3df5658695 fixing comments for the set* methods 2020-10-18 15:42:40 -07:00
psocratis 8cc5feb057 resolving conflicts with master. Minor changes addressing reviewers' comments 2020-10-18 15:33:05 -07:00
psocratis 84d4013a50 fix conflicts 2020-10-12 18:09:01 -07:00
Julian Andrej c507d3dc3d make style 2020-10-12 13:43:33 -07:00
Ben Southworth 62d78501a3 Change to three space=indent 2020-10-12 13:25:37 -07:00
Ben Southworth 5fbe7bd995 Added unit tests 2020-10-12 13:01:00 -07:00
bensworth e4a8344e94 Merge branch 'master' into RK_solvers 2020-10-09 09:41:31 -06:00
Socratis cb5f1830de checked cmake both on linux and macos 2020-10-08 16:54:57 -07:00
Will Pazner 72b919e633 Remove unused variable 2020-10-08 12:29:42 -07:00
psocratis d91e31458c minor fix in cmake 2020-10-08 11:31:27 -07:00
Julian Andrej 7893c819a9 implementation of a filter method 2020-10-07 16:03:33 -07:00
Will Pazner a6bac0be4c Formatting 2020-10-07 09:39:42 -07:00
Will Pazner 872c4dba86 Merge remote-tracking branch 'origin/master' into jump-error 2020-10-07 09:00:24 -07:00
Julian Andrej 561daa66b6 add dependencies to mumps 2020-10-02 16:52:07 -07:00
Julian Andrej cd1cacd1a6 correct findmumps cmake 2020-10-02 16:48:33 -07:00
psocratis 2b94b8bd43 configuring cmake 2020-10-02 14:56:38 -07:00
Socratis b6e4244806 minor tweaks 2020-10-02 11:32:40 -07:00
Socratis 59eaee6f13 fixing travis doc errors 2020-10-01 19:31:03 -07:00
Socratis 9fd56d22a2 fixed newly introduced valgrind mem leak 2020-10-01 19:11:19 -07:00
psocratis fc3babf85d minor, initialization of int arrays 2020-10-01 19:03:35 -07:00
Socratis 1d0b509827 mumps_solver valgrind issue free. Added mumps_solver to ex25p 2020-10-01 18:18:58 -07:00
psocratis 50b525907f minor 2020-09-30 19:11:28 -07:00
psocratis 5137ef5604 clean up 2020-09-29 19:42:44 -07:00
psocratis 8f1d08dc93 Adding symmetric and SPD matrix case 2020-09-29 19:04:17 -07:00
Julian Andrej e63f9887f4 add MUMPS version check to makefile build system 2020-09-29 14:13:14 -07:00
psocratis 2819c0e361 more cleaning up 2020-09-29 13:23:43 -07:00
psocratis 30b0ae9581 cleanup 2020-09-28 17:47:08 -07:00
psocratis 59a32942f2 make style 2020-09-28 15:06:23 -07:00
psocratis 90af7527d0 mumps interface works with any combination of distributed RHS and Solution or not... still needs some cleanup and a valgrind run 2020-09-28 15:05:18 -07:00
psocratis ac6ff275ba Adding MUMPSSolver interface. Finished the case where RHS and Solution are gathered on host 2020-09-27 18:09:25 -07:00
Julian Andrej b78402803f bugs everywhere 2020-09-26 18:21:36 -07:00
Julian Andrej 6e5bb7e5e1 more distributed solution vector fiddling 2020-09-26 16:25:48 -07:00
Julian Andrej 99a3803b4f distributed rhs and solution 2020-09-26 15:48:07 -07:00
Julian Andrej c0495229fc add MUMPS to the makefile buildsystem 2020-09-26 14:08:56 -07:00
psocratis adce9a5755 Adding interface for distributed MUMPS still needs implementation for distributed RHS 2020-09-25 20:22:36 -07:00
Will Pazner 374d71f68c Minor 2020-09-22 13:30:12 -07:00
Will Pazner 7a29a36c78 Add JumpScaling option to ComputeDGFaceJumpError 2020-09-21 14:59:02 -07:00
Will Pazner e5e58f8328 Add function GetFaceNbrElementSize 2020-09-21 14:58:16 -07:00
Ben Southworth bb28ac7435 Added three ESDIRK schemes 2019-06-18 07:49:15 -07:00
52 changed files with 1579 additions and 149 deletions
+18
View File
@@ -8,6 +8,24 @@
https://mfem.org
Version 4.2.1 (development)
===========================
- Added interface to MUMPS direct solver. Its usage is demonstrated in ex25p.
See http://mumps.enseeiht.fr/ for more details. Supported versions >= 5.1.1.
- Added three ESDIRK time integrators: implicit trapezoid rule, L-stable
ESDIRK-32, and A-stable ESDIRK-33.
- Added a "scaled Jacobian" visualization option in the Mesh Explorer miniapp to
help identify elements with poor mesh quality.
- Upgraded the Catch unit test framework from version 2.13.0 to version 2.13.2.
- Implemented a filter method for the Navier miniapp to stabilize highly
turbulent flows in direct numerical simulation.
Version 4.2, released on October 30, 2020
=========================================
+12 -3
View File
@@ -50,7 +50,7 @@ project(mfem NONE)
# Current version of MFEM, see also `makefile`.
# mfem_VERSION = (string)
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
set(${PROJECT_NAME}_VERSION 4.2.0)
set(${PROJECT_NAME}_VERSION 4.2.1)
# Prohibit in-source build
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
@@ -185,7 +185,7 @@ if (MFEM_USE_MPI)
endif()
endif()
else()
set(PKGS_NEED_MPI SUPERLU PETSC SLEPC STRUMPACK PUMI)
set(PKGS_NEED_MPI SUPERLU MUMPS PETSC SLEPC STRUMPACK PUMI)
foreach(PKG IN LISTS PKGS_NEED_MPI)
if (MFEM_USE_${PKG})
message(STATUS "Disabling package ${PKG} - requires MPI")
@@ -264,6 +264,15 @@ if (MFEM_USE_SUPERLU)
endif()
endif()
# MUMPS can only be enabled in parallel
if (MFEM_USE_MUMPS)
if (MFEM_USE_MPI)
find_package(MUMPS REQUIRED mumps_common pord)
else()
message(FATAL_ERROR " *** MUMPS requires that MPI be enabled.")
endif()
endif()
# STRUMPACK can only be enabled in parallel
if (MFEM_USE_STRUMPACK)
if (MFEM_USE_MPI)
@@ -382,7 +391,7 @@ endif()
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
# be before SuiteSparse.
set(MFEM_TPLS MPI_CXX OPENMP BLAS LAPACK METIS HYPRE SuiteSparse SUNDIALS PETSC
SLEPC MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT Ginkgo GNUTLS GSLIB NETCDF
SLEPC MESQUITE SuperLUDist MUMPS STRUMPACK AXOM CONDUIT Ginkgo GNUTLS GSLIB NETCDF
MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE ADIOS2
CUSPARSE MKL_CPARDISO AMGX)
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
+13
View File
@@ -348,6 +348,12 @@ MFEM_USE_SUPERLU5 = YES/NO
If SuperLU functionality is enabled, use the older 5.1.0 version rather than
the more recent 6+ versions.
MFEM_USE_MUMPS = YES/NO
Enable MFEM functionality based on the MUMPS library. Currently, this
option adds the class MUMPSSolver (a parallel sparse direct solver).
When enabled, this option uses the MUMPS_* library options, see
below.
MFEM_USE_STRUMPACK = YES/NO
Enable MFEM functionality based on the STRUMPACK sparse direct solver and
preconditioner through the STRUMPACKSolver and STRUMPACKRowLocMatrix
@@ -578,6 +584,12 @@ The specific libraries and their options are:
Options: SUPERLU_OPT, SUPERLU_LIB.
Versions: SuperLU_DIST >= 5.1.0.
- MUMPS (optional), used when MFEM_USE_MUMPS = YES. Note that MUMPS
requires LAPACK, SCALAPACK and a reordering package such as PORD or METIS.
URL: http://mumps.enseeiht.fr
Options: MUMPS_OPT, MUMPS_LIB.
Versions: MUMPS >= 5.1.1
- STRUMPACK (optional), used when MFEM_USE_STRUMPACK = YES. Note that STRUMPACK
requires the PT-Scotch and Scalapack libraries as well as ParMETIS, which
includes METIS 5 in its distribution. Starting with STRUMPACK v2.2.0, ParMETIS
@@ -837,6 +849,7 @@ MFEM_TIMER_TYPE - Set automatically, can be overwritten.
MFEM_USE_MESQUITE
MFEM_USE_SUITESPARSE
MFEM_USE_SUPERLU
MFEM_USE_MUMPS
MFEM_USE_STRUMPACK
MFEM_USE_GINKGO
MFEM_USE_AMGX
+1
View File
@@ -32,6 +32,7 @@ set(MFEM_USE_SUNDIALS @MFEM_USE_SUNDIALS@)
set(MFEM_USE_MESQUITE @MFEM_USE_MESQUITE@)
set(MFEM_USE_SUITESPARSE @MFEM_USE_SUITESPARSE@)
set(MFEM_USE_SUPERLU @MFEM_USE_SUPERLU@)
set(MFEM_USE_MUMPS @MFEM_USE_MUMPS@)
set(MFEM_USE_STRUMPACK @MFEM_USE_STRUMPACK@)
set(MFEM_USE_GINKGO @MFEM_USE_GINKGO@)
set(MFEM_USE_AMGX @MFEM_USE_AMGX@)
+3
View File
@@ -86,6 +86,9 @@
// Enable MFEM functionality based on the SuperLU_DIST library.
#cmakedefine MFEM_USE_SUPERLU
// Enable MFEM functionality based on the MUMPS library.
#cmakedefine MFEM_USE_MUMPS
// Enable MFEM functionality based on the STRUMPACK library.
#cmakedefine MFEM_USE_STRUMPACK
+23
View File
@@ -0,0 +1,23 @@
# Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Sets the following variables:
# - MUMPS_FOUND
# - MUMPS_INCLUDE_DIRS
# - MUMPS_LIBRARIES
include(MfemCmakeUtilities)
mfem_find_package(MUMPS MUMPS MUMPS_DIR
"include" dmumps_c.h "lib" dmumps
"Paths to headers required by MUMPS."
"Libraries required by MUMPS."
ADD_COMPONENT mumps_common "include" dmumps_c.h "lib" mumps_common
ADD_COMPONENT pord "include" dmumps_c.h "lib" pord)
+9
View File
@@ -34,6 +34,12 @@
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
#define _USE_MATH_DEFINES
#endif
// On Cygwin the option -std=c++11 prevents the definition of M_PI. Defining
// the following macro allows us to get M_PI and some needed functions, e.g.
// posix_memalign(), strdup(), strerror_r().
#ifdef __CYGWIN__
#define _XOPEN_SOURCE 600
#endif
// Check dependencies:
@@ -42,6 +48,9 @@
#ifdef MFEM_USE_SUPERLU
#error Building with SuperLU_DIST (MFEM_USE_SUPERLU=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_MUMPS
#error Building with MUMPS (MFEM_USE_MUMPS=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_STRUMPACK
#error Building with STRUMPACK (MFEM_USE_STRUMPACK=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
+4
View File
@@ -95,6 +95,10 @@
// #define MFEM_USE_SUPERLU
// #define MFEM_USE_SUPERLU5
// Enable MFEM functionality based on the MUMPS library.
// #define MFEM_USE_MUMPS
// #define MFEM_MUMPS_VERSION @MFEM_MUMPS_VERSION@
// Enable MFEM functionality based on the STRUMPACK library.
// #define MFEM_USE_STRUMPACK
+1
View File
@@ -33,6 +33,7 @@ MFEM_USE_MESQUITE = @MFEM_USE_MESQUITE@
MFEM_USE_SUITESPARSE = @MFEM_USE_SUITESPARSE@
MFEM_USE_SUPERLU = @MFEM_USE_SUPERLU@
MFEM_USE_SUPERLU5 = @MFEM_USE_SUPERLU5@
MFEM_USE_MUMPS = @MFEM_USE_MUMPS@
MFEM_USE_STRUMPACK = @MFEM_USE_STRUMPACK@
MFEM_USE_GINKGO = @MFEM_USE_GINKGO@
MFEM_USE_AMGX = @MFEM_USE_AMGX@
+10
View File
@@ -34,6 +34,7 @@ option(MFEM_USE_MESQUITE "Enable MESQUITE usage" OFF)
option(MFEM_USE_SUITESPARSE "Enable SuiteSparse usage" OFF)
option(MFEM_USE_SUPERLU "Enable SuperLU_DIST usage" OFF)
option(MFEM_USE_SUPERLU5 "Use the old SuperLU_DIST 5.1 version" OFF)
option(MFEM_USE_MUMPS "Enable MUMPS usage" OFF)
option(MFEM_USE_STRUMPACK "Enable STRUMPACK usage" OFF)
option(MFEM_USE_GINKGO "Enable Ginkgo usage" OFF)
option(MFEM_USE_AMGX "Enable AmgX usage" OFF)
@@ -118,6 +119,15 @@ set(SuperLUDist_DIR "${MFEM_DIR}/../SuperLU_DIST_6.3.1" CACHE PATH
set(SuperLUDist_REQUIRED_PACKAGES "MPI" "BLAS" "ParMETIS" CACHE STRING
"Additional packages required by SuperLU_DIST.")
set(MUMPS_DIR "${MFEM_DIR}/../MUMPS_5.2.0" CACHE PATH
"Path to the MUMPS library.")
# Packages required by MUMPS, depending on how it was compiled.
set(MUMPS_REQUIRED_PACKAGES "MPI" "BLAS" "METIS" "ScaLAPACK" CACHE STRING
"Additional packages required by MUMPS.")
# If the MPI package does not find all required Fortran libraries:
# set(MUMPS_REQUIRED_LIBRARIES "gfortran" "mpi_mpifh" CACHE STRING
# "Additional libraries required by MUMPS.")
set(STRUMPACK_DIR "${MFEM_DIR}/../STRUMPACK-build" CACHE PATH
"Path to the STRUMPACK library.")
# STRUMPACK may also depend on "OpenMP", depending on how it was compiled.
+10 -3
View File
@@ -123,6 +123,7 @@ MFEM_USE_MESQUITE = NO
MFEM_USE_SUITESPARSE = NO
MFEM_USE_SUPERLU = NO
MFEM_USE_SUPERLU5 = NO
MFEM_USE_MUMPS = NO
MFEM_USE_STRUMPACK = NO
MFEM_USE_GINKGO = NO
MFEM_USE_AMGX = NO
@@ -171,7 +172,7 @@ HYPRE_OPT = -I$(HYPRE_DIR)/include
HYPRE_LIB = -L$(HYPRE_DIR)/lib -lHYPRE
# METIS library configuration
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK),NONO)
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK)$(MFEM_USE_MUMPS),NONONO)
ifeq ($(MFEM_USE_METIS_5),NO)
METIS_DIR = @MFEM_DIR@/../metis-4.0
METIS_OPT =
@@ -252,12 +253,12 @@ SCOTCH_OPT = -I$(SCOTCH_DIR)/include
SCOTCH_LIB = -L$(SCOTCH_DIR)/lib -lptscotch -lptscotcherr -lscotch -lscotcherr\
-lpthread
# SCALAPACK library configuration (required by STRUMPACK)
# SCALAPACK library configuration (required by STRUMPACK and MUMPS)
SCALAPACK_DIR = @MFEM_DIR@/../scalapack-2.0.2
SCALAPACK_OPT = -I$(SCALAPACK_DIR)/SRC
SCALAPACK_LIB = -L$(SCALAPACK_DIR)/lib -lscalapack $(LAPACK_LIB)
# MPI Fortran library, needed e.g. by STRUMPACK
# MPI Fortran library, needed e.g. by STRUMPACK or MUMPS
# MPICH:
MPI_FORTRAN_LIB = -lmpifort
# OpenMPI:
@@ -265,6 +266,12 @@ MPI_FORTRAN_LIB = -lmpifort
# Additional Fortan library:
# MPI_FORTRAN_LIB += -lgfortran
# MUMPS library configuration
MUMPS_DIR = @MFEM_DIR@/../MUMPS_5.2.0
MUMPS_OPT = -I$(MUMPS_DIR)/include
MUMPS_LIB = -Wl,-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps\
-lmumps_common -lpord $(SCALAPACK_LIB) $(LAPACK_LIB) $(MPI_FORTRAN_LIB)
# STRUMPACK library configuration
STRUMPACK_DIR = @MFEM_DIR@/../STRUMPACK-build
STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
+33
View File
@@ -0,0 +1,33 @@
// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "dmumps_c.h"
#include <string>
#include <iostream>
#include <algorithm>
// Macros to expand a macro as a string
#define STR_EXPAND(s) #s
#define STR(s) STR_EXPAND(s)
int main()
{
#ifdef MUMPS_VERSION
const char *ptr = STR(MUMPS_VERSION);
std::string s(ptr);
s.erase(std::remove(s.begin(), s.end(), '"'), s.end());
s.erase(std::remove(s.begin(), s.end(), '.'), s.end());
std::cout << s << "\n";
return 0;
#else
return -1;
#endif
}
+21 -2
View File
@@ -42,6 +42,10 @@ GHV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(HYPRE_OPT))
SMX = $(if $(MFEM_USE_PUMI:NO=),MFEM_USE_SIMMETRIX)
SMX_PATH = $(PUMI_DIR)/include/gmi_sim.h
SMX_FILE = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(SMX_PATH))
MUMPS = $(MFEM_USE_MUMPS:NO=)
GMV_CXX ?= $(MFEM_CXX)
GMV = get_mumps_version
GMV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(MUMPS_OPT))
$(GHV): $(SRC)$(GHV).cpp
$(call mfem-info, Determining HYPRE version ...)
@@ -50,6 +54,13 @@ $(GHV).out: $(GHV)
./$(GHV) > $(GHV).out
.INTERMEDIATE: $(GHV) $(GHV).out
$(GMV): $(SRC)$(GMV).cpp
$(call mfem-info, Determining MUMPS version ...)
$(GMV_CXX) ${GMV_FLAGS} $(SRC)$(GMV).cpp -o $(GMV)
$(GMV).out: $(GMV)
./$(GMV) > $(GMV).out
.INTERMEDIATE: $(GMV) $(GMV).out
get-hypre-version: $(GHV).out
$(eval MFEM_HYPRE_VERSION:=$(shell cat $(GHV).out))
$(if $(MFEM_HYPRE_VERSION),$(eval export MFEM_HYPRE_VERSION)\
@@ -62,10 +73,18 @@ check-smx:
$(call mfem-info, MFEM_USE_SIMMETRIX = $(MFEM_USE_SIMMETRIX))
$(eval export MFEM_USE_SIMMETRIX)
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx)
get-mumps-version: $(GMV).out
$(eval MFEM_MUMPS_VERSION:=$(shell cat $(GMV).out))
$(if $(MFEM_MUMPS_VERSION),$(eval export MFEM_MUMPS_VERSION)\
$(info MUMPS version: $(MFEM_MUMPS_VERSION)),\
$(error Unable to determine MUMPS version))
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx,) \
$(if $(MUMPS),get-mumps-version,)
$(call mfem-info, Writing $(CONFIG_HPP) ...)
@set -- && \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX); do \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX) \
$(if $(MUMPS),MFEM_MUMPS_VERSION); do \
eval var=\$$$$def && \
if [ "NO" != "$${var}" ]; then \
set -- "$$@" -e "s|// \(#define $${def} \)|\1|" && \
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "MFEM"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v4.2.0
PROJECT_NUMBER = v4.2.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+33 -2
View File
@@ -164,6 +164,8 @@ int main(int argc, char *argv[])
int iprob = 4;
double freq = 5.0;
bool herm_conv = true;
bool slu_solver = false;
bool mumps_solver = false;
bool visualization = 1;
OptionsParser args(argc, argv);
@@ -185,10 +187,26 @@ int main(int argc, char *argv[])
"Frequency (in Hz).");
args.AddOption(&herm_conv, "-herm", "--hermitian", "-no-herm",
"--no-hermitian", "Use convention for Hermitian operators.");
#ifdef MFEM_USE_SUPERLU
args.AddOption(&slu_solver, "-slu", "--superlu", "-no-slu",
"--no-superlu", "Use the SuperLU Solver.");
#endif
#ifdef MFEM_USE_MUMPS
args.AddOption(&mumps_solver, "-mumps", "--mumps-solver", "-no-mumps",
"--no-mumps-solver", "Use the MUMPS Solver.");
#endif
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (slu_solver && mumps_solver)
{
if (myid == 0)
cout << "WARNING: Both SuperLU and MUMPS have been selected,"
<< " please choose either one." << endl
<< " Defaulting to SuperLU." << endl;
mumps_solver = false;
}
if (iprob > 4) { iprob = 4; }
prob = (prob_type)iprob;
@@ -430,6 +448,7 @@ int main(int argc, char *argv[])
// 15. Solve using a direct or an iterative solver
#ifdef MFEM_USE_SUPERLU
if (slu_solver)
{
// Transform to monolithic HypreParMatrix
HypreParMatrix *A = Ah.As<ComplexHypreParMatrix>()->GetSystemMatrix();
@@ -442,7 +461,19 @@ int main(int argc, char *argv[])
superlu.Mult(B, X);
delete A;
}
#else
#endif
#ifdef MFEM_USE_MUMPS
if (mumps_solver)
{
HypreParMatrix *A = Ah.As<ComplexHypreParMatrix>()->GetSystemMatrix();
MUMPSSolver mumps;
mumps.SetPrintLevel(0);
mumps.SetMatrixSymType(MUMPSSolver::MatType::UNSYMMETRIC);
mumps.SetOperator(*A);
mumps.Mult(B,X);
delete A;
}
#endif
// 16a. Set up the parallel Bilinear form a(.,.) for the preconditioner
//
// In Comp
@@ -450,6 +481,7 @@ int main(int argc, char *argv[])
//
// In PML: 1/mu (abs(1/det(J) J^T J) Curl E, Curl F)
// + omega^2 * epsilon (abs(det(J) * (J^T J)^-1) * E, F)
if (!slu_solver && !mumps_solver)
{
ConstantCoefficient absomeg(pow(omega, 2) * epsilon);
RestrictedCoefficient restr_absomeg(absomeg,attr);
@@ -499,7 +531,6 @@ int main(int argc, char *argv[])
gmres.SetPreconditioner(BlockAMS);
gmres.Mult(B, X);
}
#endif
// 17. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
-2
View File
@@ -2050,8 +2050,6 @@ public:
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
void SetupPA(const FiniteElementSpace &fes);
};
/** Mass integrator (u, v) restricted to the boundary of a domain */
+8 -8
View File
@@ -106,7 +106,7 @@ void VectorMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
template<const int T_D1D = 0,
const int T_Q1D = 0>
static void PAVectorMassApply2D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Vector &_op,
const Vector &_x,
@@ -119,7 +119,7 @@ static void PAVectorMassApply2D(const int NE,
constexpr int VDIM = 2;
MFEM_VERIFY(D1D <= MAX_D1D, "");
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(_B.Read(), Q1D, D1D);
auto B = Reshape(B_.Read(), Q1D, D1D);
auto Bt = Reshape(_Bt.Read(), D1D, Q1D);
auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
auto x = Reshape(_x.Read(), D1D, D1D, VDIM, NE);
@@ -203,7 +203,7 @@ static void PAVectorMassApply2D(const int NE,
template<const int T_D1D = 0,
const int T_Q1D = 0>
static void PAVectorMassApply3D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Vector &_op,
const Vector &_x,
@@ -216,7 +216,7 @@ static void PAVectorMassApply3D(const int NE,
constexpr int VDIM = 3;
MFEM_VERIFY(D1D <= MAX_D1D, "");
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(_B.Read(), Q1D, D1D);
auto B = Reshape(B_.Read(), Q1D, D1D);
auto Bt = Reshape(_Bt.Read(), D1D, Q1D);
auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
auto x = Reshape(_x.Read(), D1D, D1D, D1D, VDIM, NE);
@@ -381,7 +381,7 @@ void VectorMassIntegrator::AddMultPA(const Vector &x, Vector &y) const
template<const int T_D1D = 0, const int T_Q1D = 0>
static void PAVectorMassAssembleDiagonal2D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Vector &_op,
Vector &_diag,
@@ -393,7 +393,7 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
constexpr int VDIM = 2;
MFEM_VERIFY(D1D <= MAX_D1D, "");
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(_B.Read(), Q1D, D1D);
auto B = Reshape(B_.Read(), Q1D, D1D);
auto op = Reshape(_op.Read(), Q1D, Q1D, NE);
auto y = Reshape(_diag.ReadWrite(), D1D, D1D, VDIM, NE);
MFEM_FORALL(e, NE,
@@ -433,7 +433,7 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
template<const int T_D1D = 0, const int T_Q1D = 0>
static void PAVectorMassAssembleDiagonal3D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Vector &_op,
Vector &_diag,
@@ -445,7 +445,7 @@ static void PAVectorMassAssembleDiagonal3D(const int NE,
constexpr int VDIM = 3;
MFEM_VERIFY(D1D <= MAX_D1D, "");
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(_B.Read(), Q1D, D1D);
auto B = Reshape(B_.Read(), Q1D, D1D);
auto op = Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
auto y = Reshape(_diag.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
MFEM_FORALL(e, NE,
+11 -6
View File
@@ -485,32 +485,32 @@ VectorSumCoefficient::VectorSumCoefficient(int dim)
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &_A,
VectorCoefficient &_B,
VectorCoefficient &B_,
double _alpha, double _beta)
: VectorCoefficient(_A.GetVDim()),
ACoef(&_A), BCoef(&_B),
ACoef(&_A), BCoef(&B_),
A(_A.GetVDim()), B(_A.GetVDim()),
alphaCoef(NULL), betaCoef(NULL),
alpha(_alpha), beta(_beta)
{
MFEM_ASSERT(_A.GetVDim() == _B.GetVDim(),
MFEM_ASSERT(_A.GetVDim() == B_.GetVDim(),
"VectorSumCoefficient: "
"Arguments must have the same dimension.");
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &_A,
VectorCoefficient &_B,
VectorCoefficient &B_,
Coefficient &_alpha,
Coefficient &_beta)
: VectorCoefficient(_A.GetVDim()),
ACoef(&_A), BCoef(&_B),
ACoef(&_A), BCoef(&B_),
A(_A.GetVDim()),
B(_A.GetVDim()),
alphaCoef(&_alpha),
betaCoef(&_beta),
alpha(0.0), beta(0.0)
{
MFEM_ASSERT(_A.GetVDim() == _B.GetVDim(),
MFEM_ASSERT(_A.GetVDim() == B_.GetVDim(),
"VectorSumCoefficient: "
"Arguments must have the same dimension.");
}
@@ -697,6 +697,11 @@ void OuterProductCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
}
}
CrossCrossCoefficient::CrossCrossCoefficient(double A, VectorCoefficient &K)
: MatrixCoefficient(K.GetVDim(), K.GetVDim()), aConst(A), a(NULL), k(&K),
vk(K.GetVDim())
{}
CrossCrossCoefficient::CrossCrossCoefficient(Coefficient &A,
VectorCoefficient &K)
: MatrixCoefficient(K.GetVDim(), K.GetVDim()), aConst(0.0), a(&A), k(&K),
+3 -3
View File
@@ -1171,8 +1171,8 @@ public:
double _alpha = 1.0, double _beta = 1.0);
/** Constructor with scalar coefficients.
Result is _alpha * _A + _beta * _B */
VectorSumCoefficient(VectorCoefficient &_A, VectorCoefficient &_B,
Result is _alpha * _A + _beta * B_ */
VectorSumCoefficient(VectorCoefficient &_A, VectorCoefficient &B_,
Coefficient &_alpha, Coefficient &_beta);
/// Reset the first vector coefficient
@@ -1201,7 +1201,7 @@ public:
const Vector & GetA() const { return A; }
/// Reset the second vector as a constant
void SetB(const Vector &_B) { B = _B; BCoef = NULL; }
void SetB(const Vector &B_) { B = B_; BCoef = NULL; }
/// Return the second vector constant
const Vector & GetB() const { return B; }
+5
View File
@@ -981,6 +981,11 @@ ConduitDataCollection::SaveRootFile(int num_domains,
n_root["file_pattern"] = MeshFilePattern(relay_protocol);
n_root["tree_pattern"] = "";
// Add the time, time step, and cycle
n_root["blueprint_index/mesh/state/time"] = time;
n_root["blueprint_index/mesh/state/time_step"] = time_step;
n_root["blueprint_index/mesh/state/cycle"] = cycle;
relay::io::save(n_root, RootFileName(), root_proto);
}
+21 -20
View File
@@ -110,7 +110,8 @@ void ConvergenceStudy::AddL2Error(GridFunction *gf,
void ConvergenceStudy::AddGf(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad,
Coefficient *ell_coeff, double Nu)
Coefficient *ell_coeff,
JumpScaling jump_scaling)
{
cont_type = gf->FESpace()->FEColl()->GetContType();
@@ -140,7 +141,7 @@ void ConvergenceStudy::AddGf(GridFunction *gf, Coefficient *scalar_u,
if (cont_type == mfem::FiniteElementCollection::DISCONTINUOUS && ell_coeff)
{
double DGErr = gf->ComputeDGFaceJumpError(scalar_u,ell_coeff,Nu);
double DGErr = gf->ComputeDGFaceJumpError(scalar_u,ell_coeff,jump_scaling);
DGFaceErrors.Append(DGErr);
// Compute the rate of convergence by:
// rate = log (||u - u_h|| / ||u - u_{h/2}||)/log(2)
@@ -270,26 +271,26 @@ void ConvergenceStudy::Print(bool relative, std::ostream &out)
}
out << "\n";
}
if (cont_type == 3 && fcounter)
}
if (cont_type == 3 && fcounter)
{
out << " -------------------------------------------" << "\n";
out << " DG Face Jump Error " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::right<< std::setw(11)<< "DOFs "<< std::setw(13);
out << "Error ";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
for (int i =0; i<fcounter; i++)
{
out << " -------------------------------------------" << "\n";
out << " DG Face Jump Error " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::right<< std::setw(11)<< "DOFs "<< std::setw(13);
out << "Error ";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
for (int i =0; i<fcounter; i++)
{
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << DGFaceErrors[i] << std::setw(13)
<< std::fixed << DGFaceRates[i] << "\n";
}
out << "\n";
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << DGFaceErrors[i] << std::setw(13)
<< std::fixed << DGFaceRates[i] << "\n";
}
out << "\n";
}
}
}
+5 -3
View File
@@ -59,7 +59,8 @@ private:
VectorCoefficient *vector_u);
void AddGf(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad=nullptr,
Coefficient *ell_coeff=nullptr, double Nu=1.0);
Coefficient *ell_coeff=nullptr,
JumpScaling jump_scaling = {1.0, JumpScaling::ONE_OVER_H});
void AddGf(GridFunction *gf, VectorCoefficient *vector_u,
VectorCoefficient *curl, Coefficient *div);
// returns the L2-norm of scalar_u or vector_u
@@ -75,9 +76,10 @@ public:
/// DG face jumps parameters
void AddL2GridFunction(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad=nullptr,
Coefficient *ell_coeff=nullptr, double Nu=1.0)
Coefficient *ell_coeff=nullptr,
JumpScaling jump_scaling = {1.0, JumpScaling::ONE_OVER_H})
{
AddGf(gf, scalar_u, grad, ell_coeff, Nu);
AddGf(gf, scalar_u, grad, ell_coeff, jump_scaling);
}
/// Add H1 GridFunction, the exact solution and possibly its gradient
+29 -10
View File
@@ -2777,10 +2777,11 @@ double GridFunction::ComputeDivError(
}
double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff, double Nu,
Coefficient *ell_coeff,
class JumpScaling jump_scaling,
const IntegrationRule *irs[]) const
{
int fdof, dim, intorder, k;
int fdof, intorder, k;
Mesh *mesh;
const FiniteElement *fe;
ElementTransformation *transf;
@@ -2791,20 +2792,24 @@ double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
double error = 0.0;
mesh = fes->GetMesh();
dim = mesh->Dimension();
for (int i = 0; i < mesh->GetNumFaces(); i++)
{
face_elem_transf = mesh->GetFaceElementTransformations(i, 5);
int i1 = face_elem_transf->Elem1No;
int i2 = face_elem_transf->Elem2No;
int i1, i2;
mesh->GetFaceElements(i, &i1, &i2);
double h = mesh->GetElementSize(i1);
intorder = fes->GetFE(i1)->GetOrder();
if (i2 >= 0)
{
if ( (k = fes->GetFE(i2)->GetOrder()) > intorder )
{
intorder = k;
}
h = std::min(h, mesh->GetElementSize(i2));
}
int p = intorder;
intorder = 2 * intorder; // <-------------
face_elem_transf = mesh->GetFaceElementTransformations(i, 5);
const IntegrationRule *ir;
if (irs)
{
@@ -2875,8 +2880,9 @@ double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
error += (ip.weight * Nu * ell_coeff_val(j) *
pow(transf->Weight(), 1.0-1.0/(dim-1)) *
double nu = jump_scaling.Eval(h, p);
error += (ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
}
}
@@ -2884,6 +2890,15 @@ double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
const IntegrationRule *irs[]) const
{
return ComputeDGFaceJumpError(
exsol, ell_coeff, {Nu, JumpScaling::ONE_OVER_H}, irs);
}
double GridFunction::ComputeH1Error(Coefficient *exsol,
VectorCoefficient *exgrad,
Coefficient *ell_coef, double Nu,
@@ -2892,7 +2907,11 @@ double GridFunction::ComputeH1Error(Coefficient *exsol,
double error1 = 0.0;
double error2 = 0.0;
if (norm_type & 1) { error1 = GridFunction::ComputeGradError(exgrad); }
if (norm_type & 2) { error2 = GridFunction::ComputeDGFaceJumpError(exsol,ell_coef,Nu); }
if (norm_type & 2)
{
error2 = GridFunction::ComputeDGFaceJumpError(
exsol, ell_coef, {Nu, JumpScaling::ONE_OVER_H});
}
return sqrt(error1 * error1 + error2 * error2);
}
@@ -3670,7 +3689,7 @@ QuadratureFunction & QuadratureFunction::operator=(double value)
QuadratureFunction & QuadratureFunction::operator=(const Vector &v)
{
MFEM_ASSERT(qspace && v.Size() == qspace->GetSize(), "");
MFEM_ASSERT(qspace && v.Size() == this->Size(), "");
Vector::operator=(v);
return *this;
}
+39 -2
View File
@@ -451,7 +451,17 @@ public:
virtual double ComputeDivError(Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns the Face Jumps error for L2 elements
/// Returns the Face Jumps error for L2 elements. The error can be weighted
/// by a constant nu, by nu/h, or nu*p^2/h, depending on the value of
/// @a jump_scaling.
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
class JumpScaling jump_scaling,
const IntegrationRule *irs[] = NULL)
const;
/// Returns the Face Jumps error for L2 elements, with 1/h scaling.
MFEM_DEPRECATED
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
@@ -664,6 +674,32 @@ public:
derived class ParGridFunction */
std::ostream &operator<<(std::ostream &out, const GridFunction &sol);
/// Class used to specify how the jump terms in
/// GridFunction::ComputeDGFaceJumpError are scaled.
class JumpScaling
{
public:
enum JumpScalingType
{
CONSTANT,
ONE_OVER_H,
P_SQUARED_OVER_H
};
private:
double nu;
JumpScalingType type;
public:
JumpScaling(double nu_=1.0, JumpScalingType type_=CONSTANT)
: nu(nu_), type(type_) { }
double Eval(double h, int p) const
{
double val = nu;
if (type != CONSTANT) { val /= h; }
if (type == P_SQUARED_OVER_H) { val *= p*p; }
return val;
}
};
/** @brief Class representing a function through its values (scalar or vector)
at quadrature points. */
@@ -752,7 +788,8 @@ public:
/// Copy the data from @a v.
/** The size of @a v must be equal to the size of the associated
QuadratureSpace #qspace. */
QuadratureSpace #qspace times the QuadratureFunction dimension
i.e. QuadratureFunction::Size(). */
QuadratureFunction &operator=(const Vector &v);
/// Copy assignment. Only the data of the base class Vector is copied.
+1 -1
View File
@@ -10,8 +10,8 @@
// CONTRIBUTING.md for details.
#include <cmath>
#include "fem.hpp"
#include <cmath>
namespace mfem
{
+10 -7
View File
@@ -657,12 +657,12 @@ void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
JumpScaling jump_scaling,
const IntegrationRule *irs[]) const
{
const_cast<ParGridFunction *>(this)->ExchangeFaceNbrData();
int fdof, dim, intorder, k;
int fdof, intorder, k;
ElementTransformation *transf;
Vector shape, el_dofs, err_val, ell_coeff_val;
Array<int> vdofs;
@@ -670,7 +670,6 @@ double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
double error = 0.0;
ParMesh *mesh = pfes->GetParMesh();
dim = mesh->Dimension();
std::map<int,int> local_to_shared;
for (int i = 0; i < mesh->GetNSharedFaces(); ++i)
@@ -687,6 +686,7 @@ double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
mesh->GetFaceElements(i, &iel1, &iel2);
mesh->GetFaceInfos(i, &info1, &info2);
double h = mesh->GetElementSize(iel1);
intorder = fes->GetFE(iel1)->GetOrder();
FaceElementTransformations *face_elem_transf;
@@ -703,11 +703,10 @@ double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
}
shared_face = true;
shared_face_factor = 0.5;
h = std::min(h, mesh->GetFaceNbrElementSize(iel2));
}
else
{
face_elem_transf = mesh->GetFaceElementTransformations(i);
if (iel2 >= 0)
{
fe2 = pfes->GetFE(iel2);
@@ -715,12 +714,15 @@ double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
{
intorder = k;
}
h = std::min(h, mesh->GetElementSize(iel2));
}
else
{
fe2 = NULL;
}
face_elem_transf = mesh->GetFaceElementTransformations(i);
}
int p = intorder;
intorder = 2 * intorder; // <-------------
const IntegrationRule *ir;
@@ -806,8 +808,9 @@ double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
error += shared_face_factor*(ip.weight * Nu * ell_coeff_val(j) *
pow(transf->Weight(), 1.0-1.0/(dim-1)) *
double nu = jump_scaling.Eval(h, p);
error += shared_face_factor*(ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
}
}
+1 -1
View File
@@ -310,7 +310,7 @@ public:
/// Returns the Face Jumps error for L2 elements
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
JumpScaling jump_scaling,
const IntegrationRule *irs[]=NULL)
const;
+4 -2
View File
@@ -482,7 +482,8 @@ public:
HostMemorySpace(),
name(mm.GetUmpireAllocatorHostName()),
rm(umpire::ResourceManager::getInstance()),
h_allocator(rm.isAllocator(name)? rm.getAllocator(name):
h_allocator((!std::strcmp(name, "HOST") || rm.isAllocator(name)) ?
rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("HOST"))),
strat(h_allocator.getAllocationStrategy()) { }
@@ -506,7 +507,8 @@ public:
DeviceMemorySpace(),
name(mm.GetUmpireAllocatorDeviceName()),
rm(umpire::ResourceManager::getInstance()),
d_allocator(rm.isAllocator(name)? rm.getAllocator(name):
d_allocator((!std::strcmp(name, "DEVICE") || rm.isAllocator(name)) ?
rm.getAllocator(name) :
rm.makeAllocator<umpire::strategy::DynamicPool>
(name, rm.getAllocator("DEVICE"))) { }
void Alloc(Memory &base) { base.d_ptr = d_allocator.allocate(base.bytes); }
+3 -12
View File
@@ -12,6 +12,7 @@
#ifndef MFEM_TEXT
#define MFEM_TEXT
#include "../config/config.hpp"
#include <istream>
#include <iomanip>
#include <sstream>
@@ -24,6 +25,8 @@ namespace mfem
// Utilities for text parsing
using std::to_string;
/// Check if the stream starts with @a comment_char. If so skip it.
inline void skip_comment_lines(std::istream &is, const char comment_char)
{
@@ -47,18 +50,6 @@ inline void filter_dos(std::string &line)
}
}
/// Convert an integer to an std::string.
inline std::string to_string(int i)
{
std::stringstream ss;
ss << i;
// trim leading spaces
std::string out_str = ss.str();
out_str = out_str.substr(out_str.find_first_not_of(" \t"));
return out_str;
}
/// Convert an integer to a 0-padded string with the given number of @a digits
inline std::string to_padded_string(int i, int digits)
{
+5
View File
@@ -83,6 +83,11 @@ if (MFEM_USE_SUPERLU)
list(APPEND HDRS superlu.hpp)
endif()
if (MFEM_USE_MUMPS)
list(APPEND SRCS mumps.cpp)
list(APPEND HDRS mumps.hpp)
endif()
if (MFEM_USE_STRUMPACK)
list(APPEND SRCS strumpack.cpp)
list(APPEND HDRS strumpack.hpp)
-5
View File
@@ -12,11 +12,6 @@
#ifndef MFEM_KERNELS_HPP
#define MFEM_KERNELS_HPP
#ifdef _WIN32
#define _USE_MATH_DEFINES
#include <cmath>
#endif
#include "../config/config.hpp"
#include "../general/backends.hpp"
#include "../general/globals.hpp"
+4
View File
@@ -49,6 +49,10 @@
#include "hypre_parcsr.hpp"
#include "hypre.hpp"
#ifdef MFEM_USE_MUMPS
#include "mumps.hpp"
#endif
#ifdef MFEM_USE_PETSC
#include "petsc.hpp"
#endif
+422
View File
@@ -0,0 +1,422 @@
// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "../config/config.hpp"
#ifdef MFEM_USE_MUMPS
#ifdef MFEM_USE_MPI
#include "mumps.hpp"
#ifdef HYPRE_BIGINT
#error "MUMPSSolver requires HYPRE_Int == int, for now."
#endif
// macro s.t. indices match MUMPS documentation
#define MUMPS_ICNTL(I) icntl[(I) -1]
#define MUMPS_INFO(I) info[(I) -1]
namespace mfem
{
void MUMPSSolver::SetOperator(const Operator &op)
{
auto APtr = dynamic_cast<const HypreParMatrix *>(&op);
MFEM_VERIFY(APtr, "Not compatible matrix type");
height = op.Height();
width = op.Width();
comm = APtr->GetComm();
MPI_Comm_size(comm, &numProcs);
MPI_Comm_rank(comm, &myid);
auto parcsr_op = (hypre_ParCSRMatrix *) const_cast<HypreParMatrix &>(*APtr);
hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
#if MFEM_HYPRE_VERSION >= 21600
hypre_CSRMatrixBigJtoJ(csr_op);
#endif
int *Iptr = csr_op->i;
int *Jptr = csr_op->j;
int n_loc = csr_op->num_rows;
row_start = parcsr_op->first_row_index;
MUMPS_INT8 nnz = 0;
if (mat_type)
{
// count nnz in case of symmetric mode
int k = 0;
for (int i = 0; i < n_loc; i++)
{
for (int j = Iptr[i]; j < Iptr[i + 1]; j++)
{
int ii = row_start + i + 1;
int jj = Jptr[k] + 1;
k++;
if (ii>=jj) { nnz++; }
}
}
}
else
{
nnz = csr_op->num_nonzeros;
}
int * I = new int[nnz];
int * J = new int[nnz];
// Fill in I and J arrays for
// COO format in 1-based indexing
int k = 0;
double * data;
if (mat_type)
{
int l = 0;
data = new double[nnz];
for (int i = 0; i < n_loc; i++)
{
for (int j = Iptr[i]; j < Iptr[i + 1]; j++)
{
int ii = row_start + i + 1;
int jj = Jptr[k] + 1;
if (ii >= jj)
{
I[l] = ii;
J[l] = jj;
data[l++] = csr_op->data[k];
}
k++;
}
}
}
else
{
for (int i = 0; i < n_loc; i++)
{
for (int j = Iptr[i]; j < Iptr[i + 1]; j++)
{
I[k] = row_start + i + 1;
J[k] = Jptr[k] + 1;
k++;
}
}
data = csr_op->data;
}
// new MUMPS object
if (id)
{
id->job = -2;
dmumps_c(id);
delete id;
}
id = new DMUMPS_STRUC_C;
// C to Fortran communicator
id->comm_fortran = (MUMPS_INT) MPI_Comm_c2f(comm);
// Host is involved in computation
id->par = 1;
id->sym = mat_type;
// MUMPS init
id->job = -1;
dmumps_c(id);
// Set MUMPS default parameters
SetParameters();
id->n = parcsr_op->global_num_rows;
id->nnz_loc = nnz;
id->irn_loc = I;
id->jcn_loc = J;
id->a_loc = data;
// MUMPS Analysis
id->job = 1;
dmumps_c(id);
// MUMPS Factorization
id->job = 2;
dmumps_c(id);
hypre_CSRMatrixDestroy(csr_op);
delete [] I;
delete [] J;
if (mat_type) { delete [] data; }
#if MFEM_MUMPS_VERSION >= 530
delete [] irhs_loc;
irhs_loc = new int[n_loc];
for (int i = 0; i < n_loc; i++)
{
irhs_loc[i] = row_start + i + 1;
}
row_starts.SetSize(numProcs);
MPI_Allgather(&row_start, 1, MPI_INT, row_starts, 1, MPI_INT, comm);
#else
if (myid == 0)
{
delete [] rhs_glob;
delete [] recv_counts;
rhs_glob = new double[parcsr_op->global_num_rows];
recv_counts = new int[numProcs];
}
MPI_Gather(&n_loc, 1, MPI_INT, recv_counts, 1, MPI_INT, 0, comm);
if (myid == 0)
{
delete [] displs;
displs = new int[numProcs];
displs[0] = 0;
int s = 0;
for (int k = 0; k < numProcs-1; k++)
{
s += recv_counts[k];
displs[k+1] = s;
}
}
#endif
}
void MUMPSSolver::Mult(const Vector &x, Vector &y) const
{
#if MFEM_MUMPS_VERSION >= 530
id->nloc_rhs = x.Size();
id->lrhs_loc = x.Size();
id->rhs_loc = x.GetData();
id->irhs_loc = irhs_loc;
id->lsol_loc = id->MUMPS_INFO(23);
id->isol_loc = new int[id->MUMPS_INFO(23)];
id->sol_loc = new double[id->MUMPS_INFO(23)];
// MUMPS solve
id->job = 3;
dmumps_c(id);
RedistributeSol(id->isol_loc, id->sol_loc, y.GetData());
delete [] id->sol_loc;
delete [] id->isol_loc;
#else
MPI_Gatherv(x.GetData(), x.Size(), MPI_DOUBLE,
rhs_glob, recv_counts,
displs, MPI_DOUBLE, 0, comm);
if (myid == 0) { id->rhs = rhs_glob; }
// MUMPS solve
id->job = 3;
dmumps_c(id);
MPI_Scatterv(rhs_glob, recv_counts, displs,
MPI_DOUBLE, y.GetData(), y.Size(),
MPI_DOUBLE, 0, comm);
#endif
}
void MUMPSSolver::MultTranspose(const Vector &x, Vector &y) const
{
// Set flag for Transpose Solve
id->MUMPS_ICNTL(9) = 0;
Mult(x,y);
// Reset the flag
id->MUMPS_ICNTL(9) = 1;
}
void MUMPSSolver::SetPrintLevel(int print_lvl)
{
print_level = print_lvl;
}
void MUMPSSolver::SetMatrixSymType(MatType mtype)
{
mat_type = mtype;
}
MUMPSSolver::~MUMPSSolver()
{
if (id)
{
#if MFEM_MUMPS_VERSION >= 530
delete [] irhs_loc;
#else
delete [] recv_counts;
delete [] displs;
delete [] rhs_glob;
#endif
id->job = -2;
dmumps_c(id);
delete id;
}
}
void MUMPSSolver::SetParameters()
{
// output stream for error messages
id->MUMPS_ICNTL(1) = 6;
// output stream for diagnosting printing local to each proc
id->MUMPS_ICNTL(2) = 6;
// output stream for global info
id->MUMPS_ICNTL(3) = 6;
// Level of error printing
id->MUMPS_ICNTL(4) = print_level;
//input matrix format (assembled)
id->MUMPS_ICNTL(5) = 0;
// Use A or A^T
id->MUMPS_ICNTL(9) = 1;
// Iterative refinement (disabled)
id->MUMPS_ICNTL(10) = 0;
// Error analysis-statistics (disabled)
id->MUMPS_ICNTL(11) = 0;
// Use of ScaLAPACK (Parallel factorization on root)
id->MUMPS_ICNTL(13) = 0;
// Percentage increase of estimated workspace (default = 20%)
id->MUMPS_ICNTL(14) = 20;
// Number of OpenMP threads (default)
id->MUMPS_ICNTL(16) = 0;
// Matrix input format (distributed)
id->MUMPS_ICNTL(18) = 3;
// Schur complement (no Schur complement matrix returned)
id->MUMPS_ICNTL(19) = 0;
#if MFEM_MUMPS_VERSION >= 530
// Distributed RHS
id->MUMPS_ICNTL(20) = 10;
// Distributed Sol
id->MUMPS_ICNTL(21) = 1;
#else
// Centralized RHS
id->MUMPS_ICNTL(20) = 0;
// Centralized Sol
id->MUMPS_ICNTL(21) = 0;
#endif
// Out of core factorization and solve (disabled)
id->MUMPS_ICNTL(22) = 0;
// Max size of working memory (default = based on estimates)
id->MUMPS_ICNTL(23) = 0;
}
#if MFEM_MUMPS_VERSION >= 530
int MUMPSSolver::GetRowRank(int i, const Array<int> &row_starts_) const
{
if (row_starts_.Size() == 1)
{
return 0;
}
auto up = std::upper_bound(row_starts_.begin(), row_starts_.end(), i);
return std::distance(row_starts_.begin(), up) - 1;
}
void MUMPSSolver::RedistributeSol(const int * row_map,
const double * x, double * y) const
{
int size = id->MUMPS_INFO(23);
int * send_count = new int[numProcs]();
for (int i = 0; i < size; i++)
{
int j = row_map[i] - 1;
int row_rank = GetRowRank(j, row_starts);
if (myid == row_rank) { continue; }
send_count[row_rank]++;
}
int * recv_count = new int[numProcs];
MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, comm);
int * send_displ = new int [numProcs]; send_displ[0] = 0;
int * recv_displ = new int [numProcs]; recv_displ[0] = 0;
int sbuff_size = send_count[numProcs-1];
int rbuff_size = recv_count[numProcs-1];
for (int k = 0; k < numProcs - 1; k++)
{
send_displ[k + 1] = send_displ[k] + send_count[k];
recv_displ[k + 1] = recv_displ[k] + recv_count[k];
sbuff_size += send_count[k];
rbuff_size += recv_count[k];
}
int * sendbuf_index = new int[sbuff_size];
double * sendbuf_values = new double[sbuff_size];
int * soffs = new int[numProcs]();
for (int i = 0; i < size; i++)
{
int j = row_map[i] - 1;
int row_rank = GetRowRank(j, row_starts);
if (myid == row_rank)
{
int local_index = j - row_start;
y[local_index] = x[i];
}
else
{
int k = send_displ[row_rank] + soffs[row_rank];
sendbuf_index[k] = j;
sendbuf_values[k] = x[i];
soffs[row_rank]++;
}
}
int * recvbuf_index = new int[rbuff_size];
double * recvbuf_values = new double[rbuff_size];
MPI_Alltoallv(sendbuf_index,
send_count,
send_displ,
MPI_INT,
recvbuf_index,
recv_count,
recv_displ,
MPI_INT,
comm);
MPI_Alltoallv(sendbuf_values,
send_count,
send_displ,
MPI_DOUBLE,
recvbuf_values,
recv_count,
recv_displ,
MPI_DOUBLE,
comm);
// Unpack recv buffer
for (int i = 0; i < rbuff_size; i++)
{
int local_index = recvbuf_index[i] - row_start;
y[local_index] = recvbuf_values[i];
}
delete [] recvbuf_values;
delete [] recvbuf_index;
delete [] soffs;
delete [] sendbuf_values;
delete [] sendbuf_index;
delete [] recv_displ;
delete [] send_displ;
delete [] recv_count;
delete [] send_count;
}
#endif
} // namespace mfem
#endif // MFEM_USE_MPI
#endif // MFEM_USE_MUMPS
+156
View File
@@ -0,0 +1,156 @@
// Copyright (c) 2010-2020, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_MUMPS
#define MFEM_MUMPS
#include "../config/config.hpp"
#ifdef MFEM_USE_MUMPS
#ifdef MFEM_USE_MPI
#include "operator.hpp"
#include "hypre.hpp"
#include <mpi.h>
#include "dmumps_c.h"
#include <vector>
namespace mfem
{
/**
* @brief MUMPS: A Parallel Sparse Direct Solver
*
* Interface for the distributed MUMPS solver
*/
class MUMPSSolver : public mfem::Solver
{
public:
enum MatType
{
UNSYMMETRIC = 0,
SYMMETRIC_INDEFINITE = 1,
SYMMETRIC_POSITIVE_DEFINITE = 2
};
/**
* @brief Default Constructor
*/
MUMPSSolver() {}
/**
* @brief Set the Operator and perform factorization
*
* @a op needs to be of type HypreParMatrix.
*
* @param op Operator used in factorization and solve
*/
void SetOperator(const Operator &op);
/**
* @brief Solve y = Op^{-1} x.
*
* @param x RHS vector
* @param y Solution vector
*/
void Mult(const Vector &x, Vector &y) const;
/**
* @brief Transpose Solve y = Op^{-T} x.
*
* @param x RHS vector
* @param y Solution vector
*/
void MultTranspose(const Vector &x, Vector &y) const;
/**
* @brief Set the error print level for MUMPS
*
* @param print_lvl Print level
*
* @note This method has to be called before SetOperator.
*/
void SetPrintLevel(int print_lvl);
/**
* @brief Set the matrix type
*
* Supported matrix types: General, symmetric indefinite and
* symmetric positive definite
*
* @param mtype Matrix type
*
* @note This method has to be called before SetOperator.
*/
void SetMatrixSymType(MatType mtype);
// Destructor
~MUMPSSolver();
private:
// MPI communicator
MPI_Comm comm;
// Number of procs
int numProcs;
// local mpi id
int myid;
// parameter controling the matrix type
MatType mat_type = MatType::UNSYMMETRIC;
// parameter controling the printing level
int print_level = 0;
// local row offsets
int row_start;
// MUMPS object
DMUMPS_STRUC_C *id=nullptr;
// Method for setting MUMPS interal parameters
void SetParameters();
#if MFEM_MUMPS_VERSION >= 530
// row offests array on all procs
Array<int> row_starts;
// row map
int * irhs_loc = nullptr;
// These two methods are needed to distribute the local solution
// vectors returned by MUMPS to the original MFEM parallel partition
int GetRowRank(int i, const Array<int> &row_starts_) const;
void RedistributeSol(const int * row_map,
const double * x,
double * y) const;
#else
// Arrays needed for MPI_Gather and MPI_Scatter
int * recv_counts = nullptr;
int * displs = nullptr;
double * rhs_glob = nullptr;
#endif
}; // mfem::MUMPSSolver class
} // namespace mfem
#endif // MFEM_USE_MPI
#endif // MFEM_USE_MUMPS
#endif // MFEM_MUMPS
+96 -1
View File
@@ -677,7 +677,7 @@ void SDIRK33Solver::Step(Vector &x, double &t, double &dt)
f->SetTime(t + c*dt);
f->ImplicitSolve(a*dt, y, k);
x.Add((1.-a-b)*dt, k);
x.Add((1.0-a-b)*dt, k);
f->SetTime(t + dt);
f->ImplicitSolve(a*dt, x, k);
@@ -685,6 +685,101 @@ void SDIRK33Solver::Step(Vector &x, double &t, double &dt)
t += dt;
}
void TrapezoidalRuleSolver::Init(TimeDependentOperator &_f)
{
ODESolver::Init(_f);
k.SetSize(f->Width(), mem_type);
y.SetSize(f->Width(), mem_type);
}
void TrapezoidalRuleSolver::Step(Vector &x, double &t, double &dt)
{
// 0 | 0 0
// 1 | 1/2 1/2
// ------+-----------
// | 1/2 1/2
f->SetTime(t);
f->Mult(x,k);
add(x, dt/2.0, k, y);
x.Add(dt/2.0, k);
f->SetTime(t + dt);
f->ImplicitSolve(dt/2.0, y, k);
x.Add(dt/2.0, k);
t += dt;
}
void ESDIRK32Solver::Init(TimeDependentOperator &_f)
{
ODESolver::Init(_f);
k.SetSize(f->Width(), mem_type);
y.SetSize(f->Width(), mem_type);
z.SetSize(f->Width(), mem_type);
}
void ESDIRK32Solver::Step(Vector &x, double &t, double &dt)
{
// 0 | 0 0 0
// 2a | a a 0
// 1 | 1-b-a b a
// ------+--------------------
// | 1-b-a b a
const double a = (2.0 - sqrt(2.0)) / 2.0;
const double b = (1.0 - 2.0*a) / (4.0*a);
f->SetTime(t);
f->Mult(x,k);
add(x, a*dt, k, y);
add(x, (1.0-b-a)*dt, k, z);
x.Add((1.0-b-a)*dt, k);
f->SetTime(t + (2.0*a)*dt);
f->ImplicitSolve(a*dt, y, k);
z.Add(b*dt, k);
x.Add(b*dt, k);
f->SetTime(t + dt);
f->ImplicitSolve(a*dt, z, k);
x.Add(a*dt, k);
t += dt;
}
void ESDIRK33Solver::Init(TimeDependentOperator &_f)
{
ODESolver::Init(_f);
k.SetSize(f->Width(), mem_type);
y.SetSize(f->Width(), mem_type);
z.SetSize(f->Width(), mem_type);
}
void ESDIRK33Solver::Step(Vector &x, double &t, double &dt)
{
// 0 | 0 0 0
// 2a | a a 0
// 1 | 1-b-a b a
// ------+----------------------------
// | 1-b_2-b_3 b_2 b_3
const double a = (3.0 + sqrt(3.0)) / 6.0;
const double b = (1.0 - 2.0*a) / (4.0*a);
const double b_2 = 1.0 / ( 12.0*a*(1.0 - 2.0*a) );
const double b_3 = (1.0 - 3.0*a) / ( 3.0*(1.0 - 2.0*a) );
f->SetTime(t);
f->Mult(x,k);
add(x, a*dt, k, y);
add(x, (1.0-b-a)*dt, k, z);
x.Add((1.0-b_2-b_3)*dt, k);
f->SetTime(t + (2.0*a)*dt);
f->ImplicitSolve(a*dt, y, k);
z.Add(b*dt, k);
x.Add(b_2*dt, k);
f->SetTime(t + dt);
f->ImplicitSolve(a*dt, z, k);
x.Add(b_3*dt, k);
t += dt;
}
void GeneralizedAlphaSolver::Init(TimeDependentOperator &_f)
{
+42
View File
@@ -460,6 +460,48 @@ public:
};
/** Two stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
of order 2. A-stable. */
class TrapezoidalRuleSolver : public ODESolver
{
protected:
Vector k, y;
public:
virtual void Init(TimeDependentOperator &_f);
virtual void Step(Vector &x, double &t, double &dt);
};
/** Three stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
of order 2. L-stable. */
class ESDIRK32Solver : public ODESolver
{
protected:
Vector k, y, z;
public:
virtual void Init(TimeDependentOperator &_f);
virtual void Step(Vector &x, double &t, double &dt);
};
/** Three stage, explicit singly diagonal implicit Runge-Kutta (ESDIRK) method
of order 3. A-stable. */
class ESDIRK33Solver : public ODESolver
{
protected:
Vector k, y, z;
public:
virtual void Init(TimeDependentOperator &_f);
virtual void Step(Vector &x, double &t, double &dt);
};
/// Generalized-alpha ODE solver from "A generalized-α method for integrating
/// the filtered Navier-Stokes equations with a stabilized finite element
/// method" by K.E. Jansen, C.H. Whiting and G.M. Hulbert.
+30 -1
View File
@@ -22,6 +22,10 @@
#endif
#endif
#ifdef MFEM_USE_OPENMP
#include <omp.h>
#endif
#include <iostream>
#include <iomanip>
#include <cmath>
@@ -1076,6 +1080,30 @@ double Vector::operator*(const Vector &v) const
#ifdef MFEM_USE_OPENMP
if (Device::Allows(Backend::OMP_MASK))
{
#define MFEM_USE_OPENMP_DETERMINISTIC_DOT
#ifdef MFEM_USE_OPENMP_DETERMINISTIC_DOT
// By default, use a deterministic way of computing the dot product
static Vector th_dot;
#pragma omp parallel
{
const int nt = omp_get_num_threads();
#pragma omp master
th_dot.SetSize(nt);
const int tid = omp_get_thread_num();
const int stride = (size + nt - 1)/nt;
const int start = tid*stride;
const int stop = std::min(start + stride, size);
double my_dot = 0.0;
for (int i = start; i < stop; i++)
{
my_dot += m_data[i] * v_data[i];
}
#pragma omp barrier
th_dot(tid) = my_dot;
}
return th_dot.Sum();
#else
// The standard way of computing the dot product is non-deterministic
double prod = 0.0;
#pragma omp parallel for reduction(+:prod)
for (int i = 0; i < size; i++)
@@ -1083,8 +1111,9 @@ double Vector::operator*(const Vector &v) const
prod += m_data[i] * v_data[i];
}
return prod;
#endif // MFEM_USE_OPENMP_DETERMINISTIC_DOT
}
#endif
#endif // MFEM_USE_OPENMP
if (Device::Allows(Backend::DEBUG_DEVICE))
{
const int N = size;
+9
View File
@@ -42,10 +42,19 @@ namespace mfem
inline int CheckFinite(const double *v, const int n);
/// Define a shortcut for std::numeric_limits<double>::infinity()
#ifndef __CYGWIN__
inline double infinity()
{
return std::numeric_limits<double>::infinity();
}
#else
// On Cygwin math.h defines a function 'infinity()' which will conflict with the
// above definition if we have 'using namespace mfem;' and try to use something
// like 'double a = infinity();'. This 'infinity()' function is non-standard and
// is defined by the Newlib C standard library implementation used by Cygwin,
// see https://en.wikipedia.org/wiki/Newlib, http://www.sourceware.org/newlib.
using ::infinity;
#endif
/// Vector data type.
class Vector
+7 -5
View File
@@ -10,7 +10,7 @@
# CONTRIBUTING.md for details.
# The current MFEM version as an integer, see also `CMakeLists.txt`.
MFEM_VERSION = 40200
MFEM_VERSION = 40201
MFEM_VERSION_STRING = $(shell printf "%06d" $(MFEM_VERSION) | \
sed -e 's/^0*\(.*.\)\(..\)\(..\)$$/\1.\2.\3/' -e 's/\.0/./g' -e 's/\.0$$//')
@@ -204,7 +204,7 @@ CXXFLAGS ?= $(OPTIM_FLAGS)
# MPI configuration
ifneq ($(MFEM_USE_MPI),YES)
MFEM_HOST_CXX = $(CXX)
PKGS_NEED_MPI = SUPERLU STRUMPACK PETSC PUMI SLEPC MKL_CPARDISO
PKGS_NEED_MPI = SUPERLU MUMPS STRUMPACK PETSC PUMI SLEPC MKL_CPARDISO
$(foreach mpidep,$(PKGS_NEED_MPI),$(if $(MFEM_USE_$(mpidep):NO=),\
$(warning *** [MPI is OFF] setting MFEM_USE_$(mpidep) = NO)\
$(eval override MFEM_USE_$(mpidep)=NO),))
@@ -265,7 +265,7 @@ ifeq ($(MFEM_USE_LEGACY_OPENMP),YES)
endif
# List of MFEM dependencies, that require the *_LIB variable to be non-empty
MFEM_REQ_LIB_DEPS = SUPERLU METIS CONDUIT SIDRE LAPACK SUNDIALS MESQUITE\
MFEM_REQ_LIB_DEPS = SUPERLU MUMPS METIS CONDUIT SIDRE LAPACK SUNDIALS MESQUITE\
SUITESPARSE STRUMPACK GINKGO GNUTLS NETCDF PETSC SLEPC MPFR PUMI HIOP GSLIB\
OCCA CEED RAJA UMPIRE MKL_CPARDISO AMGX
@@ -332,7 +332,8 @@ MFEM_DEFINES = MFEM_VERSION MFEM_VERSION_STRING MFEM_GIT_STRING MFEM_USE_MPI\
MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_CONDUIT MFEM_USE_PUMI\
MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA MFEM_USE_HIP MFEM_USE_OCCA\
MFEM_USE_CEED MFEM_USE_RAJA MFEM_USE_UMPIRE MFEM_USE_SIMD MFEM_USE_ADIOS2\
MFEM_USE_MKL_CPARDISO MFEM_USE_AMGX MFEM_SOURCE_DIR MFEM_INSTALL_DIR
MFEM_USE_MKL_CPARDISO MFEM_USE_AMGX MFEM_USE_MUMPS MFEM_SOURCE_DIR\
MFEM_INSTALL_DIR
# List of makefile variables that will be written to config.mk:
MFEM_CONFIG_VARS = MFEM_CXX MFEM_HOST_CXX MFEM_CPPFLAGS MFEM_CXXFLAGS\
@@ -366,7 +367,7 @@ MFEM_INSTALL_DIR = $(abspath $(MFEM_PREFIX))
# If we have 'config' target, export variables used by config/makefile
ifneq (,$(filter config,$(MAKECMDGOALS)))
export $(MFEM_DEFINES) MFEM_DEFINES $(MFEM_CONFIG_VARS) MFEM_CONFIG_VARS
export VERBOSE HYPRE_OPT PUMI_DIR
export VERBOSE HYPRE_OPT PUMI_DIR MUMPS_OPT
endif
# If we have 'install' target, export variables used by config/makefile
@@ -634,6 +635,7 @@ status info:
$(info MFEM_USE_MESQUITE = $(MFEM_USE_MESQUITE))
$(info MFEM_USE_SUITESPARSE = $(MFEM_USE_SUITESPARSE))
$(info MFEM_USE_SUPERLU = $(MFEM_USE_SUPERLU))
$(info MFEM_USE_MUMPS = $(MFEM_USE_MUMPS))
$(info MFEM_USE_STRUMPACK = $(MFEM_USE_STRUMPACK))
$(info MFEM_USE_GINKGO = $(MFEM_USE_GINKGO))
$(info MFEM_USE_AMGX = $(MFEM_USE_AMGX))
+240 -2
View File
@@ -29,6 +29,7 @@
#include <cstring>
#include <ctime>
#include <functional>
#include <unordered_set>
// Include the METIS header, if using version 5. If using METIS 4, the needed
// declarations are inlined below, i.e. no header is needed.
@@ -71,10 +72,14 @@ void Mesh::GetElementCenter(int i, Vector &center)
eltransf->Transform(Geometries.GetCenter(geom), center);
}
double Mesh::GetElementSize(int i, int type)
double Mesh::GetElementSize(ElementTransformation *T, int type)
{
DenseMatrix J(Dim);
GetElementJacobian(i, J);
Geometry::Type geom = T->GetGeometryType();
T->SetIntPoint(&Geometries.GetCenter(geom));
Geometries.JacToPerfJac(geom, T->Jacobian(), J);
if (type == 0)
{
return pow(fabs(J.Det()), 1./Dim);
@@ -89,6 +94,11 @@ double Mesh::GetElementSize(int i, int type)
}
}
double Mesh::GetElementSize(int i, int type)
{
return GetElementSize(GetElementTransformation(i), type);
}
double Mesh::GetElementSize(int i, const Vector &dir)
{
DenseMatrix J(Dim);
@@ -1463,6 +1473,13 @@ void Mesh::AddBdrQuadAsTriangles(const int *vi, int attr)
}
}
int Mesh::AddBdrPoint(int v, int attr)
{
CheckEnlarge(boundary, NumOfBdrElements);
boundary[NumOfBdrElements] = new Point(&v, attr);
return NumOfBdrElements++;
}
void Mesh::GenerateBoundaryElements()
{
int i, j;
@@ -10533,6 +10550,227 @@ void Mesh::RemoveInternalBoundaries()
attribs.Copy(bdr_attributes);
}
void Mesh::RemoveInternalBoundaries(const Array<int> &_keep)
{
if (NURBSext || ncmesh) { return; }
std::unordered_set<int> keep(_keep.GetData(),
_keep.GetData() + _keep.Size());
int num_bdr_elem = 0;
int new_bel_to_edge_nnz = 0;
for (int i = 0; i < GetNBE(); i++)
{
if (FaceIsInterior(GetBdrElementEdgeIndex(i)) &&
(keep.count(boundary[i]->GetAttribute()) == 0))
{
FreeElement(boundary[i]);
}
else
{
num_bdr_elem++;
if (Dim == 3)
{
new_bel_to_edge_nnz += bel_to_edge->RowSize(i);
}
}
}
if (num_bdr_elem == GetNBE()) { return; }
Array<Element *> new_boundary(num_bdr_elem);
Array<int> new_be_to_edge, new_be_to_face;
Table *new_bel_to_edge = NULL;
new_boundary.SetSize(0);
if (Dim == 2)
{
new_be_to_edge.Reserve(num_bdr_elem);
}
else if (Dim == 3)
{
new_be_to_face.Reserve(num_bdr_elem);
new_bel_to_edge = new Table;
new_bel_to_edge->SetDims(num_bdr_elem, new_bel_to_edge_nnz);
}
for (int i = 0; i < GetNBE(); i++)
{
/// if it's not interior or is in the keep boundary list
if (!FaceIsInterior(GetBdrElementEdgeIndex(i)) ||
keep.count(boundary[i]->GetAttribute()))
{
new_boundary.Append(boundary[i]);
if (Dim == 2)
{
new_be_to_edge.Append(be_to_edge[i]);
}
else if (Dim == 3)
{
int row = new_be_to_face.Size();
new_be_to_face.Append(be_to_face[i]);
int *e = bel_to_edge->GetRow(i);
int ne = bel_to_edge->RowSize(i);
int *new_e = new_bel_to_edge->GetRow(row);
for (int j = 0; j < ne; j++)
{
new_e[j] = e[j];
}
new_bel_to_edge->GetI()[row+1] = new_bel_to_edge->GetI()[row] + ne;
}
}
}
NumOfBdrElements = new_boundary.Size();
mfem::Swap(boundary, new_boundary);
if (Dim == 2)
{
mfem::Swap(be_to_edge, new_be_to_edge);
}
else if (Dim == 3)
{
mfem::Swap(be_to_face, new_be_to_face);
delete bel_to_edge;
bel_to_edge = new_bel_to_edge;
}
Array<int> attribs(num_bdr_elem);
for (int i = 0; i < attribs.Size(); i++)
{
attribs[i] = GetBdrAttribute(i);
}
attribs.Sort();
attribs.Unique();
bdr_attributes.DeleteAll();
attribs.Copy(bdr_attributes);
}
void Mesh::RemoveInternalBoundariesNotAdjacentTo(const Array<int> &_regions)
{
if (NURBSext || ncmesh) { return; }
std::unordered_set<int> regions(_regions.GetData(),
_regions.GetData() + _regions.Size());
int num_bdr_elem = 0;
int new_bel_to_edge_nnz = 0;
for (int i = 0; i < GetNBE(); i++)
{
auto faceNo = GetBdrElementEdgeIndex(i);
bool interior = FaceIsInterior(faceNo);
auto face_info = faces_info[faceNo];
auto adj = regions.count(elements[face_info.Elem1No]->GetAttribute());
if (face_info.Elem2No > 0)
adj += regions.count(elements[face_info.Elem2No]->GetAttribute());
bool remove = interior & !adj;
// if (remove)
// {
// std::cout << "remove face on: " << boundary[i]->GetAttribute()
// << " adj to ("
// << elements[face_info.Elem1No]->GetAttribute();
// if (face_info.Elem2No > 0)
// {
// std::cout << ", "
// << elements[face_info.Elem2No]->GetAttribute() << ")\n";
// }
// else
// {
// std::cout << ")\n";
// }
// }
if (remove)
{
FreeElement(boundary[i]);
}
else
{
num_bdr_elem++;
if (Dim == 3)
{
new_bel_to_edge_nnz += bel_to_edge->RowSize(i);
}
}
}
if (num_bdr_elem == GetNBE()) { return; }
Array<Element *> new_boundary(num_bdr_elem);
Array<int> new_be_to_edge, new_be_to_face;
Table *new_bel_to_edge = NULL;
new_boundary.SetSize(0);
if (Dim == 2)
{
new_be_to_edge.Reserve(num_bdr_elem);
}
else if (Dim == 3)
{
new_be_to_face.Reserve(num_bdr_elem);
new_bel_to_edge = new Table;
new_bel_to_edge->SetDims(num_bdr_elem, new_bel_to_edge_nnz);
}
for (int i = 0; i < GetNBE(); i++)
{
auto faceNo = GetBdrElementEdgeIndex(i);
bool interior = FaceIsInterior(faceNo);
auto face_info = faces_info[faceNo];
auto adj = regions.count(elements[face_info.Elem1No]->GetAttribute());
if (face_info.Elem2No > 0)
adj += regions.count(elements[face_info.Elem2No]->GetAttribute());
bool keep = !interior || adj;
if (keep)
{
new_boundary.Append(boundary[i]);
if (Dim == 2)
{
new_be_to_edge.Append(be_to_edge[i]);
}
else if (Dim == 3)
{
int row = new_be_to_face.Size();
new_be_to_face.Append(be_to_face[i]);
int *e = bel_to_edge->GetRow(i);
int ne = bel_to_edge->RowSize(i);
int *new_e = new_bel_to_edge->GetRow(row);
for (int j = 0; j < ne; j++)
{
new_e[j] = e[j];
}
new_bel_to_edge->GetI()[row+1] = new_bel_to_edge->GetI()[row] + ne;
}
}
}
NumOfBdrElements = new_boundary.Size();
mfem::Swap(boundary, new_boundary);
if (Dim == 2)
{
mfem::Swap(be_to_edge, new_be_to_edge);
}
else if (Dim == 3)
{
mfem::Swap(be_to_face, new_be_to_face);
delete bel_to_edge;
bel_to_edge = new_bel_to_edge;
}
Array<int> attribs(num_bdr_elem);
for (int i = 0; i < attribs.Size(); i++)
{
attribs[i] = GetBdrAttribute(i);
}
attribs.Sort();
attribs.Unique();
bdr_attributes.DeleteAll();
attribs.Copy(bdr_attributes);
}
void Mesh::FreeElement(Element *E)
{
#ifdef MFEM_USE_MEMALLOC
+10
View File
@@ -471,6 +471,8 @@ protected:
void GetElementData(const Array<Element*> &elem_array, int geom,
Array<int> &elem_vtx, Array<int> &attr) const;
double GetElementSize(ElementTransformation *T, int type = 0);
public:
Mesh() { SetEmpty(); }
@@ -555,6 +557,8 @@ public:
int AddBdrQuad(const int *vi, int attr = 1);
void AddBdrQuadAsTriangles(const int *vi, int attr = 1);
int AddBdrPoint(int v, int attr = 1);
void GenerateBoundaryElements();
/// Finalize the construction of a triangular Mesh.
void FinalizeTriMesh(int generate_edges = 0, int refine = 0,
@@ -1302,6 +1306,12 @@ public:
have two adjacent faces in 3D, or edges in 2D. */
void RemoveInternalBoundaries();
/** Remove boundary elements that lie in the interior of the mesh, except
for those with boundary attributes in `keep` */
void RemoveInternalBoundaries(const Array<int> &keep);
void RemoveInternalBoundariesNotAdjacentTo(const Array<int> &regions);
/** @brief Get the size of the i-th element relative to the perfect
reference element. */
double GetElementSize(int i, int type = 0);
+5
View File
@@ -1735,6 +1735,11 @@ void ParMesh::GetFaceNbrElementTransformation(
}
}
double ParMesh::GetFaceNbrElementSize(int i, int type)
{
return GetElementSize(GetFaceNbrElementTransformation(i), type);
}
void ParMesh::DeleteFaceNbrData()
{
if (!have_face_nbr_data)
+4
View File
@@ -305,6 +305,10 @@ public:
return &FaceNbrTransformation;
}
/// Get the size of the i-th face neighbor element relative to the reference
/// element.
double GetFaceNbrElementSize(int i, int type=0);
/// Return the number of shared faces (3D), edges (2D), vertices (1D)
int GetNSharedFaces() const;
+62 -4
View File
@@ -351,6 +351,7 @@ int main (int argc, char *argv[])
"e) View elements\n"
"h) View element sizes, h\n"
"k) View element ratios, kappa\n"
"J) View scaled Jacobian\n"
"l) Plot a function\n"
"x) Print sub-element stats\n"
"f) Find physical point in reference space\n"
@@ -558,6 +559,8 @@ int main (int argc, char *argv[])
cin >> sd;
Array<int> bad_elems_by_geom(Geometry::NumGeom);
bad_elems_by_geom = 0;
// Only print so many to keep output compact
const int max_to_print = 10;
for (int i = 0; i < mesh->GetNE(); i++)
{
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
@@ -589,10 +592,23 @@ int main (int argc, char *argv[])
max_det_J = fmax(max_det_J, max_det_J_z);
if (min_det_J_z <= 0.0)
{
if (nz < max_to_print)
{
Vector center;
mesh->GetElementCenter(i, center);
cout << "det(J) < 0 = " << min_det_J_z << " in element "
<< i << ", centered at: ";
center.Print();
}
nz++;
bad_elems_by_geom[geom]++;
}
}
if (nz >= max_to_print)
{
cout << "det(J) < 0 for " << nz - max_to_print << " more elements "
<< "not printed.\n";
}
cout << "\nbad elements = " << nz;
if (nz)
{
@@ -692,7 +708,7 @@ int main (int argc, char *argv[])
// These are most of the cases that open a new GLVis window
if (mk == 'm' || mk == 'b' || mk == 'e' || mk == 'v' || mk == 'h' ||
mk == 'k' || mk == 'p')
mk == 'k' || mk == 'J' || mk == 'p')
{
Array<int> bdr_part;
Array<int> part(mesh->GetNE());
@@ -765,7 +781,7 @@ int main (int argc, char *argv[])
h_max = -h_min;
for (int i = 0; i < mesh->GetNE(); i++)
{
int geom = mesh->GetElementBaseGeometry(i);
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
ElementTransformation *T = mesh->GetElementTransformation(i);
T->SetIntPoint(&Geometries.GetCenter(geom));
Geometries.JacToPerfJac(geom, T->Jacobian(), J);
@@ -790,7 +806,7 @@ int main (int argc, char *argv[])
DenseMatrix J(dim);
for (int i = 0; i < mesh->GetNE(); i++)
{
int geom = mesh->GetElementBaseGeometry(i);
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
ElementTransformation *T = mesh->GetElementTransformation(i);
T->SetIntPoint(&Geometries.GetCenter(geom));
Geometries.JacToPerfJac(geom, T->Jacobian(), J);
@@ -798,6 +814,48 @@ int main (int argc, char *argv[])
}
}
if (mk == 'J')
{
// The "scaled Jacobian" is the determinant of the Jacobian scaled
// by the l2 norms of its columns. It can be used to identify badly
// skewed elements, since it takes values between 0 and 1, with 0
// corresponding to a flat element, and 1 to orthogonal columns.
DenseMatrix J(dim);
int sd;
cout << "subdivision factor ---> " << flush;
cin >> sd;
for (int i = 0; i < mesh->GetNE(); i++)
{
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
ElementTransformation *T = mesh->GetElementTransformation(i);
RefinedGeometry *RefG = GlobGeometryRefiner.Refine(geom, sd, 1);
IntegrationRule &ir = RefG->RefPts;
// For each element, find the minimal scaled Jacobian in a
// lattice of points with the given subdivision factor.
attr(i) = infinity();
for (int j = 0; j < ir.GetNPoints(); j++)
{
T->SetIntPoint(&ir.IntPoint(j));
Geometries.JacToPerfJac(geom, T->Jacobian(), J);
// Jacobian determinant
double sJ = J.Det();
for (int k = 0; k < J.Width(); k++)
{
Vector col;
J.GetColumnReference(k,col);
// Scale by column norms
sJ /= col.Norml2();
}
attr(i) = fmin(sJ, attr(i));
}
}
}
if (mk == 'p')
{
int *partitioning = NULL, np;
@@ -950,7 +1008,7 @@ int main (int argc, char *argv[])
else
{
sol_sock << "fem3d_gf_data_keys\n";
if (mk == 'v' || mk == 'h' || mk == 'k')
if (mk == 'v' || mk == 'h' || mk == 'k' || mk == 'J')
{
mesh->Print(sol_sock);
}
+29
View File
@@ -290,6 +290,21 @@ void NavierSolver::Setup(double dt)
un_gf.GetTrueDofs(un);
if (filter_alpha != 0.0)
{
vfec_filter = new H1_FECollection(order - filter_cutoff_modes,
pmesh->Dimension());
vfes_filter = new ParFiniteElementSpace(pmesh,
vfec_filter,
pmesh->Dimension());
un_NM1_gf.SetSpace(vfes_filter);
un_NM1_gf = 0.0;
un_filtered_gf.SetSpace(vfes);
un_filtered_gf = 0.0;
}
sw_setup.Stop();
}
@@ -518,6 +533,18 @@ void NavierSolver::Step(double &time, double dt, int cur_step)
un_gf.GetTrueDofs(un);
if (filter_alpha != 0.0)
{
un_NM1_gf.ProjectGridFunction(un_gf);
un_filtered_gf.ProjectGridFunction(un_NM1_gf);
const auto d_un_filtered_gf = un_filtered_gf.Read();
auto d_un_gf = un_gf.ReadWrite();
MFEM_FORALL(i,
un_gf.Size(),
d_un_gf[i] = (1.0 - filter_alpha) * d_un_gf[i]
+ filter_alpha * d_un_filtered_gf[i];);
}
sw_step.Stop();
if (verbose && pmesh->GetMyRank() == 0)
@@ -1075,4 +1102,6 @@ NavierSolver::~NavierSolver()
delete pfec;
delete vfes;
delete pfes;
delete vfec_filter;
delete vfes_filter;
}
+21
View File
@@ -241,6 +241,19 @@ public:
/// Compute CFL
double ComputeCFL(ParGridFunction &u, double dt);
/// Set the number of modes to cut off in the interpolation filter
void SetCutoffModes(int c) { filter_cutoff_modes = c; }
/// Set the interpolation filter parameter @a a
/**
* If @a a is > 0, the filtering algorithm for the velocity field after every
* time step from [1] is used. The parameter should be 0 > @a >= 1.
*
* [1] Paul Fischer, Julia Mullen (2001) Filter-based stabilization of
* spectral element methods
*/
void SetFilterAlpha(double a) { filter_alpha = a; }
protected:
/// Print informations about the Navier version.
void PrintInfo();
@@ -412,6 +425,14 @@ protected:
OperatorHandle Mv_lor;
OperatorHandle Sp_lor;
OperatorHandle H_lor;
// Filter-based stabilization
int filter_cutoff_modes = 1;
double filter_alpha = 0.0;
FiniteElementCollection *vfec_filter = nullptr;
ParFiniteElementSpace *vfes_filter = nullptr;
ParGridFunction un_NM1_gf;
ParGridFunction un_filtered_gf;
};
} // namespace navier
+9 -1
View File
@@ -26,6 +26,7 @@
// mpirun -np 4 prates -m ../../data/inline-hex.mesh -sr 0 -pr 1 -prob 1 -o 3
// mpirun -np 4 prates -m ../../data/square-disc.mesh -sr 1 -pr 2 -prob 1 -o 2
// mpirun -np 4 prates -m ../../data/star.mesh -sr 1 -pr 2 -prob 3 -o 2
// mpirun -np 4 prates -m ../../data/star.mesh -sr 1 -pr 2 -prob 3 -o 2 -j 0
// mpirun -np 4 prates -m ../../data/inline-hex.mesh -sr 1 -pr 1 -prob 3 -o 2
//
// Description: This example code demonstrates the use of MFEM to define and
@@ -80,6 +81,7 @@ int main(int argc, char *argv[])
bool visualization = 1;
int sr = 1;
int pr = 1;
int jump_scaling_type = 1;
double sigma = -1.0;
double kappa = -1.0;
OptionsParser args(argc, argv);
@@ -95,6 +97,9 @@ int main(int argc, char *argv[])
args.AddOption(&kappa, "-k", "--kappa",
"One of the two DG penalty parameters, should be positive."
" Negative values are replaced with (order+1)^2.");
args.AddOption(&jump_scaling_type, "-j", "--jump-scaling",
"Scaling of the jump error for DG methods: "
"0: no scaling, 1: 1/h, 2: p^2/h");
args.AddOption(&sr, "-sr", "--serial_ref",
"Number of serial refinements.");
args.AddOption(&pr, "-pr", "--parallel_ref",
@@ -285,12 +290,15 @@ int main(int argc, char *argv[])
delete solver;
x = *X;
JumpScaling js(1.0, jump_scaling_type == 2 ? JumpScaling::P_SQUARED_OVER_H
: jump_scaling_type == 1 ? JumpScaling::ONE_OVER_H
: JumpScaling::CONSTANT);
switch (prob)
{
case 0: rates.AddH1GridFunction(&x,scalar_u,gradu); break;
case 1: rates.AddHcurlGridFunction(&x,vector_u,curlu); break;
case 2: rates.AddHdivGridFunction(&x,vector_u,divu); break;
case 3: rates.AddL2GridFunction(&x,scalar_u,gradu,&one); break;
case 3: rates.AddL2GridFunction(&x,scalar_u,gradu,&one,js); break;
}
delete X;
+10 -1
View File
@@ -26,6 +26,7 @@
// rates -m ../../data/inline-hex.mesh -sr 1 -prob 1 -o 2
// rates -m ../../data/square-disc.mesh -sr 2 -prob 1 -o 1
// rates -m ../../data/star.mesh -sr 2 -prob 3 -o 2
// rates -m ../../data/star.mesh -sr 2 -prob 3 -o 2 -j 0
// rates -m ../../data/inline-hex.mesh -sr 1 -prob 3 -o 1
//
// Description: This example code demonstrates the use of MFEM to define and
@@ -73,6 +74,7 @@ int main(int argc, char *argv[])
int order = 1;
bool visualization = 1;
int sr = 1;
int jump_scaling_type = 1;
double sigma = -1.0;
double kappa = -1.0;
OptionsParser args(argc, argv);
@@ -88,6 +90,9 @@ int main(int argc, char *argv[])
args.AddOption(&kappa, "-k", "--kappa",
"One of the two DG penalty parameters, should be positive."
" Negative values are replaced with (order+1)^2.");
args.AddOption(&jump_scaling_type, "-j", "--jump-scaling",
"Scaling of the jump error for DG methods: "
"0: no scaling, 1: 1/h, 2: p^2/h");
args.AddOption(&sr, "-sr", "--serial_ref",
"Number of serial refinements.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
@@ -218,12 +223,16 @@ int main(int argc, char *argv[])
PCG(A, M, b, x, 0, 500, 1e-12, 0.0);
}
JumpScaling js(1.0, jump_scaling_type == 2 ? JumpScaling::P_SQUARED_OVER_H
: jump_scaling_type == 1 ? JumpScaling::ONE_OVER_H
: JumpScaling::CONSTANT);
switch (prob)
{
case 0: rates.AddH1GridFunction(&x,scalar_u,gradu); break;
case 1: rates.AddHcurlGridFunction(&x,vector_u,curlu); break;
case 2: rates.AddHdivGridFunction(&x,vector_u,divu); break;
case 3: rates.AddL2GridFunction(&x,scalar_u,gradu,&one); break;
case 3: rates.AddL2GridFunction(&x,scalar_u,gradu,&one,js); break;
}
if (l==sr) break;
+58 -31
View File
@@ -1,6 +1,6 @@
/*
* Catch v2.13.0
* Generated: 2020-07-12 20:07:49.015950
* Catch v2.13.2
* Generated: 2020-10-07 11:32:53.302017
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 13
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header
@@ -132,13 +132,9 @@ namespace Catch {
#endif
#if defined(__cpp_lib_uncaught_exceptions)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
// We have to avoid both ICC and Clang, because they try to mask themselves
// as gcc, and we want only GCC in this block
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC)
#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__)
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
@@ -162,7 +158,7 @@ namespace Catch {
// ```
//
// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
# if !defined(__ibmxl__)
# if !defined(__ibmxl__) && !defined(__CUDACC__)
# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
# endif
@@ -244,10 +240,6 @@ namespace Catch {
# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
// Universal Windows platform does not support SEH
// Or console colours (or console at all...)
# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
@@ -330,7 +322,10 @@ namespace Catch {
// Check if byte is available and usable
# if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
# include <cstddef>
# if __cpp_lib_byte > 0
# define CATCH_INTERNAL_CONFIG_CPP17_BYTE
# endif
# endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
// Check if variant is available and usable
@@ -373,10 +368,6 @@ namespace Catch {
# define CATCH_CONFIG_CPP17_OPTIONAL
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
# define CATCH_CONFIG_CPP17_STRING_VIEW
#endif
@@ -1105,7 +1096,7 @@ struct AutoReg : NonCopyable {
int index = 0; \
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
using expander = int[];\
(void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \
(void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -1151,7 +1142,7 @@ struct AutoReg : NonCopyable {
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\
} \
}; \
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
@@ -1195,7 +1186,7 @@ struct AutoReg : NonCopyable {
void reg_tests() { \
int index = 0; \
using expander = int[]; \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\
} \
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
@@ -1229,7 +1220,7 @@ struct AutoReg : NonCopyable {
int index = 0; \
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
using expander = int[];\
(void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \
(void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -1278,7 +1269,7 @@ struct AutoReg : NonCopyable {
constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -1325,7 +1316,7 @@ struct AutoReg : NonCopyable {
void reg_tests(){\
int index = 0;\
using expander = int[];\
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \
(void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \
}\
};\
static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
@@ -1829,8 +1820,8 @@ namespace Catch {
#endif
namespace Detail {
template<typename InputIterator>
std::string rangeToString(InputIterator first, InputIterator last) {
template<typename InputIterator, typename Sentinel = InputIterator>
std::string rangeToString(InputIterator first, Sentinel last) {
ReusableStringStream rss;
rss << "{ ";
if (first != last) {
@@ -12042,7 +12033,7 @@ namespace Catch {
if (tmpnam_s(m_buffer)) {
CATCH_RUNTIME_ERROR("Could not get a temp filename");
}
if (fopen_s(&m_file, m_buffer, "w")) {
if (fopen_s(&m_file, m_buffer, "w+")) {
char buffer[100];
if (strerror_s(buffer, errno)) {
CATCH_RUNTIME_ERROR("Could not translate errno to a string");
@@ -14091,10 +14082,10 @@ namespace Catch {
namespace {
struct TestHasher {
explicit TestHasher(Catch::SimplePcg32& rng) {
basis = rng();
explicit TestHasher(Catch::SimplePcg32& rng_instance) {
basis = rng_instance();
basis <<= 32;
basis |= rng();
basis |= rng_instance();
}
uint64_t basis;
@@ -15192,6 +15183,41 @@ namespace Catch {
// end catch_totals.cpp
// start catch_uncaught_exceptions.cpp
// start catch_config_uncaught_exceptions.hpp
// Copyright Catch2 Authors
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
// SPDX-License-Identifier: BSL-1.0
#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
#if defined(_MSC_VER)
# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
# endif
#endif
#include <exception>
#if defined(__cpp_lib_uncaught_exceptions) \
&& !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif // __cpp_lib_uncaught_exceptions
#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
&& !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
&& !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
#endif
#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
// end catch_config_uncaught_exceptions.hpp
#include <exception>
namespace Catch {
@@ -15238,7 +15264,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 13, 0, "", 0 );
static Version version( 2, 13, 2, "", 0 );
return version;
}
@@ -17796,3 +17822,4 @@ using Catch::Detail::Approx;
// end catch_reenable_warnings.h
// end catch.hpp
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
+2 -2
View File
@@ -10,9 +10,9 @@
// CONTRIBUTING.md for details.
#include <fstream>
using namespace std;
#include "mfem.hpp"
using namespace std;
using namespace mfem;
#include "unit_tests.hpp"
+18
View File
@@ -251,6 +251,24 @@ TEST_CASE("First order ODE methods",
REQUIRE(conv_rate + tol > 4.0);
}
SECTION("TrapezoidalRuleSolver")
{
std::cout <<"\nTesting TrapezoidalRuleSolver" << std::endl;
REQUIRE(check.order(new TrapezoidalRuleSolver) + tol > 2.0 );
}
SECTION("ESDIRK32Solver")
{
std::cout <<"\nTesting ESDIRK32Solver" << std::endl;
REQUIRE(check.order(new ESDIRK32Solver) + tol > 2.0 );
}
SECTION("ESDIRK33Solver")
{
std::cout <<"\nTesting ESDIRK33Solver" << std::endl;
REQUIRE(check.order(new ESDIRK33Solver) + tol > 3.0 );
}
// Generalized-alpha
SECTION("GeneralizedAlphaSolver(1.0)")
{
+8 -8
View File
@@ -98,14 +98,14 @@ struct Tensors1D
template<int DIM, int D1D, int Q1D, int L1D, int H1D, int NBZ =1> static
void kSmemForceMult2D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Array<double> &_Gt,
const DenseTensor &_sJit,
const Vector &_e,
Vector &_v)
{
auto b = Reshape(_B.Read(), Q1D, L1D);
auto b = Reshape(B_.Read(), Q1D, L1D);
auto bt = Reshape(_Bt.Read(), H1D, Q1D);
auto gt = Reshape(_Gt.Read(), H1D, Q1D);
auto sJit = Reshape(Read(_sJit.GetMemory(), Q1D*Q1D*NE*2*2),
@@ -241,14 +241,14 @@ void kSmemForceMult2D(const int NE,
template<int DIM, int D1D, int Q1D, int L1D, int H1D> static
void kSmemForceMult3D(const int NE,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_Bt,
const Array<double> &_Gt,
const DenseTensor &_sJit,
const Vector &_e,
Vector &_v)
{
auto b = Reshape(_B.Read(), Q1D, L1D);
auto b = Reshape(B_.Read(), Q1D, L1D);
auto bt = Reshape(_Bt.Read(), H1D, Q1D);
auto gt = Reshape(_Gt.Read(), H1D, Q1D);
auto sJit = Reshape(Read(_sJit.GetMemory(), Q1D*Q1D*Q1D*NE*3*3),
@@ -493,14 +493,14 @@ static void kForceMult(const int DIM,
template<int DIM, int D1D, int Q1D, int L1D, int H1D, int NBZ =1> static
void kSmemForceMultTranspose2D(const int NE,
const Array<double> &_Bt,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_G,
const DenseTensor &_sJit,
const Vector &_v,
Vector &_e)
{
MFEM_VERIFY(D1D==H1D,"");
auto b = Reshape(_B.Read(), Q1D,H1D);
auto b = Reshape(B_.Read(), Q1D,H1D);
auto g = Reshape(_G.Read(), Q1D,H1D);
auto bt = Reshape(_Bt.Read(), L1D,Q1D);
auto sJit = Reshape(Read(_sJit.GetMemory(), Q1D*Q1D*NE*2*2),
@@ -633,14 +633,14 @@ void kSmemForceMultTranspose2D(const int NE,
template<int DIM, int D1D, int Q1D, int L1D, int H1D> static
void kSmemForceMultTranspose3D(const int NE,
const Array<double> &_Bt,
const Array<double> &_B,
const Array<double> &B_,
const Array<double> &_G,
const DenseTensor &_sJit,
const Vector &_v,
Vector &_e)
{
MFEM_VERIFY(D1D==H1D,"");
auto b = Reshape(_B.Read(), Q1D,H1D);
auto b = Reshape(B_.Read(), Q1D,H1D);
auto g = Reshape(_G.Read(), Q1D,H1D);
auto bt = Reshape(_Bt.Read(), L1D,Q1D);
auto sJit = Reshape(Read(_sJit.GetMemory(), Q1D*Q1D*Q1D*NE*3*3),