Compare commits

...
304 Commits
Author SHA1 Message Date
Brendan Keith e7e0ed79e6 fixed BC issue 2024-04-14 14:59:23 -04:00
Brendan Keith 7359466ce4 fix sign error 2024-04-12 08:12:42 -04:00
Brendan Keith d5814b9d8e fixed invertibility bug 2024-04-11 22:28:15 -04:00
Brendan Keith 7dd2312ec4 minor 2024-04-11 18:56:53 -04:00
Brendan Keith aa25a12086 changing to direct solver 2024-04-11 18:05:56 -04:00
Brendan Keith 3341feb1d3 linearized problem solved. memory leak 2024-04-11 17:37:39 -04:00
Brendan Keith a6f7baeede fixed the runtime issues with integrators 2024-04-10 11:32:58 -04:00
Brendan Keith bc2ee7f3a9 layout of ex40.cpp done 2024-04-10 10:17:49 -04:00
Brendan Keith 2bcae01f71 outline of MA code 2024-04-09 21:17:45 -04:00
Brendan Keith cde13ad145 Merge branch '2x2_matrix_exponential' into MA 2024-04-09 15:26:27 -04:00
Brendan Keith 6baf95a686 Merge branch 'master' into 2x2_matrix_exponential 2024-04-09 07:00:04 -04:00
Tzanio Kolev 91710623f8 Merge pull request #4203 from mfem/stefanozampini/petsc-3.21
Changes to support PETSc 3.21 (to be released March 29th) and single precision builds
2024-04-08 06:22:04 -07:00
Tzanio Kolev eddecd5dc6 PETSc version requirement updated to 3.21 2024-04-08 06:21:15 -07:00
Brendan Keith 4ebbbc45ae override 2024-04-07 22:20:52 -04:00
Brendan Keith 77a3bb103c style 2024-04-07 22:12:02 -04:00
Brendan Keith f728fadcf7 more work on ex40 2024-04-07 22:11:21 -04:00
Brendan Keith ae3b9e23e7 Merge branch 'master' into 2x2_matrix_exponential 2024-04-07 22:09:37 -04:00
Brendan KeithandDohyun Kim 0494eb22e6 Update fem/coefficient.hpp
Co-authored-by: Dohyun Kim <dhkim.cse@gmail.com>
2024-04-07 22:08:55 -04:00
Brendan KeithandDohyun Kim 31a977ac5f Update fem/coefficient.cpp
Co-authored-by: Dohyun Kim <dhkim.cse@gmail.com>
2024-04-07 22:08:33 -04:00
Tzanio Kolev f7b104b4be Merge pull request #4225 from adam-sim-dev/pardiso-fix
Fix Pardiso for single precision
2024-04-07 13:01:26 -07:00
Veselin Dobrev 9d4bceaaa3 Merge pull request #4227 from mfem/bugfix/tomstitt/support-partial-gpu-compiles
Better GPU Guards in `config.hpp`
2024-04-06 18:37:51 -07:00
Brendan Keith 3db9688894 Merge branch '2x2_matrix_exponential' into MA
Adding coefficients from 2x2_matrix_exponential
2024-04-06 15:33:30 -04:00
Brendan Keith 821c41fba9 remove comments 2024-04-06 11:50:53 -04:00
Brendan Keith af5a7844a8 test for MatrixArrayVectorCoefficient 2024-04-06 11:16:53 -04:00
adam-sim-dev f95d82011b Merge branch 'master' into pardiso-fix 2024-04-06 19:15:42 +08:00
Brendan Keith 9bfa6c051e Merge branch 'master' into 2x2_matrix_exponential 2024-04-05 18:04:26 -04:00
Brendan Keith 850f0f7e89 typo 2024-04-05 17:45:10 -04:00
Brendan Keith 90ecbf2bfb Adding TraceCoefficient 2024-04-05 17:44:29 -04:00
Brendan Keith b0a3350622 added MatrixArrayVectorCoefficient clas 2024-04-05 17:40:59 -04:00
Tzanio Kolev 5bde929475 Merge pull request #4135 from mfem/const-hypreparmatrix-blocks
Require `const HypreParMatrix*` in `HypreParMatrixFromBlocks()`
2024-04-05 10:03:23 -07:00
Tzanio Kolev 4306815658 Merge pull request #4226 from mfem/najlkin/revert-blockop
Reverted the change of const qualifiers in BlockOperator
2024-04-05 10:02:43 -07:00
Tzanio Kolev 23b956e834 Merge pull request #4113 from mfem/bugfix/submesh-rt
Boundary attribute transfer to ParSubMesh
2024-04-05 10:02:05 -07:00
Brendan Keith 3f45c0a9d7 Merge branch '2x2_matrix_exponential' of github.com:mfem/mfem into 2x2_matrix_exponential 2024-04-05 12:38:40 -04:00
Brendan Keith 18bee592c4 move test out of #ifdef MFEM_USE_LAPACK 2024-04-05 12:38:35 -04:00
Brendan Keith d9dc18c32b starting ex40 2024-04-05 12:36:35 -04:00
Brendan KeithandDohyun Kim bc0ab53d19 Update linalg/densemat.cpp
Co-authored-by: Dohyun Kim <dhkim.cse@gmail.com>
2024-04-05 08:45:33 -04:00
Brendan Keith 99db13a3c2 missing break; 2024-04-04 17:22:06 -04:00
Brendan Keith 4dcb5933a9 bug in switch 2024-04-04 17:11:32 -04:00
Brendan Keith 1f5f30c9c4 3x3 abort message 2024-04-04 16:27:45 -04:00
Brendan Keith d453981d3c style 2024-04-04 16:09:13 -04:00
Brendan Keith 00bf53ed90 introduce the ExponentialMatrixCoefficient class 2024-04-04 15:48:32 -04:00
adam-sim-dev 0a512877b6 Merge branch 'master' into pardiso-fix 2024-04-04 07:44:03 +08:00
Tom StittandVeselin Dobrev eb8ceb35a7 Update config/config.hpp
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2024-04-03 15:28:19 -07:00
Tzanio Kolev 056a321bb0 Merge pull request #4044 from mfem/named-attr-sets
Named attribute sets
2024-04-03 13:42:46 -07:00
Tom Stitt d42e79f8da check for device compiler in addition to MFEM_USE_{CUDA,HIP} for defining __host__ __device__; adds back support for libraries that use mfem and do partial gpu builds 2024-04-03 13:32:24 -07:00
aa1d6441f8 General hyperbolic class and Refactored Ex18, Ex18p (#3598)
* include cfl

* include 2x2 periodic mesh to have 2^N elements.

* include computation of initial max char speed for t=0

* reorder classes to avoid incomplete type

* fix function spaces for solution variables

* Initial conditions and problems. Not yet done I think

* problem setting

* begin time stepping implementation

* Initial state assignment

* arg parser!

* default periodic square mesh updated

it seems that 2x2 periodic mesh does not work.
-> This is because 2x2 contains both 0->1 edge and 1->0 edge on the boundary
due to periodic constraint.
I believe that is why 3x3 elements are used in the data folder.

* correct errors in euler flux functions

* General Hyperbolic Form updated

* Burgers example included

* Rename FE_Evolution to HCL

* Give operators more meaningful names

* remove Aflux and include divA.
This will allow us to update operators within HCL class

* Allow variable size of invMe to handle p-refine.
invMe Type: DenseTensor -> vector<DenseMatrix>

* Update method included for HCL.
It is not tested yet.
Also, since Operator does not have Update method,
we needed to restrict Operator to NonlinearForm

* Finalize update functionality. Visualization not yet implemented.
Tested with derefine and refine after system construction.
Current code seems to give correct result.
May require further verification.

* update burgers equation

* Fix 1-d bug!
As MFEM positive/negative elements ordering
does not respect the original mesh ordering,
normal vector can be positive or negative in 1D.
We check this by checking integration point is either right or left for 1D.

* move global constants (num_eq, gas.. etc) inside of the classes

* revert back visualization code.

* Add comments and reorder classes

* Remove redundant example code as it is not used anymore.

* rename and move problem-specific defintions to cpp files

* Merged debugged code.

* shallow water an example with periodic boundary included

* rename num_equation to num_equations and include GetIntRule

* Element-wise form integrator for further refactoring

* just testing...

* rename to DGHyperbolicConservationLaws

* max_char_speed now shared by pointer

* use reference instead of pointer

* Rename HCL class to DGHCL

* Form now have pointer to max_char_speed which points to HCL class max_char_speed.
max_char_speed is not exposed to outside.
Use getter instead.

* MPI_Reduce -> MPI_All_Reduce as all workers share the same max_char_speed

* rename faceform to hyperbolic faceform

* Include HyperbolicElementForm for accurate flux evaluation

* Rename form to formintegrator as this is appropriate name

* evaluation template for element assembly

* funval -> state for readibility

* fix bug in the arguments of AssembleElementVector

* compute flux now takes correct function arguments

* ElementFormIntegrator is done. Not yet tested.🤞

* Euler problem is verified.
Burgers and shallow water will be updated

* correct typo Hyperboilic.... :(

* Burgers done. Euler typo fixed

* Shallow water also done!

* Shallow water gauss bump problem included

* include transformations to flux evaluation functions

* This fixes Allow HCL flux functions utilize space-dependent evaluation dohyun-cse/mfem#1.
Advection equation is now included

* Now DGHCL takes nonlinear form as an input argument to handle ParNonlinearForm

* Parallel euler implementation

* remove hello from..

* print function updated

* code cleanup

* Euler cleanup and parallel version bug fix

* Burgers code cleanup and parallel implementation

* shallow water updated.

* advection serial parallel done.

* correct typo in option (parallel refine)

* move hyperbolic_conservation_laws file to fem folder

* include path update

* Take NonlinearForm as reference, not a pointer. Updated Makefile, too.

* Documentation and change some variable names

* form integrators are now in heap memory to avoid malloc error

* changed nonlinear form as a pointer
It seems that PyMFEM does not like reference of nonlinear form... :(

* ignore generated files

* max_char_speed get set method instead of pointer

* nonilnForm pointer update

* nonlinearForm pass by reference

* typo correction

* Test for PyMFEM.. Other examples are not updated yet

* example scripts updated

* ternary to max function

* simplify creating parallel version.

* p-refinement done. test needed.

* testing begins!

* update procedure for main class is included.

* Testing. Still having problem. Not identified yet

* Correct size, but incorrect values.

* p-refinement done and remove nonlinear form exposure.
Parallel checking is done by dynamic_cast.
Therefore, there is no reason to expose nonlienar form to user.
This simplifies class creation :)

* p-refinement test done.

It seems that p-refinement does not result in more accurate solution.

* add option for refinement. h-refinement impl start

* h-refine works fine, but threshold should be modified to obtain bounded number of elements.

* namespace update

* examples tested.

* h-refinement done. Update marking procedure by using confidence interval

* formatting and remove cout from derefine

* include adaptive code to make file

* visualization update

* NumericalFlux -> RiemannSolver

* It seems that set is ambiguous for SWIG..

* comment on hDerefine and now use VectorFunctionCoefficient for IC and Velocity

* testing....

* make flux related methods public

* remove commented out codes

* make style

* doxygen update

* update ex18 with new implementation

* Combine Element/Face Form integrators.

* astyle

* remove redundant ;

* remove refinement procedures.

* thread safe clause

* remove using namespace from hpp file

* ProlongToMaxOrderDG included with interpolation

* remove lambda_function type and return VectorFunctionCoeff for initial/velocity

* removed sinpi

* Some comments

* remove other examples and style

* remove examples not included anymore

* std::cout to mfem::out and correct minor bugs

* ignore mesh file

* update makefile

* remove MPI from serial

* remove unused captured variables in lambda functions

* style

* remove ex34 from makefile and reorder initialization

* remove initialization for auxiliary variables in formintegrator

* remove gas constant from the euler system

* fix broken parts due to uninitialization

* move initialization of local variables inside of FormIntegrator constructor

* forgot to update the other constructor!

* ignore mesh and gridfunctions

* resolved memory leak. Need to check

* remove pragma omp atomic

* remove delete nonlinearForm

* resolve shadowing

* correct dof report and remove barrier in visualization

* forgot to update variable name in euler form

* nonlinearForm memory leak resolved.

destructor of nonlinearForm always delete integrators.
This results in double deletion of the form integrator if we use for both domain and face integration.
To resolve this issue, just create two integrators and pass it to nonlinearForm

* proper header setting and faster test by reducing mesh size

* delete ex18.hpp

* move lengthy functions to cpp

* header order changed

* simpler inclusion.. still have duplicated symbols

* resolved linker problem and include pnonlinear

* remove commented out functions

* documentation

* fixing memory leak..

* delete nonlinearForm

* formatting

* distclean update

* Ignore binaries and result files

* copyright

* Riemann solver comment, input updated.
Riemann solver is now passed as reference

* pass riemann solver by reference

* move default normal flux eval to cpp

* Advection uses inferred dimension from velocity field

* integration rule uses Jacobian order, too

* delete not implemented

* mark override

* format

* unique ptr and mark override

* use single HyperbolicFormIntegrator

* static GetRule

* proper creation without copying

* proper jacobian order in GetRule

* moved member function implementation to cpp file

* new line

* pass by reference

* removed 4x4 mesh and update ignore

* doxygen updated

* remove constructor with integration rule.
Users can set integration rule via NonlinearFormIntegrator::SetIntRule

* useExternalData to indicate ownership of integrator for nonlinear form

* extract flux function from the form integrator

As suggested by @pazner, flux function is now seperated from form integrator. By doing so, riemann solver takes simpler argument but can access to equation-specific information.

* documentation

* documentation --

* initialization order

* update naming of form integrators

* initialization order...

* use normal wavespeed

* shorter Rusanov flux evaluation

* minor code style update

See, https://github.com/mfem/mfem/pull/3598#pullrequestreview-1803234677

* fix syntax error due to pointer -> reference

* std::

* Update fem/nonlinearform.hpp

Co-authored-by: Will Pazner <11493037+pazner@users.noreply.github.com>

* return Mesh instead of string

* Moved DG to ex18.hpp and other styling updates
- Ex18p not yet updated

* update similar to previous commit

* remove ResetMaxChar in the constructor + comment update

Since reset max char will be called each Mult() call, we do not need reset in the constructor

* comment and include functional

* removed inlined namewspace

* style

* move common functions to hpp

* formatting and minor fixes in parallel code.

* update filename and fix typo in `GetMovingVortexInit`

* add hyperbolic to changelog and ex18 comment update

* removed Kelvin–Helmholtz instability example

It is hard to get a satisfactory result with the current DG method without additional treatment.

* fluxFunction is now input of RiemannSolver::Eval instead of being a member.

* compatibility check between flux function and Riemann solver

Some Riemann solver are system-specific. Such Riemann solver can prevent user-error by overriding `IsCompatible`.

* More error-proofing constructors of `RiemannSolver` and `HyperbolicFormIntegrator`

* documentation

* header file description updated

* add examples in the comment

* style

* copyright update

* use unique_ptr in the constructor to make ownership clear

* removed unused member, dim

* Some minor edits, mostly formatting

* add option for pre-assembly

* remove unused ComputeFlux

* keep momentum variable as in serial code

* Fix warnings

* preassembly by default and minor optimization

* remove mutable vector and revert back variable name

flux is now a local variable that changes size at each element. So, it would better to remove it from member variables.

* std::sqrt instead of sqrt

* another minor optimization

* rename options and add comments

* linearized->interpolated

* typo correction in comment

* remove auto from example

Co-authored-by: Chris Vogl <vogl2@llnl.gov>

* Comment update
Correct condition check comment on weak-divergence, and additional comments on auxiliary variable

* Momentum for visualization should be shifted.
FE implementation is correct, but visualization was using u[0,dim). It should be u[1,dim) and now fixed.

* example comments

* style..

* strangely, a trailing space was not updated.

* Fix the thread-safe build. Some doxygen and formatting tweaks.

* fix doxygen error

* Some small tweaks in ex18/ex18p; remove small diffs between the
serial and the parallel versions.

* Small formatting tweaks in ex18.hpp

* unused problem mesh transform

* Remove transformation dependent integration order

* Minor formatting

* support general precision

* format

---------

Co-authored-by: adam-sim-dev <adam.d.schmidt@hotmail.com>
Co-authored-by: Will Pazner <11493037+pazner@users.noreply.github.com>
Co-authored-by: Veselin Dobrev <dobrev@llnl.gov>
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2024-04-03 13:30:41 -07:00
Jan Nikl 6289562498 Fixed BDPMinresSolver. 2024-04-03 10:11:47 -07:00
Jan Nikl 5b79660c96 Fixed Block*Preconditioner comments. 2024-04-03 10:02:54 -07:00
Jan Nikl cf5af75215 Revert "Added const qualifiers to Operator arguments of BlockOperator."
This reverts commit d843cd6e8a.
2024-04-03 09:24:42 -07:00
adam-sim-dev 1bd99dde78 Merge branch 'master' into pardiso-fix 2024-04-03 23:57:27 +08:00
Tzanio Kolev 687ef84488 Merge pull request #4056 from mfem/yohann/fa-dg-amr
Add support for `AssemblyLevel::FULL` for DG on `NCMesh`.
2024-04-03 08:34:29 -07:00
adam-sim-dev 6fab40ce8b Fix Pardiso for single precision 2024-04-03 22:52:47 +08:00
Eric B. Chin 215cb4c585 Merge branch 'master' into const-hypreparmatrix-blocks 2024-04-02 14:02:12 -07:00
Eric B. Chin 4c93ddddc3 fn sig spacing 2024-04-02 13:59:02 -07:00
Stowell, Mark L d61d1159ec Re-enforcing "max boundary attribute + 1" convention 2024-04-02 12:24:04 -07:00
Tzanio Kolev 558bb87bab Merge pull request #4015 from mfem/tmop-pa-diag-fix
TMOP PA diagonal kernels with non-diagonal targets.
2024-04-02 12:07:25 -07:00
Stowell, Mark L 496d083c63 Removing device sample runs 2024-04-02 11:26:24 -07:00
Yohann 61cf6735db Update fem/restriction.cpp
Omitted `double`
2024-04-02 09:32:30 -07:00
Yohann c0924ad9e6 Apply suggestions from code review
Replace `double` with `real_t`.
2024-04-02 09:31:51 -07:00
Stefano Zampini 040ae1609b Merge remote-tracking branch 'origin/master' into stefanozampini/petsc-3.21 2024-04-02 12:04:25 +02:00
Stefano Zampini 503a2e2529 ex3p: Skip unsupported PETSc version in three dimensions 2024-04-02 12:00:51 +02:00
Tzanio Kolev 7bf2a79920 Merge pull request #4151 from mfem/ProjectBdrCoefficient-par-consistency
Broadcast values to other processors to have a consistent GridFunction
2024-03-31 10:41:55 -07:00
Tzanio Kolev 1d37883cc7 Merge pull request #4211 from mfem/hypre-sync-fix
Fix a synchronization issue with some HypreParMatrix constructors
2024-03-31 10:41:02 -07:00
Veselin Dobrev 442360f80d In the GNU make build system, creating an archive from all unit
test object files does not work with Catch2. Instead, combine the
object files into a single object file using 'ld -r'.
2024-03-30 23:29:56 -07:00
Veselin Dobrev 731ea03c80 In the GNU make build system, create an archive from all unit test
object files to avoid a linking issue with long link commands and
CUDA.
2024-03-30 20:39:17 -07:00
Veselin Dobrev 891b17221e Fix nvcc warning 2024-03-30 14:38:19 -07:00
Veselin Dobrev 8af7493023 Add ex38,ex39,ex39p to the GNU make build system.
Updated ex38.cpp to return MFEM_SKIP_RETURN_VALUE when MFEM is
built without LAPACK.

In the examples CMakeLists.txt, treat ex38 similar to other tests
that are conditionally skipped.
2024-03-30 14:09:01 -07:00
Tzanio Kolev 0181312468 Optional visualization in Example 34/34p 2024-03-29 16:21:04 -07:00
Stowell, Mark L 49bff9daef Fixing GLVis output which gets passed the -no-vis option 2024-03-28 14:24:39 -07:00
Veselin Dobrev 2970564990 In the TMOP method/kernel AssembleDiagonalPA_Kernel_3D, add limits
on D1D and Q1D for CUDA/ROCM that are specific to this kernel.
2024-03-27 22:04:12 -07:00
Veselin Dobrev 4fb4ab4397 In the TMOP method/kernel AssembleDiagonalPA_Kernel_3D, reduce the
size of the required shared memory and some other small tweaks.
2024-03-27 19:30:33 -07:00
Veselin Dobrev a3fd440078 Merge branch 'master' into tmop-pa-diag-fix
Resolved conflicts:
   fem/tmop/tmop_pa_h2d.cpp
   fem/tmop/tmop_pa_h3d.cpp
2024-03-27 15:34:51 -07:00
Stowell, Mark L 386fa30275 Merge remote-tracking branch 'origin/master' into named-attr-sets
# Conflicts:
#	CHANGELOG
#	mesh/mesh.hpp
2024-03-27 13:52:45 -07:00
Stowell, Mark L 56c76c0d16 double -> real_t 2024-03-27 13:07:27 -07:00
Stowell, Mark L 094346dc9e Merge remote-tracking branch 'origin/master' into bugfix/submesh-rt 2024-03-27 13:06:49 -07:00
Julian Andrej 1ec42ff5c1 remove include 2024-03-27 11:58:22 -07:00
Julian Andrej 6a1cf0d4f1 guard tests for real_t 2024-03-27 11:38:44 -07:00
Julian Andrej c2dc05c433 change to real_t 2024-03-27 11:35:13 -07:00
Stowell, Mark L 74e4f76268 Re-enabling corrected unit test 2024-03-26 19:35:49 -07:00
Stowell, Mark L 7d3906e67c Switching to modified unit test 2024-03-26 18:55:13 -07:00
Stowell, Mark L 9a4398cb66 make style 2024-03-26 18:45:14 -07:00
Stowell, Mark L fd5e104558 Re-enabling new unit test 2024-03-26 18:33:43 -07:00
Veselin Dobrev 5485f2becf Merge branch 'master' into ProjectBdrCoefficient-par-consistency 2024-03-26 18:28:09 -07:00
Stowell, Mark L b778e649d6 Adding new miniapps to gitignore 2024-03-26 17:04:38 -07:00
Veselin Dobrev ecb72984e0 The meshing miniapp 'pmesh-fitting' should now work with hypre build
with GPU support.
2024-03-26 16:54:50 -07:00
Veselin Dobrev c0e6dc573b Merge branch 'master' into hypre-sync-fix 2024-03-26 16:50:29 -07:00
Stowell, Mark L 5b481db1a3 Disabling new or modified unit tests 2024-03-26 16:40:36 -07:00
Stowell, Mark L a0f4cc6790 Adding testing of new miniapps 2024-03-26 16:05:32 -07:00
Stowell, Mark L f315883342 Merge branch 'bugfix/submesh-rt' of github.com:mfem/mfem into bugfix/submesh-rt 2024-03-26 15:15:05 -07:00
Stowell, Mark L c5e74c1b6a Adding new miniapps to to make and cmake files 2024-03-26 15:14:24 -07:00
Stowell, Mark L 63d33a88be Improving visualization in new miniapps 2024-03-26 15:13:41 -07:00
Stefano Zampini ed39df11da Fix single precision examples and SLEPc 2024-03-27 00:05:52 +03:00
Stefano Zampini 38c9bc75b5 PETSc: last updates to real_t 2024-03-26 23:10:40 +03:00
Stefano Zampini 440be80704 Merge branch 'stefanozampini/petsc-3.21' of github.com:mfem/mfem into stefanozampini/petsc-3.21 2024-03-26 23:09:34 +03:00
Stefano Zampini a79c2b81cd PETSc: update to real_t 2024-03-26 23:07:55 +03:00
Stefano Zampini a2734e6888 Fix hybridization example 2024-03-26 23:03:59 +03:00
Stefano Zampini d26ea85877 Merge remote-tracking branch 'origin/master' into stefanozampini/petsc-3.21 2024-03-26 22:20:57 +03:00
Julian Andrej 6a301e2a31 initialize gridfunction 2024-03-26 12:18:07 -07:00
Tzanio Kolev bcdf7cc648 Merge pull request #3922 from mfem/float
Generalize floating point type
2024-03-26 12:08:04 -07:00
Veselin Dobrev 0110cb715d Resolve the issue described in the parent commit 2024-03-25 23:00:16 -07:00
Veselin Dobrev 4e80106811 Add a set of tests that illustrate an issue with some HypreParMatrix
constructors that wrap external data (SparseMatrix or Table) and
reorder it to make the diagonal entry first in each row.

The issue only appears when using HYPRE + CUDA/ROCM build.

This commit can be used to see the issue by running either of
the unit tests, 'punit_tests' or 'pcunit_tests'.

The issue will be resolved in the next commit to this branch.
2024-03-25 22:51:55 -07:00
Veselin Dobrev 8487564f0d Merge branch 'master' into float 2024-03-25 13:07:23 -07:00
Veselin Dobrev f37a8142cb Update two doxygen comments 2024-03-25 13:05:43 -07:00
Veselin Dobrev 7be646b8ce Fix the HIP build with single precision.
Fix warnings about RAND_MAX when using single precision.

Introduce an inline function `real_t rand_real()` that returns a
random number in the interval [0,1) using rand(). This function
handles better the case of single precision where the expression
`real_t(rand())/(real_t(RAND_MAX)+1)` can return 1.0f due to round-off
when rand() returns a number close to RAND_MAX.

Use `rand_real()` in a few places that before used code similar to
`real_t(rand())/(real_t(RAND_MAX)+1)`.
2024-03-24 10:43:15 -07:00
Veselin Dobrev ad32ab68e0 In the CMake build system add the cublas dependency of hypre. 2024-03-23 17:26:01 -07:00
Veselin Dobrev 91204ea52e Update the CMake build system to conditionally exclude tests that
return MFEM_SKIP_RETURN_VALUE under certain config conditions. These
exclusions will need to be updated manually when a test is modified
to return or no longer return MFEM_SKIP_RETURN_VALUE.

Added some tests missing from the CMake tests compared to the
GNU make tests.
2024-03-23 16:15:46 -07:00
Vladimir Z Tomov 8c98ecbf91 fixed some tolerances during testing. 2024-03-22 23:48:18 -07:00
Veselin Dobrev dcc81ec67f Add early "skip" exit in the miniapp 'pmesh-fitting' when using hypre
build with GPU support -- there are error messages about non-SPD
operator in the 'lin_solver' in ParAdvectorCGOper::Mult().
2024-03-22 19:02:05 -07:00
Veselin Dobrev a974d724ef Instantiate Memory<T>::PrintFlags() and
Memory<real_t>::CompareHostAndDevice() for T = real_t
instead of T = double.

Extend Vector and DenseMatrix constructors from fixed size
arrays of type real_t to any type T -- this was one simple way
to get the tests to build with nvcc with single precision.

Fix the building of tests/unit/linalg/test_matrix_hypre.cpp with
single precision when using hypre built with GPU support.

Fix a warning from nvcc in miniapps/tools/tmop-check-metric.cpp.
2024-03-22 18:12:49 -07:00
Socratis Petrides c3a56ba4b5 Merge branch 'master' into bugfix/submesh-rt 2024-03-22 12:47:26 -07:00
Veselin Dobrev 90d3a987fe Modified the unit tests to print that they are not supported with
single precision and return the "skip" exit code.
2024-03-22 11:31:45 -07:00
Veselin Dobrev 5e778cdb1f Increase a tolerance for single precision in 'navier_kovasznay' to
allow the test to pass with additional compilers/platforms.
2024-03-21 17:47:47 -07:00
Veselin Dobrev a0a2fe2128 Introduce separate tolerances for single precision in the navier
miniapp.
2024-03-21 17:30:33 -07:00
Veselin Dobrev c57ef1cd2d Remove diplicate output of MFEM_USE_SINGLE in 'make info' 2024-03-21 16:16:44 -07:00
Veselin Dobrev 6facf1d3c0 Fix the single precision tests of the miniapps 'navier_kovasznay' and
'block-solvers'.
2024-03-21 15:24:31 -07:00
Veselin Dobrev 7b20790ded Mentioned the "General floating point type support" discussion in
CHANGELOG and INSTALL.

Added MFEM_PRECISION to the output from 'make info'.
2024-03-21 12:02:49 -07:00
Tzanio Kolev 189d4d7900 Merge pull request #4199 from mfem/gitlab-quartz-baseline-switch
Update the GitLab "quartz-baseline" pipeline to use the Quartz-specific baseline results
2024-03-20 10:59:55 -07:00
Sebastian Grimberg 79d0284b3d Further examples/petsc style consistency 2024-03-20 09:09:46 -07:00
Sebastian Grimberg e51be179a4 Consistency with ex14p and ex17p 2024-03-20 09:06:50 -07:00
Sebastian Grimberg 2cbbbe09d4 Fix typo (EX2_ARGS_BDDC_3D -> EX3_ARGS_BDDC_3D) and text wrapping 2024-03-20 09:03:29 -07:00
Tzanio Kolev 8c2212c457 Merge pull request #4121 from mfem/artv3/raja-v2023.06.01-update
Update RAJA for v2023.06.00 and beyond
2024-03-20 07:28:18 -07:00
Stefano Zampini 19154e65ba add 3D HCURL bddc test to CMakeList 2024-03-20 16:02:19 +03:00
Veselin Dobrev 6f37514d3f In the GNU make and CMake build systems, modify how the floating-point
precision is specified: it is now controlled by the single option
MFEM_PRECISION (single/Single/SINGLE/double/Double/DOUBLE) which is
converted into settings for MFEM_USE_SINGLE and MFEM_USE_DOUBLE which
are then used as before.
2024-03-19 15:32:15 -07:00
Stefano Zampini e34c323edf Petsc: Support 3.21
add missing 3D Hcurl test (fixed in PETSc main) see https://github.com/mfem/mfem/issues/4050
PetscH2Solver::H2SolverConstructor fix ignored error codes
2024-03-19 17:33:03 +03:00
Veselin Dobrev 1314428770 Fix two 'make test' failures in a CUDA build using HYPRE+CUDA. 2024-03-18 17:53:18 -07:00
Veselin Dobrev e7400c2552 Make mfem::operator""_r a host+device function -- this was needed to
suppress nvcc warning.

Mention MFEM_USE_{SINGLE,DOUBLE} in the INSTALL file.

Other small updates.
2024-03-18 13:40:22 -07:00
Dylan Copeland 64fa92bb1c Introducing ""_r for casting to real_t. 2024-03-18 12:32:46 -07:00
Veselin Dobrev f12827db31 Tweak ex25/ex25p to try to remove diffs with 'master' 2024-03-18 06:30:14 -07:00
Veselin Dobrev d66d1f4cd9 Move up MFEM_USE_{SINGLE,DOUBLE} in the output from 'make info' 2024-03-18 06:23:42 -07:00
Veselin Dobrev b7a47d21f5 In quartz-baseline.yml, check for “baseline-quartz.diff” instead of “baseline-${SYS_TYPE}.diff” 2024-03-17 19:13:56 -07:00
Veselin Dobrev 6b566568f1 In the GitLab "quartz-baseline" pipeline, use result files with
prefix "baseline-quartz".
2024-03-17 15:52:11 -07:00
Veselin Dobrev c201035164 Move the MFEM_USE_{DOUBLE,SINGLE} options closer to the beginning
of the various config settings -- they are important settings and
should appear earlier.

Move the definition of mfem::real_t to config.hpp along with some
macros from globals.hpp -- I think this a better place for them.

Added support for single precision to ex10 and ex10p.

Added explicit compile time checks and error messages to make
sure HYPRE is compiled with the same precision as MFEM.

Fixed an issue affecting the visualization of the results from
ex10 and ex10p on nonconforming meshes.
2024-03-16 11:32:11 -07:00
Dylan Copeland c87b67e4f6 Reverting some changes to abs, min, max. 2024-03-16 11:10:06 -07:00
Veselin Dobrev 3122df854e Fixes for building examples and miniapps in single precision mode 2024-03-15 16:32:39 -07:00
Dylan Copeland 81affd9558 Merge branch 'master' of github.com:mfem/mfem into float 2024-03-15 13:03:21 -07:00
Dylan Copeland d57b1d8a2e Some complex fixes. 2024-03-15 12:59:28 -07:00
Tzanio Kolev 37e03ab550 Merge pull request #4198 from mfem/ci-sanitize-update
Workaround for the sanitizer failures
2024-03-15 12:50:32 -07:00
Dylan Copeland 36e4caff61 Revert branch-history 2024-03-15 12:11:20 -07:00
Dylan Copeland c009fb9bde Merge branch 'master' of github.com:mfem/mfem into float 2024-03-15 11:31:39 -07:00
Veselin Dobrev d9fe115eb9 Add a temoprary workaround based on
https://github.com/actions/runner-images/issues/9491

Fix a warning in the "build-container" action.
2024-03-15 10:39:14 -07:00
Veselin Dobrev c23cbdf0d1 Try to use clang 15 in the sanitizers CI to see if that solves the
recent failures of this action which uses clang 14.
2024-03-15 09:31:34 -07:00
Veselin Dobrev daff379773 Merge pull request #4173 from mfem/feature/tomstitt/avoid-some-memcpys
Avoid some unnecessary memcpys
2024-03-15 09:08:23 -07:00
Mark L. Stowell 8dde119d0c Merge branch 'master' into bugfix/submesh-rt 2024-03-14 11:30:49 -07:00
Stowell, Mark L d9b5b6c11c Cleaning up comments in new multidomain miniapps 2024-03-14 11:29:00 -07:00
Julian Andrej a6254e863f includes 2024-03-13 13:49:58 -07:00
Julian Andrej eefada3110 correction 2024-03-13 12:14:13 -07:00
Julian Andrej 8adfc1c557 provide unit test 2024-03-13 11:59:47 -07:00
Vladimir Z Tomov 2ef8230757 Merge branch 'master' into tmop-pa-diag-fix 2024-03-13 08:55:39 -07:00
Vladimir Z Tomov 241a5ca8a3 style 2024-03-12 22:39:54 -07:00
Vladimir Z Tomov 587c8950ee Improved the 3D diagonal PA computation. 2024-03-12 22:38:33 -07:00
Vladimir Z Tomov efc5e8e8eb Improved the 2D diagonal PA computation. 2024-03-12 22:09:37 -07:00
Dylan Copeland d2e89166f9 Merge branch 'master' of github.com:mfem/mfem into float 2024-03-05 10:23:02 -08:00
Tom Stitt c43da76cff only ReadWrite eadata if add==true, other just Write 2024-03-04 12:02:24 -08:00
Julian Andrej 20c9a68ee9 remove comments 2024-03-04 08:08:04 -08:00
Stowell, Mark L 91bcdd1ab2 Mostly documentation and style fixes 2024-02-29 14:17:22 -08:00
Stowell, Mark L dd02c49856 Exchanging floating point for integer 2024-02-29 13:54:14 -08:00
Stowell, Mark L 35c2fc9a79 Adding RT to the pre-existing ParSubMesh unit tests 2024-02-29 10:55:19 -08:00
Stowell, Mark L 7d149334b6 make style 2024-02-29 10:54:46 -08:00
Stowell, Mark L eeb2eb2a07 Fix for boundaries of 2D meshes 2024-02-28 15:50:39 -08:00
Stowell, Mark L 5ffbee1199 Adding unit test for parallel sub-meshes with interior boundaries 2024-02-28 13:16:56 -08:00
Mark L. Stowell 001e3cd8fc Merge branch 'master' into bugfix/submesh-rt 2024-02-28 10:57:22 -08:00
Stowell, Mark L 954b3dce73 Updating examples 2024-02-27 21:02:45 -08:00
Stowell, Mark L c521b4b8d6 Changing AttributeSets into a simple wrapper class around ArraysByName 2024-02-27 20:18:07 -08:00
Stowell, Mark L e5508fc1b4 Clarifying documentation 2024-02-27 20:17:17 -08:00
Stowell, Mark L 3f0e74c732 Merge branch 'named-attr-sets' of github.com:mfem/mfem into named-attr-sets 2024-02-27 19:14:11 -08:00
Mark L. Stowell c87a46f4b3 Merge branch 'master' into named-attr-sets 2024-02-27 19:12:58 -08:00
Stowell, Mark L cbf819362d Fixing doxygen reference errors 2024-02-27 19:10:05 -08:00
Stowell, Mark L 08c25c64cf Removing Mesh::AttrToMarker and adding similar limited functionality to the AttributeSets class 2024-02-27 17:30:51 -08:00
Stowell, Mark L be4089e9be Modifying output format as discussed in a meeting 2024-02-26 16:41:49 -08:00
Stowell, Mark L 1c95d630ba Creating Print* methods on the AttributeSets class so that the output width can be defined in one location 2024-02-26 16:41:00 -08:00
Stowell, Mark L 1281f0de29 Trimming examples 2024-02-26 16:37:58 -08:00
Stowell, Mark L 0645d5eca5 Removing unnecessary file 2024-02-26 16:37:30 -08:00
Stowell, Mark L c8a68cf60e Updating copyright dates 2024-02-26 13:11:27 -08:00
Julian Andrej 2f94ba3786 Broadcast values to other processors to have a consistent GridFunction 2024-02-23 13:27:58 -08:00
Stowell, Mark L 668ad9a800 Adding unit tests (and fixing newly uncovered bugs) for sorting and removing duplicates in ArraysByName 2024-02-20 14:28:42 -08:00
Stowell, Mark L c795d6bd00 Adding class description for ArraysByName 2024-02-20 14:27:28 -08:00
Stowell, Mark L 0f862ccfc3 Adding unit tests of sorting and removing duplicates from arrays 2024-02-20 14:26:32 -08:00
Stowell, Mark L d64cb93f89 Updating copyright dates 2024-02-20 14:25:39 -08:00
Stowell, Mark L dfa86e0668 Improved comments in new examples 2024-02-20 14:25:01 -08:00
Arturo Vargas 5c9d9aca95 Merge branch 'master' into artv3/raja-v2023.06.01-update 2024-02-14 09:09:20 -08:00
Arturo Vargas 3224d79ee5 Update CHANGELOG 2024-02-14 09:08:57 -08:00
Eric B. Chin 8a1e61967a Merge branch 'master' into const-hypreparmatrix-blocks 2024-02-13 16:51:03 -08:00
Eric B. Chin 5a15bbe2e9 reordering functions, add doxygen 2024-02-13 16:50:38 -08:00
Eric B. Chin 2887738161 add deprecated version 2024-02-13 16:43:33 -08:00
Eric B. Chin e428593ab0 formatting 2024-02-12 15:17:46 -08:00
Eric B. Chin f0a9546c03 add const to hypreparmatrix pointers 2024-02-12 15:10:48 -08:00
Arturo Vargas e939e4e432 fix raja logic 2024-02-11 13:58:43 -08:00
Stowell, Mark L cdaabd67ee Recreating interior boundary elements in submeshes 2024-02-10 14:13:49 -08:00
Stowell, Mark L 950fd77063 Adding explanatory comments and switching to FaceInformation struct for cleaner code 2024-02-10 13:35:32 -08:00
Stowell, Mark L e2c9258889 Communicating interior boundary attributes during ParSubMesh construction 2024-02-10 11:57:01 -08:00
Stowell, Mark L f62bf0bb6b merging master into current branch 2024-02-10 11:55:40 -08:00
Stowell, Mark L 37578e2fb8 Replacing multidomain_rt.cpp which was accidentally overwritten 2024-02-09 15:12:26 -08:00
Socratis Petrides 9364fc377f minor 2024-02-08 15:25:00 -08:00
Arturo Vargas b54f08a765 update raja for v2023.06.01 and beyond 2024-02-07 10:30:22 -08:00
Dylan Copeland 61f950a68d Defined and documented magic number for skipped test return value. Changed errors for failing tests to return this value. 2024-02-06 12:07:29 -08:00
Dylan Copeland 046a874cfb Merge branch 'master' of github.com:mfem/mfem into float 2024-02-06 10:56:41 -08:00
Stowell, Mark L 970833e98c Adding ND and RT variants of multidomain miniapp 2024-02-04 20:19:02 -08:00
Socratis Petrides 0ad4acf6a5 edits to mumps interface to accomodate single precision 2024-01-29 17:55:00 -08:00
Socratis Petrides 097e93e4ab adjusting some dpg sample runs to accomodate single precision 2024-01-29 17:52:27 -08:00
Will Pazner 8b555a7bf8 Generic version of PointMatrixHash::operator() 2024-01-23 12:31:41 -08:00
Dylan Copeland fb0cdbb9f7 Merge PR 3806. 2024-01-23 11:13:34 -08:00
Dylan Copeland a8090e318d Merge branch 'master' of github.com:mfem/mfem into float 2024-01-23 11:07:47 -08:00
Stowell, Mark L bc44bb9ebf Removing unused instantiations to avoid errors in CI 2024-01-19 11:22:58 -08:00
Stowell, Mark L bec527fe0b Removing unit tests related to convertible type methods 2024-01-19 10:57:56 -08:00
Stowell, Mark L 68d117accd Merge remote-tracking branch 'origin/master' into named-attr-sets
# Conflicts:
#	tests/unit/CMakeLists.txt
2024-01-19 10:44:59 -08:00
Stowell, Mark L 047acf0b7c Fixing corner case where attribute arrays are zero length 2024-01-19 10:41:44 -08:00
Stowell, Mark L 1009445194 Fixing Mesh::AttrToMarker when attrs is empty. 2024-01-17 21:25:26 -08:00
Stowell, Mark L 5f72e2d601 Declaring Mesh::AttrToMarker as static 2024-01-17 21:15:21 -08:00
Stowell, Mark L b23efc92df Tweaking "inline" declarations in header 2024-01-17 21:08:53 -08:00
Stowell, Mark L 495c730f39 Trimming the example codes 2024-01-17 21:07:57 -08:00
Stowell, Mark L 8680ca4bcf Moving templated code to header and adding more template instantiations 2024-01-17 17:06:10 -08:00
dylan-copeland 5896f590e7 Added precision flags to cmake files. Added compile-time checks for double or single being defined, not both. Reverted appveyor.yml. 2024-01-17 16:54:18 -08:00
Stowell, Mark L 0364c990a0 Merge remote-tracking branch 'origin/master' into named-attr-sets 2024-01-17 08:25:21 -08:00
Stowell, Mark L 23a7b101cd Removing GetNames(set<string>&) method in favor of returning by value 2024-01-16 16:46:21 -08:00
Stowell, Mark L 599ee41f2f Replacing call to removed "Copy" method 2024-01-16 16:25:24 -08:00
dylan-copeland cda68d779c Restore parallel build instructions in appveyor.yml. 2024-01-16 16:21:09 -08:00
dylan-copeland d54d2668a2 Restart CI 2024-01-16 15:30:08 -08:00
dylan-copeland 1af666cb9a Restart CI 2024-01-16 14:07:58 -08:00
Dylan Copeland ad87b9cb5f appveyor.yml 2024-01-16 13:23:10 -08:00
Stowell, Mark L ed95441729 Removing "Copy" method and declaring copy/move constructors and operators as "default" 2024-01-16 12:24:23 -08:00
Stowell, Mark L f273eea4c6 Updating unit test to check all copy/move constructors and assignment operators 2024-01-16 12:23:37 -08:00
Dylan Copeland 1c037bf476 Merge branch 'master' of github.com:mfem/mfem into float 2024-01-16 12:17:04 -08:00
Stowell, Mark L ed8fa3a89b Fixing comparison in unit test 2024-01-14 15:29:07 -08:00
Stowell, Mark L ec92ba8aa4 Removing custom iterator headache (thanks @pazner!) 2024-01-14 15:17:10 -08:00
Stowell, Mark L dfd7376d74 More "friend" fixes 2024-01-14 14:47:32 -08:00
Stowell, Mark L 3abd1bd2d1 Typo in doxygen command 2024-01-14 14:43:05 -08:00
Stowell, Mark L 2b3b8a9ee6 Adjusting "friend" declarations to satisfy different compilers 2024-01-14 14:23:18 -08:00
Stowell, Mark L 64521d5848 Fixing errors found by CI 2024-01-14 12:02:06 -08:00
Stowell, Mark L f6dfb11945 Merge remote-tracking branch 'origin/master' into named-attr-sets
# Conflicts:
#	mesh/mesh.hpp
2024-01-14 11:40:43 -08:00
Stowell, Mark L 64e11cce6b Manually adjusting indenting to conform to standard style (not sure why astyle failed to modify this) 2024-01-14 11:13:57 -08:00
Stowell, Mark L 3b4ea628f0 Altering Mesh and the new examples to use the new AttributeSets container class 2024-01-14 11:06:45 -08:00
Stowell, Mark L b9e7116648 Adding unit tests for the new container class 2024-01-14 11:05:24 -08:00
Stowell, Mark L f6e13f92c0 Adding an AttributeSets class for use within the Mesh class 2024-01-14 11:04:11 -08:00
Stowell, Mark L c57e1c33c9 Adding a container class for maps of arrays keyed by strings 2024-01-14 11:02:05 -08:00
Dylan Copeland 47e042245e Merge branch 'master' of github.com:mfem/mfem into float 2024-01-11 14:26:05 -08:00
Stowell, Mark L 341e00aa09 Adding return by value options for sets of set names 2024-01-09 10:42:43 -08:00
Stowell, Mark L d90a567378 Removing unneeded scopes 2024-01-09 10:28:42 -08:00
Stowell, Mark L 37f9fc565d make style 2024-01-08 15:46:44 -08:00
Stowell, Mark L 860e16f693 Modifying CHANGELOG 2024-01-08 15:46:33 -08:00
Stowell, Mark L 373d088d0c Renaming new examples and editing their headers 2024-01-08 15:42:58 -08:00
Stowell, Mark L 696f0e2f2b Adding attribute array -> marker array methods to Mesh class 2024-01-05 15:04:25 -08:00
Stowell, Mark L 9844e4d925 Improvements to RemoveFromAttributeSet and RemoveFromBdrAttributeSet 2024-01-05 14:40:03 -08:00
Stowell, Mark L ae9689cad1 Switching to ranged-for loop in mesh reader 2024-01-05 13:51:07 -08:00
dylan-copeland 4e25b1ba6b Merge branch 'master' of github.com:mfem/mfem into float 2024-01-05 11:37:18 -08:00
Stowell, Mark L 8ac2f38e41 Switching to range-based for loops 2024-01-04 17:34:43 -08:00
Yohann 957848d6ad Merge branch 'master' into yohann/fa-dg-amr 2024-01-04 16:30:18 -08:00
Yohann Dudouit a2667cd239 Add parallel support for full assembly on NCMesh. 2024-01-04 16:18:51 -08:00
dylan-copeland 30a8a51e20 Error messages for examples and miniapps that fail in single precision. 2024-01-03 20:32:53 -08:00
dylan-copeland d9ae367705 Reinstate KDTree templates. 2024-01-03 10:41:58 -08:00
dylan-copeland b3a3ad3488 Using real_t in KDTree. 2024-01-03 10:30:39 -08:00
dylan-copeland ceaabce20d More KDTree typedefs. 2024-01-02 18:27:51 -08:00
dylan-copeland 49fe6fc429 Remove use of KDTree typedefs. 2024-01-02 18:18:21 -08:00
dylan-copeland 1c1e8293e1 Remove a double from last merge. 2024-01-02 17:05:57 -08:00
Dylan Copeland bcad115dda Merge branch 'master' of github.com:mfem/mfem into float 2024-01-02 14:41:02 -08:00
Dylan Copeland 7c81683d1b Introducing MFEM_USE_DOUBLE. 2024-01-02 14:40:33 -08:00
Yohann Dudouit 8eef6da0c1 Add support for full assembly on non-conforming meshes. 2023-12-29 09:55:43 -08:00
Stowell, Mark L a5b53962e6 Adding Doxygen style comments 2023-12-22 15:45:19 -08:00
Stowell, Mark L 0b4d6a181d Fixing shadowed variables flagged by GitHub testing 2023-12-22 11:38:45 -08:00
Stowell, Mark L e51c4e8bff Adding example files and test program 2023-12-21 19:16:45 -08:00
Stowell, Mark L c3e7eb045d Adding support for named attribute sets 2023-12-21 19:15:45 -08:00
Dylan Copeland 7d1b07f873 CHANGELOG 2023-12-21 13:46:36 -08:00
Dylan Copeland 80449bbd15 Merge branch 'master' of github.com:mfem/mfem into float 2023-12-21 13:20:38 -08:00
dylan-copeland bf4c7ea8c1 Fix examples and miniapps on mac. 2023-12-19 19:29:34 -08:00
dylan-copeland 9beaa836b0 MFEM_USE_FLOAT -> MFEM_USE_SINGLE 2023-12-19 17:51:19 -08:00
Dylan Copeland b5670b4daf Fixed a new example and a new miniapp. 2023-12-19 14:39:20 -08:00
dylan-copeland fd44d57e91 Merge branch 'master' of github.com:mfem/mfem into float 2023-12-18 09:39:48 -08:00
dylan-copeland 7d15a638be Replace some doubles that somehow snuck in. 2023-12-13 14:59:11 -08:00
Veselin Dobrev b273b7669f Fix shadow typedefs 2023-12-13 14:39:36 -08:00
Tzanio Kolev d983b34924 Renamed ftype -> real_t 2023-12-13 12:51:43 -08:00
Dylan Copeland 373a3a0099 Merge branch 'master' of github.com:mfem/mfem into float 2023-12-12 12:53:39 -08:00
Dylan Copeland aa4d4efc04 Merge branch 'master' of github.com:mfem/mfem into float 2023-12-07 10:05:17 -08:00
Vladimir Z Tomov 9d3125efe6 style 2023-12-06 18:46:14 -08:00
Vladimir Z Tomov f890c279c2 Fixed the 3d diagonal kernel. 2023-12-06 18:36:40 -08:00
Vladimir Z Tomov 077d9fc6bd 3d unit test (failing) 2023-12-06 18:08:38 -08:00
Vladimir Z Tomov 9d2c0d185f Fix 2D diagonal kernel + unit test. 2023-12-06 17:39:13 -08:00
Dylan Copeland e9fbd5057f Merge branch 'master' of github.com:mfem/mfem into float 2023-12-05 13:08:02 -08:00
dylan-copeland a4aa7d70b9 Generalized PR 3852. 2023-11-30 09:51:09 -08:00
dylan-copeland d96152a08a Merge branch 'master' of github.com:mfem/mfem into float 2023-11-30 09:32:47 -08:00
Dylan Copeland d41b97552c Merge branch 'master' of github.com:mfem/mfem into float 2023-11-16 17:37:34 -08:00
nbeams 4db39d6d4b Update Ginkgo CBGMRES documentation to include fptype of float 2023-11-16 17:16:30 -05:00
Dylan Copeland b3813ed053 Using fptype in ginkgo interface. 2023-11-13 13:46:19 -08:00
dylan-copeland b78275e79e Merge branch 'master' of github.com:mfem/mfem into float 2023-11-13 07:41:47 -08:00
Dylan Copeland a8c34e351e Reverted to fmin and fmax for GPU kernels. Fixed some examples for pcuda build. 2023-11-10 21:30:07 -08:00
Dylan Copeland a3d2036838 MFEM_EXPORT for MPITypeMap. 2023-11-10 17:25:21 -08:00
Dylan Copeland f36873a150 Updating CONTRIBUTING.md with policy about fptype. 2023-11-10 13:35:07 -08:00
Dylan Copeland e617238cc5 Style 2023-11-09 21:56:11 -08:00
Dylan Copeland 47e62a55f9 Merge branch 'master' of github.com:mfem/mfem into float 2023-11-09 21:38:06 -08:00
Dylan Copeland 89f62d04e1 Temporary change to branch-history so CI can pass. 2023-11-09 20:17:18 -08:00
Dylan Copeland 686756d73f Generalized the remaining miniapps, except gslib. 2023-11-09 14:39:59 -08:00
Dylan Copeland a3e7080fc1 Generalized more miniapps. 2023-11-09 13:28:59 -08:00
Dylan Copeland 1911fbc883 Generalized miniapps hdiv and hooke. 2023-11-08 09:34:48 -08:00
Dylan Copeland 36106d6fe4 Generalized miniapps in autodiff and electromagnetics. 2023-11-07 15:11:45 -08:00
Dylan Copeland eea5e91bb3 Generalized miniapps in dpg and toys. 2023-11-07 14:00:04 -08:00
Dylan Copeland 9eca33b09d Generalized everything in miniapps/meshing. 2023-11-06 19:06:55 -08:00
Dylan Copeland b89222762d Generalized floating point type for all remaining examples. 2023-11-06 15:34:42 -08:00
Dylan Copeland 69e4e13185 Merge branch 'float' of github.com:mfem/mfem into float 2023-11-04 19:56:13 -07:00
Dylan Copeland c80fdc6f74 Generalized CUDA for float case, so example device runs succeed with a pcuda build. 2023-11-04 19:55:18 -07:00
Veselin Dobrev bada9b86f0 Fix a warning from Apple clang 2023-11-04 18:07:51 -07:00
Dylan Copeland d02a90f9f2 Generalized type for PA kernels. 2023-11-01 16:31:49 -07:00
Dylan Copeland 9017b9700d Finished generalizing type in fem directory. 2023-11-01 15:54:41 -07:00
Dylan Copeland 3b4fc3b1df Generalized for MPI and hypre. 2023-10-31 21:12:15 -07:00
Dylan Copeland ee3a46af24 Added support for LAPACK in single-precision. Changed fmax -> std::max, etc. 2023-10-31 14:30:44 -07:00
Dylan Copeland c64d7858e8 Adding build option for single-precision. 2023-10-31 12:04:38 -07:00
Dylan Copeland f106c03dd1 Generalized floating point type. So far, ex1 works for a serial build without lapack. 2023-10-09 14:19:25 -07:00
563 changed files with 22310 additions and 15768 deletions
+1 -1
View File
@@ -65,7 +65,7 @@ jobs:
- name: GHCR Login
if: (github.event_name != 'pull_request')
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
+6
View File
@@ -27,6 +27,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Temporary workaround for sanitizer crashes
# See https://github.com/actions/runner-images/issues/9491
# The issue should be fixed in the next runner image for Ubuntu 22.04,
# see https://github.com/actions/runner-images/pull/9513
run: sudo sysctl vm.mmap_rnd_bits=28
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
+4 -4
View File
@@ -91,10 +91,6 @@ examples/ex16.mesh
examples/ex16-mesh.*
examples/ex16-init.*
examples/ex16-final.*
examples/vortex-mesh.*
examples/vortex.mesh
examples/vortex-?-init.*
examples/vortex-?-final.*
examples/deformation.*
examples/pressure.*
examples/ex20.dat
@@ -120,6 +116,8 @@ examples/cond_mesh.*
examples/port_mesh.*
examples/port_mode.*
examples/euler-*
examples/amgx/ex1
examples/amgx/ex1p
examples/amgx/.logamgx
@@ -354,6 +352,8 @@ miniapps/parelag/MultilevelHcurlHdivSolver
miniapps/parelag/*.mesh
miniapps/multidomain/multidomain
miniapps/multidomain/multidomain_nd
miniapps/multidomain/multidomain_rt
miniapps/hooke/hooke
miniapps/dpg/diffusion
+1 -1
View File
@@ -87,7 +87,7 @@ report_baseline:
# We create an autotest-email.html file, because that's how we signal
# that there was an error / diff (temporary).
if [[ -f ${rundir}/${BASELINE_TEST}.err ]] || \
[[ -f ${rundir}/${BASELINE_TEST}-${SYS_TYPE}.diff ]]; then
[[ -f ${rundir}/${BASELINE_TEST}-${MACHINE_NAME}.diff ]]; then
cp ${rundir}/pipeline.txt ${rundir}/autotest-email.html
fi
msg="GitLab CI log for ${BASELINE_TEST} on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
+3
View File
@@ -14,6 +14,9 @@
# locals
glob_err=${BASELINE_TEST}.err
base=${BASELINE_TEST}-${SYS_TYPE}
if [[ "${MACHINE_NAME}" == "quartz" ]]; then
base="${BASELINE_TEST}-${MACHINE_NAME}"
fi
base_diff=${base}.diff
base_patch=${base}.patch
base_out=${base}.out
+20
View File
@@ -28,6 +28,13 @@ Discretization improvements
IntegrationRules through a moment-fitting approach. The cut is specified by
the zero level set of a Coefficient. See fem/intrules_cut.hpp and Example 38.
- Added a new nonlinear integrator, `HyperbolicFormIntegrator`. This implements
both element-wise weak divergence and face-wise numerical flux for a general
system of hyperbolic conservation laws. To use this integrator for a specific
flux function, users can define a derived class of `FluxFunction`. Currently,
advection, Burgers', shallow-water, Euler equations (see, Example 18) are
available.
GPU support
----------------------------
- Added support for full assembly on simplices.
@@ -47,6 +54,10 @@ New and updated examples and miniapps
Miscellaneous
-------------
- Added support for single and double precision, with corresponding hypre build.
Generalized the floating point type from `double` to `real_t`. For more
details see https://github.com/orgs/mfem/discussions/4207.
- The ReadCubit Genesis mesh importer has been rewritten to improve readability.
- Updated the Doxygen documentation style, which now requires Doxygen version
@@ -56,6 +67,15 @@ Miscellaneous
IntegrationRules IntRules, RefinedIntRules, GeometryRefiner
GlobGeometryRefiner, and FiniteElement::dof2quad_array.
- PETSc integration now generally requires PETSc version 3.21 or later, though
depending on the functionality older versions may still work.
- RAJA backend will use seq_exec for serial loop execution when RAJA
v2023.06.00 and beyond is detected as loop_exec is deprecated.
- Adding named attribute sets and basic supporting methods to the Mesh class as
a convenient means of referring to sets of domain or boundary attribute
numbers. Also adding related serial and parallel examples which illustrate.
Version 4.6, released on September 27, 2023
===========================================
+13
View File
@@ -183,6 +183,19 @@ endif()
# Process configuration options
#-------------------------------------------------------------------------------
# MFEM_PRECISION -> MFEM_USE_SINGLE, MFEM_USE_DOUBLE
if (MFEM_PRECISION MATCHES "^(double|Double|DOUBLE)$")
set(MFEM_USE_SINGLE OFF)
set(MFEM_USE_DOUBLE ON)
elseif (MFEM_PRECISION MATCHES "^(single|Single|SINGLE)$")
set(MFEM_USE_SINGLE ON)
set(MFEM_USE_DOUBLE OFF)
else()
message(FATAL_ERROR " *** Invalid floating-point precision: "
"MFEM_PRECISION = ${MFEM_PRECISION}")
endif()
message(STATUS "Floating-point precision: MFEM_PRECISION = ${MFEM_PRECISION}")
# MFEM_DEBUG
if (CMAKE_BUILD_TYPE MATCHES "Debug|debug|DEBUG")
set(MFEM_DEBUG ON)
+2
View File
@@ -362,6 +362,8 @@ Before you can start, you need a GitHub account, here are a few suggestions:
conflicted files in the commit message.
- All significant new features and changes should be documented in CHANGELOG.
- New examples and miniapps should have documentation on the MFEM webpage.
- The general floating-point type `real_t` should be used, rather than
`float` or `double`, except in special cases where only one is possible.
### Pull Requests
+15 -6
View File
@@ -284,6 +284,15 @@ MFEM_USE_METIS = YES/NO
option in the library will be Cartesian partitioning with box meshes, and
thus most of the parallel examples and miniapps will fail.
MFEM_PRECISION = double/Double/DOUBLE/single/Single/SINGLE
Use single (float type) or double floating-point precision. In the
configuration header 'config/_config.hpp' this option is represented by
defining exactly one of the macros: MFEM_USE_DOUBLE, or MFEM_USE_SINGLE.
In the exported config files 'config.mk' and 'MFEMConfig.cmake', the option
is represented by the variables MFEM_USE_DOUBLE and MFEM_USE_SINGLE defined
as YES/NO (make) or ON/OFF (cmake). For more details see
https://github.com/orgs/mfem/discussions/4207
MFEM_DEBUG = YES/NO
Choose debug/optimized build. The debug build enables a number of messages
and consistency checks that may simplify bug-hunting.
@@ -692,9 +701,10 @@ The specific libraries and their options are:
Options: NETCDF_OPT, NETCDF_LIB.
Versions: NetCDF >= 4.4.0.
- PETSc (optional), used when MFEM_USE_PETSC = YES. Version 3.8 or higher of
the PETSC dev branch is required. The MFEM and PETSc builds can share common
libraries, e.g., hypre and SUNDIALS. Here's an example configuration, assuming
- PETSc (optional), used when MFEM_USE_PETSC = YES. Version 3.21 or higher of
the PETSC dev branch is required, though depending on the functionality older
versions may work too. The MFEM and PETSc builds can share common libraries,
e.g., hypre and SUNDIALS. Here's an example configuration, assuming
PETSc has been cloned on the same level as mfem and hypre:
./configure --download-fblaslapack=yes --download-scalapack=yes \
--download-mumps=yes --download-suitesparse=yes \
@@ -704,9 +714,7 @@ The specific libraries and their options are:
CFLAGS to allow proper parsing of the hipsparse header under C.
URL: https://www.mcs.anl.gov/petsc
Options: PETSC_OPT, PETSC_LIB.
Versions: PETSc >= 3.8.0 (PETSc build without CUDA/HIP)
PETSc >= 3.15.0 (PETSc built with CUDA)
PETSc >= 3.19.0 (PETSc built with HIP, older versions may work too)
Versions: PETSc >= 3.21.0, older versions may work too.
- SLEPc (optional), used when MFEM_USE_SLEPC = YES. SLEPc depends on PETSc and
uses some of the PETSc options when compiled.
@@ -959,6 +967,7 @@ The following options are equivalent to the GNU make options with the same name:
MFEM_USE_MPI
MFEM_USE_METIS - Set to ${MFEM_USE_MPI}, can be overwritten.
MFEM_PRECISION
MFEM_USE_LIBUNWIND
MFEM_USE_LAPACK
MFEM_THREAD_SAFE
+2
View File
@@ -18,6 +18,8 @@ set(MFEM_GIT_STRING "@MFEM_GIT_STRING@")
set(MFEM_USE_MPI @MFEM_USE_MPI@)
set(MFEM_USE_METIS @MFEM_USE_METIS@)
set(MFEM_USE_METIS_5 @MFEM_USE_METIS_5@)
set(MFEM_USE_DOUBLE @MFEM_USE_DOUBLE@)
set(MFEM_USE_SINGLE @MFEM_USE_SINGLE@)
set(MFEM_DEBUG @MFEM_DEBUG@)
set(MFEM_USE_EXCEPTIONS @MFEM_USE_EXCEPTIONS@)
set(MFEM_USE_ZLIB @MFEM_USE_ZLIB@)
+6
View File
@@ -46,6 +46,12 @@
// Requires an MPI compiler, and the libraries HYPRE and METIS.
#cmakedefine MFEM_USE_MPI
// Use double-precision floating point type
#cmakedefine MFEM_USE_DOUBLE
// Use single-precision floating point type
#cmakedefine MFEM_USE_SINGLE
// Enable debug checks in MFEM.
#cmakedefine MFEM_DEBUG
+3 -1
View File
@@ -79,7 +79,9 @@ if (HYPRE_FOUND AND HYPRE_USING_CUDA)
find_package(CUDAToolkit REQUIRED)
get_target_property(CUSPARSE_LIBRARIES CUDA::cusparse LOCATION)
get_target_property(CURAND_LIBRARIES CUDA::curand LOCATION)
list(APPEND HYPRE_LIBRARIES ${CUSPARSE_LIBRARIES} ${CURAND_LIBRARIES})
get_target_property(CUBLAS_LIBRARIES CUDA::cublas LOCATION)
list(APPEND HYPRE_LIBRARIES ${CUSPARSE_LIBRARIES} ${CURAND_LIBRARIES}
${CUBLAS_LIBRARIES})
set(HYPRE_LIBRARIES ${HYPRE_LIBRARIES} CACHE STRING
"HYPRE libraries + dependencies." FORCE)
message(STATUS "Updated HYPRE_LIBRARIES: ${HYPRE_LIBRARIES}")
+12 -11
View File
@@ -842,17 +842,18 @@ function(mfem_export_mk_files)
# Convert Boolean vars to YES/NO without writing the values to cache
set(CONFIG_MK_BOOL_VARS MFEM_USE_MPI MFEM_USE_METIS MFEM_USE_METIS_5
MFEM_DEBUG MFEM_USE_EXCEPTIONS MFEM_USE_ZLIB MFEM_USE_LIBUNWIND
MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_LEGACY_OPENMP MFEM_USE_OPENMP
MFEM_USE_MEMALLOC MFEM_USE_SUNDIALS MFEM_USE_SUITESPARSE
MFEM_USE_SUPERLU MFEM_USE_SUPERLU5 MFEM_USE_MUMPS MFEM_USE_STRUMPACK
MFEM_USE_GINKGO MFEM_USE_AMGX MFEM_USE_GNUTLS MFEM_USE_NETCDF
MFEM_USE_PETSC MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS
MFEM_USE_CONDUIT MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA
MFEM_USE_HIP MFEM_USE_RAJA MFEM_USE_OCCA MFEM_USE_CEED MFEM_USE_CALIPER
MFEM_USE_UMPIRE MFEM_USE_SIMD MFEM_USE_ADIOS2 MFEM_USE_MKL_CPARDISO
MFEM_USE_ADFORWARD MFEM_USE_CODIPACK MFEM_USE_BENCHMARK MFEM_USE_PARELAG
MFEM_USE_MOONOLITH MFEM_USE_ALGOIM MFEM_USE_ENZYME)
MFEM_USE_SINGLE MFEM_USE_DOUBLE MFEM_DEBUG MFEM_USE_EXCEPTIONS
MFEM_USE_ZLIB MFEM_USE_LIBUNWIND MFEM_USE_LAPACK MFEM_THREAD_SAFE
MFEM_USE_LEGACY_OPENMP MFEM_USE_OPENMP MFEM_USE_MEMALLOC MFEM_USE_SUNDIALS
MFEM_USE_SUITESPARSE MFEM_USE_SUPERLU MFEM_USE_SUPERLU5 MFEM_USE_MUMPS
MFEM_USE_STRUMPACK MFEM_USE_GINKGO MFEM_USE_AMGX MFEM_USE_GNUTLS
MFEM_USE_NETCDF MFEM_USE_PETSC MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE
MFEM_USE_FMS MFEM_USE_CONDUIT MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB
MFEM_USE_CUDA MFEM_USE_HIP MFEM_USE_RAJA MFEM_USE_OCCA MFEM_USE_CEED
MFEM_USE_CALIPER MFEM_USE_UMPIRE MFEM_USE_SIMD MFEM_USE_ADIOS2
MFEM_USE_MKL_CPARDISO MFEM_USE_MKL_PARDISO MFEM_USE_ADFORWARD
MFEM_USE_CODIPACK MFEM_USE_BENCHMARK MFEM_USE_PARELAG MFEM_USE_MOONOLITH
MFEM_USE_ALGOIM MFEM_USE_ENZYME)
foreach(var ${CONFIG_MK_BOOL_VARS})
if (${var})
set(${var} YES)
+56
View File
@@ -23,6 +23,62 @@
#include "_config.hpp"
#endif
namespace mfem
{
#if (defined(MFEM_USE_CUDA) && defined(__CUDACC__)) || \
(defined(MFEM_USE_HIP) && defined(__HIPCC__))
#define MFEM_HOST_DEVICE __host__ __device__
#else
#define MFEM_HOST_DEVICE
#endif
// MFEM precision configuration
#if defined MFEM_USE_SINGLE && defined MFEM_USE_DOUBLE
#error "DOUBLE and SINGLE precision cannot both be specified"
#endif
#ifdef MFEM_USE_SINGLE
typedef float real_t;
#elif defined MFEM_USE_DOUBLE
typedef double real_t;
#else
#error "Either DOUBLE or SINGLE precision must be specified"
#endif
MFEM_HOST_DEVICE
constexpr real_t operator""_r(long double v)
{
return static_cast<real_t>(v);
}
MFEM_HOST_DEVICE
constexpr real_t operator""_r(unsigned long long v)
{
return static_cast<real_t>(v);
}
} // namespace mfem
// Return value for main function in examples that should be skipped by testing
// in some case. This return value prevents failures in testing.
#define MFEM_SKIP_RETURN_VALUE 242
// Request a global object to be instantiated for each thread in its TLS.
#define MFEM_THREAD_LOCAL thread_local
// MFEM_DEPRECATED macro to mark obsolete functions and methods
// see https://stackoverflow.com/questions/295120/c-mark-as-deprecated
#if defined(__GNUC__) || defined(__clang__)
#define MFEM_DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
#define MFEM_DEPRECATED __declspec(deprecated)
#else
#pragma message("WARNING: You need to implement MFEM_DEPRECATED for this compiler")
#define MFEM_DEPRECATED
#endif
// Common configuration macros
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)
+6
View File
@@ -46,6 +46,12 @@
// Requires an MPI compiler, and the libraries HYPRE and METIS.
// #define MFEM_USE_MPI
// Use double-precision floating point type
// #define MFEM_USE_DOUBLE
// Use single-precision floating point type
// #define MFEM_USE_SINGLE
// Enable debug checks in MFEM.
// #define MFEM_DEBUG
+2
View File
@@ -18,6 +18,8 @@ MFEM_GIT_STRING = @MFEM_GIT_STRING@
MFEM_USE_MPI = @MFEM_USE_MPI@
MFEM_USE_METIS = @MFEM_USE_METIS@
MFEM_USE_METIS_5 = @MFEM_USE_METIS_5@
MFEM_USE_DOUBLE = @MFEM_USE_DOUBLE@
MFEM_USE_SINGLE = @MFEM_USE_SINGLE@
MFEM_DEBUG = @MFEM_DEBUG@
MFEM_USE_EXCEPTIONS = @MFEM_USE_EXCEPTIONS@
MFEM_USE_ZLIB = @MFEM_USE_ZLIB@
+2
View File
@@ -22,6 +22,8 @@ endif()
option(BUILD_SHARED_LIBS "Enable shared library build of MFEM" OFF)
option(MFEM_USE_MPI "Enable MPI parallel build" OFF)
option(MFEM_USE_METIS "Enable METIS usage" ${MFEM_USE_MPI})
set(MFEM_PRECISION "double" CACHE STRING
"Floating-point precision to use: single, or double")
option(MFEM_USE_EXCEPTIONS "Enable the use of exceptions" OFF)
option(MFEM_USE_ZLIB "Enable zlib for compressed data streams." OFF)
option(MFEM_USE_LIBUNWIND "Enable backtrace for errors." OFF)
+7 -1
View File
@@ -120,6 +120,7 @@ MFEM_MPI_NP = 4
MFEM_USE_MPI = NO
MFEM_USE_METIS = $(MFEM_USE_MPI)
MFEM_USE_METIS_5 = NO
MFEM_PRECISION = double
MFEM_DEBUG = NO
MFEM_USE_EXCEPTIONS = NO
MFEM_USE_ZLIB = NO
@@ -317,8 +318,13 @@ MPI_FORTRAN_LIB = -lmpifort
# MUMPS library configuration
MUMPS_DIR = @MFEM_DIR@/../MUMPS_5.5.0
MUMPS_OPT = -I$(MUMPS_DIR)/include
MUMPS_LIB = $(XLINKER)-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps\
MUMPS_LIB = $(XLINKER)-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib \
-lmumps_common -lpord $(SCALAPACK_LIB) $(LAPACK_LIB) $(MPI_FORTRAN_LIB)
ifeq ($(MFEM_USE_SINGLE),YES)
MUMPS_LIB += -lsmumps
else
MUMPS_LIB += -ldmumps
endif
# STRUMPACK library configuration
STRUMPACK_DIR = @MFEM_DIR@/../STRUMPACK-build
+4
View File
@@ -9,7 +9,11 @@
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifdef MFEM_USE_SINGLE
#include "smumps_c.h"
#else
#include "dmumps_c.h"
#endif
#include <string>
#include <iostream>
#include <algorithm>
+118
View File
@@ -0,0 +1,118 @@
SetFactory("OpenCASCADE");
order = 1;
R = 1;
r = 0.2;
Point(1) = {0,0,0};
Point(2) = {r/Sqrt(2),r/Sqrt(2),0};
Point(3) = {-r/Sqrt(2),r/Sqrt(2),0};
Point(4) = {-r/Sqrt(2),-r/Sqrt(2),0};
Point(5) = {r/Sqrt(2),-r/Sqrt(2),0};
Point(6) = {R,0,0};
Point(7) = {R/Sqrt(2),R/Sqrt(2),0};
Point(8) = {0,R,0};
Point(9) = {-R/Sqrt(2),R/Sqrt(2),0};
Point(10) = {-R,0,0};
Point(11) = {-R/Sqrt(2),-R/Sqrt(2),0};
Point(12) = {0,-R,0};
Point(13) = {R/Sqrt(2),-R/Sqrt(2),0};
Line(1) = {1,2};
Line(2) = {1,3};
Line(3) = {1,4};
Line(4) = {1,5};
Line(5) = {1,6};
Line(6) = {1,8};
Line(7) = {1,10};
Line(8) = {1,12};
Line(9) = {2,6};
Line(10) = {2,8};
Line(11) = {3,8};
Line(12) = {3,10};
Line(13) = {4,10};
Line(14) = {4,12};
Line(15) = {5,12};
Line(16) = {5,6};
Line(17) = {6,7};
Line(18) = {7,8};
Line(19) = {8,9};
Line(20) = {9,10};
Line(21) = {10,11};
Line(22) = {11,12};
Line(23) = {12,13};
Line(24) = {13,6};
Transfinite Curve{1:24} = 2;
Physical Curve("ENE") = {17};
Physical Curve("NNE") = {18};
Physical Curve("NNW") = {19};
Physical Curve("WNW") = {20};
Physical Curve("WSW") = {21};
Physical Curve("SSW") = {22};
Physical Curve("SSE") = {23};
Physical Curve("ESE") = {24};
Curve Loop(1) = {9,17,18,-10};
Curve Loop(2) = {11,19,20,-12};
Curve Loop(3) = {13,21,22,-14};
Curve Loop(4) = {15,23,24,-16};
Plane Surface(1) = {1};
Plane Surface(2) = {2};
Plane Surface(3) = {3};
Plane Surface(4) = {4};
Transfinite Surface{1} = {2,6,7,8};
Transfinite Surface{2} = {3,8,9,10};
Transfinite Surface{3} = {4,10,11,12};
Transfinite Surface{4} = {5,12,13,6};
Recombine Surface{1:4};
Physical Surface("Base") = {1,2,3,4};
Curve Loop(5) = {1,10,-6};
Plane Surface(5) = {5};
Physical Surface("N Even") = {5};
Curve Loop(6) = {6,-11,-2};
Plane Surface(6) = {6};
Physical Surface("N Odd") = {6};
Curve Loop(7) = {2,12,-7};
Plane Surface(7) = {7};
Physical Surface("W Even") = {7};
Curve Loop(8) = {7,-13,-3};
Plane Surface(8) = {8};
Physical Surface("W Odd") = {8};
Curve Loop(9) = {3,14,-8};
Plane Surface(9) = {9};
Physical Surface("S Even") = {9};
Curve Loop(10) = {8,-15,-4};
Plane Surface(10) = {10};
Physical Surface("S Odd") = {10};
Curve Loop(11) = {4,16,-5};
Plane Surface(11) = {11};
Physical Surface("E Even") = {11};
Curve Loop(12) = {5,-9,-1};
Plane Surface(12) = {12};
Physical Surface("E Odd") = {12};
// Generate 2D mesh
Mesh 2;
SetOrder order;
Mesh.MshFileVersion = 2.2;
Save "compass.msh";
+95
View File
@@ -0,0 +1,95 @@
MFEM mesh v1.3
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
2
elements
12
10 2 7 0 1
11 2 0 7 2
12 2 9 0 2
13 2 0 9 3
14 2 11 0 3
15 2 0 11 4
16 2 5 0 4
17 2 0 5 1
9 3 1 5 6 7
9 3 2 7 8 9
9 3 3 9 10 11
9 3 4 11 12 5
attribute_sets
16
"Base" 1 9
"E Even" 1 16
"E Odd" 1 17
"East" 2 16 17
"N Even" 1 10
"N Odd" 1 11
"North" 2 10 11
"Rose" 8 10 11 12 13 14 15 16 17
"Rose Even" 4 10 12 14 16
"Rose Odd" 4 11 13 15 17
"S Even" 1 14
"S Odd" 1 15
"South" 2 14 15
"W Even" 1 12
"W Odd" 1 13
"West" 2 12 13
boundary
8
1 1 5 6
2 1 6 7
3 1 7 8
4 1 8 9
5 1 9 10
6 1 10 11
7 1 11 12
8 1 12 5
bdr_attribute_sets
13
"Boundary" 8 1 2 3 4 5 6 7 8
"ENE" 1 1
"ESE" 1 8
"Eastern Boundary" 2 1 8
"NNE" 1 2
"NNW" 1 3
"Northern Boundary" 2 2 3
"SSE" 1 7
"SSW" 1 6
"Southern Boundary" 2 6 7
"WNW" 1 4
"WSW" 1 5
"Western Boundary" 2 4 5
vertices
13
2
0 0
0.14142136 0.14142136
-0.14142136 0.14142136
-0.14142136 -0.14142136
0.14142136 -0.14142136
1 0
0.70710678 0.70710678
0 1
-0.70710678 0.70710678
-1 0
-0.70710678 -0.70710678
0 -1
0.70710678 -0.70710678
mfem_mesh_end
+62
View File
@@ -0,0 +1,62 @@
$MeshFormat
2.2 0 8
$EndMeshFormat
$PhysicalNames
17
1 1 "ENE"
1 2 "NNE"
1 3 "NNW"
1 4 "WNW"
1 5 "WSW"
1 6 "SSW"
1 7 "SSE"
1 8 "ESE"
2 9 "Base"
2 10 "N Even"
2 11 "N Odd"
2 12 "W Even"
2 13 "W Odd"
2 14 "S Even"
2 15 "S Odd"
2 16 "E Even"
2 17 "E Odd"
$EndPhysicalNames
$Nodes
13
1 0 0 0
2 0.1414213562373095 0.1414213562373095 0
3 -0.1414213562373095 0.1414213562373095 0
4 -0.1414213562373095 -0.1414213562373095 0
5 0.1414213562373095 -0.1414213562373095 0
6 1 0 0
7 0.7071067811865475 0.7071067811865475 0
8 0 1 0
9 -0.7071067811865475 0.7071067811865475 0
10 -1 0 0
11 -0.7071067811865475 -0.7071067811865475 0
12 0 -1 0
13 0.7071067811865475 -0.7071067811865475 0
$EndNodes
$Elements
20
1 1 2 1 17 6 7
2 1 2 2 18 7 8
3 1 2 3 19 8 9
4 1 2 4 20 9 10
5 1 2 5 21 10 11
6 1 2 6 22 11 12
7 1 2 7 23 12 13
8 1 2 8 24 13 6
9 2 2 10 5 1 2 8
10 2 2 11 6 1 8 3
11 2 2 12 7 1 3 10
12 2 2 13 8 1 10 4
13 2 2 14 9 1 4 12
14 2 2 15 10 1 12 5
15 2 2 16 11 1 5 6
16 2 2 17 12 1 6 2
17 3 2 9 1 2 6 7 8
18 3 2 9 2 3 8 9 10
19 3 2 9 3 4 10 11 12
20 3 2 9 4 5 12 13 6
$EndElements
+20 -6
View File
@@ -43,13 +43,10 @@ list(APPEND ALL_EXE_SRCS
ex34.cpp
ex36.cpp
ex37.cpp
)
if(MFEM_USE_LAPACK)
list(APPEND ALL_EXE_SRCS
ex38.cpp
ex39.cpp
ex40.cpp
)
endif()
if (MFEM_USE_MPI)
list(APPEND ALL_EXE_SRCS
@@ -90,7 +87,21 @@ if (MFEM_USE_MPI)
ex35p.cpp
ex36p.cpp
ex37p.cpp
)
ex39p.cpp
ex40p.cpp
)
endif()
# Examples that return MFEM_SKIP_RETURN_VALUE in some cases:
set(SKIP_TESTS)
if (HYPRE_USING_CUDA OR HYPRE_USING_HIP)
list(APPEND SKIP_TESTS ex19p.cpp ex28p.cpp)
endif()
if (MFEM_USE_SINGLE)
list(APPEND SKIP_TESTS ex33.cpp ex33p.cpp)
endif()
if (NOT MFEM_USE_LAPACK)
list(APPEND SKIP_TESTS ex38.cpp)
endif()
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
@@ -102,6 +113,9 @@ add_mfem_examples(ALL_EXE_SRCS)
# Add a test for each example
if (MFEM_ENABLE_TESTING)
foreach(SRC_FILE ${ALL_EXE_SRCS})
if (SRC_FILE IN_LIST SKIP_TESTS)
continue()
endif()
get_filename_component(SRC_FILENAME ${SRC_FILE} NAME)
string(REPLACE ".cpp" "" TEST_NAME ${SRC_FILENAME})
+41 -31
View File
@@ -62,7 +62,7 @@ protected:
BilinearForm M, S;
NonlinearForm H;
double viscosity;
real_t viscosity;
HyperelasticModel *model;
CGSolver M_solver; // Krylov solver for inverting the mass matrix M
@@ -84,16 +84,16 @@ protected:
public:
HyperelasticOperator(FiniteElementSpace &f, Array<int> &ess_bdr,
double visc, double mu, double K);
real_t visc, real_t mu, real_t K);
/// Compute the right-hand side of the ODE system.
virtual void Mult(const Vector &vx, Vector &dvx_dt) const;
/** Solve the Backward-Euler equation: k = f(x + dt*k, t), for the unknown k.
This is the only requirement for high-order SDIRK implicit integration.*/
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &x, Vector &k);
double ElasticEnergy(const Vector &x) const;
double KineticEnergy(const Vector &v) const;
real_t ElasticEnergy(const Vector &x) const;
real_t KineticEnergy(const Vector &v) const;
void GetElasticEnergyDensity(const GridFunction &x, GridFunction &w) const;
virtual ~HyperelasticOperator();
@@ -109,7 +109,7 @@ private:
BilinearForm *M, *S;
NonlinearForm *H;
mutable SparseMatrix *Jacobian;
double dt;
real_t dt;
const Vector *v, *x;
mutable Vector w, z;
@@ -117,7 +117,7 @@ public:
ReducedSystemOperator(BilinearForm *M_, BilinearForm *S_, NonlinearForm *H_);
/// Set current dt, v, x values - needed to compute action and Jacobian.
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
void SetParameters(real_t dt_, const Vector *v_, const Vector *x_);
/// Compute y = H(x + dt (v + dt k)) + M k + S (v + dt k).
virtual void Mult(const Vector &k, Vector &y) const;
@@ -141,7 +141,7 @@ private:
public:
ElasticEnergyCoefficient(HyperelasticModel &m, const GridFunction &x_)
: model(m), x(x_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual ~ElasticEnergyCoefficient() { }
};
@@ -161,11 +161,11 @@ int main(int argc, char *argv[])
int ref_levels = 2;
int order = 2;
int ode_solver_type = 3;
double t_final = 300.0;
double dt = 3.0;
double visc = 1e-2;
double mu = 0.25;
double K = 5.0;
real_t t_final = 300.0;
real_t dt = 3.0;
real_t visc = 1e-2;
real_t mu = 0.25;
real_t K = 5.0;
bool visualization = true;
int vis_steps = 1;
@@ -309,13 +309,13 @@ int main(int argc, char *argv[])
<< " Press space (in the GLVis window) to resume it.\n";
}
double ee0 = oper.ElasticEnergy(x.GetTrueVector());
double ke0 = oper.KineticEnergy(v.GetTrueVector());
real_t ee0 = oper.ElasticEnergy(x.GetTrueVector());
real_t ke0 = oper.KineticEnergy(v.GetTrueVector());
cout << "initial elastic energy (EE) = " << ee0 << endl;
cout << "initial kinetic energy (KE) = " << ke0 << endl;
cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
double t = 0.0;
real_t t = 0.0;
oper.SetTime(t);
ode_solver->Init(oper);
@@ -324,7 +324,7 @@ int main(int argc, char *argv[])
bool last_step = false;
for (int ti = 1; !last_step; ti++)
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(vx, t, dt_real);
@@ -332,8 +332,8 @@ int main(int argc, char *argv[])
if (last_step || (ti % vis_steps) == 0)
{
double ee = oper.ElasticEnergy(x.GetTrueVector());
double ke = oper.KineticEnergy(v.GetTrueVector());
real_t ee = oper.ElasticEnergy(x.GetTrueVector());
real_t ke = oper.KineticEnergy(v.GetTrueVector());
cout << "step " << ti << ", t = " << t << ", EE = " << ee << ", KE = "
<< ke << ", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
@@ -419,7 +419,7 @@ ReducedSystemOperator::ReducedSystemOperator(
dt(0.0), v(NULL), x(NULL), w(height), z(height)
{ }
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
void ReducedSystemOperator::SetParameters(real_t dt_, const Vector *v_,
const Vector *x_)
{
dt = dt_; v = v_; x = x_;
@@ -453,16 +453,26 @@ ReducedSystemOperator::~ReducedSystemOperator()
HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
Array<int> &ess_bdr, double visc,
double mu, double K)
: TimeDependentOperator(2*f.GetTrueVSize(), 0.0), fespace(f),
Array<int> &ess_bdr, real_t visc,
real_t mu, real_t K)
: TimeDependentOperator(2*f.GetTrueVSize(), (real_t) 0.0), fespace(f),
M(&fespace), S(&fespace), H(&fespace),
viscosity(visc), z(height/2)
{
const double rel_tol = 1e-8;
#if defined(MFEM_USE_DOUBLE)
const real_t rel_tol = 1e-8;
const real_t newton_abs_tol = 0.0;
#elif defined(MFEM_USE_SINGLE)
const real_t rel_tol = 1e-3;
const real_t newton_abs_tol = 1e-4;
#else
#error "Only single and double precision are supported!"
const real_t rel_tol = real_t(1);
const real_t newton_abs_tol = real_t(0);
#endif
const int skip_zero_entries = 0;
const double ref_density = 1.0; // density in the reference configuration
const real_t ref_density = 1.0; // density in the reference configuration
ConstantCoefficient rho0(ref_density);
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
M.Assemble(skip_zero_entries);
@@ -509,7 +519,7 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
newton_solver.SetOperator(*reduced_oper);
newton_solver.SetPrintLevel(1); // print Newton iterations
newton_solver.SetRelTol(rel_tol);
newton_solver.SetAbsTol(0.0);
newton_solver.SetAbsTol(newton_abs_tol);
newton_solver.SetMaxIter(10);
}
@@ -533,7 +543,7 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
dx_dt = v;
}
void HyperelasticOperator::ImplicitSolve(const double dt,
void HyperelasticOperator::ImplicitSolve(const real_t dt,
const Vector &vx, Vector &dvx_dt)
{
int sc = height/2;
@@ -555,12 +565,12 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
add(v, dt, dv_dt, dx_dt);
}
double HyperelasticOperator::ElasticEnergy(const Vector &x) const
real_t HyperelasticOperator::ElasticEnergy(const Vector &x) const
{
return H.GetEnergy(x);
}
double HyperelasticOperator::KineticEnergy(const Vector &v) const
real_t HyperelasticOperator::KineticEnergy(const Vector &v) const
{
return 0.5*M.InnerProduct(v, v);
}
@@ -581,7 +591,7 @@ HyperelasticOperator::~HyperelasticOperator()
}
double ElasticEnergyCoefficient::Eval(ElementTransformation &T,
real_t ElasticEnergyCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
model.SetTransformation(T);
@@ -601,7 +611,7 @@ void InitialDeformation(const Vector &x, Vector &y)
void InitialVelocity(const Vector &x, Vector &v)
{
const int dim = x.Size();
const double s = 0.1/64.;
const real_t s = 0.1/64.;
v = 0.0;
v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
+45 -35
View File
@@ -63,7 +63,7 @@ protected:
ParBilinearForm M, S;
ParNonlinearForm H;
double viscosity;
real_t viscosity;
HyperelasticModel *model;
HypreParMatrix *Mmat; // Mass matrix from ParallelAssemble()
@@ -86,16 +86,16 @@ protected:
public:
HyperelasticOperator(ParFiniteElementSpace &f, Array<int> &ess_bdr,
double visc, double mu, double K);
real_t visc, real_t mu, real_t K);
/// Compute the right-hand side of the ODE system.
virtual void Mult(const Vector &vx, Vector &dvx_dt) const;
/** Solve the Backward-Euler equation: k = f(x + dt*k, t), for the unknown k.
This is the only requirement for high-order SDIRK implicit integration.*/
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &x, Vector &k);
double ElasticEnergy(const ParGridFunction &x) const;
double KineticEnergy(const ParGridFunction &v) const;
real_t ElasticEnergy(const ParGridFunction &x) const;
real_t KineticEnergy(const ParGridFunction &v) const;
void GetElasticEnergyDensity(const ParGridFunction &x,
ParGridFunction &w) const;
@@ -112,7 +112,7 @@ private:
ParBilinearForm *M, *S;
ParNonlinearForm *H;
mutable HypreParMatrix *Jacobian;
double dt;
real_t dt;
const Vector *v, *x;
mutable Vector w, z;
const Array<int> &ess_tdof_list;
@@ -122,7 +122,7 @@ public:
ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
/// Set current dt, v, x values - needed to compute action and Jacobian.
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
void SetParameters(real_t dt_, const Vector *v_, const Vector *x_);
/// Compute y = H(x + dt (v + dt k)) + M k + S (v + dt k).
virtual void Mult(const Vector &k, Vector &y) const;
@@ -146,7 +146,7 @@ private:
public:
ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
: model(m), x(x_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual ~ElasticEnergyCoefficient() { }
};
@@ -173,11 +173,11 @@ int main(int argc, char *argv[])
int par_ref_levels = 0;
int order = 2;
int ode_solver_type = 3;
double t_final = 300.0;
double dt = 3.0;
double visc = 1e-2;
double mu = 0.25;
double K = 5.0;
real_t t_final = 300.0;
real_t dt = 3.0;
real_t visc = 1e-2;
real_t mu = 0.25;
real_t K = 5.0;
bool adaptive_lin_rtol = true;
bool visualization = true;
int vis_steps = 1;
@@ -358,8 +358,8 @@ int main(int argc, char *argv[])
}
}
double ee0 = oper.ElasticEnergy(x_gf);
double ke0 = oper.KineticEnergy(v_gf);
real_t ee0 = oper.ElasticEnergy(x_gf);
real_t ke0 = oper.KineticEnergy(v_gf);
if (myid == 0)
{
cout << "initial elastic energy (EE) = " << ee0 << endl;
@@ -367,7 +367,7 @@ int main(int argc, char *argv[])
cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
}
double t = 0.0;
real_t t = 0.0;
oper.SetTime(t);
ode_solver->Init(oper);
@@ -376,7 +376,7 @@ int main(int argc, char *argv[])
bool last_step = false;
for (int ti = 1; !last_step; ti++)
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(vx, t, dt_real);
@@ -386,8 +386,8 @@ int main(int argc, char *argv[])
{
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
double ee = oper.ElasticEnergy(x_gf);
double ke = oper.KineticEnergy(v_gf);
real_t ee = oper.ElasticEnergy(x_gf);
real_t ke = oper.KineticEnergy(v_gf);
if (myid == 0)
{
@@ -485,7 +485,7 @@ ReducedSystemOperator::ReducedSystemOperator(
ess_tdof_list(ess_tdof_list_)
{ }
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
void ReducedSystemOperator::SetParameters(real_t dt_, const Vector *v_,
const Vector *x_)
{
dt = dt_; v = v_; x = x_;
@@ -523,17 +523,27 @@ ReducedSystemOperator::~ReducedSystemOperator()
HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
Array<int> &ess_bdr, double visc,
double mu, double K)
: TimeDependentOperator(2*f.TrueVSize(), 0.0), fespace(f),
Array<int> &ess_bdr, real_t visc,
real_t mu, real_t K)
: TimeDependentOperator(2*f.TrueVSize(), (real_t) 0.0), fespace(f),
M(&fespace), S(&fespace), H(&fespace),
viscosity(visc), M_solver(f.GetComm()), newton_solver(f.GetComm()),
z(height/2)
{
const double rel_tol = 1e-8;
#if defined(MFEM_USE_DOUBLE)
const real_t rel_tol = 1e-8;
const real_t newton_abs_tol = 0.0;
#elif defined(MFEM_USE_SINGLE)
const real_t rel_tol = 1e-3;
const real_t newton_abs_tol = 1e-4;
#else
#error "Only single and double precision are supported!"
const real_t rel_tol = real_t(1);
const real_t newton_abs_tol = real_t(0);
#endif
const int skip_zero_entries = 0;
const double ref_density = 1.0; // density in the reference configuration
const real_t ref_density = 1.0; // density in the reference configuration
ConstantCoefficient rho0(ref_density);
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
M.Assemble(skip_zero_entries);
@@ -581,7 +591,7 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
newton_solver.SetOperator(*reduced_oper);
newton_solver.SetPrintLevel(1); // print Newton iterations
newton_solver.SetRelTol(rel_tol);
newton_solver.SetAbsTol(0.0);
newton_solver.SetAbsTol(newton_abs_tol);
newton_solver.SetAdaptiveLinRtol(2, 0.5, 0.9);
newton_solver.SetMaxIter(10);
}
@@ -607,7 +617,7 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
dx_dt = v;
}
void HyperelasticOperator::ImplicitSolve(const double dt,
void HyperelasticOperator::ImplicitSolve(const real_t dt,
const Vector &vx, Vector &dvx_dt)
{
int sc = height/2;
@@ -629,17 +639,17 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
add(v, dt, dv_dt, dx_dt);
}
double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
real_t HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
{
return H.GetEnergy(x);
}
double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
real_t HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
{
double loc_energy = 0.5*M.InnerProduct(v, v);
double energy;
MPI_Allreduce(&loc_energy, &energy, 1, MPI_DOUBLE, MPI_SUM,
fespace.GetComm());
real_t loc_energy = 0.5*M.InnerProduct(v, v);
real_t energy;
MPI_Allreduce(&loc_energy, &energy, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, fespace.GetComm());
return energy;
}
@@ -660,7 +670,7 @@ HyperelasticOperator::~HyperelasticOperator()
}
double ElasticEnergyCoefficient::Eval(ElementTransformation &T,
real_t ElasticEnergyCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
model.SetTransformation(T);
@@ -680,7 +690,7 @@ void InitialDeformation(const Vector &x, Vector &y)
void InitialVelocity(const Vector &x, Vector &v)
{
const int dim = x.Size();
const double s = 0.1/64.;
const real_t s = 0.1/64.;
v = 0.0;
v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
+2 -2
View File
@@ -211,7 +211,7 @@ int main(int argc, char *argv[])
m->AddDomainIntegrator(new MassIntegrator(one));
m->Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m->Finalize();
HypreParMatrix *A = a->ParallelAssemble();
@@ -300,7 +300,7 @@ int main(int argc, char *argv[])
// 9. Compute the eigenmodes and extract the array of eigenvalues. Define a
// parallel grid function to represent each of the eigenmodes returned by
// the solver.
Array<double> eigenvalues;
Array<real_t> eigenvalues;
lobpcg->Solve();
lobpcg->GetEigenvalues(eigenvalues);
ParGridFunction x(fespace);
+2 -2
View File
@@ -206,7 +206,7 @@ int main(int argc, char *argv[])
m->AddDomainIntegrator(new VectorMassIntegrator());
m->Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m->Finalize();
if (myid == 0)
{
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
// 10. Compute the eigenmodes and extract the array of eigenvalues. Define a
// parallel grid function to represent each of the eigenmodes returned by
// the solver.
Array<double> eigenvalues;
Array<real_t> eigenvalues;
lobpcg->Solve();
lobpcg->GetEigenvalues(eigenvalues);
ParGridFunction x(fespace);
+2 -2
View File
@@ -170,7 +170,7 @@ int main(int argc, char *argv[])
m->AddDomainIntegrator(new VectorFEMassIntegrator(one));
m->Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m->Finalize();
HypreParMatrix *A = a->ParallelAssemble();
@@ -198,7 +198,7 @@ int main(int argc, char *argv[])
// 10. Compute the eigenmodes and extract the array of eigenvalues. Define a
// parallel grid function to represent each of the eigenmodes returned by
// the solver.
Array<double> eigenvalues;
Array<real_t> eigenvalues;
ame->Solve();
ame->GetEigenvalues(eigenvalues);
ParGridFunction x(fespace);
+3 -3
View File
@@ -43,9 +43,9 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/star.mesh";
int ref_levels = -1;
int order = 1;
double sigma = -1.0;
double kappa = -1.0;
double eta = 0.0;
real_t sigma = -1.0;
real_t kappa = -1.0;
real_t eta = 0.0;
bool visualization = 1;
OptionsParser args(argc, argv);
+4 -4
View File
@@ -44,7 +44,7 @@ public:
pmesh(m),
pgf(f) {}
void MonitorSolution(int i, double norm, const Vector &x, bool final)
void MonitorSolution(int i, real_t norm, const Vector &x, bool final)
{
char vishost[] = "localhost";
int visport = 19916;
@@ -81,9 +81,9 @@ int main(int argc, char *argv[])
int ser_ref_levels = -1;
int par_ref_levels = 2;
int order = 1;
double sigma = -1.0;
double kappa = -1.0;
double eta = 0.0;
real_t sigma = -1.0;
real_t kappa = -1.0;
real_t eta = 0.0;
bool visualization = 1;
OptionsParser args(argc, argv);
+30 -30
View File
@@ -63,8 +63,8 @@ int problem;
int nfeatures;
// Prescribed time-dependent boundary and right-hand side functions.
double bdr_func(const Vector &pt, double t);
double rhs_func(const Vector &pt, double t);
real_t bdr_func(const Vector &pt, real_t t);
real_t rhs_func(const Vector &pt, real_t t);
// Update the finite element space, interpolate the solution and perform
// parallel load balancing.
@@ -79,9 +79,9 @@ int main(int argc, char *argv[])
nfeatures = 1;
const char *mesh_file = "../data/star-hilbert.mesh";
int order = 2;
double t_final = 1.0;
double max_elem_error = 5.0e-3;
double hysteresis = 0.15; // derefinement safety coefficient
real_t t_final = 1.0;
real_t max_elem_error = 5.0e-3;
real_t hysteresis = 0.15; // derefinement safety coefficient
int ref_levels = 0;
int nc_limit = 3; // maximum level of hanging nodes
bool visualization = true;
@@ -247,7 +247,7 @@ int main(int argc, char *argv[])
// refine the mesh as many times as necessary. Then we derefine any
// elements which have very small errors.
x = 0.0;
for (double time = 0.0; time < t_final + 1e-10; time += 0.01)
for (real_t time = 0.0; time < t_final + 1e-10; time += 0.01)
{
cout << "\nTime " << time << "\n\nRefinement:" << endl;
@@ -366,47 +366,47 @@ void UpdateProblem(Mesh &mesh, FiniteElementSpace &fespace,
}
const double alpha = 0.02;
const real_t alpha = 0.02;
// Spherical front with a Gaussian cross section and radius t
double front(double x, double y, double z, double t, int)
real_t front(real_t x, real_t y, real_t z, real_t t, int)
{
double r = sqrt(x*x + y*y + z*z);
real_t r = sqrt(x*x + y*y + z*z);
return exp(-0.5*pow((r - t)/alpha, 2));
}
double front_laplace(double x, double y, double z, double t, int dim)
real_t front_laplace(real_t x, real_t y, real_t z, real_t t, int dim)
{
double x2 = x*x, y2 = y*y, z2 = z*z, t2 = t*t;
double r = sqrt(x2 + y2 + z2);
double a2 = alpha*alpha, a4 = a2*a2;
real_t x2 = x*x, y2 = y*y, z2 = z*z, t2 = t*t;
real_t r = sqrt(x2 + y2 + z2);
real_t a2 = alpha*alpha, a4 = a2*a2;
return -exp(-0.5*pow((r - t)/alpha, 2)) / a4 *
(-2*t*(x2 + y2 + z2 - (dim-1)*a2/2)/r + x2 + y2 + z2 + t2 - dim*a2);
}
// Smooth spherical step function with radius t
double ball(double x, double y, double z, double t, int)
real_t ball(real_t x, real_t y, real_t z, real_t t, int)
{
double r = sqrt(x*x + y*y + z*z);
real_t r = sqrt(x*x + y*y + z*z);
return -atan(2*(r - t)/alpha);
}
double ball_laplace(double x, double y, double z, double t, int dim)
real_t ball_laplace(real_t x, real_t y, real_t z, real_t t, int dim)
{
double x2 = x*x, y2 = y*y, z2 = z*z, t2 = 4*t*t;
double r = sqrt(x2 + y2 + z2);
double a2 = alpha*alpha;
double den = pow(-a2 - 4*(x2 + y2 + z2 - 2*r*t) - t2, 2.0);
real_t x2 = x*x, y2 = y*y, z2 = z*z, t2 = 4*t*t;
real_t r = sqrt(x2 + y2 + z2);
real_t a2 = alpha*alpha;
real_t den = pow(-a2 - 4*(x2 + y2 + z2 - 2*r*t) - t2, 2.0);
return (dim == 2) ? 2*alpha*(a2 + t2 - 4*x2 - 4*y2)/r/den
/* */ : 4*alpha*(a2 + t2 - 4*r*t)/r/den;
}
// Composes several features into one function
template<typename F0, typename F1>
double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
real_t composite_func(const Vector &pt, real_t t, F0 f0, F1 f1)
{
int dim = pt.Size();
double x = pt(0), y = pt(1), z = 0.0;
real_t x = pt(0), y = pt(1), z = 0.0;
if (dim == 3) { z = pt(2); }
if (problem == 0)
@@ -417,11 +417,11 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
else
{
double sum = 0.0;
real_t sum = 0.0;
for (int i = 0; i < nfeatures; i++)
{
double x0 = 0.5*cos(2*M_PI * i / nfeatures);
double y0 = 0.5*sin(2*M_PI * i / nfeatures);
real_t x0 = 0.5*cos(2*M_PI * i / nfeatures);
real_t y0 = 0.5*sin(2*M_PI * i / nfeatures);
sum += f0(x - x0, y - y0, z, t, dim);
}
return sum;
@@ -429,11 +429,11 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
else
{
double sum = 0.0;
real_t sum = 0.0;
for (int i = 0; i < nfeatures; i++)
{
double x0 = 0.5*cos(2*M_PI * i / nfeatures + M_PI*t);
double y0 = 0.5*sin(2*M_PI * i / nfeatures + M_PI*t);
real_t x0 = 0.5*cos(2*M_PI * i / nfeatures + M_PI*t);
real_t y0 = 0.5*sin(2*M_PI * i / nfeatures + M_PI*t);
sum += f1(x - x0, y - y0, z, 0.25, dim);
}
return sum;
@@ -441,13 +441,13 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
// Exact solution, used for the Dirichlet BC.
double bdr_func(const Vector &pt, double t)
real_t bdr_func(const Vector &pt, real_t t)
{
return composite_func(pt, t, front, ball);
}
// Laplace of the exact solution, used for the right hand side.
double rhs_func(const Vector &pt, double t)
real_t rhs_func(const Vector &pt, real_t t)
{
return composite_func(pt, t, front_laplace, ball_laplace);
}
+30 -30
View File
@@ -68,8 +68,8 @@ int problem;
int nfeatures;
// Prescribed time-dependent boundary and right-hand side functions.
double bdr_func(const Vector &pt, double t);
double rhs_func(const Vector &pt, double t);
real_t bdr_func(const Vector &pt, real_t t);
real_t rhs_func(const Vector &pt, real_t t);
// Update the finite element space, interpolate the solution and perform
// parallel load balancing.
@@ -91,9 +91,9 @@ int main(int argc, char *argv[])
nfeatures = 1;
const char *mesh_file = "../data/star-hilbert.mesh";
int order = 2;
double t_final = 1.0;
double max_elem_error = 1.0e-4;
double hysteresis = 0.25; // derefinement safety coefficient
real_t t_final = 1.0;
real_t max_elem_error = 1.0e-4;
real_t hysteresis = 0.25; // derefinement safety coefficient
int ref_levels = 0;
int nc_limit = 3; // maximum level of hanging nodes
bool visualization = true;
@@ -282,7 +282,7 @@ int main(int argc, char *argv[])
// solve the problem on the current mesh, visualize the solution and
// refine the mesh as many times as necessary. Then we derefine any
// elements which have very small errors.
for (double time = 0.0; time < t_final + 1e-10; time += 0.01)
for (real_t time = 0.0; time < t_final + 1e-10; time += 0.01)
{
if (myid == 0)
{
@@ -427,47 +427,47 @@ void UpdateAndRebalance(ParMesh &pmesh, ParFiniteElementSpace &fespace,
}
const double alpha = 0.02;
const real_t alpha = 0.02;
// Spherical front with a Gaussian cross section and radius t
double front(double x, double y, double z, double t, int)
real_t front(real_t x, real_t y, real_t z, real_t t, int)
{
double r = sqrt(x*x + y*y + z*z);
real_t r = sqrt(x*x + y*y + z*z);
return exp(-0.5*pow((r - t)/alpha, 2));
}
double front_laplace(double x, double y, double z, double t, int dim)
real_t front_laplace(real_t x, real_t y, real_t z, real_t t, int dim)
{
double x2 = x*x, y2 = y*y, z2 = z*z, t2 = t*t;
double r = sqrt(x2 + y2 + z2);
double a2 = alpha*alpha, a4 = a2*a2;
real_t x2 = x*x, y2 = y*y, z2 = z*z, t2 = t*t;
real_t r = sqrt(x2 + y2 + z2);
real_t a2 = alpha*alpha, a4 = a2*a2;
return -exp(-0.5*pow((r - t)/alpha, 2)) / a4 *
(-2*t*(x2 + y2 + z2 - (dim-1)*a2/2)/r + x2 + y2 + z2 + t2 - dim*a2);
}
// Smooth spherical step function with radius t
double ball(double x, double y, double z, double t, int)
real_t ball(real_t x, real_t y, real_t z, real_t t, int)
{
double r = sqrt(x*x + y*y + z*z);
real_t r = sqrt(x*x + y*y + z*z);
return -atan(2*(r - t)/alpha);
}
double ball_laplace(double x, double y, double z, double t, int dim)
real_t ball_laplace(real_t x, real_t y, real_t z, real_t t, int dim)
{
double x2 = x*x, y2 = y*y, z2 = z*z, t2 = 4*t*t;
double r = sqrt(x2 + y2 + z2);
double a2 = alpha*alpha;
double den = pow(-a2 - 4*(x2 + y2 + z2 - 2*r*t) - t2, 2.0);
real_t x2 = x*x, y2 = y*y, z2 = z*z, t2 = 4*t*t;
real_t r = sqrt(x2 + y2 + z2);
real_t a2 = alpha*alpha;
real_t den = pow(-a2 - 4*(x2 + y2 + z2 - 2*r*t) - t2, 2.0);
return (dim == 2) ? 2*alpha*(a2 + t2 - 4*x2 - 4*y2)/r/den
/* */ : 4*alpha*(a2 + t2 - 4*r*t)/r/den;
}
// Composes several features into one function
template<typename F0, typename F1>
double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
real_t composite_func(const Vector &pt, real_t t, F0 f0, F1 f1)
{
int dim = pt.Size();
double x = pt(0), y = pt(1), z = 0.0;
real_t x = pt(0), y = pt(1), z = 0.0;
if (dim == 3) { z = pt(2); }
if (problem == 0)
@@ -478,11 +478,11 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
else
{
double sum = 0.0;
real_t sum = 0.0;
for (int i = 0; i < nfeatures; i++)
{
double x0 = 0.5*cos(2*M_PI * i / nfeatures);
double y0 = 0.5*sin(2*M_PI * i / nfeatures);
real_t x0 = 0.5*cos(2*M_PI * i / nfeatures);
real_t y0 = 0.5*sin(2*M_PI * i / nfeatures);
sum += f0(x - x0, y - y0, z, t, dim);
}
return sum;
@@ -490,11 +490,11 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
else
{
double sum = 0.0;
real_t sum = 0.0;
for (int i = 0; i < nfeatures; i++)
{
double x0 = 0.5*cos(2*M_PI * i / nfeatures + M_PI*t);
double y0 = 0.5*sin(2*M_PI * i / nfeatures + M_PI*t);
real_t x0 = 0.5*cos(2*M_PI * i / nfeatures + M_PI*t);
real_t y0 = 0.5*sin(2*M_PI * i / nfeatures + M_PI*t);
sum += f1(x - x0, y - y0, z, 0.25, dim);
}
return sum;
@@ -502,13 +502,13 @@ double composite_func(const Vector &pt, double t, F0 f0, F1 f1)
}
// Exact solution, used for the Dirichlet BC.
double bdr_func(const Vector &pt, double t)
real_t bdr_func(const Vector &pt, real_t t)
{
return composite_func(pt, t, front, ball);
}
// Laplace of the exact solution, used for the right hand side.
double rhs_func(const Vector &pt, double t)
real_t rhs_func(const Vector &pt, real_t t)
{
return composite_func(pt, t, front_laplace, ball_laplace);
}
+17 -17
View File
@@ -60,7 +60,7 @@ protected:
SparseMatrix Mmat, Kmat;
SparseMatrix *T; // T = M + dt K
double current_dt;
real_t current_dt;
CGSolver M_solver; // Krylov solver for inverting the mass matrix M
DSmoother M_prec; // Preconditioner for the mass matrix M
@@ -68,18 +68,18 @@ protected:
CGSolver T_solver; // Implicit solver for T = M + dt K
DSmoother T_prec; // Preconditioner for the implicit solver
double alpha, kappa;
real_t alpha, kappa;
mutable Vector z; // auxiliary vector
public:
ConductionOperator(FiniteElementSpace &f, double alpha, double kappa,
ConductionOperator(FiniteElementSpace &f, real_t alpha, real_t kappa,
const Vector &u);
virtual void Mult(const Vector &u, Vector &du_dt) const;
/** Solve the Backward-Euler equation: k = f(u + dt*k, t), for the unknown k.
This is the only requirement for high-order SDIRK implicit integration.*/
virtual void ImplicitSolve(const double dt, const Vector &u, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &u, Vector &k);
/// Update the diffusion BilinearForm K using the given true-dof vector `u`.
void SetParameters(const Vector &u);
@@ -87,7 +87,7 @@ public:
virtual ~ConductionOperator();
};
double InitialTemperature(const Vector &x);
real_t InitialTemperature(const Vector &x);
int main(int argc, char *argv[])
{
@@ -96,10 +96,10 @@ int main(int argc, char *argv[])
int ref_levels = 2;
int order = 2;
int ode_solver_type = 3;
double t_final = 0.5;
double dt = 1.0e-2;
double alpha = 1.0e-2;
double kappa = 0.5;
real_t t_final = 0.5;
real_t dt = 1.0e-2;
real_t alpha = 1.0e-2;
real_t kappa = 0.5;
bool visualization = true;
bool visit = false;
int vis_steps = 5;
@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
// 8. Perform time-integration (looping over the time iterations, ti, with a
// time-step dt).
ode_solver->Init(oper);
double t = 0.0;
real_t t = 0.0;
bool last_step = false;
for (int ti = 1; !last_step; ti++)
@@ -293,12 +293,12 @@ int main(int argc, char *argv[])
return 0;
}
ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
double kap, const Vector &u)
: TimeDependentOperator(f.GetTrueVSize(), 0.0), fespace(f), M(NULL), K(NULL),
T(NULL), current_dt(0.0), z(height)
ConductionOperator::ConductionOperator(FiniteElementSpace &f, real_t al,
real_t kap, const Vector &u)
: TimeDependentOperator(f.GetTrueVSize(), (real_t) 0.0), fespace(f),
M(NULL), K(NULL), T(NULL), current_dt(0.0), z(height)
{
const double rel_tol = 1e-8;
const real_t rel_tol = 1e-8;
M = new BilinearForm(&fespace);
M->AddDomainIntegrator(new MassIntegrator());
@@ -336,7 +336,7 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
M_solver.Mult(z, du_dt);
}
void ConductionOperator::ImplicitSolve(const double dt,
void ConductionOperator::ImplicitSolve(const real_t dt,
const Vector &u, Vector &du_dt)
{
// Solve the equation:
@@ -382,7 +382,7 @@ ConductionOperator::~ConductionOperator()
delete K;
}
double InitialTemperature(const Vector &x)
real_t InitialTemperature(const Vector &x)
{
if (x.Norml2() < 0.5)
{
+17 -17
View File
@@ -62,7 +62,7 @@ protected:
HypreParMatrix Mmat;
HypreParMatrix Kmat;
HypreParMatrix *T; // T = M + dt K
double current_dt;
real_t current_dt;
CGSolver M_solver; // Krylov solver for inverting the mass matrix M
HypreSmoother M_prec; // Preconditioner for the mass matrix M
@@ -70,18 +70,18 @@ protected:
CGSolver T_solver; // Implicit solver for T = M + dt K
HypreSmoother T_prec; // Preconditioner for the implicit solver
double alpha, kappa;
real_t alpha, kappa;
mutable Vector z; // auxiliary vector
public:
ConductionOperator(ParFiniteElementSpace &f, double alpha, double kappa,
ConductionOperator(ParFiniteElementSpace &f, real_t alpha, real_t kappa,
const Vector &u);
virtual void Mult(const Vector &u, Vector &du_dt) const;
/** Solve the Backward-Euler equation: k = f(u + dt*k, t), for the unknown k.
This is the only requirement for high-order SDIRK implicit integration.*/
virtual void ImplicitSolve(const double dt, const Vector &u, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &u, Vector &k);
/// Update the diffusion BilinearForm K using the given true-dof vector `u`.
void SetParameters(const Vector &u);
@@ -89,7 +89,7 @@ public:
virtual ~ConductionOperator();
};
double InitialTemperature(const Vector &x);
real_t InitialTemperature(const Vector &x);
int main(int argc, char *argv[])
{
@@ -105,10 +105,10 @@ int main(int argc, char *argv[])
int par_ref_levels = 1;
int order = 2;
int ode_solver_type = 3;
double t_final = 0.5;
double dt = 1.0e-2;
double alpha = 1.0e-2;
double kappa = 0.5;
real_t t_final = 0.5;
real_t dt = 1.0e-2;
real_t alpha = 1.0e-2;
real_t kappa = 0.5;
bool visualization = true;
bool visit = false;
int vis_steps = 5;
@@ -313,7 +313,7 @@ int main(int argc, char *argv[])
// 10. Perform time-integration (looping over the time iterations, ti, with a
// time-step dt).
ode_solver->Init(oper);
double t = 0.0;
real_t t = 0.0;
bool last_step = false;
for (int ti = 1; !last_step; ti++)
@@ -382,13 +382,13 @@ int main(int argc, char *argv[])
return 0;
}
ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, double al,
double kap, const Vector &u)
: TimeDependentOperator(f.GetTrueVSize(), 0.0), fespace(f), M(NULL), K(NULL),
T(NULL), current_dt(0.0),
ConductionOperator::ConductionOperator(ParFiniteElementSpace &f, real_t al,
real_t kap, const Vector &u)
: TimeDependentOperator(f.GetTrueVSize(), (real_t) 0.0), fespace(f),
M(NULL), K(NULL), T(NULL), current_dt(0.0),
M_solver(f.GetComm()), T_solver(f.GetComm()), z(height)
{
const double rel_tol = 1e-8;
const real_t rel_tol = 1e-8;
M = new ParBilinearForm(&fespace);
M->AddDomainIntegrator(new MassIntegrator());
@@ -427,7 +427,7 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
M_solver.Mult(z, du_dt);
}
void ConductionOperator::ImplicitSolve(const double dt,
void ConductionOperator::ImplicitSolve(const real_t dt,
const Vector &u, Vector &du_dt)
{
// Solve the equation:
@@ -473,7 +473,7 @@ ConductionOperator::~ConductionOperator()
delete K;
}
double InitialTemperature(const Vector &x)
real_t InitialTemperature(const Vector &x)
{
if (x.Norml2() < 0.5)
{
+8 -8
View File
@@ -69,7 +69,7 @@ public:
void SetDisplacement(GridFunction &u_) { u = &u_; }
void SetComponent(int i, int j) { si = i; sj = j; }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
// Simple GLVis visualization manager.
@@ -104,8 +104,8 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/beam-tri.mesh";
int ref_levels = -1;
int order = 1;
double alpha = -1.0;
double kappa = -1.0;
real_t alpha = -1.0;
real_t kappa = -1.0;
bool visualization = 1;
OptionsParser args(argc, argv);
@@ -245,7 +245,7 @@ int main(int argc, char *argv[])
// solve the system Ax=b with PCG for the symmetric formulation, or GMRES
// for the non-symmetric.
GSSmoother M(A);
const double rtol = 1e-6;
const real_t rtol = 1e-6;
if (alpha == -1.0)
{
PCG(A, M, B, X, 3, 5000, rtol*rtol, 0.0);
@@ -337,17 +337,17 @@ void InitDisplacement(const Vector &x, Vector &u)
}
double StressCoefficient::Eval(ElementTransformation &T,
real_t StressCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "displacement field is not set");
double L = lambda.Eval(T, ip);
double M = mu.Eval(T, ip);
real_t L = lambda.Eval(T, ip);
real_t M = mu.Eval(T, ip);
u->GetVectorGradient(T, grad);
if (si == sj)
{
double div_u = grad.Trace();
real_t div_u = grad.Trace();
return L*div_u + 2*M*grad(si,si);
}
else
+8 -8
View File
@@ -69,7 +69,7 @@ public:
void SetDisplacement(GridFunction &u_) { u = &u_; }
void SetComponent(int i, int j) { si = i; sj = j; }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
// Simple GLVis visualization manager.
@@ -108,8 +108,8 @@ int main(int argc, char *argv[])
int ser_ref_levels = -1;
int par_ref_levels = 1;
int order = 1;
double alpha = -1.0;
double kappa = -1.0;
real_t alpha = -1.0;
real_t kappa = -1.0;
bool amg_elast = false;
bool visualization = 1;
@@ -268,7 +268,7 @@ int main(int argc, char *argv[])
// 11. Define a simple symmetric Gauss-Seidel preconditioner and use it to
// solve the system Ax=b with PCG for the symmetric formulation, or GMRES
// for the non-symmetric.
const double rtol = 1e-6;
const real_t rtol = 1e-6;
HypreBoomerAMG amg(A);
if (amg_elast)
{
@@ -376,17 +376,17 @@ void InitDisplacement(const Vector &x, Vector &u)
}
double StressCoefficient::Eval(ElementTransformation &T,
real_t StressCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "displacement field is not set");
double L = lambda.Eval(T, ip);
double M = mu.Eval(T, ip);
real_t L = lambda.Eval(T, ip);
real_t M = mu.Eval(T, ip);
u->GetVectorGradient(T, grad);
if (si == sj)
{
double div_u = grad.Trace();
real_t div_u = grad.Trace();
return L*div_u + 2*M*grad(si,si);
}
else
+125 -123
View File
@@ -7,13 +7,19 @@
// ex18 -p 1 -r 2 -o 1 -s 3
// ex18 -p 1 -r 1 -o 3 -s 4
// ex18 -p 1 -r 0 -o 5 -s 6
// ex18 -p 2 -r 1 -o 1 -s 3
// ex18 -p 2 -r 0 -o 3 -s 3
// ex18 -p 2 -r 1 -o 1 -s 3 -mf
// ex18 -p 2 -r 0 -o 3 -s 3 -mf
//
// Description: This example code solves the compressible Euler system of
// equations, a model nonlinear hyperbolic PDE, with a
// discontinuous Galerkin (DG) formulation.
//
// (u_t, v)_T - (F(u), ∇ v)_T + <F̂(u,n), [[v]]>_F = 0
//
// where (⋅,⋅)_T is volume integration, and <⋅,⋅>_F is face
// integration, F is the Euler flux function, and F̂ is the
// numerical flux.
//
// Specifically, it solves for an exact solution of the equations
// whereby a vortex is transported by a uniform flow. Since all
// boundaries are periodic here, the method's accuracy can be
@@ -27,49 +33,47 @@
// method. An additional factor can be tuned by passing the --cfl
// (or -c shorter) flag.
//
// The example demonstrates user-defined bilinear and nonlinear
// form integrators for systems of equations that are defined with
// block vectors, and how these are used with an operator for
// explicit time integrators. In this case the system also
// involves an external approximate Riemann solver for the DG
// interface flux. It also demonstrates how to use GLVis for
// in-situ visualization of vector grid functions.
// The example demonstrates usage of DGHyperbolicConservationLaws
// that wraps NonlinearFormIntegrators containing element and face
// integration schemes. In this case the system also involves an
// external approximate Riemann solver for the DG interface flux.
// By default, weak-divergence is pre-assembled in element-wise
// manner, which corresponds to (I_h(F(u_h)), ∇ v). This yields
// better performance and similar accuracy for the included test
// problems. This can be turned off and use nonlinear assembly
// similar to matrix-free assembly when -mf flag is provided.
// It also demonstrates how to use GLVis for in-situ visualization
// of vector grid function and how to set top-view.
//
// We recommend viewing examples 9, 14 and 17 before viewing this
// example.
#include "mfem.hpp"
#include <fstream>
#include <sstream>
#include <iostream>
// Classes FE_Evolution, RiemannSolver, and FaceIntegrator
// shared between the serial and parallel version of the example.
#include <sstream>
#include "ex18.hpp"
// Choice for the problem setup. See InitialCondition in ex18.hpp.
int problem;
// Equation constant parameters.
const int num_equation = 4;
const double specific_heat_ratio = 1.4;
const double gas_constant = 1.0;
// Maximum characteristic speed (updated by integrators)
double max_char_speed;
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
problem = 1;
const char *mesh_file = "../data/periodic-square.mesh";
int problem = 1;
const real_t specific_heat_ratio = 1.4;
const real_t gas_constant = 1.0;
string mesh_file = "";
int IntOrderOffset = 1;
int ref_levels = 1;
int order = 3;
int ode_solver_type = 4;
double t_final = 2.0;
double dt = -0.01;
double cfl = 0.3;
real_t t_final = 2.0;
real_t dt = -0.01;
real_t cfl = 0.3;
bool visualization = true;
bool preassembleWeakDiv = true;
int vis_steps = 50;
int precision = 8;
@@ -77,9 +81,10 @@ int main(int argc, char *argv[])
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
"Mesh file to use. If not provided, then a periodic square"
" mesh will be used.");
args.AddOption(&problem, "-p", "--problem",
"Problem setup to use. See options in velocity_function().");
"Problem setup to use. See EulerInitialCondition().");
args.AddOption(&ref_levels, "-r", "--refine",
"Number of times to refine the mesh uniformly.");
args.AddOption(&order, "-o", "--order",
@@ -87,8 +92,7 @@ int main(int argc, char *argv[])
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
"ODE solver: 1 - Forward Euler,\n\t"
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
args.AddOption(&t_final, "-tf", "--t-final",
"Final time; start time is 0.");
args.AddOption(&t_final, "-tf", "--t-final", "Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step. Positive number skips CFL timestep calculation.");
args.AddOption(&cfl, "-c", "--cfl-number",
@@ -96,23 +100,28 @@ int main(int argc, char *argv[])
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&preassembleWeakDiv, "-ea", "--element-assembly-divergence",
"-mf", "--matrix-free-divergence",
"Weak divergence assembly level\n"
" ea - Element assembly with interpolated F\n"
" mf - Nonlinear assembly in matrix-free manner");
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
"Visualize every n-th timestep.");
args.ParseCheck();
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
args.PrintOptions(cout);
// 2. Read the mesh from the given mesh file. This example requires a 2D
// periodic mesh, such as ../data/periodic-square.mesh.
Mesh mesh(mesh_file, 1, 1);
// 2. Read the mesh from the given mesh file. When the user does not provide
// mesh file, use the default mesh file for the problem.
Mesh mesh = mesh_file.empty() ? EulerMesh(problem) : Mesh(mesh_file);
const int dim = mesh.Dimension();
const int num_equations = dim + 2;
MFEM_ASSERT(dim == 2, "Need a two-dimensional mesh for the problem definition");
// Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement, where 'ref_levels' is a command-line
// parameter.
for (int lev = 0; lev < ref_levels; lev++)
{
mesh.UniformRefinement();
}
// 3. Define the ODE solver used for time integration. Several explicit
// Runge-Kutta methods are available.
@@ -129,15 +138,7 @@ int main(int argc, char *argv[])
return 3;
}
// 4. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
// command-line parameter.
for (int lev = 0; lev < ref_levels; lev++)
{
mesh.UniformRefinement();
}
// 5. Define the discontinuous DG finite element space of the given
// 4. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
DG_FECollection fec(order, dim);
// Finite element space for a scalar (thermodynamic quantity)
@@ -145,81 +146,74 @@ int main(int argc, char *argv[])
// Finite element space for a mesh-dim vector quantity (momentum)
FiniteElementSpace dfes(&mesh, &fec, dim, Ordering::byNODES);
// Finite element space for all variables together (total thermodynamic state)
FiniteElementSpace vfes(&mesh, &fec, num_equation, Ordering::byNODES);
FiniteElementSpace vfes(&mesh, &fec, num_equations, Ordering::byNODES);
// This example depends on this ordering of the space.
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
cout << "Number of unknowns: " << vfes.GetVSize() << endl;
// 6. Define the initial conditions, save the corresponding mesh and grid
// functions to a file. This can be opened with GLVis with the -gc option.
// The solution u has components {density, x-momentum, y-momentum, energy}.
// These are stored contiguously in the BlockVector u_block.
Array<int> offsets(num_equation + 1);
for (int k = 0; k <= num_equation; k++) { offsets[k] = k * vfes.GetNDofs(); }
BlockVector u_block(offsets);
// Momentum grid function on dfes for visualization.
GridFunction mom(&dfes, u_block.GetData() + offsets[1]);
// 5. Define the initial conditions, save the corresponding mesh and grid
// functions to files. These can be opened with GLVis using:
// "glvis -m euler-mesh.mesh -g euler-1-init.gf" (for x-momentum).
// Initialize the state.
VectorFunctionCoefficient u0(num_equation, InitialCondition);
GridFunction sol(&vfes, u_block.GetData());
VectorFunctionCoefficient u0 = EulerInitialCondition(problem,
specific_heat_ratio,
gas_constant);
GridFunction sol(&vfes);
sol.ProjectCoefficient(u0);
GridFunction mom(&dfes, sol.GetData() + fes.GetNDofs());
// Output the initial solution.
{
ofstream mesh_ofs("vortex.mesh");
ostringstream mesh_name;
mesh_name << "euler-mesh.mesh";
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(precision);
mesh_ofs << mesh;
for (int k = 0; k < num_equation; k++)
for (int k = 0; k < num_equations; k++)
{
GridFunction uk(&fes, u_block.GetBlock(k));
GridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
ostringstream sol_name;
sol_name << "vortex-" << k << "-init.gf";
sol_name << "euler-" << k << "-init.gf";
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
}
}
// 7. Set up the nonlinear form corresponding to the DG discretization of the
// flux divergence, and assemble the corresponding mass matrix.
MixedBilinearForm Aflux(&dfes, &fes);
Aflux.AddDomainIntegrator(new TransposeIntegrator(new GradientIntegrator()));
Aflux.Assemble();
// 6. Set up the nonlinear form with euler flux and numerical flux
EulerFlux flux(dim, specific_heat_ratio);
RusanovFlux numericalFlux(flux);
DGHyperbolicConservationLaws euler(
vfes, std::unique_ptr<HyperbolicFormIntegrator>(
new HyperbolicFormIntegrator(numericalFlux, IntOrderOffset)),
preassembleWeakDiv);
NonlinearForm A(&vfes);
RiemannSolver rsolver;
A.AddInteriorFaceIntegrator(new FaceIntegrator(rsolver, dim));
// 8. Define the time-dependent evolution operator describing the ODE
// right-hand side, and perform time-integration (looping over the time
// iterations, ti, with a time-step dt).
FE_Evolution euler(vfes, A, Aflux.SpMat());
// Visualize the density
// 7. Visualize momentum with its magnitude
socketstream sout;
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
int visport = 19916;
sout.open(vishost, visport);
if (!sout)
{
cout << "Unable to connect to GLVis server at "
<< vishost << ':' << visport << endl;
visualization = false;
cout << "Unable to connect to GLVis server at " << vishost << ':'
<< visport << endl;
cout << "GLVis visualization disabled.\n";
}
else
{
sout.precision(precision);
// Plot magnitude of vector-valued momentum
sout << "solution\n" << mesh << mom;
sout << "window_title 'momentum, t = 0'\n";
sout << "view 0 0\n"; // view from top
sout << "keys jlm\n"; // turn off perspective and light, show mesh
sout << "pause\n";
sout << flush;
cout << "GLVis visualization paused."
@@ -227,54 +221,57 @@ int main(int argc, char *argv[])
}
}
// Determine the minimum element size.
double hmin = 0.0;
// 8. Time integration
// When dt is not specified, use CFL condition.
// Compute h_min and initial maximum characteristic speed
real_t hmin = infinity();
if (cfl > 0)
{
hmin = mesh.GetElementSize(0, 1);
for (int i = 1; i < mesh.GetNE(); i++)
for (int i = 0; i < mesh.GetNE(); i++)
{
hmin = min(mesh.GetElementSize(i, 1), hmin);
}
// Find a safe dt, using a temporary vector. Calling Mult() computes the
// maximum char speed at all quadrature points on all faces (and all
// elements with -mf).
Vector z(sol.Size());
euler.Mult(sol, z);
real_t max_char_speed = euler.GetMaxCharSpeed();
dt = cfl * hmin / max_char_speed / (2 * order + 1);
}
// Start the timer.
tic_toc.Clear();
tic_toc.Start();
double t = 0.0;
// Init time integration
real_t t = 0.0;
euler.SetTime(t);
ode_solver->Init(euler);
if (cfl > 0)
{
// Find a safe dt, using a temporary vector. Calling Mult() computes the
// maximum char speed at all quadrature points on all faces.
Vector z(A.Width());
max_char_speed = 0.;
A.Mult(sol, z);
dt = cfl * hmin / max_char_speed / (2*order+1);
}
// Integrate in time.
bool done = false;
for (int ti = 0; !done; )
for (int ti = 0; !done;)
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(sol, t, dt_real);
if (cfl > 0)
if (cfl > 0) // update time step size with CFL
{
dt = cfl * hmin / max_char_speed / (2*order+1);
real_t max_char_speed = euler.GetMaxCharSpeed();
dt = cfl * hmin / max_char_speed / (2 * order + 1);
}
ti++;
done = (t >= t_final - 1e-8*dt);
done = (t >= t_final - 1e-8 * dt);
if (done || ti % vis_steps == 0)
{
cout << "time step: " << ti << ", time: " << t << endl;
if (visualization)
{
sout << "window_title 'momentum, t = " << t << "'\n";
sout << "solution\n" << mesh << mom << flush;
}
}
@@ -284,23 +281,28 @@ int main(int argc, char *argv[])
cout << " done, " << tic_toc.RealTime() << "s." << endl;
// 9. Save the final solution. This output can be viewed later using GLVis:
// "glvis -m vortex.mesh -g vortex-1-final.gf".
for (int k = 0; k < num_equation; k++)
// "glvis -m euler-mesh-final.mesh -g euler-1-final.gf" (for x-momentum).
{
GridFunction uk(&fes, u_block.GetBlock(k));
ostringstream sol_name;
sol_name << "vortex-" << k << "-final.gf";
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
ostringstream mesh_name;
mesh_name << "euler-mesh-final.mesh";
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(precision);
mesh_ofs << mesh;
for (int k = 0; k < num_equations; k++)
{
GridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
ostringstream sol_name;
sol_name << "euler-" << k << "-final.gf";
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
}
}
// 10. Compute the L2 solution error summed for all components.
if (t_final == 2.0)
{
const double error = sol.ComputeLpError(2, u0);
cout << "Solution error: " << error << endl;
}
const real_t error = sol.ComputeLpError(2, u0);
cout << "Solution error: " << error << endl;
// Free the used memory.
delete ode_solver;
+313 -436
View File
@@ -1,490 +1,367 @@
// MFEM Example 18 - Serial/Parallel Shared Code
// (Implementation of Time-dependent DG Operator)
//
// This code provide example problems for the Euler equations and implements
// the time-dependent DG operator given by the equation:
//
// (u_t, v)_T - (F(u), ∇ v)_T + <F̂(u, n), [[v]]>_F = 0.
//
// This operator is designed for explicit time stepping methods. Specifically,
// the function DGHyperbolicConservationLaws::Mult implements the following
// transformation:
//
// u ↦ M⁻¹(-DF(u) + NF(u))
//
// where M is the mass matrix, DF is the weak divergence of flux, and NF is the
// interface flux. The inverse of the mass matrix is computed element-wise by
// leveraging the block-diagonal structure of the DG mass matrix. Additionally,
// the flux-related terms are computed using the HyperbolicFormIntegrator.
//
// The maximum characteristic speed is determined for each time step. For more
// details, refer to the documentation of DGHyperbolicConservationLaws::Mult.
//
#include <functional>
#include "mfem.hpp"
using namespace std;
using namespace mfem;
namespace mfem
{
// Problem definition
extern int problem;
// Maximum characteristic speed (updated by integrators)
extern double max_char_speed;
extern const int num_equation;
extern const double specific_heat_ratio;
extern const double gas_constant;
// Time-dependent operator for the right-hand side of the ODE representing the
// DG weak form.
class FE_Evolution : public TimeDependentOperator
/// @brief Time dependent DG operator for hyperbolic conservation laws
class DGHyperbolicConservationLaws : public TimeDependentOperator
{
private:
const int num_equations; // the number of equations
const int dim;
FiniteElementSpace &vfes;
Operator &A;
SparseMatrix &Aflux;
DenseTensor Me_inv;
mutable Vector state;
mutable DenseMatrix f;
mutable DenseTensor flux;
FiniteElementSpace &vfes; // vector finite element space
// Element integration form. Should contain ComputeFlux
std::unique_ptr<HyperbolicFormIntegrator> formIntegrator;
// Base Nonlinear Form
std::unique_ptr<NonlinearForm> nonlinearForm;
// element-wise inverse mass matrix
std::vector<DenseMatrix> invmass; // local scalar inverse mass.
std::vector<DenseMatrix> weakdiv; // local weakdivergence. Trial space is ByDim.
// global maximum characteristic speed. Updated by form integrators
mutable real_t max_char_speed;
// auxiliary variable used in Mult
mutable Vector z;
void GetFlux(const DenseMatrix &state_, DenseTensor &flux_) const;
// Compute element-wise inverse mass matrix
void ComputeInvMass();
// Compute element-wise weak-divergence matrix
void ComputeWeakDivergence();
public:
FE_Evolution(FiniteElementSpace &vfes_,
Operator &A_, SparseMatrix &Aflux_);
/**
* @brief Construct a new DGHyperbolicConservationLaws object
*
* @param vfes_ vector finite element space. Only tested for DG [Pₚ]ⁿ
* @param formIntegrator_ integrator (F(u,x), grad v)
* @param preassembleWeakDivergence preassemble weak divergence for faster
* assembly
*/
DGHyperbolicConservationLaws(
FiniteElementSpace &vfes_,
std::unique_ptr<HyperbolicFormIntegrator> formIntegrator_,
bool preassembleWeakDivergence=true);
/**
* @brief Apply nonlinear form to obtain M⁻¹(DIVF + JUMP HAT(F))
*
* @param x current solution vector
* @param y resulting dual vector to be used in an EXPLICIT solver
*/
void Mult(const Vector &x, Vector &y) const override;
// get global maximum characteristic speed to be used in CFL condition
// where max_char_speed is updated during Mult.
real_t GetMaxCharSpeed() { return max_char_speed; }
void Update();
virtual void Mult(const Vector &x, Vector &y) const;
virtual ~FE_Evolution() { }
};
// Implements a simple Rusanov flux
class RiemannSolver
{
private:
Vector flux1;
Vector flux2;
//////////////////////////////////////////////////////////////////
/// HYPERBOLIC CONSERVATION LAWS IMPLEMENTATION ///
//////////////////////////////////////////////////////////////////
public:
RiemannSolver();
double Eval(const Vector &state1, const Vector &state2,
const Vector &nor, Vector &flux);
};
// Interior face term: <F.n(u),[w]>
class FaceIntegrator : public NonlinearFormIntegrator
{
private:
RiemannSolver rsolver;
Vector shape1;
Vector shape2;
Vector funval1;
Vector funval2;
Vector nor;
Vector fluxN;
public:
FaceIntegrator(RiemannSolver &rsolver_, const int dim);
virtual void AssembleFaceVector(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Tr,
const Vector &elfun, Vector &elvect);
};
// Implementation of class FE_Evolution
FE_Evolution::FE_Evolution(FiniteElementSpace &vfes_,
Operator &A_, SparseMatrix &Aflux_)
: TimeDependentOperator(A_.Height()),
dim(vfes_.GetFE(0)->GetDim()),
// Implementation of class DGHyperbolicConservationLaws
DGHyperbolicConservationLaws::DGHyperbolicConservationLaws(
FiniteElementSpace &vfes_,
std::unique_ptr<HyperbolicFormIntegrator> formIntegrator_,
bool preassembleWeakDivergence)
: TimeDependentOperator(vfes_.GetTrueVSize()),
num_equations(formIntegrator_->num_equations),
dim(vfes_.GetMesh()->SpaceDimension()),
vfes(vfes_),
A(A_),
Aflux(Aflux_),
Me_inv(vfes.GetFE(0)->GetDof(), vfes.GetFE(0)->GetDof(), vfes.GetNE()),
state(num_equation),
f(num_equation, dim),
flux(vfes.GetNDofs(), dim, num_equation),
z(A.Height())
formIntegrator(std::move(formIntegrator_)),
z(vfes_.GetTrueVSize())
{
// Standard local assembly and inversion for energy mass matrices.
const int dof = vfes.GetFE(0)->GetDof();
DenseMatrix Me(dof);
DenseMatrixInverse inv(&Me);
MassIntegrator mi;
for (int i = 0; i < vfes.GetNE(); i++)
ComputeInvMass();
#ifndef MFEM_USE_MPI
nonlinearForm.reset(new NonlinearForm(&vfes));
#else
ParFiniteElementSpace *pvfes = dynamic_cast<ParFiniteElementSpace *>(&vfes);
if (pvfes)
{
mi.AssembleElementMatrix(*vfes.GetFE(i), *vfes.GetElementTransformation(i), Me);
inv.Factor();
inv.GetInverseMatrix(Me_inv(i));
nonlinearForm.reset(new ParNonlinearForm(pvfes));
}
}
void FE_Evolution::Mult(const Vector &x, Vector &y) const
{
// 0. Reset wavespeed computation before operator application.
max_char_speed = 0.;
// 1. Create the vector z with the face terms -<F.n(u), [w]>.
A.Mult(x, z);
// 2. Add the element terms.
// i. computing the flux approximately as a grid function by interpolating
// at the solution nodes.
// ii. multiplying this grid function by a (constant) mixed bilinear form for
// each of the num_equation, computing (F(u), grad(w)) for each equation.
DenseMatrix xmat(x.GetData(), vfes.GetNDofs(), num_equation);
GetFlux(xmat, flux);
for (int k = 0; k < num_equation; k++)
{
Vector fk(flux(k).GetData(), dim * vfes.GetNDofs());
Vector zk(z.GetData() + k * vfes.GetNDofs(), vfes.GetNDofs());
Aflux.AddMult(fk, zk);
}
// 3. Multiply element-wise by the inverse mass matrices.
Vector zval;
Array<int> vdofs;
const int dof = vfes.GetFE(0)->GetDof();
DenseMatrix zmat, ymat(dof, num_equation);
for (int i = 0; i < vfes.GetNE(); i++)
{
// Return the vdofs ordered byNODES
vfes.GetElementVDofs(i, vdofs);
z.GetSubVector(vdofs, zval);
zmat.UseExternalData(zval.GetData(), dof, num_equation);
mfem::Mult(Me_inv(i), zmat, ymat);
y.SetSubVector(vdofs, ymat.GetData());
}
}
// Physicality check (at end)
bool StateIsPhysical(const Vector &state, const int dim);
// Pressure (EOS) computation
inline double ComputePressure(const Vector &state, int dim)
{
const double den = state(0);
const Vector den_vel(state.GetData() + 1, dim);
const double den_energy = state(1 + dim);
double den_vel2 = 0;
for (int d = 0; d < dim; d++) { den_vel2 += den_vel(d) * den_vel(d); }
den_vel2 /= den;
return (specific_heat_ratio - 1.0) * (den_energy - 0.5 * den_vel2);
}
// Compute the vector flux F(u)
void ComputeFlux(const Vector &state, int dim, DenseMatrix &flux)
{
const double den = state(0);
const Vector den_vel(state.GetData() + 1, dim);
const double den_energy = state(1 + dim);
MFEM_ASSERT(StateIsPhysical(state, dim), "");
const double pres = ComputePressure(state, dim);
for (int d = 0; d < dim; d++)
{
flux(0, d) = den_vel(d);
for (int i = 0; i < dim; i++)
{
flux(1+i, d) = den_vel(i) * den_vel(d) / den;
}
flux(1+d, d) += pres;
}
const double H = (den_energy + pres) / den;
for (int d = 0; d < dim; d++)
{
flux(1+dim, d) = den_vel(d) * H;
}
}
// Compute the scalar F(u).n
void ComputeFluxDotN(const Vector &state, const Vector &nor,
Vector &fluxN)
{
// NOTE: nor in general is not a unit normal
const int dim = nor.Size();
const double den = state(0);
const Vector den_vel(state.GetData() + 1, dim);
const double den_energy = state(1 + dim);
MFEM_ASSERT(StateIsPhysical(state, dim), "");
const double pres = ComputePressure(state, dim);
double den_velN = 0;
for (int d = 0; d < dim; d++) { den_velN += den_vel(d) * nor(d); }
fluxN(0) = den_velN;
for (int d = 0; d < dim; d++)
{
fluxN(1+d) = den_velN * den_vel(d) / den + pres * nor(d);
}
const double H = (den_energy + pres) / den;
fluxN(1 + dim) = den_velN * H;
}
// Compute the maximum characteristic speed.
inline double ComputeMaxCharSpeed(const Vector &state, const int dim)
{
const double den = state(0);
const Vector den_vel(state.GetData() + 1, dim);
double den_vel2 = 0;
for (int d = 0; d < dim; d++) { den_vel2 += den_vel(d) * den_vel(d); }
den_vel2 /= den;
const double pres = ComputePressure(state, dim);
const double sound = sqrt(specific_heat_ratio * pres / den);
const double vel = sqrt(den_vel2 / den);
return vel + sound;
}
// Compute the flux at solution nodes.
void FE_Evolution::GetFlux(const DenseMatrix &x_, DenseTensor &flux_) const
{
const int flux_dof = flux_.SizeI();
const int flux_dim = flux_.SizeJ();
for (int i = 0; i < flux_dof; i++)
{
for (int k = 0; k < num_equation; k++) { state(k) = x_(i, k); }
ComputeFlux(state, flux_dim, f);
for (int d = 0; d < flux_dim; d++)
{
for (int k = 0; k < num_equation; k++)
{
flux_(i, d, k) = f(k, d);
}
}
// Update max char speed
const double mcs = ComputeMaxCharSpeed(state, flux_dim);
if (mcs > max_char_speed) { max_char_speed = mcs; }
}
}
// Implementation of class RiemannSolver
RiemannSolver::RiemannSolver() :
flux1(num_equation),
flux2(num_equation) { }
double RiemannSolver::Eval(const Vector &state1, const Vector &state2,
const Vector &nor, Vector &flux)
{
// NOTE: nor in general is not a unit normal
const int dim = nor.Size();
MFEM_ASSERT(StateIsPhysical(state1, dim), "");
MFEM_ASSERT(StateIsPhysical(state2, dim), "");
const double maxE1 = ComputeMaxCharSpeed(state1, dim);
const double maxE2 = ComputeMaxCharSpeed(state2, dim);
const double maxE = max(maxE1, maxE2);
ComputeFluxDotN(state1, nor, flux1);
ComputeFluxDotN(state2, nor, flux2);
double normag = 0;
for (int i = 0; i < dim; i++)
{
normag += nor(i) * nor(i);
}
normag = sqrt(normag);
for (int i = 0; i < num_equation; i++)
{
flux(i) = 0.5 * (flux1(i) + flux2(i))
- 0.5 * maxE * (state2(i) - state1(i)) * normag;
}
return maxE;
}
// Implementation of class FaceIntegrator
FaceIntegrator::FaceIntegrator(RiemannSolver &rsolver_, const int dim) :
rsolver(rsolver_),
funval1(num_equation),
funval2(num_equation),
nor(dim),
fluxN(num_equation) { }
void FaceIntegrator::AssembleFaceVector(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Tr,
const Vector &elfun, Vector &elvect)
{
// Compute the term <F.n(u),[w]> on the interior faces.
const int dof1 = el1.GetDof();
const int dof2 = el2.GetDof();
shape1.SetSize(dof1);
shape2.SetSize(dof2);
elvect.SetSize((dof1 + dof2) * num_equation);
elvect = 0.0;
DenseMatrix elfun1_mat(elfun.GetData(), dof1, num_equation);
DenseMatrix elfun2_mat(elfun.GetData() + dof1 * num_equation, dof2,
num_equation);
DenseMatrix elvect1_mat(elvect.GetData(), dof1, num_equation);
DenseMatrix elvect2_mat(elvect.GetData() + dof1 * num_equation, dof2,
num_equation);
// Integration order calculation from DGTraceIntegrator
int intorder;
if (Tr.Elem2No >= 0)
intorder = (min(Tr.Elem1->OrderW(), Tr.Elem2->OrderW()) +
2*max(el1.GetOrder(), el2.GetOrder()));
else
{
intorder = Tr.Elem1->OrderW() + 2*el1.GetOrder();
nonlinearForm.reset(new NonlinearForm(&vfes));
}
if (el1.Space() == FunctionSpace::Pk)
#endif
if (preassembleWeakDivergence)
{
intorder++;
ComputeWeakDivergence();
}
const IntegrationRule *ir = &IntRules.Get(Tr.GetGeometryType(), intorder);
for (int i = 0; i < ir->GetNPoints(); i++)
else
{
const IntegrationPoint &ip = ir->IntPoint(i);
nonlinearForm->AddDomainIntegrator(formIntegrator.get());
}
nonlinearForm->AddInteriorFaceIntegrator(formIntegrator.get());
nonlinearForm->UseExternalIntegrators();
Tr.SetAllIntPoints(&ip); // set face and element int. points
}
// Calculate basis functions on both elements at the face
el1.CalcShape(Tr.GetElement1IntPoint(), shape1);
el2.CalcShape(Tr.GetElement2IntPoint(), shape2);
void DGHyperbolicConservationLaws::ComputeInvMass()
{
InverseIntegrator inv_mass(new MassIntegrator());
// Interpolate elfun at the point
elfun1_mat.MultTranspose(shape1, funval1);
elfun2_mat.MultTranspose(shape2, funval2);
// Get the normal vector and the flux on the face
CalcOrtho(Tr.Jacobian(), nor);
const double mcs = rsolver.Eval(funval1, funval2, nor, fluxN);
// Update max char speed
if (mcs > max_char_speed) { max_char_speed = mcs; }
fluxN *= ip.weight;
for (int k = 0; k < num_equation; k++)
{
for (int s = 0; s < dof1; s++)
{
elvect1_mat(s, k) -= fluxN(k) * shape1(s);
}
for (int s = 0; s < dof2; s++)
{
elvect2_mat(s, k) += fluxN(k) * shape2(s);
}
}
invmass.resize(vfes.GetNE());
for (int i=0; i<vfes.GetNE(); i++)
{
int dof = vfes.GetFE(i)->GetDof();
invmass[i].SetSize(dof);
inv_mass.AssembleElementMatrix(*vfes.GetFE(i),
*vfes.GetElementTransformation(i),
invmass[i]);
}
}
// Check that the state is physical - enabled in debug mode
bool StateIsPhysical(const Vector &state, const int dim)
void DGHyperbolicConservationLaws::ComputeWeakDivergence()
{
const double den = state(0);
const Vector den_vel(state.GetData() + 1, dim);
const double den_energy = state(1 + dim);
TransposeIntegrator weak_div(new GradientIntegrator());
DenseMatrix weakdiv_bynodes;
if (den < 0)
weakdiv.resize(vfes.GetNE());
for (int i=0; i<vfes.GetNE(); i++)
{
cout << "Negative density: ";
for (int i = 0; i < state.Size(); i++)
int dof = vfes.GetFE(i)->GetDof();
weakdiv_bynodes.SetSize(dof, dof*dim);
weak_div.AssembleElementMatrix2(*vfes.GetFE(i), *vfes.GetFE(i),
*vfes.GetElementTransformation(i),
weakdiv_bynodes);
weakdiv[i].SetSize(dof, dof*dim);
// Reorder so that trial space is ByDim.
// This makes applying weak divergence to flux value simpler.
for (int j=0; j<dof; j++)
{
cout << state(i) << " ";
for (int d=0; d<dim; d++)
{
weakdiv[i].SetCol(j*dim + d, weakdiv_bynodes.GetColumn(d*dof + j));
}
}
cout << endl;
return false;
}
if (den_energy <= 0)
}
void DGHyperbolicConservationLaws::Mult(const Vector &x, Vector &y) const
{
// 0. Reset wavespeed computation before operator application.
formIntegrator->ResetMaxCharSpeed();
// 1. Apply Nonlinear form to obtain an axiliary result
// z = - <F̂(u_h,n), [[v]]>_e
// If weak-divergencee is not preassembled, we also have weak-divergence
// z = - <F̂(u_h,n), [[v]]>_e + (F(u_h), ∇v)
nonlinearForm->Mult(x, z);
if (!weakdiv.empty()) // if weak divergence is pre-assembled
{
cout << "Negative energy: ";
for (int i = 0; i < state.Size(); i++)
// Apply weak divergence to F(u_h), and inverse mass to z_loc + weakdiv_loc
Vector current_state; // view of current state at a node
DenseMatrix current_flux; // flux of current state
DenseMatrix flux; // element flux value. Whose column is ordered by dim.
DenseMatrix current_xmat; // view of current states in an element, dof x num_eq
DenseMatrix current_zmat; // view of element auxiliary result, dof x num_eq
DenseMatrix current_ymat; // view of element result, dof x num_eq
const FluxFunction &fluxFunction = formIntegrator->GetFluxFunction();
Array<int> vdofs;
Vector xval, zval;
for (int i=0; i<vfes.GetNE(); i++)
{
cout << state(i) << " ";
ElementTransformation* Tr = vfes.GetElementTransformation(i);
int dof = vfes.GetFE(i)->GetDof();
vfes.GetElementVDofs(i, vdofs);
x.GetSubVector(vdofs, xval);
current_xmat.UseExternalData(xval.GetData(), dof, num_equations);
flux.SetSize(num_equations, dim*dof);
for (int j=0; j<dof; j++) // compute flux for all nodes in the element
{
current_xmat.GetRow(j, current_state);
current_flux.UseExternalData(flux.GetData() + num_equations*dim*j,
num_equations, dof);
fluxFunction.ComputeFlux(current_state, *Tr, current_flux);
}
// Compute weak-divergence and add it to auxiliary result, z
// Recalling that weakdiv is reordered by dim, we can apply
// weak-divergence to the transpose of flux.
z.GetSubVector(vdofs, zval);
current_zmat.UseExternalData(zval.GetData(), dof, num_equations);
mfem::AddMult_a_ABt(1.0, weakdiv[i], flux, current_zmat);
// Apply inverse mass to auxiliary result to obtain the final result
current_ymat.SetSize(dof, num_equations);
mfem::Mult(invmass[i], current_zmat, current_ymat);
y.SetSubVector(vdofs, current_ymat.GetData());
}
cout << endl;
return false;
}
double den_vel2 = 0;
for (int i = 0; i < dim; i++) { den_vel2 += den_vel(i) * den_vel(i); }
den_vel2 /= den;
const double pres = (specific_heat_ratio - 1.0) * (den_energy - 0.5 * den_vel2);
if (pres <= 0)
else
{
cout << "Negative pressure: " << pres << ", state: ";
for (int i = 0; i < state.Size(); i++)
// Apply block inverse mass
Vector zval; // z_loc, dof*num_eq
DenseMatrix current_zmat; // view of element auxiliary result, dof x num_eq
DenseMatrix current_ymat; // view of element result, dof x num_eq
Array<int> vdofs;
for (int i=0; i<vfes.GetNE(); i++)
{
cout << state(i) << " ";
int dof = vfes.GetFE(i)->GetDof();
vfes.GetElementVDofs(i, vdofs);
z.GetSubVector(vdofs, zval);
current_zmat.UseExternalData(zval.GetData(), dof, num_equations);
current_ymat.SetSize(dof, num_equations);
mfem::Mult(invmass[i], current_zmat, current_ymat);
y.SetSubVector(vdofs, current_ymat.GetData());
}
cout << endl;
return false;
}
return true;
max_char_speed = formIntegrator->GetMaxCharSpeed();
}
void DGHyperbolicConservationLaws::Update()
{
nonlinearForm->Update();
height = nonlinearForm->Height();
width = height;
z.SetSize(height);
ComputeInvMass();
if (!weakdiv.empty()) {ComputeWeakDivergence();}
}
std::function<void(const Vector&, Vector&)> GetMovingVortexInit(
const real_t radius, const real_t Minf, const real_t beta,
const real_t gas_constant, const real_t specific_heat_ratio)
{
return [specific_heat_ratio,
gas_constant, Minf, radius, beta](const Vector &x, Vector &y)
{
MFEM_ASSERT(x.Size() == 2, "");
const real_t xc = 0.0, yc = 0.0;
// Nice units
const real_t vel_inf = 1.;
const real_t den_inf = 1.;
// Derive remainder of background state from this and Minf
const real_t pres_inf = (den_inf / specific_heat_ratio) *
(vel_inf / Minf) * (vel_inf / Minf);
const real_t temp_inf = pres_inf / (den_inf * gas_constant);
real_t r2rad = 0.0;
r2rad += (x(0) - xc) * (x(0) - xc);
r2rad += (x(1) - yc) * (x(1) - yc);
r2rad /= (radius * radius);
const real_t shrinv1 = 1.0 / (specific_heat_ratio - 1.);
const real_t velX =
vel_inf * (1 - beta * (x(1) - yc) / radius * std::exp(-0.5 * r2rad));
const real_t velY =
vel_inf * beta * (x(0) - xc) / radius * std::exp(-0.5 * r2rad);
const real_t vel2 = velX * velX + velY * velY;
const real_t specific_heat =
gas_constant * specific_heat_ratio * shrinv1;
const real_t temp = temp_inf - 0.5 * (vel_inf * beta) *
(vel_inf * beta) / specific_heat *
std::exp(-r2rad);
const real_t den = den_inf * std::pow(temp / temp_inf, shrinv1);
const real_t pres = den * gas_constant * temp;
const real_t energy = shrinv1 * pres / den + 0.5 * vel2;
y(0) = den;
y(1) = den * velX;
y(2) = den * velY;
y(3) = den * energy;
};
}
Mesh EulerMesh(const int problem)
{
switch (problem)
{
case 1:
case 2:
case 3:
return Mesh("../data/periodic-square.mesh");
break;
case 4:
return Mesh("../data/periodic-segment.mesh");
break;
default:
MFEM_ABORT("Problem Undefined");
}
}
// Initial condition
void InitialCondition(const Vector &x, Vector &y)
VectorFunctionCoefficient EulerInitialCondition(const int problem,
const real_t specific_heat_ratio,
const real_t gas_constant)
{
MFEM_ASSERT(x.Size() == 2, "");
double radius = 0, Minf = 0, beta = 0;
if (problem == 1)
switch (problem)
{
// "Fast vortex"
radius = 0.2;
Minf = 0.5;
beta = 1. / 5.;
case 1: // fast moving vortex
return VectorFunctionCoefficient(
4, GetMovingVortexInit(0.2, 0.5, 1. / 5., gas_constant,
specific_heat_ratio));
case 2: // slow moving vortex
return VectorFunctionCoefficient(
4, GetMovingVortexInit(0.2, 0.05, 1. / 50., gas_constant,
specific_heat_ratio));
case 3: // moving sine wave
return VectorFunctionCoefficient(4, [](const Vector &x, Vector &y)
{
MFEM_ASSERT(x.Size() == 2, "");
const real_t density = 1.0 + 0.2 * std::sin(M_PI*(x(0) + x(1)));
const real_t velocity_x = 0.7;
const real_t velocity_y = 0.3;
const real_t pressure = 1.0;
const real_t energy =
pressure / (1.4 - 1.0) +
density * 0.5 * (velocity_x * velocity_x + velocity_y * velocity_y);
y(0) = density;
y(1) = density * velocity_x;
y(2) = density * velocity_y;
y(3) = energy;
});
case 4:
return VectorFunctionCoefficient(3, [](const Vector &x, Vector &y)
{
MFEM_ASSERT(x.Size() == 1, "");
const real_t density = 1.0 + 0.2 * std::sin(M_PI * 2 * x(0));
const real_t velocity_x = 1.0;
const real_t pressure = 1.0;
const real_t energy =
pressure / (1.4 - 1.0) + density * 0.5 * (velocity_x * velocity_x);
y(0) = density;
y(1) = density * velocity_x;
y(2) = energy;
});
default:
MFEM_ABORT("Problem Undefined");
}
else if (problem == 2)
{
// "Slow vortex"
radius = 0.2;
Minf = 0.05;
beta = 1. / 50.;
}
else
{
mfem_error("Cannot recognize problem."
"Options are: 1 - fast vortex, 2 - slow vortex");
}
const double xc = 0.0, yc = 0.0;
// Nice units
const double vel_inf = 1.;
const double den_inf = 1.;
// Derive remainder of background state from this and Minf
const double pres_inf = (den_inf / specific_heat_ratio) * (vel_inf / Minf) *
(vel_inf / Minf);
const double temp_inf = pres_inf / (den_inf * gas_constant);
double r2rad = 0.0;
r2rad += (x(0) - xc) * (x(0) - xc);
r2rad += (x(1) - yc) * (x(1) - yc);
r2rad /= (radius * radius);
const double shrinv1 = 1.0 / (specific_heat_ratio - 1.);
const double velX = vel_inf * (1 - beta * (x(1) - yc) / radius * exp(
-0.5 * r2rad));
const double velY = vel_inf * beta * (x(0) - xc) / radius * exp(-0.5 * r2rad);
const double vel2 = velX * velX + velY * velY;
const double specific_heat = gas_constant * specific_heat_ratio * shrinv1;
const double temp = temp_inf - 0.5 * (vel_inf * beta) *
(vel_inf * beta) / specific_heat * exp(-r2rad);
const double den = den_inf * pow(temp/temp_inf, shrinv1);
const double pres = den * gas_constant * temp;
const double energy = shrinv1 * pres / den + 0.5 * vel2;
y(0) = den;
y(1) = den * velX;
y(2) = den * velY;
y(3) = den * energy;
}
} // namespace mfem
+168 -181
View File
@@ -1,18 +1,24 @@
// MFEM Example 18 - Parallel Version
// MFEM Example 18 - Parallel Version
//
// Compile with: make ex18
// Compile with: make ex18p
//
// Sample runs:
//
// mpirun -np 4 ex18p -p 1 -rs 2 -rp 1 -o 1 -s 3
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 1 -o 3 -s 4
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 1 -o 5 -s 6
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 1 -s 3
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 3 -s 3
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 1 -s 3 -mf
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 3 -s 3 -mf
//
// Description: This example code solves the compressible Euler system of
// equations, a model nonlinear hyperbolic PDE, with a
// discontinuous Galerkin (DG) formulation.
// discontinuous Galerkin (DG) formulation in parallel.
//
// (u_t, v)_T - (F(u), ∇ v)_T + <F̂(u,n), [[v]]>_F = 0
//
// where (⋅,⋅)_T is volume integration, and <⋅,⋅>_F is face
// integration, F is the Euler flux function, and F̂ is the
// numerical flux.
//
// Specifically, it solves for an exact solution of the equations
// whereby a vortex is transported by a uniform flow. Since all
@@ -27,54 +33,54 @@
// method. An additional factor can be tuned by passing the --cfl
// (or -c shorter) flag.
//
// The example demonstrates user-defined bilinear and nonlinear
// form integrators for systems of equations that are defined with
// block vectors, and how these are used with an operator for
// explicit time integrators. In this case the system also
// involves an external approximate Riemann solver for the DG
// interface flux. It also demonstrates how to use GLVis for
// in-situ visualization of vector grid functions.
// The example demonstrates usage of DGHyperbolicConservationLaws
// that wraps NonlinearFormIntegrators containing element and face
// integration schemes. In this case the system also involves an
// external approximate Riemann solver for the DG interface flux.
// By default, weak-divergence is pre-assembled in element-wise
// manner, which corresponds to (I_h(F(u_h)), ∇ v). This yields
// better performance and similar accuracy for the included test
// problems. This can be turned off and use nonlinear assembly
// similar to matrix-free assembly when -mf flag is provided.
// It also demonstrates how to use GLVis for in-situ visualization
// of vector grid function and how to set top-view.
//
// We recommend viewing examples 9, 14 and 17 before viewing this
// example.
#include "mfem.hpp"
#include <fstream>
#include <sstream>
#include <iostream>
// Classes FE_Evolution, RiemannSolver, and FaceIntegrator
// shared between the serial and parallel version of the example.
#include <sstream>
#include "ex18.hpp"
// Choice for the problem setup. See InitialCondition in ex18.hpp.
int problem;
// Equation constant parameters.
const int num_equation = 4;
const double specific_heat_ratio = 1.4;
const double gas_constant = 1.0;
// Maximum characteristic speed (updated by integrators)
double max_char_speed;
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
// 0. Parallel setup
Mpi::Init(argc, argv);
const int numProcs = Mpi::WorldSize();
const int myRank = Mpi::WorldRank();
Hypre::Init();
// 2. Parse command-line options.
problem = 1;
const char *mesh_file = "../data/periodic-square.mesh";
// 1. Parse command-line options.
int problem = 1;
const real_t specific_heat_ratio = 1.4;
const real_t gas_constant = 1.0;
string mesh_file = "";
int IntOrderOffset = 1;
int ser_ref_levels = 0;
int par_ref_levels = 1;
int order = 3;
int ode_solver_type = 4;
double t_final = 2.0;
double dt = -0.01;
double cfl = 0.3;
real_t t_final = 2.0;
real_t dt = -0.01;
real_t cfl = 0.3;
bool visualization = true;
bool preassembleWeakDiv = true;
int vis_steps = 50;
int precision = 8;
@@ -82,22 +88,20 @@ int main(int argc, char *argv[])
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
"Mesh file to use. If not provided, then a periodic square"
" mesh will be used.");
args.AddOption(&problem, "-p", "--problem",
"Problem setup to use. See options in velocity_function().");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly before parallel"
" partitioning, -1 for auto.");
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly after parallel"
" partitioning.");
"Problem setup to use. See EulerInitialCondition().");
args.AddOption(&ser_ref_levels, "-rs", "--serial-refine",
"Number of times to refine the serial mesh uniformly.");
args.AddOption(&par_ref_levels, "-rp", "--parallel-refine",
"Number of times to refine the parallel mesh uniformly.");
args.AddOption(&order, "-o", "--order",
"Order (degree) of the finite elements.");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
"ODE solver: 1 - Forward Euler,\n\t"
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
args.AddOption(&t_final, "-tf", "--t-final",
"Final time; start time is 0.");
args.AddOption(&t_final, "-tf", "--t-final", "Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step. Positive number skips CFL timestep calculation.");
args.AddOption(&cfl, "-c", "--cfl-number",
@@ -105,25 +109,44 @@ int main(int argc, char *argv[])
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&preassembleWeakDiv, "-ea", "--element-assembly-divergence",
"-mf", "--matrix-free-divergence",
"Weak divergence assembly level\n"
" ea - Element assembly with interpolated F\n"
" mf - Nonlinear assembly in matrix-free manner");
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
"Visualize every n-th timestep.");
args.ParseCheck();
args.Parse();
if (!args.Good())
{
if (Mpi::Root()) { args.PrintUsage(cout); }
return 1;
}
if (Mpi::Root()) { args.PrintOptions(cout); }
// 3. Read the mesh from the given mesh file. This example requires a 2D
// periodic mesh, such as ../data/periodic-square.mesh.
Mesh mesh(mesh_file, 1, 1);
// 2. Read the mesh from the given mesh file. When the user does not provide
// mesh file, use the default mesh file for the problem.
Mesh mesh = mesh_file.empty() ? EulerMesh(problem) : Mesh(mesh_file);
const int dim = mesh.Dimension();
const int num_equations = dim + 2;
MFEM_ASSERT(dim == 2, "Need a two-dimensional mesh for the problem definition");
// Refine the mesh to increase the resolution. In this example we do
// 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is a
// command-line parameter.
for (int lev = 0; lev < ser_ref_levels; lev++)
{
mesh.UniformRefinement();
}
// 4. Define the ODE solver used for time integration. Several explicit
// Define a parallel mesh by a partitioning of the serial mesh. Refine this
// mesh further in parallel to increase the resolution. Once the parallel
// mesh is defined, the serial mesh can be deleted.
ParMesh pmesh = ParMesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
// Refine the mesh to increase the resolution. In this example we do
// 'par_ref_levels' of uniform refinement, where 'par_ref_levels' is a
// command-line parameter.
for (int lev = 0; lev < par_ref_levels; lev++)
{
pmesh.UniformRefinement();
}
// 3. Define the ODE solver used for time integration. Several explicit
// Runge-Kutta methods are available.
ODESolver *ode_solver = NULL;
switch (ode_solver_type)
@@ -134,32 +157,11 @@ int main(int argc, char *argv[])
case 4: ode_solver = new RK4Solver; break;
case 6: ode_solver = new RK6Solver; break;
default:
if (Mpi::Root())
{
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
}
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
return 3;
}
// 5. Refine the mesh in serial to increase the resolution. In this example
// we do 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is
// a command-line parameter.
for (int lev = 0; lev < ser_ref_levels; lev++)
{
mesh.UniformRefinement();
}
// 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted.
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
for (int lev = 0; lev < par_ref_levels; lev++)
{
pmesh.UniformRefinement();
}
// 7. Define the discontinuous DG finite element space of the given
// 4. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
DG_FECollection fec(order, dim);
// Finite element space for a scalar (thermodynamic quantity)
@@ -167,7 +169,7 @@ int main(int argc, char *argv[])
// Finite element space for a mesh-dim vector quantity (momentum)
ParFiniteElementSpace dfes(&pmesh, &fec, dim, Ordering::byNODES);
// Finite element space for all variables together (total thermodynamic state)
ParFiniteElementSpace vfes(&pmesh, &fec, num_equation, Ordering::byNODES);
ParFiniteElementSpace vfes(&pmesh, &fec, num_equations, Ordering::byNODES);
// This example depends on this ordering of the space.
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
@@ -178,87 +180,72 @@ int main(int argc, char *argv[])
cout << "Number of unknowns: " << glob_size << endl;
}
// 8. Define the initial conditions, save the corresponding mesh and grid
// functions to a file. This can be opened with GLVis with the -gc option.
// The solution u has components {density, x-momentum, y-momentum, energy}.
// These are stored contiguously in the BlockVector u_block.
Array<int> offsets(num_equation + 1);
for (int k = 0; k <= num_equation; k++) { offsets[k] = k * vfes.GetNDofs(); }
BlockVector u_block(offsets);
// Momentum grid function on dfes for visualization.
ParGridFunction mom(&dfes, u_block.GetData() + offsets[1]);
// 5. Define the initial conditions, save the corresponding mesh and grid
// functions to files. These can be opened with GLVis using:
// "glvis -np 4 -m euler-mesh -g euler-1-init" (for x-momentum).
// Initialize the state.
VectorFunctionCoefficient u0(num_equation, InitialCondition);
ParGridFunction sol(&vfes, u_block.GetData());
VectorFunctionCoefficient u0 = EulerInitialCondition(problem,
specific_heat_ratio,
gas_constant);
ParGridFunction sol(&vfes);
sol.ProjectCoefficient(u0);
ParGridFunction mom(&dfes, sol.GetData() + fes.GetNDofs());
// Output the initial solution.
{
ostringstream mesh_name;
mesh_name << "vortex-mesh." << setfill('0')
<< setw(6) << Mpi::WorldRank();
mesh_name << "euler-mesh." << setfill('0') << setw(6) << Mpi::WorldRank();
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(precision);
mesh_ofs << pmesh;
for (int k = 0; k < num_equation; k++)
for (int k = 0; k < num_equations; k++)
{
ParGridFunction uk(&fes, u_block.GetBlock(k));
ParGridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
ostringstream sol_name;
sol_name << "vortex-" << k << "-init."
<< setfill('0') << setw(6) << Mpi::WorldRank();
sol_name << "euler-" << k << "-init." << setfill('0') << setw(6)
<< Mpi::WorldRank();
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
}
}
// 9. Set up the nonlinear form corresponding to the DG discretization of the
// flux divergence, and assemble the corresponding mass matrix.
MixedBilinearForm Aflux(&dfes, &fes);
Aflux.AddDomainIntegrator(new TransposeIntegrator(new GradientIntegrator()));
Aflux.Assemble();
// 6. Set up the nonlinear form with euler flux and numerical flux
EulerFlux flux(dim, specific_heat_ratio);
RusanovFlux numericalFlux(flux);
DGHyperbolicConservationLaws euler(
vfes, std::unique_ptr<HyperbolicFormIntegrator>(
new HyperbolicFormIntegrator(numericalFlux, IntOrderOffset)),
preassembleWeakDiv);
ParNonlinearForm A(&vfes);
RiemannSolver rsolver;
A.AddInteriorFaceIntegrator(new FaceIntegrator(rsolver, dim));
// 10. Define the time-dependent evolution operator describing the ODE
// right-hand side, and perform time-integration (looping over the time
// iterations, ti, with a time-step dt).
FE_Evolution euler(vfes, A, Aflux.SpMat());
// Visualize the density
// 7. Visualize momentum with its magnitude
socketstream sout;
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
int visport = 19916;
MPI_Barrier(pmesh.GetComm());
sout.open(vishost, visport);
if (!sout)
{
if (Mpi::Root())
{
cout << "Unable to connect to GLVis server at "
<< vishost << ':' << visport << endl;
}
visualization = false;
if (Mpi::Root())
{
cout << "Unable to connect to GLVis server at " << vishost << ':'
<< visport << endl;
cout << "GLVis visualization disabled.\n";
}
}
else
{
sout << "parallel " << Mpi::WorldSize()
<< " " << Mpi::WorldRank() << "\n";
sout.precision(precision);
// Plot magnitude of vector-valued momentum
sout << "parallel " << numProcs << " " << myRank << "\n";
sout << "solution\n" << pmesh << mom;
sout << "window_title 'momentum, t = 0'\n";
sout << "view 0 0\n"; // view from top
sout << "keys jlm\n"; // turn off perspective and light, show mesh
sout << "pause\n";
sout << flush;
if (Mpi::Root())
@@ -266,68 +253,63 @@ int main(int argc, char *argv[])
cout << "GLVis visualization paused."
<< " Press space (in the GLVis window) to resume it.\n";
}
MPI_Barrier(pmesh.GetComm());
}
}
// Determine the minimum element size.
double hmin;
// 8. Time integration
// When dt is not specified, use CFL condition.
// Compute h_min and initial maximum characteristic speed
real_t hmin = infinity();
if (cfl > 0)
{
double my_hmin = pmesh.GetElementSize(0, 1);
for (int i = 1; i < pmesh.GetNE(); i++)
for (int i = 0; i < pmesh.GetNE(); i++)
{
my_hmin = min(pmesh.GetElementSize(i, 1), my_hmin);
hmin = min(pmesh.GetElementSize(i, 1), hmin);
}
// Reduce to find the global minimum element size
MPI_Allreduce(&my_hmin, &hmin, 1, MPI_DOUBLE, MPI_MIN, pmesh.GetComm());
MPI_Allreduce(MPI_IN_PLACE, &hmin, 1, MPITypeMap<real_t>::mpi_type, MPI_MIN,
pmesh.GetComm());
// Find a safe dt, using a temporary vector. Calling Mult() computes the
// maximum char speed at all quadrature points on all faces (and all
// elements with -mf).
Vector z(sol.Size());
euler.Mult(sol, z);
real_t max_char_speed = euler.GetMaxCharSpeed();
MPI_Allreduce(MPI_IN_PLACE, &max_char_speed, 1, MPITypeMap<real_t>::mpi_type,
MPI_MAX,
pmesh.GetComm());
dt = cfl * hmin / max_char_speed / (2 * order + 1);
}
// Start the timer.
tic_toc.Clear();
tic_toc.Start();
double t = 0.0;
// Init time integration
real_t t = 0.0;
euler.SetTime(t);
ode_solver->Init(euler);
if (cfl > 0)
{
// Find a safe dt, using a temporary vector. Calling Mult() computes the
// maximum char speed at all quadrature points on all faces.
max_char_speed = 0.;
Vector z(sol.Size());
A.Mult(sol, z);
// Reduce to find the global maximum wave speed
{
double all_max_char_speed;
MPI_Allreduce(&max_char_speed, &all_max_char_speed,
1, MPI_DOUBLE, MPI_MAX, pmesh.GetComm());
max_char_speed = all_max_char_speed;
}
dt = cfl * hmin / max_char_speed / (2*order+1);
}
// Integrate in time.
bool done = false;
for (int ti = 0; !done; )
for (int ti = 0; !done;)
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(sol, t, dt_real);
if (cfl > 0)
if (cfl > 0) // update time step size with CFL
{
// Reduce to find the global maximum wave speed
{
double all_max_char_speed;
MPI_Allreduce(&max_char_speed, &all_max_char_speed,
1, MPI_DOUBLE, MPI_MAX, pmesh.GetComm());
max_char_speed = all_max_char_speed;
}
dt = cfl * hmin / max_char_speed / (2*order+1);
real_t max_char_speed = euler.GetMaxCharSpeed();
MPI_Allreduce(MPI_IN_PLACE, &max_char_speed, 1, MPITypeMap<real_t>::mpi_type,
MPI_MAX,
pmesh.GetComm());
dt = cfl * hmin / max_char_speed / (2 * order + 1);
}
ti++;
done = (t >= t_final - 1e-8*dt);
done = (t >= t_final - 1e-8 * dt);
if (done || ti % vis_steps == 0)
{
if (Mpi::Root())
@@ -336,9 +318,8 @@ int main(int argc, char *argv[])
}
if (visualization)
{
MPI_Barrier(pmesh.GetComm());
sout << "parallel " << Mpi::WorldSize()
<< " " << Mpi::WorldRank() << "\n";
sout << "window_title 'momentum, t = " << t << "'\n";
sout << "parallel " << numProcs << " " << myRank << "\n";
sout << "solution\n" << pmesh << mom << flush;
}
}
@@ -350,27 +331,33 @@ int main(int argc, char *argv[])
cout << " done, " << tic_toc.RealTime() << "s." << endl;
}
// 11. Save the final solution. This output can be viewed later using GLVis:
// "glvis -np 4 -m vortex-mesh -g vortex-1-final".
for (int k = 0; k < num_equation; k++)
// 9. Save the final solution. This output can be viewed later using GLVis:
// "glvis -np 4 -m euler-mesh-final -g euler-1-final" (for x-momentum).
{
ParGridFunction uk(&fes, u_block.GetBlock(k));
ostringstream sol_name;
sol_name << "vortex-" << k << "-final."
<< setfill('0') << setw(6) << Mpi::WorldRank();
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
ostringstream mesh_name;
mesh_name << "euler-mesh-final." << setfill('0') << setw(6)
<< Mpi::WorldRank();
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(precision);
mesh_ofs << pmesh;
for (int k = 0; k < num_equations; k++)
{
ParGridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
ostringstream sol_name;
sol_name << "euler-" << k << "-final." << setfill('0') << setw(6)
<< Mpi::WorldRank();
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(precision);
sol_ofs << uk;
}
}
// 12. Compute the L2 solution error summed for all components.
if (t_final == 2.0)
// 10. Compute the L2 solution error summed for all components.
const real_t error = sol.ComputeLpError(2, u0);
if (Mpi::Root())
{
const double error = sol.ComputeLpError(2, u0);
if (Mpi::Root())
{
cout << "Solution error: " << error << endl;
}
cout << "Solution error: " << error << endl;
}
// Free the used memory.
+10 -10
View File
@@ -48,15 +48,15 @@ public:
print_level = print_lvl;
}
virtual void MonitorResidual(int it, double norm, const Vector &r, bool final);
virtual void MonitorResidual(int it, real_t norm, const Vector &r, bool final);
private:
const std::string prefix;
int print_level;
mutable double norm0;
mutable real_t norm0;
};
void GeneralResidualMonitor::MonitorResidual(int it, double norm,
void GeneralResidualMonitor::MonitorResidual(int it, real_t norm,
const Vector &r, bool final)
{
if (print_level == 1 || (print_level == 3 && (final || it == 0)))
@@ -103,7 +103,7 @@ protected:
BlockOperator *jacobian;
// Scaling factor for the pressure mass matrix in the block preconditioner
double gamma;
real_t gamma;
// Objects for the block preconditioner application
SparseMatrix *pressure_mass;
@@ -157,7 +157,7 @@ protected:
public:
RubberOperator(Array<FiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
Array<int> &block_trueOffsets, double rel_tol, double abs_tol,
Array<int> &block_trueOffsets, real_t rel_tol, real_t abs_tol,
int iter, Coefficient &mu);
// Required to use the native newton solver
@@ -187,10 +187,10 @@ int main(int argc, char *argv[])
int ref_levels = 0;
int order = 2;
bool visualization = true;
double newton_rel_tol = 1e-4;
double newton_abs_tol = 1e-6;
real_t newton_rel_tol = 1e-4;
real_t newton_abs_tol = 1e-6;
int newton_iter = 500;
double mu = 1.0;
real_t mu = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -449,8 +449,8 @@ JacobianPreconditioner::~JacobianPreconditioner()
RubberOperator::RubberOperator(Array<FiniteElementSpace *> &fes,
Array<Array<int> *> &ess_bdr,
Array<int> &offsets,
double rel_tol,
double abs_tol,
real_t rel_tol,
real_t abs_tol,
int iter,
Coefficient &c_mu)
: Operator(fes[0]->GetTrueVSize() + fes[1]->GetTrueVSize()),
+11 -11
View File
@@ -62,15 +62,15 @@ public:
#endif
}
virtual void MonitorResidual(int it, double norm, const Vector &r, bool final);
virtual void MonitorResidual(int it, real_t norm, const Vector &r, bool final);
private:
const std::string prefix;
int print_level;
mutable double norm0;
mutable real_t norm0;
};
void GeneralResidualMonitor::MonitorResidual(int it, double norm,
void GeneralResidualMonitor::MonitorResidual(int it, real_t norm,
const Vector &r, bool final)
{
if (print_level == 1 || (print_level == 3 && (final || it == 0)))
@@ -117,7 +117,7 @@ protected:
BlockOperator *jacobian;
// Scaling factor for the pressure mass matrix in the block preconditioner
double gamma;
real_t gamma;
// Objects for the block preconditioner application
Operator *pressure_mass;
@@ -171,7 +171,7 @@ protected:
public:
RubberOperator(Array<ParFiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
Array<int> &block_trueOffsets, double rel_tol, double abs_tol,
Array<int> &block_trueOffsets, real_t rel_tol, real_t abs_tol,
int iter, Coefficient &mu);
// Required to use the native newton solver
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
#ifdef HYPRE_USING_GPU
cout << "\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this example\n"
<< "is NOT supported with the GPU version of hypre.\n\n";
return 242;
return MFEM_SKIP_RETURN_VALUE;
#endif
// 1. Initialize MPI and HYPRE.
@@ -214,10 +214,10 @@ int main(int argc, char *argv[])
int par_ref_levels = 0;
int order = 2;
bool visualization = true;
double newton_rel_tol = 1e-4;
double newton_abs_tol = 1e-6;
real_t newton_rel_tol = 1e-4;
real_t newton_abs_tol = 1e-6;
int newton_iter = 500;
double mu = 1.0;
real_t mu = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -524,8 +524,8 @@ JacobianPreconditioner::~JacobianPreconditioner()
RubberOperator::RubberOperator(Array<ParFiniteElementSpace *> &fes,
Array<Array<int> *> &ess_bdr,
Array<int> &trueOffsets,
double rel_tol,
double abs_tol,
real_t rel_tol,
real_t abs_tol,
int iter,
Coefficient &c_mu)
: Operator(fes[0]->TrueVSize() + fes[1]->TrueVSize()),
+10 -10
View File
@@ -69,11 +69,11 @@ using namespace mfem;
// Constants used in the Hamiltonian
static int prob_ = 0;
static double m_ = 1.0;
static double k_ = 1.0;
static real_t m_ = 1.0;
static real_t k_ = 1.0;
// Hamiltonian functional, see below for implementation
double hamiltonian(double q, double p, double t);
real_t hamiltonian(real_t q, real_t p, real_t t);
class GradT : public Operator
{
@@ -94,7 +94,7 @@ int main(int argc, char *argv[])
// 1. Parse command-line options.
int order = 1;
int nsteps = 100;
double dt = 0.1;
real_t dt = 0.1;
bool visualization = true;
bool gnuplot = false;
@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
siaSolver.Init(P,F);
// 3. Set the initial conditions
double t = 0.0;
real_t t = 0.0;
Vector q(1), p(1);
Vector e(nsteps+1);
q(0) = 0.0;
@@ -160,7 +160,7 @@ int main(int argc, char *argv[])
Vector x1(3); x1 = 0.0;
// 6. Perform time-stepping
double e_mean = 0.0;
real_t e_mean = 0.0;
for (int i = 0; i < nsteps; i++)
{
@@ -210,13 +210,13 @@ int main(int argc, char *argv[])
// 7. Compute and display mean and standard deviation of the energy
e_mean /= (nsteps + 1);
double e_var = 0.0;
real_t e_var = 0.0;
for (int i=0; i<=nsteps; i++)
{
e_var += pow(e[i] - e_mean, 2);
}
e_var /= (nsteps + 1);
double e_sd = sqrt(e_var);
real_t e_sd = sqrt(e_var);
cout << endl << "Mean and standard deviation of the energy" << endl;
cout << e_mean << "\t" << e_sd << endl;
@@ -256,9 +256,9 @@ int main(int argc, char *argv[])
}
}
double hamiltonian(double q, double p, double t)
real_t hamiltonian(real_t q, real_t p, real_t t)
{
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
real_t h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
switch (prob_)
{
case 1:
+16 -15
View File
@@ -74,11 +74,11 @@ using namespace mfem;
// Constants used in the Hamiltonian
static int prob_ = 0;
static double m_ = 1.0;
static double k_ = 1.0;
static real_t m_ = 1.0;
static real_t k_ = 1.0;
// Hamiltonian functional, see below for implementation
double hamiltonian(double q, double p, double t);
real_t hamiltonian(real_t q, real_t p, real_t t);
class GradT : public Operator
{
@@ -106,7 +106,7 @@ int main(int argc, char *argv[])
// 2. Parse command-line options.
int order = 1;
int nsteps = 100;
double dt = 0.1;
real_t dt = 0.1;
bool visualization = true;
bool gnuplot = false;
@@ -154,11 +154,11 @@ int main(int argc, char *argv[])
siaSolver.Init(P,F);
// 4. Set the initial conditions
double t = 0.0;
real_t t = 0.0;
Vector q(1), p(1);
Vector e(nsteps+1);
q(0) = sin(2.0*M_PI*(double)myid/num_procs);
p(0) = cos(2.0*M_PI*(double)myid/num_procs);
q(0) = sin(2.0*M_PI*(real_t)myid/num_procs);
p(0) = cos(2.0*M_PI*(real_t)myid/num_procs);
// 5. Prepare GnuPlot output file if needed
ostringstream oss;
@@ -181,7 +181,7 @@ int main(int argc, char *argv[])
Vector x1(3); x1 = 0.0;
// 7. Perform time-stepping
double e_mean = 0.0;
real_t e_mean = 0.0;
for (int i = 0; i < nsteps; i++)
{
@@ -238,20 +238,21 @@ int main(int argc, char *argv[])
// 8. Compute and display mean and standard deviation of the energy
e_mean /= (nsteps + 1);
double e_var = 0.0;
real_t e_var = 0.0;
for (int i = 0; i <= nsteps; i++)
{
e_var += pow(e[i] - e_mean, 2);
}
e_var /= (nsteps + 1);
double e_sd = sqrt(e_var);
real_t e_sd = sqrt(e_var);
double e_loc_stats[2];
double *e_stats = (myid == 0) ? new double[2 * num_procs] : (double*)NULL;
real_t e_loc_stats[2];
real_t *e_stats = (myid == 0) ? new real_t[2 * num_procs] : (real_t*)NULL;
e_loc_stats[0] = e_mean;
e_loc_stats[1] = e_sd;
MPI_Gather(e_loc_stats, 2, MPI_DOUBLE, e_stats, 2, MPI_DOUBLE, 0, comm);
MPI_Gather(e_loc_stats, 2, MPITypeMap<real_t>::mpi_type, e_stats, 2,
MPITypeMap<real_t>::mpi_type, 0, comm);
if (myid == 0)
{
@@ -324,9 +325,9 @@ int main(int argc, char *argv[])
}
}
double hamiltonian(double q, double p, double t)
real_t hamiltonian(real_t q, real_t p, real_t t)
{
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
real_t h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
switch (prob_)
{
case 1:
+18 -18
View File
@@ -57,13 +57,13 @@
using namespace std;
using namespace mfem;
static double mu_ = 1.0;
static double epsilon_ = 1.0;
static double sigma_ = 20.0;
static double omega_ = 10.0;
static real_t mu_ = 1.0;
static real_t epsilon_ = 1.0;
static real_t sigma_ = 20.0;
static real_t omega_ = 10.0;
double u0_real_exact(const Vector &);
double u0_imag_exact(const Vector &);
real_t u0_real_exact(const Vector &);
real_t u0_imag_exact(const Vector &);
void u1_real_exact(const Vector &, Vector &);
void u1_imag_exact(const Vector &, Vector &);
@@ -80,8 +80,8 @@ int main(int argc, char *argv[])
int ref_levels = 0;
int order = 1;
int prob = 0;
double freq = -1.0;
double a_coef = 0.0;
real_t freq = -1.0;
real_t a_coef = 0.0;
bool visualization = 1;
bool herm_conv = true;
bool exact_sol = true;
@@ -412,7 +412,7 @@ int main(int argc, char *argv[])
break; // This should be unreachable
}
}
double s = (prob != 1) ? 1.0 : -1.0;
real_t s = (prob != 1) ? 1.0 : -1.0;
pc_i = new ScaledOperator(pc_r,
(conv == ComplexOperator::HERMITIAN) ?
s:-s);
@@ -436,8 +436,8 @@ int main(int argc, char *argv[])
if (exact_sol)
{
double err_r = -1.0;
double err_i = -1.0;
real_t err_r = -1.0;
real_t err_i = -1.0;
switch (prob)
{
@@ -524,7 +524,7 @@ int main(int argc, char *argv[])
int i = 0;
while (sol_sock)
{
double t = (double)(i % num_frames) / num_frames;
real_t t = (real_t)(i % num_frames) / num_frames;
ostringstream oss;
oss << "Harmonic Solution (t = " << t << " T)";
@@ -555,21 +555,21 @@ bool check_for_inline_mesh(const char * mesh_file)
return s0 == "inline-";
}
complex<double> u0_exact(const Vector &x)
complex<real_t> u0_exact(const Vector &x)
{
int dim = x.Size();
complex<double> i(0.0, 1.0);
complex<double> alpha = (epsilon_ * omega_ - i * sigma_);
complex<double> kappa = std::sqrt(mu_ * omega_* alpha);
complex<real_t> i(0.0, 1.0);
complex<real_t> alpha = (epsilon_ * omega_ - i * sigma_);
complex<real_t> kappa = std::sqrt(mu_ * omega_* alpha);
return std::exp(-i * kappa * x[dim - 1]);
}
double u0_real_exact(const Vector &x)
real_t u0_real_exact(const Vector &x)
{
return u0_exact(x).real();
}
double u0_imag_exact(const Vector &x)
real_t u0_imag_exact(const Vector &x)
{
return u0_exact(x).imag();
}
+17 -17
View File
@@ -57,13 +57,13 @@
using namespace std;
using namespace mfem;
static double mu_ = 1.0;
static double epsilon_ = 1.0;
static double sigma_ = 20.0;
static double omega_ = 10.0;
static real_t mu_ = 1.0;
static real_t epsilon_ = 1.0;
static real_t sigma_ = 20.0;
static real_t omega_ = 10.0;
double u0_real_exact(const Vector &);
double u0_imag_exact(const Vector &);
real_t u0_real_exact(const Vector &);
real_t u0_imag_exact(const Vector &);
void u1_real_exact(const Vector &, Vector &);
void u1_imag_exact(const Vector &, Vector &);
@@ -87,8 +87,8 @@ int main(int argc, char *argv[])
int par_ref_levels = 1;
int order = 1;
int prob = 0;
double freq = -1.0;
double a_coef = 0.0;
real_t freq = -1.0;
real_t a_coef = 0.0;
bool visualization = 1;
bool herm_conv = true;
bool exact_sol = true;
@@ -475,8 +475,8 @@ int main(int argc, char *argv[])
if (exact_sol)
{
double err_r = -1.0;
double err_i = -1.0;
real_t err_r = -1.0;
real_t err_i = -1.0;
switch (prob)
{
@@ -576,7 +576,7 @@ int main(int argc, char *argv[])
int i = 0;
while (sol_sock)
{
double t = (double)(i % num_frames) / num_frames;
real_t t = (real_t)(i % num_frames) / num_frames;
ostringstream oss;
oss << "Harmonic Solution (t = " << t << " T)";
@@ -608,21 +608,21 @@ bool check_for_inline_mesh(const char * mesh_file)
return s0 == "inline-";
}
complex<double> u0_exact(const Vector &x)
complex<real_t> u0_exact(const Vector &x)
{
int dim = x.Size();
complex<double> i(0.0, 1.0);
complex<double> alpha = (epsilon_ * omega_ - i * sigma_);
complex<double> kappa = std::sqrt(mu_ * omega_* alpha);
complex<real_t> i(0.0, 1.0);
complex<real_t> alpha = (epsilon_ * omega_ - i * sigma_);
complex<real_t> kappa = std::sqrt(mu_ * omega_* alpha);
return std::exp(-i * kappa * x[dim - 1]);
}
double u0_real_exact(const Vector &x)
real_t u0_real_exact(const Vector &x)
{
return u0_exact(x).real();
}
double u0_imag_exact(const Vector &x)
real_t u0_imag_exact(const Vector &x)
{
return u0_exact(x).imag();
}
+14 -15
View File
@@ -46,7 +46,7 @@ protected:
SparseMatrix Mmat, Kmat, Kmat0;
SparseMatrix *T; // T = M + dt K
double current_dt;
real_t current_dt;
CGSolver M_solver; // Krylov solver for inverting the mass matrix M
DSmoother M_prec; // Preconditioner for the mass matrix M
@@ -58,7 +58,7 @@ protected:
mutable Vector z; // auxiliary vector
public:
WaveOperator(FiniteElementSpace &f, Array<int> &ess_bdr,double speed);
WaveOperator(FiniteElementSpace &f, Array<int> &ess_bdr, real_t speed);
using SecondOrderTimeDependentOperator::Mult;
virtual void Mult(const Vector &u, const Vector &du_dt,
@@ -68,7 +68,7 @@ public:
d2udt2 = f(u + fac0*d2udt2,dudt + fac1*d2udt2, t),
for the unknown d2udt2. */
using SecondOrderTimeDependentOperator::ImplicitSolve;
virtual void ImplicitSolve(const double fac0, const double fac1,
virtual void ImplicitSolve(const real_t fac0, const real_t fac1,
const Vector &u, const Vector &dudt, Vector &d2udt2);
///
@@ -79,12 +79,11 @@ public:
WaveOperator::WaveOperator(FiniteElementSpace &f,
Array<int> &ess_bdr, double speed)
: SecondOrderTimeDependentOperator(f.GetTrueVSize(), 0.0), fespace(f), M(NULL),
K(NULL),
T(NULL), current_dt(0.0), z(height)
Array<int> &ess_bdr, real_t speed)
: SecondOrderTimeDependentOperator(f.GetTrueVSize(), (real_t) 0.0),
fespace(f), M(NULL), K(NULL), T(NULL), current_dt(0.0), z(height)
{
const double rel_tol = 1e-8;
const real_t rel_tol = 1e-8;
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
@@ -132,7 +131,7 @@ void WaveOperator::Mult(const Vector &u, const Vector &du_dt,
M_solver.Mult(z, d2udt2);
}
void WaveOperator::ImplicitSolve(const double fac0, const double fac1,
void WaveOperator::ImplicitSolve(const real_t fac0, const real_t fac1,
const Vector &u, const Vector &dudt, Vector &d2udt2)
{
// Solve the equation:
@@ -167,12 +166,12 @@ WaveOperator::~WaveOperator()
delete c2;
}
double InitialSolution(const Vector &x)
real_t InitialSolution(const Vector &x)
{
return exp(-x.Norml2()*x.Norml2()*30);
}
double InitialRate(const Vector &x)
real_t InitialRate(const Vector &x)
{
return 0.0;
}
@@ -186,9 +185,9 @@ int main(int argc, char *argv[])
int ref_levels = 2;
int order = 2;
int ode_solver_type = 10;
double t_final = 0.5;
double dt = 1.0e-2;
double speed = 1.0;
real_t t_final = 0.5;
real_t dt = 1.0e-2;
real_t speed = 1.0;
bool visualization = true;
bool visit = true;
bool dirichlet = true;
@@ -366,7 +365,7 @@ int main(int argc, char *argv[])
// 8. Perform time-integration (looping over the time iterations, ti, with a
// time-step dt).
ode_solver->Init(oper);
double t = 0.0;
real_t t = 0.0;
bool last_step = false;
for (int ti = 1; !last_step; ti++)
+14 -14
View File
@@ -44,14 +44,14 @@
using namespace std;
using namespace mfem;
double p_exact(const Vector &x);
real_t p_exact(const Vector &x);
void gradp_exact(const Vector &, Vector &);
double div_gradp_exact(const Vector &x);
real_t div_gradp_exact(const Vector &x);
void v_exact(const Vector &x, Vector &v);
void curlv_exact(const Vector &x, Vector &cv);
int dim;
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -304,9 +304,9 @@ int main(int argc, char *argv[])
// 12. Compute and print the L_2 norm of the error.
if (prob == 0)
{
double errSol = x.ComputeL2Error(gradp_coef);
double errInterp = discreteInterpolant.ComputeL2Error(gradp_coef);
double errProj = exact_proj.ComputeL2Error(gradp_coef);
real_t errSol = x.ComputeL2Error(gradp_coef);
real_t errInterp = discreteInterpolant.ComputeL2Error(gradp_coef);
real_t errProj = exact_proj.ComputeL2Error(gradp_coef);
cout << "\n Solution of (E_h,v) = (grad p_h,v) for E_h and v in H(curl): "
"|| E_h - grad p ||_{L_2} = " << errSol << '\n' << endl;
@@ -317,9 +317,9 @@ int main(int argc, char *argv[])
}
else if (prob == 1)
{
double errSol = x.ComputeL2Error(curlv_coef);
double errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
double errProj = exact_proj.ComputeL2Error(curlv_coef);
real_t errSol = x.ComputeL2Error(curlv_coef);
real_t errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
real_t errProj = exact_proj.ComputeL2Error(curlv_coef);
cout << "\n Solution of (E_h,w) = (curl v_h,w) for E_h and w in H(div): "
"|| E_h - curl v ||_{L_2} = " << errSol << '\n' << endl;
@@ -337,9 +337,9 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double errSol = x.ComputeL2Error(divgradp_coef, irs);
double errInterp = discreteInterpolant.ComputeL2Error(divgradp_coef, irs);
double errProj = exact_proj.ComputeL2Error(divgradp_coef, irs);
real_t errSol = x.ComputeL2Error(divgradp_coef, irs);
real_t errInterp = discreteInterpolant.ComputeL2Error(divgradp_coef, irs);
real_t errProj = exact_proj.ComputeL2Error(divgradp_coef, irs);
cout << "\n Solution of (f_h,q) = (div v_h,q) for f_h and q in L_2: "
"|| f_h - div v ||_{L_2} = " << errSol << '\n' << endl;
@@ -376,7 +376,7 @@ int main(int argc, char *argv[])
return 0;
}
double p_exact(const Vector &x)
real_t p_exact(const Vector &x)
{
if (dim == 3)
{
@@ -406,7 +406,7 @@ void gradp_exact(const Vector &x, Vector &f)
}
}
double div_gradp_exact(const Vector &x)
real_t div_gradp_exact(const Vector &x)
{
if (dim == 3)
{
+14 -14
View File
@@ -44,14 +44,14 @@
using namespace std;
using namespace mfem;
double p_exact(const Vector &x);
real_t p_exact(const Vector &x);
void gradp_exact(const Vector &, Vector &);
double div_gradp_exact(const Vector &x);
real_t div_gradp_exact(const Vector &x);
void v_exact(const Vector &x, Vector &v);
void curlv_exact(const Vector &x, Vector &cv);
int dim;
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -352,9 +352,9 @@ int main(int argc, char *argv[])
// 14. Compute and print the L_2 norm of the error.
if (prob == 0)
{
double errSol = x.ComputeL2Error(gradp_coef);
double errInterp = discreteInterpolant.ComputeL2Error(gradp_coef);
double errProj = exact_proj.ComputeL2Error(gradp_coef);
real_t errSol = x.ComputeL2Error(gradp_coef);
real_t errInterp = discreteInterpolant.ComputeL2Error(gradp_coef);
real_t errProj = exact_proj.ComputeL2Error(gradp_coef);
if (myid == 0)
{
@@ -368,9 +368,9 @@ int main(int argc, char *argv[])
}
else if (prob == 1)
{
double errSol = x.ComputeL2Error(curlv_coef);
double errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
double errProj = exact_proj.ComputeL2Error(curlv_coef);
real_t errSol = x.ComputeL2Error(curlv_coef);
real_t errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
real_t errProj = exact_proj.ComputeL2Error(curlv_coef);
if (myid == 0)
{
@@ -391,9 +391,9 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double errSol = x.ComputeL2Error(divgradp_coef, irs);
double errInterp = discreteInterpolant.ComputeL2Error(divgradp_coef, irs);
double errProj = exact_proj.ComputeL2Error(divgradp_coef, irs);
real_t errSol = x.ComputeL2Error(divgradp_coef, irs);
real_t errInterp = discreteInterpolant.ComputeL2Error(divgradp_coef, irs);
real_t errProj = exact_proj.ComputeL2Error(divgradp_coef, irs);
if (myid == 0)
{
@@ -441,7 +441,7 @@ int main(int argc, char *argv[])
return 0;
}
double p_exact(const Vector &x)
real_t p_exact(const Vector &x)
{
if (dim == 3)
{
@@ -471,7 +471,7 @@ void gradp_exact(const Vector &x, Vector &f)
}
}
double div_gradp_exact(const Vector &x)
real_t div_gradp_exact(const Vector &x)
{
if (dim == 3)
{
+120 -116
View File
@@ -53,13 +53,13 @@ private:
int dim;
// Length of the PML Region in each direction
Array2D<double> length;
Array2D<real_t> length;
// Computational Domain Boundary
Array2D<double> comp_dom_bdr;
Array2D<real_t> comp_dom_bdr;
// Domain Boundary
Array2D<double> dom_bdr;
Array2D<real_t> dom_bdr;
// Integer Array identifying elements in the PML
// 0: in the PML, 1: not in the PML
@@ -70,13 +70,13 @@ private:
public:
// Constructor
PML(Mesh *mesh_,Array2D<double> length_);
PML(Mesh *mesh_,Array2D<real_t> length_);
// Return Computational Domain Boundary
Array2D<double> GetCompDomainBdr() {return comp_dom_bdr;}
Array2D<real_t> GetCompDomainBdr() {return comp_dom_bdr;}
// Return Domain Boundary
Array2D<double> GetDomainBdr() {return dom_bdr;}
Array2D<real_t> GetDomainBdr() {return dom_bdr;}
// Return Markers list for elements
Array<int> * GetMarkedPMLElements() {return &elems;}
@@ -85,7 +85,7 @@ public:
void SetAttributes(Mesh *mesh_);
// PML complex stretching function
void StretchFunction(const Vector &x, vector<complex<double>> &dxs);
void StretchFunction(const Vector &x, vector<complex<real_t>> &dxs);
};
// Class for returning the PML coefficients of the bilinear form
@@ -106,7 +106,7 @@ public:
virtual void Eval(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{
double x[3];
real_t x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
K.SetSize(vdim);
@@ -114,7 +114,7 @@ public:
}
};
void maxwell_solution(const Vector &x, vector<complex<double>> &Eval);
void maxwell_solution(const Vector &x, vector<complex<real_t>> &Eval);
void E_bdr_data_Re(const Vector &x, Vector &E);
void E_bdr_data_Im(const Vector &x, Vector &E);
@@ -134,15 +134,17 @@ void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector &D);
void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector &D);
void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector &D);
Array2D<double> comp_domain_bdr;
Array2D<double> domain_bdr;
Array2D<real_t> comp_domain_bdr;
Array2D<real_t> domain_bdr;
double mu = 1.0;
double epsilon = 1.0;
double omega;
real_t mu = 1.0;
real_t epsilon = 1.0;
real_t omega;
int dim;
bool exact_known = false;
template <typename T> T pow2(const T &x) { return x*x; }
enum prob_type
{
beam, // Wave propagating in a beam-like domain
@@ -160,7 +162,7 @@ int main(int argc, char *argv[])
int order = 1;
int ref_levels = 3;
int iprob = 4;
double freq = 5.0;
real_t freq = 5.0;
bool herm_conv = true;
bool umf_solver = false;
bool visualization = 1;
@@ -241,10 +243,10 @@ int main(int argc, char *argv[])
dim = mesh->Dimension();
// Angular frequency
omega = 2.0 * M_PI * freq;
omega = real_t(2.0 * M_PI) * freq;
// Setup PML length
Array2D<double> length(dim, 2); length = 0.0;
Array2D<real_t> length(dim, 2); length = 0.0;
// 4. Setup the Cartesian PML region.
switch (prob)
@@ -312,14 +314,15 @@ int main(int argc, char *argv[])
switch (prob)
{
case lshape:
if (center[0] == 1.0 || center[0] == 0.5 || center[1] == 0.5)
if (center[0] == 1_r || center[0] == 0.5_r ||
center[1] == 0.5_r)
{
ess_bdr[k - 1] = 1;
}
break;
case fichera:
if (center[0] == -1.0 || center[0] == 0.0 ||
center[1] == 0.0 || center[2] == 0.0)
if (center[0] == -1_r || center[0] == 0_r ||
center[1] == 0_r || center[2] == 0_r)
{
ess_bdr[k - 1] = 1;
}
@@ -378,8 +381,8 @@ int main(int argc, char *argv[])
}
}
ConstantCoefficient muinv(1.0/mu);
ConstantCoefficient omeg(-pow(omega, 2) * epsilon);
ConstantCoefficient muinv(1_r / mu);
ConstantCoefficient omeg(-pow2(omega) * epsilon);
RestrictedCoefficient restr_muinv(muinv,attr);
RestrictedCoefficient restr_omeg(omeg,attr);
@@ -439,7 +442,7 @@ int main(int argc, char *argv[])
// + omega^2 * epsilon (abs(det(J) * (J^T J)^-1) * E, F)
if (pa || !umf_solver)
{
ConstantCoefficient absomeg(pow(omega, 2) * epsilon);
ConstantCoefficient absomeg(pow2(omega) * epsilon);
RestrictedCoefficient restr_absomeg(absomeg,attr);
BilinearForm prec(fespace);
@@ -470,7 +473,7 @@ int main(int argc, char *argv[])
std::unique_ptr<Operator> pc_r;
std::unique_ptr<Operator> pc_i;
double s = (conv == ComplexOperator::HERMITIAN) ? -1.0 : 1.0;
real_t s = (conv == ComplexOperator::HERMITIAN) ? -1_r : 1_r;
if (pa)
{
// Jacobi Smoother
@@ -519,14 +522,14 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double L2Error_Re = x.real().ComputeL2Error(E_ex_Re, irs,
real_t L2Error_Re = x.real().ComputeL2Error(E_ex_Re, irs,
pml->GetMarkedPMLElements());
double L2Error_Im = x.imag().ComputeL2Error(E_ex_Im, irs,
real_t L2Error_Im = x.imag().ComputeL2Error(E_ex_Im, irs,
pml->GetMarkedPMLElements());
ComplexGridFunction x_gf0(fespace);
x_gf0 = 0.0;
double norm_E_Re, norm_E_Im;
real_t norm_E_Re, norm_E_Im;
norm_E_Re = x_gf0.real().ComputeL2Error(E_ex_Re, irs,
pml->GetMarkedPMLElements());
norm_E_Im = x_gf0.imag().ComputeL2Error(E_ex_Im, irs,
@@ -593,12 +596,12 @@ int main(int argc, char *argv[])
int i = 0;
while (sol_sock)
{
double t = (double)(i % num_frames) / num_frames;
real_t t = (real_t)(i % num_frames) / num_frames;
ostringstream oss;
oss << "Harmonic Solution (t = " << t << " T)";
add(cos(2.0 * M_PI * t), x.real(),
sin(2.0 * M_PI * t), x.imag(), x_t);
add(cos(real_t(2.0 * M_PI) * t), x.real(),
sin(real_t(2.0 * M_PI) * t), x.imag(), x_t);
sol_sock << "solution\n"
<< *mesh << x_t
<< "window_title '" << oss.str() << "'" << flush;
@@ -617,20 +620,20 @@ int main(int argc, char *argv[])
void source(const Vector &x, Vector &f)
{
Vector center(dim);
double r = 0.0;
real_t r = 0.0;
for (int i = 0; i < dim; ++i)
{
center(i) = 0.5 * (comp_domain_bdr(i, 0) + comp_domain_bdr(i, 1));
r += pow(x[i] - center[i], 2.);
center(i) = 0.5_r * (comp_domain_bdr(i, 0) + comp_domain_bdr(i, 1));
r += pow2(x[i] - center[i]);
}
double n = 5.0 * omega * sqrt(epsilon * mu) / M_PI;
double coeff = pow(n, 2) / M_PI;
double alpha = -pow(n, 2) * r;
real_t n = 5_r * omega * sqrt(epsilon * mu) / real_t(M_PI);
real_t coeff = pow2(n) / real_t(M_PI);
real_t alpha = -pow2(n) * r;
f = 0.0;
f[0] = coeff * exp(alpha);
}
void maxwell_solution(const Vector &x, vector<complex<double>> &E)
void maxwell_solution(const Vector &x, vector<complex<real_t>> &E)
{
// Initialize
for (int i = 0; i < dim; ++i)
@@ -638,8 +641,8 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
E[i] = 0.0;
}
complex<double> zi = complex<double>(0., 1.);
double k = omega * sqrt(epsilon * mu);
constexpr complex<real_t> zi = complex<real_t>(0., 1.);
real_t k = omega * sqrt(epsilon * mu);
switch (prob)
{
case disc:
@@ -654,58 +657,58 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
if (dim == 2)
{
double x0 = x(0) + shift(0);
double x1 = x(1) + shift(1);
double r = sqrt(x0 * x0 + x1 * x1);
double beta = k * r;
real_t x0 = x(0) + shift(0);
real_t x1 = x(1) + shift(1);
real_t r = sqrt(x0 * x0 + x1 * x1);
real_t beta = k * r;
// Bessel functions
complex<double> Ho, Ho_r, Ho_rr;
Ho = jn(0, beta) + zi * yn(0, beta);
Ho_r = -k * (jn(1, beta) + zi * yn(1, beta));
Ho_rr = -k * k * (1.0 / beta *
(jn(1, beta) + zi * yn(1, beta)) -
(jn(2, beta) + zi * yn(2, beta)));
complex<real_t> Ho, Ho_r, Ho_rr;
Ho = real_t(jn(0, beta)) + zi * real_t(yn(0, beta));
Ho_r = -k * (real_t(jn(1, beta)) + zi * real_t(yn(1, beta)));
Ho_rr = -k * k * (1_r / beta *
(real_t(jn(1, beta)) + zi * real_t(yn(1, beta))) -
(real_t(jn(2, beta)) + zi * real_t(yn(2, beta))));
// First derivatives
double r_x = x0 / r;
double r_y = x1 / r;
double r_xy = -(r_x / r) * r_y;
double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
real_t r_x = x0 / r;
real_t r_y = x1 / r;
real_t r_xy = -(r_x / r) * r_y;
real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
complex<double> val, val_xx, val_xy;
val = 0.25 * zi * Ho;
val_xx = 0.25 * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
val_xy = 0.25 * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
complex<real_t> val, val_xx, val_xy;
val = real_t(0.25) * zi * Ho;
val_xx = real_t(0.25) * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
val_xy = real_t(0.25) * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
E[0] = zi / k * (k * k * val + val_xx);
E[1] = zi / k * val_xy;
}
else if (dim == 3)
{
double x0 = x(0) + shift(0);
double x1 = x(1) + shift(1);
double x2 = x(2) + shift(2);
double r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
real_t x0 = x(0) + shift(0);
real_t x1 = x(1) + shift(1);
real_t x2 = x(2) + shift(2);
real_t r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
double r_x = x0 / r;
double r_y = x1 / r;
double r_z = x2 / r;
double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
double r_yx = -(r_y / r) * r_x;
double r_zx = -(r_z / r) * r_x;
real_t r_x = x0 / r;
real_t r_y = x1 / r;
real_t r_z = x2 / r;
real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
real_t r_yx = -(r_y / r) * r_x;
real_t r_zx = -(r_z / r) * r_x;
complex<double> val, val_r, val_rr;
complex<real_t> val, val_r, val_rr;
val = exp(zi * k * r) / r;
val_r = val / r * (zi * k * r - 1.0);
val_r = val / r * (zi * k * r - 1_r);
val_rr = val / (r * r) * (-k * k * r * r
- 2.0 * zi * k * r + 2.0);
- real_t(2) * zi * k * r + real_t(2));
complex<double> val_xx, val_yx, val_zx;
complex<real_t> val_xx, val_yx, val_zx;
val_xx = val_rr * r_x * r_x + val_r * r_xx;
val_yx = val_rr * r_x * r_y + val_r * r_yx;
val_zx = val_rr * r_x * r_z + val_r * r_zx;
complex<double> alpha = zi * k / 4.0 / M_PI / k / k;
complex<real_t> alpha = zi * k / real_t(4) / (real_t) M_PI / k / k;
E[0] = alpha * (k * k * val + val_xx);
E[1] = alpha * val_yx;
E[2] = alpha * val_zx;
@@ -717,12 +720,13 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
// T_10 mode
if (dim == 3)
{
double k10 = sqrt(k * k - M_PI * M_PI);
E[1] = -zi * k / M_PI * sin(M_PI*x(2))*exp(zi * k10 * x(0));
real_t k10 = sqrt(k * k - real_t(M_PI * M_PI));
E[1] = -zi * k / (real_t) M_PI *
sin((real_t) M_PI*x(2))*exp(zi * k10 * x(0));
}
else if (dim == 2)
{
E[1] = -zi * k / M_PI * exp(zi * k * x(0));
E[1] = -zi * k / (real_t) M_PI * exp(zi * k * x(0));
}
break;
}
@@ -733,7 +737,7 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
void E_exact_Re(const Vector &x, Vector &E)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -743,7 +747,7 @@ void E_exact_Re(const Vector &x, Vector &E)
void E_exact_Im(const Vector &x, Vector &E)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -759,8 +763,8 @@ void E_bdr_data_Re(const Vector &x, Vector &E)
for (int i = 0; i < dim; ++i)
{
// check if in PML
if (x(i) - comp_domain_bdr(i, 0) < 0.0 ||
x(i) - comp_domain_bdr(i, 1) > 0.0)
if (x(i) - comp_domain_bdr(i, 0) < 0_r ||
x(i) - comp_domain_bdr(i, 1) > 0_r)
{
in_pml = true;
break;
@@ -768,7 +772,7 @@ void E_bdr_data_Re(const Vector &x, Vector &E)
}
if (!in_pml)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -786,8 +790,8 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
for (int i = 0; i < dim; ++i)
{
// check if in PML
if (x(i) - comp_domain_bdr(i, 0) < 0.0 ||
x(i) - comp_domain_bdr(i, 1) > 0.0)
if (x(i) - comp_domain_bdr(i, 0) < 0_r ||
x(i) - comp_domain_bdr(i, 1) > 0_r)
{
in_pml = true;
break;
@@ -795,7 +799,7 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
}
if (!in_pml)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -806,8 +810,8 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
void detJ_JT_J_inv_Re(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
vector<complex<real_t>> dxs(dim);
complex<real_t> det(1.0, 0.0);
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -817,14 +821,14 @@ void detJ_JT_J_inv_Re(const Vector &x, PML * pml, Vector &D)
for (int i = 0; i < dim; ++i)
{
D(i) = (det / pow(dxs[i], 2)).real();
D(i) = (det / pow2(dxs[i])).real();
}
}
void detJ_JT_J_inv_Im(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -834,14 +838,14 @@ void detJ_JT_J_inv_Im(const Vector &x, PML * pml, Vector &D)
for (int i = 0; i < dim; ++i)
{
D(i) = (det / pow(dxs[i], 2)).imag();
D(i) = (det / pow2(dxs[i])).imag();
}
}
void detJ_JT_J_inv_abs(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -851,14 +855,14 @@ void detJ_JT_J_inv_abs(const Vector &x, PML * pml, Vector &D)
for (int i = 0; i < dim; ++i)
{
D(i) = abs(det / pow(dxs[i], 2));
D(i) = abs(det / pow2(dxs[i]));
}
}
void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
vector<complex<real_t>> dxs(dim);
complex<real_t> det(1.0, 0.0);
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -869,21 +873,21 @@ void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector &D)
// in the 2D case the coefficient is scalar 1/det(J)
if (dim == 2)
{
D = (1.0 / det).real();
D = (1_r / det).real();
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = (pow(dxs[i], 2) / det).real();
D(i) = (pow2(dxs[i]) / det).real();
}
}
}
void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -893,21 +897,21 @@ void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector &D)
if (dim == 2)
{
D = (1.0 / det).imag();
D = (1_r / det).imag();
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = (pow(dxs[i], 2) / det).imag();
D(i) = (pow2(dxs[i]) / det).imag();
}
}
}
void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -917,18 +921,18 @@ void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector &D)
if (dim == 2)
{
D = abs(1.0 / det);
D = abs(1_r / det);
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = abs(pow(dxs[i], 2) / det);
D(i) = abs(pow2(dxs[i]) / det);
}
}
}
PML::PML(Mesh *mesh_, Array2D<double> length_)
PML::PML(Mesh *mesh_, Array2D<real_t> length_)
: mesh(mesh_), length(length_)
{
dim = mesh->Dimension();
@@ -979,7 +983,7 @@ void PML::SetAttributes(Mesh *mesh_)
for (int iv = 0; iv < nrvert; ++iv)
{
int vert_idx = vertices[iv];
double *coords = mesh_->GetVertex(vert_idx);
real_t *coords = mesh_->GetVertex(vert_idx);
for (int comp = 0; comp < dim; ++comp)
{
if (coords[comp] > comp_dom_bdr(comp, 1) ||
@@ -1000,14 +1004,14 @@ void PML::SetAttributes(Mesh *mesh_)
}
void PML::StretchFunction(const Vector &x,
vector<complex<double>> &dxs)
vector<complex<real_t>> &dxs)
{
complex<double> zi = complex<double>(0., 1.);
constexpr complex<real_t> zi = complex<real_t>(0., 1.);
double n = 2.0;
double c = 5.0;
double coeff;
double k = omega * sqrt(epsilon * mu);
real_t n = 2.0;
real_t c = 5.0;
real_t coeff;
real_t k = omega * sqrt(epsilon * mu);
// Stretch in each direction independently
for (int i = 0; i < dim; ++i)
@@ -1016,14 +1020,14 @@ void PML::StretchFunction(const Vector &x,
if (x(i) >= comp_domain_bdr(i, 1))
{
coeff = n * c / k / pow(length(i, 1), n);
dxs[i] = 1.0 + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 1), n - 1.0));
dxs[i] = 1_r + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 1), n - 1_r));
}
if (x(i) <= comp_domain_bdr(i, 0))
{
coeff = n * c / k / pow(length(i, 0), n);
dxs[i] = 1.0 + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 0), n - 1.0));
dxs[i] = 1_r + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 0), n - 1_r));
}
}
}
+120 -115
View File
@@ -52,13 +52,13 @@ private:
int dim;
// Length of the PML Region in each direction
Array2D<double> length;
Array2D<real_t> length;
// Computational Domain Boundary
Array2D<double> comp_dom_bdr;
Array2D<real_t> comp_dom_bdr;
// Domain Boundary
Array2D<double> dom_bdr;
Array2D<real_t> dom_bdr;
// Integer Array identifying elements in the PML
// 0: in the PML, 1: not in the PML
@@ -69,13 +69,13 @@ private:
public:
// Constructor
PML(Mesh *mesh_,Array2D<double> length_);
PML(Mesh *mesh_,Array2D<real_t> length_);
// Return Computational Domain Boundary
Array2D<double> GetCompDomainBdr() {return comp_dom_bdr;}
Array2D<real_t> GetCompDomainBdr() {return comp_dom_bdr;}
// Return Domain Boundary
Array2D<double> GetDomainBdr() {return dom_bdr;}
Array2D<real_t> GetDomainBdr() {return dom_bdr;}
// Return Markers list for elements
Array<int> * GetMarkedPMLElements() {return &elems;}
@@ -84,7 +84,7 @@ public:
void SetAttributes(ParMesh *pmesh);
// PML complex stretching function
void StretchFunction(const Vector &x, vector<complex<double>> &dxs);
void StretchFunction(const Vector &x, vector<complex<real_t>> &dxs);
};
// Class for returning the PML coefficients of the bilinear form
@@ -105,7 +105,7 @@ public:
virtual void Eval(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{
double x[3];
real_t x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
K.SetSize(vdim);
@@ -113,7 +113,7 @@ public:
}
};
void maxwell_solution(const Vector &x, vector<complex<double>> &Eval);
void maxwell_solution(const Vector &x, vector<complex<real_t>> &Eval);
void E_bdr_data_Re(const Vector &x, Vector &E);
void E_bdr_data_Im(const Vector &x, Vector &E);
@@ -133,15 +133,17 @@ void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector & D);
void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector & D);
void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector & D);
Array2D<double> comp_domain_bdr;
Array2D<double> domain_bdr;
Array2D<real_t> comp_domain_bdr;
Array2D<real_t> domain_bdr;
double mu = 1.0;
double epsilon = 1.0;
double omega;
real_t mu = 1.0;
real_t epsilon = 1.0;
real_t omega;
int dim;
bool exact_known = false;
template <typename T> T pow2(const T &x) { return x*x; }
enum prob_type
{
beam, // Wave propagating in a beam-like domain
@@ -166,7 +168,7 @@ int main(int argc, char *argv[])
int ref_levels = 1;
int par_ref_levels = 2;
int iprob = 4;
double freq = 5.0;
real_t freq = 5.0;
bool herm_conv = true;
bool slu_solver = false;
bool mumps_solver = false;
@@ -275,10 +277,10 @@ int main(int argc, char *argv[])
dim = mesh->Dimension();
// Angular frequency
omega = 2.0 * M_PI * freq;
omega = real_t(2.0 * M_PI) * freq;
// Setup PML length
Array2D<double> length(dim, 2); length = 0.0;
Array2D<real_t> length(dim, 2); length = 0.0;
// 5. Setup the Cartesian PML region.
switch (prob)
@@ -357,14 +359,15 @@ int main(int argc, char *argv[])
switch (prob)
{
case lshape:
if (center[0] == 1.0 || center[0] == 0.5 || center[1] == 0.5)
if (center[0] == 1_r || center[0] == 0.5_r ||
center[1] == 0.5_r)
{
ess_bdr[k - 1] = 1;
}
break;
case fichera:
if (center[0] == -1.0 || center[0] == 0.0 ||
center[1] == 0.0 || center[2] == 0.0)
if (center[0] == -1_r || center[0] == 0_r ||
center[1] == 0_r || center[2] == 0_r)
{
ess_bdr[k - 1] = 1;
}
@@ -423,8 +426,8 @@ int main(int argc, char *argv[])
}
}
ConstantCoefficient muinv(1.0/mu);
ConstantCoefficient omeg(-pow(omega, 2) * epsilon);
ConstantCoefficient muinv(1_r / mu);
ConstantCoefficient omeg(-pow2(omega) * epsilon);
RestrictedCoefficient restr_muinv(muinv,attr);
RestrictedCoefficient restr_omeg(omeg,attr);
@@ -520,7 +523,7 @@ int main(int argc, char *argv[])
// + omega^2 * epsilon (abs(det(J) * (J^T J)^-1) * E, F)
if (pa || (!slu_solver && !mumps_solver && !strumpack_solver))
{
ConstantCoefficient absomeg(pow(omega, 2) * epsilon);
ConstantCoefficient absomeg(pow2(omega) * epsilon);
RestrictedCoefficient restr_absomeg(absomeg,attr);
ParBilinearForm prec(fespace);
@@ -551,7 +554,7 @@ int main(int argc, char *argv[])
std::unique_ptr<Operator> pc_r;
std::unique_ptr<Operator> pc_i;
int s = (conv == ComplexOperator::HERMITIAN) ? -1.0 : 1.0;
int s = (conv == ComplexOperator::HERMITIAN) ? -1 : 1;
if (pa)
{
// Jacobi Smoother
@@ -599,14 +602,14 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double L2Error_Re = x.real().ComputeL2Error(E_ex_Re, irs,
real_t L2Error_Re = x.real().ComputeL2Error(E_ex_Re, irs,
pml->GetMarkedPMLElements());
double L2Error_Im = x.imag().ComputeL2Error(E_ex_Im, irs,
real_t L2Error_Im = x.imag().ComputeL2Error(E_ex_Im, irs,
pml->GetMarkedPMLElements());
ParComplexGridFunction x_gf0(fespace);
x_gf0 = 0.0;
double norm_E_Re, norm_E_Im;
real_t norm_E_Re, norm_E_Im;
norm_E_Re = x_gf0.real().ComputeL2Error(E_ex_Re, irs,
pml->GetMarkedPMLElements());
norm_E_Im = x_gf0.imag().ComputeL2Error(E_ex_Im, irs,
@@ -694,11 +697,12 @@ int main(int argc, char *argv[])
int i = 0;
while (sol_sock)
{
double t = (double)(i % num_frames) / num_frames;
real_t t = (real_t)(i % num_frames) / num_frames;
ostringstream oss;
oss << "Harmonic Solution (t = " << t << " T)";
add(cos(2.0*M_PI*t), x.real(), sin(2.0*M_PI*t), x.imag(), x_t);
add(cos(real_t(2.0*M_PI)*t), x.real(),
sin(real_t(2.0*M_PI)*t), x.imag(), x_t);
sol_sock << "parallel " << num_procs << " " << myid << "\n";
sol_sock << "solution\n" << *pmesh << x_t
<< "window_title '" << oss.str() << "'" << flush;
@@ -718,20 +722,20 @@ int main(int argc, char *argv[])
void source(const Vector &x, Vector &f)
{
Vector center(dim);
double r = 0.0;
real_t r = 0.0;
for (int i = 0; i < dim; ++i)
{
center(i) = 0.5 * (comp_domain_bdr(i, 0) + comp_domain_bdr(i, 1));
r += pow(x[i] - center[i], 2.);
center(i) = real_t(0.5) * (comp_domain_bdr(i, 0) + comp_domain_bdr(i, 1));
r += pow2(x[i] - center[i]);
}
double n = 5.0 * omega * sqrt(epsilon * mu) / M_PI;
double coeff = pow(n, 2) / M_PI;
double alpha = -pow(n, 2) * r;
real_t n = real_t(5) * omega * sqrt(epsilon * mu) / real_t(M_PI);
real_t coeff = pow2(n) / real_t(M_PI);
real_t alpha = -pow2(n) * r;
f = 0.0;
f[0] = coeff * exp(alpha);
}
void maxwell_solution(const Vector &x, vector<complex<double>> &E)
void maxwell_solution(const Vector &x, vector<complex<real_t>> &E)
{
// Initialize
for (int i = 0; i < dim; ++i)
@@ -739,8 +743,8 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
E[i] = 0.0;
}
complex<double> zi = complex<double>(0., 1.);
double k = omega * sqrt(epsilon * mu);
constexpr complex<real_t> zi = complex<real_t>(0., 1.);
real_t k = omega * sqrt(epsilon * mu);
switch (prob)
{
case disc:
@@ -755,58 +759,58 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
if (dim == 2)
{
double x0 = x(0) + shift(0);
double x1 = x(1) + shift(1);
double r = sqrt(x0 * x0 + x1 * x1);
double beta = k * r;
real_t x0 = x(0) + shift(0);
real_t x1 = x(1) + shift(1);
real_t r = sqrt(x0 * x0 + x1 * x1);
real_t beta = k * r;
// Bessel functions
complex<double> Ho, Ho_r, Ho_rr;
Ho = jn(0, beta) + zi * yn(0, beta);
Ho_r = -k * (jn(1, beta) + zi * yn(1, beta));
Ho_rr = -k * k * (1.0 / beta *
(jn(1, beta) + zi * yn(1, beta)) -
(jn(2, beta) + zi * yn(2, beta)));
complex<real_t> Ho, Ho_r, Ho_rr;
Ho = real_t(jn(0, beta)) + zi * real_t(yn(0, beta));
Ho_r = -k * (real_t(jn(1, beta)) + zi * real_t(yn(1, beta)));
Ho_rr = -k * k * (1_r / beta *
(real_t(jn(1, beta)) + zi * real_t(yn(1, beta))) -
(real_t(jn(2, beta)) + zi * real_t(yn(2, beta))));
// First derivatives
double r_x = x0 / r;
double r_y = x1 / r;
double r_xy = -(r_x / r) * r_y;
double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
real_t r_x = x0 / r;
real_t r_y = x1 / r;
real_t r_xy = -(r_x / r) * r_y;
real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
complex<double> val, val_xx, val_xy;
val = 0.25 * zi * Ho;
val_xx = 0.25 * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
val_xy = 0.25 * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
complex<real_t> val, val_xx, val_xy;
val = real_t(0.25) * zi * Ho;
val_xx = real_t(0.25) * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
val_xy = real_t(0.25) * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
E[0] = zi / k * (k * k * val + val_xx);
E[1] = zi / k * val_xy;
}
else if (dim == 3)
{
double x0 = x(0) + shift(0);
double x1 = x(1) + shift(1);
double x2 = x(2) + shift(2);
double r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
real_t x0 = x(0) + shift(0);
real_t x1 = x(1) + shift(1);
real_t x2 = x(2) + shift(2);
real_t r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
double r_x = x0 / r;
double r_y = x1 / r;
double r_z = x2 / r;
double r_xx = (1.0 / r) * (1.0 - r_x * r_x);
double r_yx = -(r_y / r) * r_x;
double r_zx = -(r_z / r) * r_x;
real_t r_x = x0 / r;
real_t r_y = x1 / r;
real_t r_z = x2 / r;
real_t r_xx = (1_r / r) * (1_r - r_x * r_x);
real_t r_yx = -(r_y / r) * r_x;
real_t r_zx = -(r_z / r) * r_x;
complex<double> val, val_r, val_rr;
complex<real_t> val, val_r, val_rr;
val = exp(zi * k * r) / r;
val_r = val / r * (zi * k * r - 1.0);
val_r = val / r * (zi * k * r - 1_r);
val_rr = val / (r * r) * (-k * k * r * r
- 2.0 * zi * k * r + 2.0);
- real_t(2) * zi * k * r + real_t(2));
complex<double> val_xx, val_yx, val_zx;
complex<real_t> val_xx, val_yx, val_zx;
val_xx = val_rr * r_x * r_x + val_r * r_xx;
val_yx = val_rr * r_x * r_y + val_r * r_yx;
val_zx = val_rr * r_x * r_z + val_r * r_zx;
complex<double> alpha = zi * k / 4.0 / M_PI / k / k;
complex<real_t> alpha = zi * k / real_t(4) / (real_t) M_PI / k / k;
E[0] = alpha * (k * k * val + val_xx);
E[1] = alpha * val_yx;
E[2] = alpha * val_zx;
@@ -818,12 +822,13 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
// T_10 mode
if (dim == 3)
{
double k10 = sqrt(k * k - M_PI * M_PI);
E[1] = -zi * k / M_PI * sin(M_PI*x(2))*exp(zi * k10 * x(0));
real_t k10 = sqrt(k * k - real_t(M_PI * M_PI));
E[1] = -zi * k / (real_t) M_PI *
sin((real_t) M_PI*x(2))*exp(zi * k10 * x(0));
}
else if (dim == 2)
{
E[1] = -zi * k / M_PI * exp(zi * k * x(0));
E[1] = -zi * k / (real_t) M_PI * exp(zi * k * x(0));
}
break;
}
@@ -834,7 +839,7 @@ void maxwell_solution(const Vector &x, vector<complex<double>> &E)
void E_exact_Re(const Vector &x, Vector &E)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -844,7 +849,7 @@ void E_exact_Re(const Vector &x, Vector &E)
void E_exact_Im(const Vector &x, Vector &E)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -860,8 +865,8 @@ void E_bdr_data_Re(const Vector &x, Vector &E)
for (int i = 0; i < dim; ++i)
{
// check if in PML
if (x(i) - comp_domain_bdr(i, 0) < 0.0 ||
x(i) - comp_domain_bdr(i, 1) > 0.0)
if (x(i) - comp_domain_bdr(i, 0) < 0_r ||
x(i) - comp_domain_bdr(i, 1) > 0_r)
{
in_pml = true;
break;
@@ -869,7 +874,7 @@ void E_bdr_data_Re(const Vector &x, Vector &E)
}
if (!in_pml)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -887,8 +892,8 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
for (int i = 0; i < dim; ++i)
{
// check if in PML
if (x(i) - comp_domain_bdr(i, 0) < 0.0 ||
x(i) - comp_domain_bdr(i, 1) > 0.0)
if (x(i) - comp_domain_bdr(i, 0) < 0_r ||
x(i) - comp_domain_bdr(i, 1) > 0_r)
{
in_pml = true;
break;
@@ -896,7 +901,7 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
}
if (!in_pml)
{
vector<complex<double>> Eval(E.Size());
vector<complex<real_t>> Eval(E.Size());
maxwell_solution(x, Eval);
for (int i = 0; i < dim; ++i)
{
@@ -907,8 +912,8 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
void detJ_JT_J_inv_Re(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
vector<complex<real_t>> dxs(dim);
complex<real_t> det(1.0, 0.0);
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -918,14 +923,14 @@ void detJ_JT_J_inv_Re(const Vector &x, PML * pml, Vector & D)
for (int i = 0; i < dim; ++i)
{
D(i) = (det / pow(dxs[i], 2)).real();
D(i) = (det / pow2(dxs[i])).real();
}
}
void detJ_JT_J_inv_Im(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -935,14 +940,14 @@ void detJ_JT_J_inv_Im(const Vector &x, PML * pml, Vector & D)
for (int i = 0; i < dim; ++i)
{
D(i) = (det / pow(dxs[i], 2)).imag();
D(i) = (det / pow2(dxs[i])).imag();
}
}
void detJ_JT_J_inv_abs(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -952,14 +957,14 @@ void detJ_JT_J_inv_abs(const Vector &x, PML * pml, Vector & D)
for (int i = 0; i < dim; ++i)
{
D(i) = abs(det / pow(dxs[i], 2));
D(i) = abs(det / pow2(dxs[i]));
}
}
void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
vector<complex<real_t>> dxs(dim);
complex<real_t> det(1.0, 0.0);
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -970,21 +975,21 @@ void detJ_inv_JT_J_Re(const Vector &x, PML * pml, Vector & D)
// in the 2D case the coefficient is scalar 1/det(J)
if (dim == 2)
{
D = (1.0 / det).real();
D = (1_r / det).real();
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = (pow(dxs[i], 2) / det).real();
D(i) = (pow2(dxs[i]) / det).real();
}
}
}
void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -994,21 +999,21 @@ void detJ_inv_JT_J_Im(const Vector &x, PML * pml, Vector & D)
if (dim == 2)
{
D = (1.0 / det).imag();
D = (1_r / det).imag();
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = (pow(dxs[i], 2) / det).imag();
D(i) = (pow2(dxs[i]) / det).imag();
}
}
}
void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
vector<complex<real_t>> dxs(dim);
complex<real_t> det = 1.0;
pml->StretchFunction(x, dxs);
for (int i = 0; i < dim; ++i)
@@ -1018,18 +1023,18 @@ void detJ_inv_JT_J_abs(const Vector &x, PML * pml, Vector & D)
if (dim == 2)
{
D = abs(1.0 / det);
D = abs(1_r / det);
}
else
{
for (int i = 0; i < dim; ++i)
{
D(i) = abs(pow(dxs[i], 2) / det);
D(i) = abs(pow2(dxs[i]) / det);
}
}
}
PML::PML(Mesh *mesh_, Array2D<double> length_)
PML::PML(Mesh *mesh_, Array2D<real_t> length_)
: mesh(mesh_), length(length_)
{
dim = mesh->Dimension();
@@ -1081,7 +1086,7 @@ void PML::SetAttributes(ParMesh *pmesh)
for (int iv = 0; iv < nrvert; ++iv)
{
int vert_idx = vertices[iv];
double *coords = pmesh->GetVertex(vert_idx);
real_t *coords = pmesh->GetVertex(vert_idx);
for (int comp = 0; comp < dim; ++comp)
{
if (coords[comp] > comp_dom_bdr(comp, 1) ||
@@ -1102,14 +1107,14 @@ void PML::SetAttributes(ParMesh *pmesh)
}
void PML::StretchFunction(const Vector &x,
vector<complex<double>> &dxs)
vector<complex<real_t>> &dxs)
{
complex<double> zi = complex<double>(0., 1.);
constexpr complex<real_t> zi = complex<real_t>(0., 1.);
double n = 2.0;
double c = 5.0;
double coeff;
double k = omega * sqrt(epsilon * mu);
real_t n = 2.0;
real_t c = 5.0;
real_t coeff;
real_t k = omega * sqrt(epsilon * mu);
// Stretch in each direction independently
for (int i = 0; i < dim; ++i)
@@ -1118,14 +1123,14 @@ void PML::StretchFunction(const Vector &x,
if (x(i) >= comp_domain_bdr(i, 1))
{
coeff = n * c / k / pow(length(i, 1), n);
dxs[i] = 1.0 + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 1), n - 1.0));
dxs[i] = 1_r + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 1), n - 1_r));
}
if (x(i) <= comp_domain_bdr(i, 0))
{
coeff = n * c / k / pow(length(i, 0), n);
dxs[i] = 1.0 + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 0), n - 1.0));
dxs[i] = 1_r + zi * coeff *
abs(pow(x(i) - comp_domain_bdr(i, 0), n - 1_r));
}
}
}
+32 -32
View File
@@ -63,7 +63,7 @@
using namespace std;
using namespace mfem;
static double a_ = 0.2;
static real_t a_ = 0.2;
// Normal to hole with boundary attribute 4
void n4Vec(const Vector &x, Vector &n) { n = x; n[0] -= 0.5; n /= -n.Norml2(); }
@@ -73,25 +73,25 @@ Mesh * GenerateSerialMesh(int ref);
// Compute the average value of alpha*n.Grad(sol) + beta*sol over the boundary
// attributes marked in bdr_marker. Also computes the L2 norm of
// alpha*n.Grad(sol) + beta*sol - gamma over the same boundary.
double IntegrateBC(const GridFunction &sol, const Array<int> &bdr_marker,
double alpha, double beta, double gamma,
double &error);
real_t IntegrateBC(const GridFunction &sol, const Array<int> &bdr_marker,
real_t alpha, real_t beta, real_t gamma,
real_t &error);
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
int ser_ref_levels = 2;
int order = 1;
double sigma = -1.0;
double kappa = -1.0;
real_t sigma = -1.0;
real_t kappa = -1.0;
bool h1 = true;
bool visualization = true;
double mat_val = 1.0;
double dbc_val = 0.0;
double nbc_val = 1.0;
double rbc_a_val = 1.0; // du/dn + a * u = b
double rbc_b_val = 1.0;
real_t mat_val = 1.0;
real_t dbc_val = 0.0;
real_t nbc_val = 1.0;
real_t rbc_a_val = 1.0; // du/dn + a * u = b
real_t rbc_b_val = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&h1, "-h1", "--continuous", "-dg", "--discontinuous",
@@ -302,7 +302,7 @@ int main(int argc, char *argv[])
{
// Integrate the solution on the Dirichlet boundary and compare to the
// expected value.
double error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
real_t error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
bool hom_dbc = (dbc_val == 0.0);
error /= hom_dbc ? 1.0 : fabs(dbc_val);
@@ -314,7 +314,7 @@ int main(int argc, char *argv[])
{
// Integrate n.Grad(u) on the inhomogeneous Neumann boundary and compare
// to the expected value.
double error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
real_t error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
bool hom_nbc = (nbc_val == 0.0);
error /= hom_nbc ? 1.0 : fabs(nbc_val);
@@ -330,7 +330,7 @@ int main(int argc, char *argv[])
nbc0_bdr = 0;
nbc0_bdr[3] = 1;
double error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
real_t error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
bool hom_nbc = true;
mfem::out << "Average of n.Grad(u) on Gamma_nbc0:\t"
@@ -341,8 +341,8 @@ int main(int argc, char *argv[])
{
// Integrate n.Grad(u) + a * u on the Robin boundary and compare to the
// expected value.
double error;
double avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, error);
real_t error;
real_t avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, error);
bool hom_rbc = (rbc_b_val == 0.0);
error /= hom_rbc ? 1.0 : fabs(rbc_b_val);
@@ -383,22 +383,22 @@ int main(int argc, char *argv[])
return 0;
}
void quad_trans(double u, double v, double &x, double &y, bool log = false)
void quad_trans(real_t u, real_t v, real_t &x, real_t &y, bool log = false)
{
double a = a_; // Radius of disc
real_t a = a_; // Radius of disc
double d = 4.0 * a * (M_SQRT2 - 2.0 * a) * (1.0 - 2.0 * v);
real_t d = 4.0 * a * (M_SQRT2 - 2.0 * a) * (1.0 - 2.0 * v);
double v0 = (1.0 + M_SQRT2) * (M_SQRT2 * a - 2.0 * v) *
real_t v0 = (1.0 + M_SQRT2) * (M_SQRT2 * a - 2.0 * v) *
((4.0 - 3 * M_SQRT2) * a +
(8.0 * (M_SQRT2 - 1.0) * a - 2.0) * v) / d;
double r = 2.0 * ((M_SQRT2 - 1.0) * a * a * (1.0 - 4.0 *v) +
real_t r = 2.0 * ((M_SQRT2 - 1.0) * a * a * (1.0 - 4.0 *v) +
2.0 * (1.0 + M_SQRT2 *
(1.0 + 2.0 * (2.0 * a - M_SQRT2 - 1.0) * a)) * v * v
) / d;
double t = asin(v / r) * u / v;
real_t t = asin(v / r) * u / v;
if (log)
{
mfem::out << "u, v, r, v0, t "
@@ -411,7 +411,7 @@ void quad_trans(double u, double v, double &x, double &y, bool log = false)
void trans(const Vector &u, Vector &x)
{
double tol = 1e-4;
real_t tol = 1e-4;
if (u[1] > 0.5 - tol || u[1] < -0.5 + tol)
{
@@ -542,8 +542,8 @@ Mesh * GenerateSerialMesh(int ref)
vi[0] = o + 3; vi[1] = o + 4; mesh->AddBdrSegment(vi, 3 + i);
}
double d[2];
double a = a_ / M_SQRT2;
real_t d[2];
real_t a = a_ / M_SQRT2;
d[0] = -1.0; d[1] = -0.5; mesh->AddVertex(d);
d[0] = -1.0; d[1] = 0.0; mesh->AddVertex(d);
@@ -636,12 +636,12 @@ Mesh * GenerateSerialMesh(int ref)
return mesh;
}
double IntegrateBC(const GridFunction &x, const Array<int> &bdr,
double alpha, double beta, double gamma,
double &error)
real_t IntegrateBC(const GridFunction &x, const Array<int> &bdr,
real_t alpha, real_t beta, real_t gamma,
real_t &error)
{
double nrm = 0.0;
double avg = 0.0;
real_t nrm = 0.0;
real_t avg = 0.0;
error = 0.0;
const bool a_is_zero = alpha == 0.0;
@@ -683,8 +683,8 @@ double IntegrateBC(const GridFunction &x, const Array<int> &bdr,
IntegrationPoint eip;
FTr->Loc1.Transform(ip, eip);
FTr->Face->SetIntPoint(&ip);
double face_weight = FTr->Face->Weight();
double val = 0.0;
real_t face_weight = FTr->Face->Weight();
real_t val = 0.0;
if (!a_is_zero)
{
FTr->Elem1->SetIntPoint(&eip);
+38 -37
View File
@@ -63,7 +63,7 @@
using namespace std;
using namespace mfem;
static double a_ = 0.2;
static real_t a_ = 0.2;
// Normal to hole with boundary attribute 4
void n4Vec(const Vector &x, Vector &n) { n = x; n[0] -= 0.5; n /= -n.Norml2(); }
@@ -73,9 +73,9 @@ Mesh * GenerateSerialMesh(int ref);
// Compute the average value of alpha*n.Grad(sol) + beta*sol over the boundary
// attributes marked in bdr_marker. Also computes the L2 norm of
// alpha*n.Grad(sol) + beta*sol - gamma over the same boundary.
double IntegrateBC(const ParGridFunction &sol, const Array<int> &bdr_marker,
double alpha, double beta, double gamma,
double &error);
real_t IntegrateBC(const ParGridFunction &sol, const Array<int> &bdr_marker,
real_t alpha, real_t beta, real_t gamma,
real_t &error);
int main(int argc, char *argv[])
{
@@ -88,16 +88,16 @@ int main(int argc, char *argv[])
int ser_ref_levels = 2;
int par_ref_levels = 1;
int order = 1;
double sigma = -1.0;
double kappa = -1.0;
real_t sigma = -1.0;
real_t kappa = -1.0;
bool h1 = true;
bool visualization = true;
double mat_val = 1.0;
double dbc_val = 0.0;
double nbc_val = 1.0;
double rbc_a_val = 1.0; // du/dn + a * u = b
double rbc_b_val = 1.0;
real_t mat_val = 1.0;
real_t dbc_val = 0.0;
real_t nbc_val = 1.0;
real_t rbc_a_val = 1.0; // du/dn + a * u = b
real_t rbc_b_val = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&h1, "-h1", "--continuous", "-dg", "--discontinuous",
@@ -322,7 +322,7 @@ int main(int argc, char *argv[])
{
// Integrate the solution on the Dirichlet boundary and compare to the
// expected value.
double error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
real_t error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
bool hom_dbc = (dbc_val == 0.0);
error /= hom_dbc ? 1.0 : fabs(dbc_val);
@@ -334,7 +334,7 @@ int main(int argc, char *argv[])
{
// Integrate n.Grad(u) on the inhomogeneous Neumann boundary and compare
// to the expected value.
double error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
real_t error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
bool hom_nbc = (nbc_val == 0.0);
error /= hom_nbc ? 1.0 : fabs(nbc_val);
@@ -350,7 +350,7 @@ int main(int argc, char *argv[])
nbc0_bdr = 0;
nbc0_bdr[3] = 1;
double error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
real_t error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
bool hom_nbc = true;
mfem::out << "Average of n.Grad(u) on Gamma_nbc0:\t"
@@ -361,7 +361,7 @@ int main(int argc, char *argv[])
{
// Integrate n.Grad(u) + a * u on the Robin boundary and compare to the
// expected value.
double error, avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val,
real_t error, avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val,
error);
bool hom_rbc = (rbc_b_val == 0.0);
@@ -409,22 +409,22 @@ int main(int argc, char *argv[])
return 0;
}
void quad_trans(double u, double v, double &x, double &y, bool log = false)
void quad_trans(real_t u, real_t v, real_t &x, real_t &y, bool log = false)
{
double a = a_; // Radius of disc
real_t a = a_; // Radius of disc
double d = 4.0 * a * (M_SQRT2 - 2.0 * a) * (1.0 - 2.0 * v);
real_t d = 4.0 * a * (M_SQRT2 - 2.0 * a) * (1.0 - 2.0 * v);
double v0 = (1.0 + M_SQRT2) * (M_SQRT2 * a - 2.0 * v) *
real_t v0 = (1.0 + M_SQRT2) * (M_SQRT2 * a - 2.0 * v) *
((4.0 - 3 * M_SQRT2) * a +
(8.0 * (M_SQRT2 - 1.0) * a - 2.0) * v) / d;
double r = 2.0 * ((M_SQRT2 - 1.0) * a * a * (1.0 - 4.0 *v) +
real_t r = 2.0 * ((M_SQRT2 - 1.0) * a * a * (1.0 - 4.0 *v) +
2.0 * (1.0 + M_SQRT2 *
(1.0 + 2.0 * (2.0 * a - M_SQRT2 - 1.0) * a)) * v * v
) / d;
double t = asin(v / r) * u / v;
real_t t = asin(v / r) * u / v;
if (log)
{
mfem::out << "u, v, r, v0, t "
@@ -437,7 +437,7 @@ void quad_trans(double u, double v, double &x, double &y, bool log = false)
void trans(const Vector &u, Vector &x)
{
double tol = 1e-4;
real_t tol = 1e-4;
if (u[1] > 0.5 - tol || u[1] < -0.5 + tol)
{
@@ -568,8 +568,8 @@ Mesh * GenerateSerialMesh(int ref)
vi[0] = o + 3; vi[1] = o + 4; mesh->AddBdrSegment(vi, 3 + i);
}
double d[2];
double a = a_ / M_SQRT2;
real_t d[2];
real_t a = a_ / M_SQRT2;
d[0] = -1.0; d[1] = -0.5; mesh->AddVertex(d);
d[0] = -1.0; d[1] = 0.0; mesh->AddVertex(d);
@@ -662,14 +662,14 @@ Mesh * GenerateSerialMesh(int ref)
return mesh;
}
double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
double alpha, double beta, double gamma,
double &glb_err)
real_t IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
real_t alpha, real_t beta, real_t gamma,
real_t &glb_err)
{
double loc_vals[3];
double &nrm = loc_vals[0];
double &avg = loc_vals[1];
double &error = loc_vals[2];
real_t loc_vals[3];
real_t &nrm = loc_vals[0];
real_t &avg = loc_vals[1];
real_t &error = loc_vals[2];
nrm = 0.0;
avg = 0.0;
@@ -714,8 +714,8 @@ double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
IntegrationPoint eip;
FTr->Loc1.Transform(ip, eip);
FTr->Face->SetIntPoint(&ip);
double face_weight = FTr->Face->Weight();
double val = 0.0;
real_t face_weight = FTr->Face->Weight();
real_t val = 0.0;
if (!a_is_zero)
{
FTr->Elem1->SetIntPoint(&eip);
@@ -741,11 +741,12 @@ double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
}
}
double glb_vals[3];
MPI_Allreduce(loc_vals, glb_vals, 3, MPI_DOUBLE, MPI_SUM, fes.GetComm());
real_t glb_vals[3];
MPI_Allreduce(loc_vals, glb_vals, 3, MPITypeMap<real_t>::mpi_type,
MPI_SUM, fes.GetComm());
double glb_nrm = glb_vals[0];
double glb_avg = glb_vals[1];
real_t glb_nrm = glb_vals[0];
real_t glb_avg = glb_vals[1];
glb_err = glb_vals[2];
// Normalize by the length of the boundary
+3 -3
View File
@@ -35,7 +35,7 @@ using namespace mfem;
// Return a mesh with a single element with vertices (0, 0), (1, 0), (1, 1),
// (offset, 1) to demonstrate boundary conditions on a surface that is not
// axis-aligned.
Mesh * build_trapezoid_mesh(double offset)
Mesh * build_trapezoid_mesh(real_t offset)
{
MFEM_VERIFY(offset < 0.9, "offset is too large!");
@@ -45,7 +45,7 @@ Mesh * build_trapezoid_mesh(double offset)
Mesh * mesh = new Mesh(dimension, nvt, 1, nbe);
// vertices
double vc[dimension];
real_t vc[dimension];
vc[0] = 0.0; vc[1] = 0.0;
mesh->AddVertex(vc);
vc[0] = 1.0; vc[1] = 0.0;
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
// 1. Parse command-line options.
int order = 1;
bool visualization = 1;
double offset = 0.3;
real_t offset = 0.3;
bool visit = false;
OptionsParser args(argc, argv);
+5 -5
View File
@@ -38,7 +38,7 @@ using namespace mfem;
// Return a mesh with a single element with vertices (0, 0), (1, 0), (1, 1),
// (offset, 1) to demonstrate boundary conditions on a surface that is not
// axis-aligned.
Mesh * build_trapezoid_mesh(double offset)
Mesh * build_trapezoid_mesh(real_t offset)
{
MFEM_VERIFY(offset < 0.9, "offset is too large!");
@@ -48,7 +48,7 @@ Mesh * build_trapezoid_mesh(double offset)
Mesh * mesh = new Mesh(dimension, nvt, 1, nbe);
// vertices
double vc[dimension];
real_t vc[dimension];
vc[0] = 0.0; vc[1] = 0.0;
mesh->AddVertex(vc);
vc[0] = 1.0; vc[1] = 0.0;
@@ -84,7 +84,7 @@ int main(int argc, char *argv[])
#ifdef HYPRE_USING_GPU
cout << "\nAs of mfem-4.3 and hypre-2.22.0 (July 2021) this example\n"
<< "is NOT supported with the GPU version of hypre.\n\n";
return 242;
return MFEM_SKIP_RETURN_VALUE;
#endif
// 1. Initialize MPI and HYPRE.
@@ -97,9 +97,9 @@ int main(int argc, char *argv[])
int order = 1;
bool visualization = 1;
bool reorder_space = false;
double offset = 0.3;
real_t offset = 0.3;
bool visit = false;
double penalty = 0.0;
real_t penalty = 0.0;
OptionsParser args(argc, argv);
args.AddOption(&order, "-o", "--order",
+6 -6
View File
@@ -34,7 +34,7 @@ void trans(const Vector &x, Vector &r);
void sigmaFunc(const Vector &x, DenseMatrix &s);
double uExact(const Vector &x)
real_t uExact(const Vector &x)
{
return (0.25 * (2.0 + x[0]) - x[2]) * (x[2] + 0.25 * (2.0 + x[0]));
}
@@ -167,7 +167,7 @@ int main(int argc, char *argv[])
// 13. Compute error in the solution and its flux
FunctionCoefficient uCoef(uExact);
double error = x.ComputeL2Error(uCoef);
real_t error = x.ComputeL2Error(uCoef);
cout << "|u - u_h|_2 = " << error << endl;
@@ -176,7 +176,7 @@ int main(int argc, char *argv[])
x.ComputeFlux(*integ, flux); flux *= -1.0;
VectorFunctionCoefficient fluxCoef(3, fluxExact);
double flux_err = flux.ComputeL2Error(fluxCoef);
real_t flux_err = flux.ComputeL2Error(fluxCoef);
cout << "|f - f_h|_2 = " << flux_err << endl;
@@ -304,8 +304,8 @@ void trans(const Vector &x, Vector &r)
{
r.SetSize(3);
double tol = 1e-6;
double theta = 0.0;
real_t tol = 1e-6;
real_t theta = 0.0;
if (fabs(x[1] + 1.0) < tol)
{
theta = 0.25 * M_PI * (x[0] - 2.0);
@@ -337,7 +337,7 @@ void trans(const Vector &x, Vector &r)
void sigmaFunc(const Vector &x, DenseMatrix &s)
{
s.SetSize(3);
double a = 17.0 - 2.0 * x[0] * (1.0 + x[0]);
real_t a = 17.0 - 2.0 * x[0] * (1.0 + x[0]);
s(0,0) = 0.5 + x[0] * x[0] * (8.0 / a - 0.5);
s(0,1) = x[0] * x[1] * (8.0 / a - 0.5);
s(0,2) = 0.0;
+6 -6
View File
@@ -34,7 +34,7 @@ void trans(const Vector &x, Vector &r);
void sigmaFunc(const Vector &x, DenseMatrix &s);
double uExact(const Vector &x)
real_t uExact(const Vector &x)
{
return (0.25 * (2.0 + x[0]) - x[2]) * (x[2] + 0.25 * (2.0 + x[0]));
}
@@ -201,7 +201,7 @@ int main(int argc, char *argv[])
// 15. Compute error in the solution and its flux
FunctionCoefficient uCoef(uExact);
double error = x.ComputeL2Error(uCoef);
real_t error = x.ComputeL2Error(uCoef);
if (myid == 0) { cout << "|u - u_h|_2 = " << error << endl; }
@@ -210,7 +210,7 @@ int main(int argc, char *argv[])
x.ComputeFlux(*integ, flux); flux *= -1.0;
VectorFunctionCoefficient fluxCoef(3, fluxExact);
double flux_err = flux.ComputeL2Error(fluxCoef);
real_t flux_err = flux.ComputeL2Error(fluxCoef);
if (myid == 0) { cout << "|f - f_h|_2 = " << flux_err << endl; }
@@ -349,8 +349,8 @@ void trans(const Vector &x, Vector &r)
{
r.SetSize(3);
double tol = 1e-6;
double theta = 0.0;
real_t tol = 1e-6;
real_t theta = 0.0;
if (fabs(x[1] + 1.0) < tol)
{
theta = 0.25 * M_PI * (x[0] - 2.0);
@@ -382,7 +382,7 @@ void trans(const Vector &x, Vector &r)
void sigmaFunc(const Vector &x, DenseMatrix &s)
{
s.SetSize(3);
double a = 17.0 - 2.0 * x[0] * (1.0 + x[0]);
real_t a = 17.0 - 2.0 * x[0] * (1.0 + x[0]);
s(0,0) = 0.5 + x[0] * x[0] * (8.0 / a - 0.5);
s(0,1) = x[0] * x[1] * (8.0 / a - 0.5);
s(0,2) = 0.0;
+1 -1
View File
@@ -53,7 +53,7 @@ using namespace mfem;
// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int dim;
int main(int argc, char *argv[])
+14 -14
View File
@@ -42,9 +42,9 @@ using namespace std;
using namespace mfem;
// Piecewise-affine function which is sometimes mesh-conforming
double affine_function(const Vector &p)
real_t affine_function(const Vector &p)
{
double x = p(0), y = p(1);
real_t x = p(0), y = p(1);
if (x < 0.0)
{
return 1.0 + x + y;
@@ -56,7 +56,7 @@ double affine_function(const Vector &p)
}
// Piecewise-constant function which is never mesh-conforming
double jump_function(const Vector &p)
real_t jump_function(const Vector &p)
{
if (p.Normlp(2.0) > 0.4 && p.Normlp(2.0) < 0.6)
{
@@ -70,17 +70,17 @@ double jump_function(const Vector &p)
// Singular function derived from the Laplacian of the "steep wavefront" problem
// in [2].
double singular_function(const Vector &p)
real_t singular_function(const Vector &p)
{
double x = p(0), y = p(1);
double alpha = 1000.0;
double xc = 0.75, yc = 0.5;
double r0 = 0.7;
double r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
double num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
double denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
real_t x = p(0), y = p(1);
real_t alpha = 1000.0;
real_t xc = 0.75, yc = 0.5;
real_t r0 = 0.7;
real_t r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
real_t num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
real_t denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
- 2 * pow(alpha,2) * r0 * r + 1.0 ),2);
denom = max(denom,1e-8);
denom = std::max(denom, (real_t) 1.0e-8);
return num / denom;
}
@@ -91,9 +91,9 @@ int main(int argc, char *argv[])
int order = 1;
int nc_limit = 1;
int max_elems = 100*1000;
double double_max_elems = double(max_elems);
real_t double_max_elems = real_t(max_elems);
bool visualization = true;
double osc_threshold = 1e-3;
real_t osc_threshold = 1e-3;
int enriched_order = 5;
OptionsParser args(argc, argv);
+15 -15
View File
@@ -42,9 +42,9 @@ using namespace std;
using namespace mfem;
// Piecewise-affine function which is sometimes mesh-conforming
double affine_function(const Vector &p)
real_t affine_function(const Vector &p)
{
double x = p(0), y = p(1);
real_t x = p(0), y = p(1);
if (x < 0.0)
{
return 1.0 + x + y;
@@ -56,7 +56,7 @@ double affine_function(const Vector &p)
}
// Piecewise-constant function which is never mesh-conforming
double jump_function(const Vector &p)
real_t jump_function(const Vector &p)
{
if (p.Normlp(2.0) > 0.4 && p.Normlp(2.0) < 0.6)
{
@@ -70,17 +70,17 @@ double jump_function(const Vector &p)
// Singular function derived from the Laplacian of the "steep wavefront" problem
// in [2].
double singular_function(const Vector &p)
real_t singular_function(const Vector &p)
{
double x = p(0), y = p(1);
double alpha = 1000.0;
double xc = 0.75, yc = 0.5;
double r0 = 0.7;
double r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
double num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
double denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
real_t x = p(0), y = p(1);
real_t alpha = 1000.0;
real_t xc = 0.75, yc = 0.5;
real_t r0 = 0.7;
real_t r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
real_t num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
real_t denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
- 2 * pow(alpha,2) * r0 * r + 1.0 ),2);
denom = max(denom,1e-8);
denom = std::max(denom, (real_t) 1.0e-8);
return num / denom;
}
@@ -97,10 +97,10 @@ int main(int argc, char *argv[])
int order = 1;
int nc_limit = 1;
int max_elems = 1e5;
double double_max_elems = double(max_elems);
real_t double_max_elems = real_t(max_elems);
bool visualization = true;
bool nc_simplices = true;
double osc_threshold = 1e-3;
real_t osc_threshold = 1e-3;
int enriched_order = 5;
OptionsParser args(argc, argv);
@@ -199,7 +199,7 @@ int main(int argc, char *argv[])
coeffrefiner.PreprocessMesh(pmesh);
int globalNE = pmesh.GetGlobalNE();
double osc = coeffrefiner.GetOsc();
real_t osc = coeffrefiner.GetOsc();
if (myid == 0)
{
mfem::out << "\n";
+28 -28
View File
@@ -39,7 +39,7 @@ using namespace mfem;
void E_exact(const Vector &, Vector &);
void CurlE_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int dim;
int main(int argc, char *argv[])
@@ -177,7 +177,7 @@ int main(int argc, char *argv[])
// 13. Compute and print the H(Curl) norm of the error.
{
double error = sol.ComputeHCurlError(&E, &CurlE);
real_t error = sol.ComputeHCurlError(&E, &CurlE);
cout << "\n|| E_h - E ||_{H(Curl)} = " << error << '\n' << endl;
}
@@ -376,8 +376,8 @@ void CurlE_exact(const Vector &x, Vector &dE)
{
if (dim == 1)
{
double c4 = cos(kappa * x(0) + 0.4 * M_PI);
double c9 = cos(kappa * x(0) + 0.9 * M_PI);
real_t c4 = cos(kappa * x(0) + 0.4 * M_PI);
real_t c9 = cos(kappa * x(0) + 0.9 * M_PI);
dE(0) = 0.0;
dE(1) = -1.3 * c9;
@@ -386,9 +386,9 @@ void CurlE_exact(const Vector &x, Vector &dE)
}
else if (dim == 2)
{
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
dE(0) = 1.3 * c9;
dE(1) = -1.3 * c9;
@@ -397,13 +397,13 @@ void CurlE_exact(const Vector &x, Vector &dE)
}
else
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double sk = sin(kappa * x(2));
double ck = cos(kappa * x(2));
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t sk = sin(kappa * x(2));
real_t ck = cos(kappa * x(2));
dE(0) = 1.2 * s4 * sk + 1.3 * M_SQRT1_2 * c9 * ck;
dE(1) = -1.1 * s0 * sk - 1.3 * M_SQRT1_2 * c9 * ck;
@@ -416,9 +416,9 @@ void f_exact(const Vector &x, Vector &f)
{
if (dim == 1)
{
double s0 = sin(kappa * x(0) + 0.0 * M_PI);
double s4 = sin(kappa * x(0) + 0.4 * M_PI);
double s9 = sin(kappa * x(0) + 0.9 * M_PI);
real_t s0 = sin(kappa * x(0) + 0.0 * M_PI);
real_t s4 = sin(kappa * x(0) + 0.4 * M_PI);
real_t s9 = sin(kappa * x(0) + 0.9 * M_PI);
f(0) = 2.2 * s0 + 1.2 * M_SQRT1_2 * s4;
f(1) = 1.2 * (2.0 + kappa * kappa) * s4 +
@@ -427,9 +427,9 @@ void f_exact(const Vector &x, Vector &f)
}
else if (dim == 2)
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
f(0) = 0.55 * (4.0 + kappa * kappa) * s0 +
0.6 * (M_SQRT2 - kappa * kappa) * s4;
@@ -440,14 +440,14 @@ void f_exact(const Vector &x, Vector &f)
}
else
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double sk = sin(kappa * x(2));
double ck = cos(kappa * x(2));
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t sk = sin(kappa * x(2));
real_t ck = cos(kappa * x(2));
f(0) = 0.55 * (4.0 + 3.0 * kappa * kappa) * s0 * ck +
0.6 * (M_SQRT2 - kappa * kappa) * s4 * ck -
+28 -28
View File
@@ -39,7 +39,7 @@ using namespace mfem;
void E_exact(const Vector &, Vector &);
void CurlE_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int dim;
int main(int argc, char *argv[])
@@ -224,7 +224,7 @@ int main(int argc, char *argv[])
// 14. Compute and print the H(Curl) norm of the error.
{
double error = sol.ComputeHCurlError(&E, &CurlE);
real_t error = sol.ComputeHCurlError(&E, &CurlE);
if (Mpi::Root())
{
cout << "\n|| E_h - E ||_{H(Curl)} = " << error << '\n' << endl;
@@ -442,8 +442,8 @@ void CurlE_exact(const Vector &x, Vector &dE)
{
if (dim == 1)
{
double c4 = cos(kappa * x(0) + 0.4 * M_PI);
double c9 = cos(kappa * x(0) + 0.9 * M_PI);
real_t c4 = cos(kappa * x(0) + 0.4 * M_PI);
real_t c9 = cos(kappa * x(0) + 0.9 * M_PI);
dE(0) = 0.0;
dE(1) = -1.3 * c9;
@@ -452,9 +452,9 @@ void CurlE_exact(const Vector &x, Vector &dE)
}
else if (dim == 2)
{
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
dE(0) = 1.3 * c9;
dE(1) = -1.3 * c9;
@@ -463,13 +463,13 @@ void CurlE_exact(const Vector &x, Vector &dE)
}
else
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double sk = sin(kappa * x(2));
double ck = cos(kappa * x(2));
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t sk = sin(kappa * x(2));
real_t ck = cos(kappa * x(2));
dE(0) = 1.2 * s4 * sk + 1.3 * M_SQRT1_2 * c9 * ck;
dE(1) = -1.1 * s0 * sk - 1.3 * M_SQRT1_2 * c9 * ck;
@@ -482,9 +482,9 @@ void f_exact(const Vector &x, Vector &f)
{
if (dim == 1)
{
double s0 = sin(kappa * x(0) + 0.0 * M_PI);
double s4 = sin(kappa * x(0) + 0.4 * M_PI);
double s9 = sin(kappa * x(0) + 0.9 * M_PI);
real_t s0 = sin(kappa * x(0) + 0.0 * M_PI);
real_t s4 = sin(kappa * x(0) + 0.4 * M_PI);
real_t s9 = sin(kappa * x(0) + 0.9 * M_PI);
f(0) = 2.2 * s0 + 1.2 * M_SQRT1_2 * s4;
f(1) = 1.2 * (2.0 + kappa * kappa) * s4 +
@@ -493,9 +493,9 @@ void f_exact(const Vector &x, Vector &f)
}
else if (dim == 2)
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
f(0) = 0.55 * (4.0 + kappa * kappa) * s0 +
0.6 * (M_SQRT2 - kappa * kappa) * s4;
@@ -506,14 +506,14 @@ void f_exact(const Vector &x, Vector &f)
}
else
{
double s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
double s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
double s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
double sk = sin(kappa * x(2));
double ck = cos(kappa * x(2));
real_t s0 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t c0 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.0 * M_PI);
real_t s4 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t c4 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.4 * M_PI);
real_t s9 = sin(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t c9 = cos(kappa * M_SQRT1_2 * (x(0) + x(1)) + 0.9 * M_PI);
real_t sk = sin(kappa * x(2));
real_t ck = cos(kappa * x(2));
f(0) = 0.55 * (4.0 + 3.0 * kappa * kappa) * s0 * ck +
0.6 * (M_SQRT2 - kappa * kappa) * s4 * ck -
+18 -18
View File
@@ -35,8 +35,8 @@
using namespace std;
using namespace mfem;
double GetVectorMax(int vdim, const ParGridFunction &x);
double GetScalarMax(const ParGridFunction &x);
real_t GetVectorMax(int vdim, const ParGridFunction &x);
real_t GetScalarMax(const ParGridFunction &x);
int main(int argc, char *argv[])
{
@@ -140,7 +140,7 @@ int main(int argc, char *argv[])
// extract the corresponding parallel matrices A and M.
HypreParMatrix *A = NULL;
HypreParMatrix *M = NULL;
double shift = 0.0;
real_t shift = 0.0;
{
DenseMatrix epsilonMat(3);
epsilonMat(0,0) = 2.0; epsilonMat(1,1) = 2.0; epsilonMat(2,2) = 2.0;
@@ -178,7 +178,7 @@ int main(int argc, char *argv[])
m.AddDomainIntegrator(new VectorFEMassIntegrator(epsilon));
m.Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m.Finalize();
A = a.ParallelAssemble();
@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
// 9. Compute the eigenmodes and extract the array of eigenvalues. Define
// parallel grid functions to represent each of the eigenmodes returned by
// the solver and their derivatives.
Array<double> eigenvalues;
Array<real_t> eigenvalues;
ame->Solve();
ame->GetEigenvalues(eigenvalues);
ParGridFunction x(&fespace_nd);
@@ -308,10 +308,10 @@ int main(int argc, char *argv[])
yComp.ProjectCoefficient(yCoef);
zComp.ProjectCoefficient(zCoef);
double max_x = GetScalarMax(xComp);
double max_y = GetScalarMax(yComp);
double max_z = GetScalarMax(zComp);
double max_r = std::max(max_x, std::max(max_y, max_z));
real_t max_x = GetScalarMax(xComp);
real_t max_y = GetScalarMax(yComp);
real_t max_z = GetScalarMax(zComp);
real_t max_r = std::max(max_x, std::max(max_y, max_z));
ostringstream x_cmd;
x_cmd << " window_title 'Eigenmode " << i+1 << '/' << nev
@@ -368,7 +368,7 @@ int main(int argc, char *argv[])
dyComp.ProjectCoefficient(dyCoef);
dzComp.ProjectCoefficient(dzCoef);
double min_d = max_r / (bbMax[0] - bbMin[0]);
real_t min_d = max_r / (bbMax[0] - bbMin[0]);
max_y = GetScalarMax(dyComp);
max_z = GetScalarMax(dzComp);
@@ -480,9 +480,9 @@ int main(int argc, char *argv[])
xyComp.ProjectCoefficient(xyCoef);
zComp.ProjectCoefficient(zCoef);
double max_v = GetVectorMax(2, xyComp);
double max_s = GetScalarMax(zComp);
double max_r = std::max(max_v, max_s);
real_t max_v = GetVectorMax(2, xyComp);
real_t max_s = GetScalarMax(zComp);
real_t max_r = std::max(max_v, max_s);
ostringstream xy_cmd;
xy_cmd << " window_title 'Eigenmode " << i+1 << '/' << nev
@@ -523,7 +523,7 @@ int main(int argc, char *argv[])
dxyComp.ProjectCoefficient(dxyCoef);
dzComp.ProjectCoefficient(dzCoef);
double min_d = max_r / std::min(bbMax[0] - bbMin[0],
real_t min_d = max_r / std::min(bbMax[0] - bbMin[0],
bbMax[1] - bbMin[1]);
max_v = GetVectorMax(2, dxyComp);
@@ -649,17 +649,17 @@ int main(int argc, char *argv[])
return 0;
}
double GetVectorMax(int vdim, const ParGridFunction &x)
real_t GetVectorMax(int vdim, const ParGridFunction &x)
{
Vector zeroVec(vdim); zeroVec = 0.0;
VectorConstantCoefficient zero(zeroVec);
double nrm = x.ComputeMaxError(zero);
real_t nrm = x.ComputeMaxError(zero);
return nrm;
}
double GetScalarMax(const ParGridFunction &x)
real_t GetScalarMax(const ParGridFunction &x)
{
ConstantCoefficient zero(0.0);
double nrm = x.ComputeMaxError(zero);
real_t nrm = x.ComputeMaxError(zero);
return nrm;
}
+12 -7
View File
@@ -86,11 +86,16 @@ using namespace mfem;
int main(int argc, char *argv[])
{
#ifdef MFEM_USE_SINGLE
cout << "This example is not supported in single precision.\n\n";
return MFEM_SKIP_RETURN_VALUE;
#endif
// 1. Parse command-line options.
const char *mesh_file = "../data/star.mesh";
int order = 1;
int num_refs = 3;
double alpha = 0.5;
real_t alpha = 0.5;
bool visualization = true;
bool verification = false;
@@ -118,13 +123,13 @@ int main(int argc, char *argv[])
}
args.PrintOptions(cout);
Array<double> coeffs, poles;
Array<real_t> coeffs, poles;
int progress_steps = 1;
// 2. Compute the rational expansion coefficients that define the
// integer-order PDEs.
const int power_of_laplace = (int)floor(alpha);
double exponent_to_approximate = alpha - power_of_laplace;
real_t exponent_to_approximate = alpha - power_of_laplace;
bool integer_order = false;
// Check if alpha is an integer or not.
if (abs(exponent_to_approximate) > 1e-12)
@@ -135,7 +140,7 @@ int main(int argc, char *argv[])
ComputePartialFractionApproximation(exponent_to_approximate, coeffs,
poles);
// If the example is build without LAPACK, the exponent_to_approximate
// If the example is built without LAPACK, the exponent_to_approximate
// might be modified by the function call above.
alpha = exponent_to_approximate + power_of_laplace;
}
@@ -173,7 +178,7 @@ int main(int argc, char *argv[])
// 7. Define diffusion coefficient, load, and solution GridFunction.
auto func = [&alpha](const Vector &x)
{
double val = 1.0;
real_t val = 1.0;
for (int i=0; i<x.Size(); i++)
{
val *= sin(M_PI*x(i));
@@ -364,7 +369,7 @@ int main(int argc, char *argv[])
{
auto solution = [] (const Vector &x)
{
double val = 1.0;
real_t val = 1.0;
for (int i=0; i<x.Size(); i++)
{
val *= sin(M_PI*x(i));
@@ -372,7 +377,7 @@ int main(int argc, char *argv[])
return val;
};
FunctionCoefficient sol(solution);
double l2_error = u.ComputeL2Error(sol);
real_t l2_error = u.ComputeL2Error(sol);
string analytic_solution,expected_mesh;
switch (dim)
+28 -28
View File
@@ -50,8 +50,8 @@ using namespace mfem;
See pg. A1501 of Nakatsukasa et al. [1]. */
void RationalApproximation_AAA(const Vector &val, const Vector &pt,
Array<double> &z, Array<double> &f, Vector &w,
double tol, int max_order)
Array<real_t> &z, Array<real_t> &f, Vector &w,
real_t tol, int max_order)
{
// number of sample points
@@ -67,11 +67,11 @@ void RationalApproximation_AAA(const Vector &val, const Vector &pt,
DenseMatrix C, Ctemp, A, Am;
// auxiliary arrays and vectors
Vector f_vec;
Array<double> c_i;
Array<real_t> c_i;
// mean of the value vector
Vector R(val.Size());
double mean_val = val.Sum()/size;
real_t mean_val = val.Sum()/size;
for (int i = 0; i<R.Size(); i++) { R(i) = mean_val; }
@@ -79,10 +79,10 @@ void RationalApproximation_AAA(const Vector &val, const Vector &pt,
{
// select next support point
int idx = 0;
double tmp_max = 0;
real_t tmp_max = 0;
for (int j = 0; j < size; j++)
{
double tmp = abs(val(j)-R(j));
real_t tmp = abs(val(j)-R(j));
if (tmp > tmp_max)
{
tmp_max = tmp;
@@ -98,7 +98,7 @@ void RationalApproximation_AAA(const Vector &val, const Vector &pt,
J.DeleteFirst(idx);
// next column in Cauchy matrix
Array<double> C_tmp(size);
Array<real_t> C_tmp(size);
for (int j = 0; j < size; j++)
{
C_tmp[j] = 1.0/(pt(j)-pt(idx));
@@ -173,7 +173,7 @@ void RationalApproximation_AAA(const Vector &val, const Vector &pt,
See pg. A1501 of Nakatsukasa et al. [1]. */
void ComputePolesAndZeros(const Vector &z, const Vector &f, const Vector &w,
Array<double> & poles, Array<double> & zeros, double &scale)
Array<real_t> & poles, Array<real_t> & zeros, real_t &scale)
{
// Initialization
poles.SetSize(0);
@@ -242,8 +242,8 @@ void ComputePolesAndZeros(const Vector &z, const Vector &f, const Vector &w,
@param[in] zeros Array of zeros
@param[in] scale Scaling constant
@param[out] coeffs Coefficients c_i */
void PartialFractionExpansion(double scale, Array<double> & poles,
Array<double> & zeros, Array<double> & coeffs)
void PartialFractionExpansion(real_t scale, Array<real_t> & poles,
Array<real_t> & zeros, Array<real_t> & coeffs)
{
int psize = poles.Size();
int zsize = zeros.Size();
@@ -259,13 +259,13 @@ void PartialFractionExpansion(double scale, Array<double> & poles,
for (int i=0; i<psize; i++)
{
double tmp_numer=1.0;
real_t tmp_numer=1.0;
for (int j=0; j<zsize; j++)
{
tmp_numer *= poles[i]-zeros[j];
}
double tmp_denom=1.0;
real_t tmp_denom=1.0;
for (int k=0; k<psize; k++)
{
if (k != i) { tmp_denom *= poles[i]-poles[k]; }
@@ -292,10 +292,10 @@ void PartialFractionExpansion(double scale, Array<double> & poles,
@a alpha != 0.99, then @a alpha = 0.5 is used by default.
See pg. A1501 of Nakatsukasa et al. [1]. */
void ComputePartialFractionApproximation(double & alpha,
Array<double> & coeffs, Array<double> & poles,
double lmax = 1000.,
double tol=1e-10, int npoints = 1000,
void ComputePartialFractionApproximation(real_t & alpha,
Array<real_t> & coeffs, Array<real_t> & poles,
real_t lmax = 1000.,
real_t tol=1e-10, int npoints = 1000,
int max_order = 100)
{
MFEM_VERIFY(alpha < 1., "alpha must be less than 1");
@@ -320,26 +320,26 @@ void ComputePartialFractionApproximation(double & alpha,
<< "\nThe default is alpha = 0.5.\n" << string(80, '=') << "\n"
<< endl;
}
const double eps = std::numeric_limits<double>::epsilon();
const real_t eps = std::numeric_limits<real_t>::epsilon();
if (abs(alpha - 0.33) < eps)
{
coeffs = Array<double> ({1.821898e+03, 9.101221e+01, 2.650611e+01,
coeffs = Array<real_t> ({1.821898e+03, 9.101221e+01, 2.650611e+01,
1.174937e+01, 6.140444e+00, 3.441713e+00,
1.985735e+00, 1.162634e+00, 6.891560e-01,
4.111574e-01, 2.298736e-01});
poles = Array<double> ({-4.155583e+04, -2.956285e+03, -8.331715e+02,
poles = Array<real_t> ({-4.155583e+04, -2.956285e+03, -8.331715e+02,
-3.139332e+02, -1.303448e+02, -5.563385e+01,
-2.356255e+01, -9.595516e+00, -3.552160e+00,
-1.032136e+00, -1.241480e-01});
}
else if (abs(alpha - 0.99) < eps)
{
coeffs = Array<double>({2.919591e-02, 1.419750e-02, 1.065798e-02,
coeffs = Array<real_t>({2.919591e-02, 1.419750e-02, 1.065798e-02,
9.395094e-03, 8.915329e-03, 8.822991e-03,
9.058247e-03, 9.814521e-03, 1.180396e-02,
1.834554e-02, 9.840482e-01});
poles = Array<double> ({-1.069683e+04, -1.769370e+03, -5.718374e+02,
poles = Array<real_t> ({-1.069683e+04, -1.769370e+03, -5.718374e+02,
-2.242095e+02, -9.419132e+01, -4.031012e+01,
-1.701525e+01, -6.810088e+00, -2.382810e+00,
-5.700059e-01, -1.384324e-03});
@@ -350,11 +350,11 @@ void ComputePartialFractionApproximation(double & alpha,
{
alpha = 0.5;
}
coeffs = Array<double>({2.290262e+02, 2.641819e+01, 1.005566e+01,
coeffs = Array<real_t>({2.290262e+02, 2.641819e+01, 1.005566e+01,
5.390411e+00, 3.340725e+00, 2.211205e+00,
1.508883e+00, 1.049474e+00, 7.462709e-01,
5.482686e-01, 4.232510e-01, 3.578967e-01});
poles = Array<double>({-3.168211e+04, -3.236077e+03, -9.868287e+02,
poles = Array<real_t>({-3.168211e+04, -3.236077e+03, -9.868287e+02,
-3.945597e+02, -1.738889e+02, -7.925178e+01,
-3.624992e+01, -1.629196e+01, -6.982956e+00,
-2.679984e+00, -7.782607e-01, -7.649166e-02});
@@ -372,15 +372,15 @@ void ComputePartialFractionApproximation(double & alpha,
Vector x(npoints);
Vector val(npoints);
double dx = lmax / (double)(npoints-1);
real_t dx = lmax / (real_t)(npoints-1);
for (int i = 0; i<npoints; i++)
{
x(i) = dx * (double)i;
x(i) = dx * (real_t)i;
val(i) = pow(x(i),1.-alpha);
}
// Apply triple-A algorithm to f(x) = x^{1-a}
Array<double> z, f;
Array<real_t> z, f;
Vector w;
RationalApproximation_AAA(val,x,z,f,w,tol,max_order);
@@ -389,8 +389,8 @@ void ComputePartialFractionApproximation(double & alpha,
vecf.SetDataAndSize(f.GetData(), f.Size());
// Compute poles and zeros for RA of f(x) = x^{1-a}
double scale;
Array<double> zeros;
real_t scale;
Array<real_t> zeros;
ComputePolesAndZeros(vecz, vecf, w, poles, zeros, scale);
// Remove the zero at x=0, thus, delivering a RA for f(x) = x^{-a}
+11 -6
View File
@@ -86,6 +86,11 @@ using namespace mfem;
int main(int argc, char *argv[])
{
#ifdef MFEM_USE_SINGLE
cout << "This example is not supported in single precision.\n\n";
return MFEM_SKIP_RETURN_VALUE;
#endif
// 0. Initialize MPI.
Mpi::Init(argc, argv);
int num_procs = Mpi::WorldSize();
@@ -96,7 +101,7 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/star.mesh";
int order = 1;
int num_refs = 3;
double alpha = 0.5;
real_t alpha = 0.5;
bool visualization = true;
bool verification = false;
@@ -127,13 +132,13 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
Array<double> coeffs, poles;
Array<real_t> coeffs, poles;
int progress_steps = 1;
// 2. Compute the rational expansion coefficients that define the
// integer-order PDEs.
const int power_of_laplace = floor(alpha);
double exponent_to_approximate = alpha - power_of_laplace;
real_t exponent_to_approximate = alpha - power_of_laplace;
bool integer_order = false;
// Check if alpha is an integer or not.
if (abs(exponent_to_approximate) > 1e-12)
@@ -193,7 +198,7 @@ int main(int argc, char *argv[])
// 7. Define diffusion coefficient, load, and solution GridFunction.
auto func = [&alpha](const Vector &x)
{
double val = 1.0;
real_t val = 1.0;
for (int i=0; i<x.Size(); i++)
{
val *= sin(M_PI*x(i));
@@ -398,7 +403,7 @@ int main(int argc, char *argv[])
{
auto solution = [] (const Vector &x)
{
double val = 1.0;
real_t val = 1.0;
for (int i=0; i<x.Size(); i++)
{
val *= sin(M_PI*x(i));
@@ -406,7 +411,7 @@ int main(int argc, char *argv[])
return val;
};
FunctionCoefficient sol(solution);
double l2_error = u.ComputeL2Error(sol);
real_t l2_error = u.ComputeL2Error(sol);
if (Mpi::Root())
{
+7 -3
View File
@@ -52,6 +52,7 @@ static bool pa_ = false;
static bool algebraic_ceed_ = false;
void ComputeCurrentDensityOnSubMesh(int order,
bool visualization,
const Array<int> &phi0_attr,
const Array<int> &phi1_attr,
const Array<int> &jn_zero_attr,
@@ -69,7 +70,7 @@ int main(int argc, char *argv[])
Array<int> jn_zero_attr;
int ref_levels = 1;
int order = 1;
double delta_const = 1e-6;
real_t delta_const = 1e-6;
bool mixed = true;
bool static_cond = false;
const char *device_config = "cpu";
@@ -236,8 +237,8 @@ int main(int argc, char *argv[])
FiniteElementSpace fes_cond_rt(&mesh_cond, &fec_cond_rt);
GridFunction j_cond(&fes_cond_rt);
ComputeCurrentDensityOnSubMesh(order, phi0_attr, phi1_attr, jn_zero_attr,
j_cond);
ComputeCurrentDensityOnSubMesh(order, visualization,
phi0_attr, phi1_attr, jn_zero_attr, j_cond);
// 6a. Save the SubMesh and associated current density in parallel. This
// output can be viewed later using GLVis:
@@ -255,6 +256,7 @@ int main(int argc, char *argv[])
cond_ofs.precision(8);
j_cond.Save(cond_ofs);
}
// 6b. Send the current density, computed on the SubMesh, to a GLVis server.
if (visualization)
{
@@ -450,6 +452,7 @@ int main(int argc, char *argv[])
}
void ComputeCurrentDensityOnSubMesh(int order,
bool visualization,
const Array<int> &phi0_attr,
const Array<int> &phi1_attr,
const Array<int> &jn_zero_attr,
@@ -567,6 +570,7 @@ void ComputeCurrentDensityOnSubMesh(int order,
a_h1.RecoverFEMSolution(X, b_h1, phi_h1);
}
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
+8 -3
View File
@@ -49,6 +49,7 @@ using namespace std;
using namespace mfem;
void ComputeCurrentDensityOnSubMesh(int order,
bool visualization,
const Array<int> &phi0_attr,
const Array<int> &phi1_attr,
const Array<int> &jn_zero_attr,
@@ -73,7 +74,7 @@ int main(int argc, char *argv[])
int ser_ref_levels = 1;
int par_ref_levels = 1;
int order = 1;
double delta_const = 1e-6;
real_t delta_const = 1e-6;
bool mixed = true;
bool static_cond = false;
bool pa = false;
@@ -270,8 +271,8 @@ int main(int argc, char *argv[])
ParFiniteElementSpace fes_cond_rt(&pmesh_cond, &fec_cond_rt);
ParGridFunction j_cond(&fes_cond_rt);
ComputeCurrentDensityOnSubMesh(order, phi0_attr, phi1_attr, jn_zero_attr,
j_cond);
ComputeCurrentDensityOnSubMesh(order, visualization,
phi0_attr, phi1_attr, jn_zero_attr, j_cond);
// 7a. Save the SubMesh and associated current density in parallel. This
// output can be viewed later using GLVis:
@@ -289,6 +290,7 @@ int main(int argc, char *argv[])
cond_ofs.precision(8);
j_cond.Save(cond_ofs);
}
// 7b. Send the current density, computed on the SubMesh, to a GLVis server.
if (visualization)
{
@@ -498,6 +500,7 @@ int main(int argc, char *argv[])
}
void ComputeCurrentDensityOnSubMesh(int order,
bool visualization,
const Array<int> &phi0_attr,
const Array<int> &phi1_attr,
const Array<int> &jn_zero_attr,
@@ -586,6 +589,8 @@ void ComputeCurrentDensityOnSubMesh(int order,
cg.Mult(B, X);
a_h1.RecoverFEMSolution(X, b_h1, phi_h1);
}
if (visualization)
{
int num_procs = fes_cond_h1.GetNRanks();
char vishost[] = "localhost";
+9 -9
View File
@@ -55,9 +55,9 @@
using namespace std;
using namespace mfem;
static double mu_ = 1.0;
static double epsilon_ = 1.0;
static double sigma_ = 2.0;
static real_t mu_ = 1.0;
static real_t epsilon_ = 1.0;
static real_t sigma_ = 2.0;
void SetPortBC(int prob, int dim, int mode, ParGridFunction &port_bc);
@@ -77,9 +77,9 @@ int main(int argc, char *argv[])
Array<int> port_bc_attr;
int prob = 0;
int mode = 1;
double freq = -1.0;
double omega = 2.0 * M_PI;
double a_coef = 0.0;
real_t freq = -1.0;
real_t omega = 2.0 * M_PI;
real_t a_coef = 0.0;
bool herm_conv = true;
bool slu_solver = false;
bool visualization = 1;
@@ -587,7 +587,7 @@ int main(int argc, char *argv[])
int i = 0;
while (sol_sock)
{
double t = (double)(i % num_frames) / num_frames;
real_t t = (real_t)(i % num_frames) / num_frames;
ostringstream oss;
oss << "Harmonic Solution (t = " << t << " T)";
@@ -637,7 +637,7 @@ void ScalarWaveGuide(int mode, ParGridFunction &x)
m.AddDomainIntegrator(new MassIntegrator);
m.Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m.Finalize();
HypreParMatrix *A = a.ParallelAssemble();
@@ -694,7 +694,7 @@ void VectorWaveGuide(int mode, ParGridFunction &x)
m.AddDomainIntegrator(new VectorFEMassIntegrator);
m.Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m.EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m.Finalize();
HypreParMatrix *A = a.ParallelAssemble();
+45 -45
View File
@@ -37,8 +37,8 @@
using namespace std;
using namespace mfem;
double spherical_obstacle(const Vector &pt);
double exact_solution_obstacle(const Vector &pt);
real_t spherical_obstacle(const Vector &pt);
real_t exact_solution_obstacle(const Vector &pt);
void exact_solution_gradient_obstacle(const Vector &pt, Vector &grad);
class LogarithmGridFunctionCoefficient : public Coefficient
@@ -46,14 +46,14 @@ class LogarithmGridFunctionCoefficient : public Coefficient
protected:
GridFunction *u; // grid function
Coefficient *obstacle;
double min_val;
real_t min_val;
public:
LogarithmGridFunctionCoefficient(GridFunction &u_, Coefficient &obst_,
double min_val_=-36)
real_t min_val_=-36)
: u(&u_), obstacle(&obst_), min_val(min_val_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
class ExponentialGridFunctionCoefficient : public Coefficient
@@ -61,15 +61,15 @@ class ExponentialGridFunctionCoefficient : public Coefficient
protected:
GridFunction *u;
Coefficient *obstacle;
double min_val;
double max_val;
real_t min_val;
real_t max_val;
public:
ExponentialGridFunctionCoefficient(GridFunction &u_, Coefficient &obst_,
double min_val_=0.0, double max_val_=1e6)
real_t min_val_=0.0, real_t max_val_=1e6)
: u(&u_), obstacle(&obst_), min_val(min_val_), max_val(max_val_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
int main(int argc, char *argv[])
@@ -78,8 +78,8 @@ int main(int argc, char *argv[])
int order = 1;
int max_it = 10;
int ref_levels = 3;
double alpha = 1.0;
double tol = 1e-5;
real_t alpha = 1.0;
real_t tol = 1e-5;
bool visualization = true;
OptionsParser args(argc, argv);
@@ -124,7 +124,7 @@ int main(int argc, char *argv[])
// 3C. Rescale the domain to a unit circle (radius = 1).
GridFunction *nodes = mesh.GetNodes();
double scale = 2*sqrt(2);
real_t scale = 2*sqrt(2);
*nodes /= scale;
// 4. Define the necessary finite element spaces on the mesh.
@@ -159,8 +159,8 @@ int main(int argc, char *argv[])
// 6. Define an initial guess for the solution.
auto IC_func = [](const Vector &x)
{
double r0 = 1.0;
double rr = 0.0;
real_t r0 = 1.0;
real_t rr = 0.0;
for (int i=0; i<x.Size(); i++)
{
rr += x(i)*x(i);
@@ -211,7 +211,7 @@ int main(int argc, char *argv[])
// 10. Iterate
int k;
int total_iterations = 0;
double increment_u = 0.1;
real_t increment_u = 0.1;
for (k = 0; k < max_it; k++)
{
GridFunction u_tmp(&H1fes);
@@ -300,10 +300,10 @@ int main(int argc, char *argv[])
delta_psi_gf.MakeRef(&L2fes, x.GetBlock(1), 0);
u_tmp -= u_gf;
double Newton_update_size = u_tmp.ComputeL2Error(zero);
real_t Newton_update_size = u_tmp.ComputeL2Error(zero);
u_tmp = u_gf;
double gamma = 1.0;
real_t gamma = 1.0;
delta_psi_gf *= gamma;
psi_gf += delta_psi_gf;
@@ -337,7 +337,7 @@ int main(int argc, char *argv[])
break;
}
double H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
real_t H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
mfem::out << "H1-error (|| u - uₕᵏ||) = " << H1_error << endl;
}
@@ -362,13 +362,13 @@ int main(int argc, char *argv[])
}
{
double L2_error = u_gf.ComputeL2Error(exact_coef);
double H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
real_t L2_error = u_gf.ComputeL2Error(exact_coef);
real_t H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
ExponentialGridFunctionCoefficient u_alt_cf(psi_gf,obstacle);
GridFunction u_alt_gf(&L2fes);
u_alt_gf.ProjectCoefficient(u_alt_cf);
double L2_error_alt = u_alt_gf.ComputeL2Error(exact_coef);
real_t L2_error_alt = u_alt_gf.ComputeL2Error(exact_coef);
mfem::out << "\n Final L2-error (|| u - uₕ||) = " << L2_error <<
endl;
@@ -380,35 +380,35 @@ int main(int argc, char *argv[])
return 0;
}
double LogarithmGridFunctionCoefficient::Eval(ElementTransformation &T,
real_t LogarithmGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "grid function is not set");
double val = u->GetValue(T, ip) - obstacle->Eval(T, ip);
real_t val = u->GetValue(T, ip) - obstacle->Eval(T, ip);
return max(min_val, log(val));
}
double ExponentialGridFunctionCoefficient::Eval(ElementTransformation &T,
real_t ExponentialGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "grid function is not set");
double val = u->GetValue(T, ip);
real_t val = u->GetValue(T, ip);
return min(max_val, max(min_val, exp(val) + obstacle->Eval(T, ip)));
}
double spherical_obstacle(const Vector &pt)
real_t spherical_obstacle(const Vector &pt)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double beta = 0.9;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t beta = 0.9;
double b = r0*beta;
double tmp = sqrt(r0*r0 - b*b);
double B = tmp + b*b/tmp;
double C = -b/tmp;
real_t b = r0*beta;
real_t tmp = sqrt(r0*r0 - b*b);
real_t B = tmp + b*b/tmp;
real_t C = -b/tmp;
if (r > b)
{
@@ -420,13 +420,13 @@ double spherical_obstacle(const Vector &pt)
}
}
double exact_solution_obstacle(const Vector &pt)
real_t exact_solution_obstacle(const Vector &pt)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double a = 0.348982574111686;
double A = -0.340129705945858;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t a = 0.348982574111686;
real_t A = -0.340129705945858;
if (r > a)
{
@@ -440,11 +440,11 @@ double exact_solution_obstacle(const Vector &pt)
void exact_solution_gradient_obstacle(const Vector &pt, Vector &grad)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double a = 0.348982574111686;
double A = -0.340129705945858;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t a = 0.348982574111686;
real_t A = -0.340129705945858;
if (r > a)
{
+45 -45
View File
@@ -37,8 +37,8 @@
using namespace std;
using namespace mfem;
double spherical_obstacle(const Vector &pt);
double exact_solution_obstacle(const Vector &pt);
real_t spherical_obstacle(const Vector &pt);
real_t exact_solution_obstacle(const Vector &pt);
void exact_solution_gradient_obstacle(const Vector &pt, Vector &grad);
class LogarithmGridFunctionCoefficient : public Coefficient
@@ -46,14 +46,14 @@ class LogarithmGridFunctionCoefficient : public Coefficient
protected:
GridFunction *u; // grid function
Coefficient *obstacle;
double min_val;
real_t min_val;
public:
LogarithmGridFunctionCoefficient(GridFunction &u_, Coefficient &obst_,
double min_val_=-36)
real_t min_val_=-36)
: u(&u_), obstacle(&obst_), min_val(min_val_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
class ExponentialGridFunctionCoefficient : public Coefficient
@@ -61,15 +61,15 @@ class ExponentialGridFunctionCoefficient : public Coefficient
protected:
GridFunction *u;
Coefficient *obstacle;
double min_val;
double max_val;
real_t min_val;
real_t max_val;
public:
ExponentialGridFunctionCoefficient(GridFunction &u_, Coefficient &obst_,
double min_val_=0.0, double max_val_=1e6)
real_t min_val_=0.0, real_t max_val_=1e6)
: u(&u_), obstacle(&obst_), min_val(min_val_), max_val(max_val_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
};
int main(int argc, char *argv[])
@@ -84,8 +84,8 @@ int main(int argc, char *argv[])
int order = 1;
int max_it = 10;
int ref_levels = 3;
double alpha = 1.0;
double tol = 1e-5;
real_t alpha = 1.0;
real_t tol = 1e-5;
bool visualization = true;
OptionsParser args(argc, argv);
@@ -136,7 +136,7 @@ int main(int argc, char *argv[])
// 3C. Rescale the domain to a unit circle (radius = 1).
GridFunction *nodes = mesh.GetNodes();
double scale = 2*sqrt(2);
real_t scale = 2*sqrt(2);
*nodes /= scale;
ParMesh pmesh(MPI_COMM_WORLD, mesh);
@@ -192,8 +192,8 @@ int main(int argc, char *argv[])
// 6. Define an initial guess for the solution.
auto IC_func = [](const Vector &x)
{
double r0 = 1.0;
double rr = 0.0;
real_t r0 = 1.0;
real_t rr = 0.0;
for (int i=0; i<x.Size(); i++)
{
rr += x(i)*x(i);
@@ -243,7 +243,7 @@ int main(int argc, char *argv[])
// 10. Iterate
int k;
int total_iterations = 0;
double increment_u = 0.1;
real_t increment_u = 0.1;
for (k = 0; k < max_it; k++)
{
ParGridFunction u_tmp(&H1fes);
@@ -346,10 +346,10 @@ int main(int argc, char *argv[])
delta_psi_gf.SetFromTrueDofs(tx.GetBlock(1));
u_tmp -= u_gf;
double Newton_update_size = u_tmp.ComputeL2Error(zero);
real_t Newton_update_size = u_tmp.ComputeL2Error(zero);
u_tmp = u_gf;
double gamma = 1.0;
real_t gamma = 1.0;
delta_psi_gf *= gamma;
psi_gf += delta_psi_gf;
@@ -391,7 +391,7 @@ int main(int argc, char *argv[])
break;
}
double H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
real_t H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
if (myid == 0)
{
mfem::out << "H1-error (|| u - uₕᵏ||) = " << H1_error << endl;
@@ -423,13 +423,13 @@ int main(int argc, char *argv[])
}
{
double L2_error = u_gf.ComputeL2Error(exact_coef);
double H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
real_t L2_error = u_gf.ComputeL2Error(exact_coef);
real_t H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
ExponentialGridFunctionCoefficient u_alt_cf(psi_gf,obstacle);
ParGridFunction u_alt_gf(&L2fes);
u_alt_gf.ProjectCoefficient(u_alt_cf);
double L2_error_alt = u_alt_gf.ComputeL2Error(exact_coef);
real_t L2_error_alt = u_alt_gf.ComputeL2Error(exact_coef);
if (myid == 0)
{
@@ -444,35 +444,35 @@ int main(int argc, char *argv[])
return 0;
}
double LogarithmGridFunctionCoefficient::Eval(ElementTransformation &T,
real_t LogarithmGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "grid function is not set");
double val = u->GetValue(T, ip) - obstacle->Eval(T, ip);
real_t val = u->GetValue(T, ip) - obstacle->Eval(T, ip);
return max(min_val, log(val));
}
double ExponentialGridFunctionCoefficient::Eval(ElementTransformation &T,
real_t ExponentialGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_ASSERT(u != NULL, "grid function is not set");
double val = u->GetValue(T, ip);
real_t val = u->GetValue(T, ip);
return min(max_val, max(min_val, exp(val) + obstacle->Eval(T, ip)));
}
double spherical_obstacle(const Vector &pt)
real_t spherical_obstacle(const Vector &pt)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double beta = 0.9;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t beta = 0.9;
double b = r0*beta;
double tmp = sqrt(r0*r0 - b*b);
double B = tmp + b*b/tmp;
double C = -b/tmp;
real_t b = r0*beta;
real_t tmp = sqrt(r0*r0 - b*b);
real_t B = tmp + b*b/tmp;
real_t C = -b/tmp;
if (r > b)
{
@@ -484,13 +484,13 @@ double spherical_obstacle(const Vector &pt)
}
}
double exact_solution_obstacle(const Vector &pt)
real_t exact_solution_obstacle(const Vector &pt)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double a = 0.348982574111686;
double A = -0.340129705945858;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t a = 0.348982574111686;
real_t A = -0.340129705945858;
if (r > a)
{
@@ -504,11 +504,11 @@ double exact_solution_obstacle(const Vector &pt)
void exact_solution_gradient_obstacle(const Vector &pt, Vector &grad)
{
double x = pt(0), y = pt(1);
double r = sqrt(x*x + y*y);
double r0 = 0.5;
double a = 0.348982574111686;
double A = -0.340129705945858;
real_t x = pt(0), y = pt(1);
real_t r = sqrt(x*x + y*y);
real_t r0 = 0.5;
real_t a = 0.348982574111686;
real_t A = -0.340129705945858;
if (r > a)
{
+24 -24
View File
@@ -67,9 +67,9 @@ using namespace mfem;
* @param target_volume θ vol(Ω)
* @param tol Newton iteration tolerance
* @param max_its Newton maximum iteration number
* @return double Final volume, sigmoid(ψ)
* @return real_t Final volume, sigmoid(ψ)
*/
double proj(GridFunction &psi, double target_volume, double tol=1e-12,
real_t proj(GridFunction &psi, real_t target_volume, real_t tol=1e-12,
int max_its=10)
{
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
@@ -84,12 +84,12 @@ double proj(GridFunction &psi, double target_volume, double tol=1e-12,
for (int k=0; k<max_its; k++) // Newton iteration
{
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
const double f = int_sigmoid_psi.Sum() - target_volume;
const real_t f = int_sigmoid_psi.Sum() - target_volume;
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
const double df = int_der_sigmoid_psi.Sum();
const real_t df = int_der_sigmoid_psi.Sum();
const double dc = -f/df;
const real_t dc = -f/df;
psi += dc;
if (abs(dc) < tol) { done = true; break; }
}
@@ -179,15 +179,15 @@ int main(int argc, char *argv[])
// 1. Parse command-line options.
int ref_levels = 5;
int order = 2;
double alpha = 1.0;
double epsilon = 0.01;
double vol_fraction = 0.5;
real_t alpha = 1.0;
real_t epsilon = 0.01;
real_t vol_fraction = 0.5;
int max_it = 1e3;
double itol = 1e-1;
double ntol = 1e-4;
double rho_min = 1e-6;
double lambda = 1.0;
double mu = 1.0;
real_t itol = 1e-1;
real_t ntol = 1e-4;
real_t rho_min = 1e-6;
real_t lambda = 1.0;
real_t mu = 1.0;
bool glvis_visualization = true;
bool paraview_output = false;
@@ -239,8 +239,8 @@ int main(int argc, char *argv[])
Array<int> vertices;
be->GetVertices(vertices);
double * coords1 = mesh.GetVertex(vertices[0]);
double * coords2 = mesh.GetVertex(vertices[1]);
real_t * coords1 = mesh.GetVertex(vertices[0]);
real_t * coords2 = mesh.GetVertex(vertices[1]);
Vector center(2);
center(0) = 0.5*(coords1[0] + coords2[0]);
@@ -312,7 +312,7 @@ int main(int argc, char *argv[])
ElasticitySolver->SetupFEM();
Vector center(2); center(0) = 2.9; center(1) = 0.5;
Vector force(2); force(0) = 0.0; force(1) = -1.0;
double r = 0.05;
real_t r = 0.05;
VolumeForceCoefficient vforce_cf(r,center,force);
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
ElasticitySolver->SetEssentialBoundary(ess_bdr);
@@ -353,8 +353,8 @@ int main(int argc, char *argv[])
LinearForm vol_form(&control_fes);
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
vol_form.Assemble();
double domain_volume = vol_form(onegf);
const double target_volume = domain_volume * vol_fraction;
real_t domain_volume = vol_form(onegf);
const real_t target_volume = domain_volume * vol_fraction;
// 10. Connect to GLVis. Prepare for VisIt output.
char vishost[] = "localhost";
@@ -385,7 +385,7 @@ int main(int argc, char *argv[])
// 11. Iterate:
for (int k = 1; k <= max_it; k++)
{
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
if (k > 1) { alpha *= ((real_t) k) / ((real_t) k-1); }
mfem::out << "\nStep = " << k << std::endl;
@@ -422,14 +422,14 @@ int main(int argc, char *argv[])
// Step 5 - Update design variable ψ ← proj(ψ - αG)
psi.Add(-alpha, grad);
const double material_volume = proj(psi, target_volume);
const real_t material_volume = proj(psi, target_volume);
// Compute ||ρ - ρ_old|| in control fes.
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
double norm_reduced_gradient = norm_increment/alpha;
real_t norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
real_t norm_reduced_gradient = norm_increment/alpha;
psi_old = psi;
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
real_t compliance = (*(ElasticitySolver->GetLinearForm()))(u);
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient <<
std::endl;
mfem::out << "norm of the increment = " << norm_increment << endl;
@@ -449,7 +449,7 @@ int main(int argc, char *argv[])
{
rho_gf.ProjectCoefficient(rho);
paraview_dc.SetCycle(k);
paraview_dc.SetTime((double)k);
paraview_dc.SetTime((real_t)k);
paraview_dc.Save();
}
+40 -40
View File
@@ -9,15 +9,15 @@ namespace mfem
{
/// @brief Inverse sigmoid function
double inv_sigmoid(double x)
real_t inv_sigmoid(real_t x)
{
double tol = 1e-12;
x = std::min(std::max(tol,x),1.0-tol);
real_t tol = 1e-12;
x = std::min(std::max(tol,x), real_t(1.0)-tol);
return std::log(x/(1.0-x));
}
/// @brief Sigmoid function
double sigmoid(double x)
real_t sigmoid(real_t x)
{
if (x >= 0)
{
@@ -30,9 +30,9 @@ double sigmoid(double x)
}
/// @brief Derivative of sigmoid function
double der_sigmoid(double x)
real_t der_sigmoid(real_t x)
{
double tmp = sigmoid(-x);
real_t tmp = sigmoid(-x);
return tmp - std::pow(tmp,2);
}
@@ -40,24 +40,24 @@ double der_sigmoid(double x)
class MappedGridFunctionCoefficient : public GridFunctionCoefficient
{
protected:
std::function<double(const double)> fun; // f:R → R
std::function<real_t(const real_t)> fun; // f:R → R
public:
MappedGridFunctionCoefficient()
:GridFunctionCoefficient(),
fun([](double x) {return x;}) {}
fun([](real_t x) {return x;}) {}
MappedGridFunctionCoefficient(const GridFunction *gf,
std::function<double(const double)> fun_,
std::function<real_t(const real_t)> fun_,
int comp=1)
:GridFunctionCoefficient(gf, comp),
fun(fun_) {}
virtual double Eval(ElementTransformation &T,
virtual real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
return fun(GridFunctionCoefficient::Eval(T, ip));
}
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
void SetFunction(std::function<real_t(const real_t)> fun_) { fun = fun_; }
};
@@ -67,30 +67,30 @@ class DiffMappedGridFunctionCoefficient : public GridFunctionCoefficient
protected:
const GridFunction *OtherGridF;
GridFunctionCoefficient OtherGridF_cf;
std::function<double(const double)> fun; // f:R → R
std::function<real_t(const real_t)> fun; // f:R → R
public:
DiffMappedGridFunctionCoefficient()
:GridFunctionCoefficient(),
OtherGridF(nullptr),
OtherGridF_cf(),
fun([](double x) {return x;}) {}
fun([](real_t x) {return x;}) {}
DiffMappedGridFunctionCoefficient(const GridFunction *gf,
const GridFunction *other_gf,
std::function<double(const double)> fun_,
std::function<real_t(const real_t)> fun_,
int comp=1)
:GridFunctionCoefficient(gf, comp),
OtherGridF(other_gf),
OtherGridF_cf(OtherGridF),
fun(fun_) {}
virtual double Eval(ElementTransformation &T,
virtual real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
const double value1 = fun(GridFunctionCoefficient::Eval(T, ip));
const double value2 = fun(OtherGridF_cf.Eval(T, ip));
const real_t value1 = fun(GridFunctionCoefficient::Eval(T, ip));
const real_t value2 = fun(OtherGridF_cf.Eval(T, ip));
return value1 - value2;
}
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
void SetFunction(std::function<real_t(const real_t)> fun_) { fun = fun_; }
};
/// @brief Solid isotropic material penalization (SIMP) coefficient
@@ -98,20 +98,20 @@ class SIMPInterpolationCoefficient : public Coefficient
{
protected:
GridFunction *rho_filter;
double min_val;
double max_val;
double exponent;
real_t min_val;
real_t max_val;
real_t exponent;
public:
SIMPInterpolationCoefficient(GridFunction *rho_filter_, double min_val_= 1e-6,
double max_val_ = 1.0, double exponent_ = 3)
SIMPInterpolationCoefficient(GridFunction *rho_filter_, real_t min_val_= 1e-6,
real_t max_val_ = 1.0, real_t exponent_ = 3)
: rho_filter(rho_filter_), min_val(min_val_), max_val(max_val_),
exponent(exponent_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)
{
double val = rho_filter->GetValue(T, ip);
double coeff = min_val + pow(val,exponent)*(max_val-min_val);
real_t val = rho_filter->GetValue(T, ip);
real_t coeff = min_val + pow(val,exponent)*(max_val-min_val);
return coeff;
}
};
@@ -126,13 +126,13 @@ protected:
GridFunction *u = nullptr; // displacement
GridFunction *rho_filter = nullptr; // filter density
DenseMatrix grad; // auxiliary matrix, used in Eval
double exponent;
double rho_min;
real_t exponent;
real_t rho_min;
public:
StrainEnergyDensityCoefficient(Coefficient *lambda_, Coefficient *mu_,
GridFunction * u_, GridFunction * rho_filter_, double rho_min_=1e-6,
double exponent_ = 3.0)
GridFunction * u_, GridFunction * rho_filter_, real_t rho_min_=1e-6,
real_t exponent_ = 3.0)
: lambda(lambda_), mu(mu_), u(u_), rho_filter(rho_filter_),
exponent(exponent_), rho_min(rho_min_)
{
@@ -142,13 +142,13 @@ public:
MFEM_ASSERT(rho_filter, "density field is not set");
}
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)
{
double L = lambda->Eval(T, ip);
double M = mu->Eval(T, ip);
real_t L = lambda->Eval(T, ip);
real_t M = mu->Eval(T, ip);
u->GetVectorGradient(T, grad);
double div_u = grad.Trace();
double density = L*div_u*div_u;
real_t div_u = grad.Trace();
real_t density = L*div_u*div_u;
int dim = T.GetSpaceDim();
for (int i=0; i<dim; i++)
{
@@ -157,7 +157,7 @@ public:
density += M*grad(i,j)*(grad(i,j)+grad(j,i));
}
}
double val = rho_filter->GetValue(T,ip);
real_t val = rho_filter->GetValue(T,ip);
return -exponent * pow(val, exponent-1.0) * (1-rho_min) * density;
}
@@ -167,11 +167,11 @@ public:
class VolumeForceCoefficient : public VectorCoefficient
{
private:
double r;
real_t r;
Vector center;
Vector force;
public:
VolumeForceCoefficient(double r_,Vector & center_, Vector & force_) :
VolumeForceCoefficient(real_t r_,Vector & center_, Vector & force_) :
VectorCoefficient(center_.Size()), r(r_), center(center_), force(force_) { }
using VectorCoefficient::Eval;
@@ -186,7 +186,7 @@ public:
xx[i]=xx[i]-center[i];
}
double cr=xx.Norml2();
real_t cr=xx.Norml2();
V.SetSize(T.GetDimension());
if (cr <= r)
{
@@ -198,7 +198,7 @@ public:
}
}
void Set(double r_,Vector & center_, Vector & force_)
void Set(real_t r_,Vector & center_, Vector & force_)
{
r=r_;
center = center_;
+33 -30
View File
@@ -66,9 +66,9 @@ using namespace mfem;
* @param target_volume θ vol(Ω)
* @param tol Newton iteration tolerance
* @param max_its Newton maximum iteration number
* @return double Final volume, sigmoid(ψ)
* @return real_t Final volume, sigmoid(ψ)
*/
double proj(ParGridFunction &psi, double target_volume, double tol=1e-12,
real_t proj(ParGridFunction &psi, real_t target_volume, real_t tol=1e-12,
int max_its=10)
{
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
@@ -83,15 +83,17 @@ double proj(ParGridFunction &psi, double target_volume, double tol=1e-12,
for (int k=0; k<max_its; k++) // Newton iteration
{
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
double f = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &f, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
real_t f = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &f, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
f -= target_volume;
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
double df = int_der_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &df, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
real_t df = int_der_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &df, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
const double dc = -f/df;
const real_t dc = -f/df;
psi += dc;
if (abs(dc) < tol) { done = true; break; }
}
@@ -101,9 +103,9 @@ double proj(ParGridFunction &psi, double target_volume, double tol=1e-12,
"Result may not be accurate.");
}
int_sigmoid_psi.Assemble();
double material_volume = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1, MPI_DOUBLE, MPI_SUM,
MPI_COMM_WORLD);
real_t material_volume = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1,
MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
return material_volume;
}
@@ -190,15 +192,15 @@ int main(int argc, char *argv[])
// 1. Parse command-line options.
int ref_levels = 5;
int order = 2;
double alpha = 1.0;
double epsilon = 0.01;
double vol_fraction = 0.5;
real_t alpha = 1.0;
real_t epsilon = 0.01;
real_t vol_fraction = 0.5;
int max_it = 1e3;
double itol = 1e-1;
double ntol = 1e-4;
double rho_min = 1e-6;
double lambda = 1.0;
double mu = 1.0;
real_t itol = 1e-1;
real_t ntol = 1e-4;
real_t rho_min = 1e-6;
real_t lambda = 1.0;
real_t mu = 1.0;
bool glvis_visualization = true;
bool paraview_output = false;
@@ -258,8 +260,8 @@ int main(int argc, char *argv[])
Array<int> vertices;
be->GetVertices(vertices);
double * coords1 = mesh.GetVertex(vertices[0]);
double * coords2 = mesh.GetVertex(vertices[1]);
real_t * coords1 = mesh.GetVertex(vertices[0]);
real_t * coords2 = mesh.GetVertex(vertices[1]);
Vector center(2);
center(0) = 0.5*(coords1[0] + coords2[0]);
@@ -337,7 +339,7 @@ int main(int argc, char *argv[])
ElasticitySolver->SetupFEM();
Vector center(2); center(0) = 2.9; center(1) = 0.5;
Vector force(2); force(0) = 0.0; force(1) = -1.0;
double r = 0.05;
real_t r = 0.05;
VolumeForceCoefficient vforce_cf(r,center,force);
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
ElasticitySolver->SetEssentialBoundary(ess_bdr);
@@ -378,8 +380,8 @@ int main(int argc, char *argv[])
ParLinearForm vol_form(&control_fes);
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
vol_form.Assemble();
double domain_volume = vol_form(onegf);
const double target_volume = domain_volume * vol_fraction;
real_t domain_volume = vol_form(onegf);
const real_t target_volume = domain_volume * vol_fraction;
// 10. Connect to GLVis. Prepare for VisIt output.
char vishost[] = "localhost";
@@ -410,7 +412,7 @@ int main(int argc, char *argv[])
// 11. Iterate:
for (int k = 1; k <= max_it; k++)
{
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
if (k > 1) { alpha *= ((real_t) k) / ((real_t) k-1); }
if (myid == 0)
{
@@ -450,15 +452,16 @@ int main(int argc, char *argv[])
// Step 5 - Update design variable ψ ← proj(ψ - αG)
psi.Add(-alpha, grad);
const double material_volume = proj(psi, target_volume);
const real_t material_volume = proj(psi, target_volume);
// Compute ||ρ - ρ_old|| in control fes.
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
double norm_reduced_gradient = norm_increment/alpha;
real_t norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
real_t norm_reduced_gradient = norm_increment/alpha;
psi_old = psi;
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
MPI_Allreduce(MPI_IN_PLACE,&compliance,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
real_t compliance = (*(ElasticitySolver->GetLinearForm()))(u);
MPI_Allreduce(MPI_IN_PLACE, &compliance, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
if (myid == 0)
{
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient << endl;
@@ -480,7 +483,7 @@ int main(int argc, char *argv[])
{
rho_gf.ProjectCoefficient(rho);
paraview_dc.SetCycle(k);
paraview_dc.SetTime((double)k);
paraview_dc.SetTime((real_t)k);
paraview_dc.Save();
}
+12 -12
View File
@@ -46,7 +46,7 @@ enum class IntegrationType { Volumetric1D, Surface2D, Volumetric2D,
IntegrationType itype;
/// @brief Level-set function defining the implicit interface
double lvlset(const Vector& X)
real_t lvlset(const Vector& X)
{
switch (itype)
{
@@ -66,7 +66,7 @@ double lvlset(const Vector& X)
}
/// @brief Function that should be integrated
double integrand(const Vector& X)
real_t integrand(const Vector& X)
{
switch (itype)
{
@@ -86,7 +86,7 @@ double integrand(const Vector& X)
}
/// @brief Analytic surface integral
double Surface()
real_t Surface()
{
switch (itype)
{
@@ -106,7 +106,7 @@ double Surface()
}
/// @brief Analytic volume integral over subdomain with positive level-set
double Volume()
real_t Volume()
{
switch (itype)
{
@@ -424,7 +424,7 @@ public:
for (int ip = 0; ip < SIntRule->GetNPoints(); ip++)
{
Tr.SetIntPoint((&(SIntRule->IntPoint(ip))));
double val = Tr.Weight() * Q.Eval(Tr, SIntRule->IntPoint(ip));
real_t val = Tr.Weight() * Q.Eval(Tr, SIntRule->IntPoint(ip));
el.CalcShape(SIntRule->IntPoint(ip), shape);
add(elvect, SIntRule->IntPoint(ip).weight * val, shape, elvect);
}
@@ -492,7 +492,7 @@ public:
for (int ip = 0; ip < CIntRule->GetNPoints(); ip++)
{
Tr.SetIntPoint((&(CIntRule->IntPoint(ip))));
double val = Tr.Weight()
real_t val = Tr.Weight()
* Q.Eval(Tr, CIntRule->IntPoint(ip));
el.CalcPhysShape(Tr, shape);
add(elvect, CIntRule->IntPoint(ip).weight * val, shape, elvect);
@@ -504,8 +504,8 @@ public:
int main(int argc, char *argv[])
{
#ifndef MFEM_USE_LAPACK
cout << "MFEM must be build with LAPACK for this example." << endl;
return EXIT_FAILURE;
cout << "MFEM must be built with LAPACK for this example." << endl;
return MFEM_SKIP_RETURN_VALUE;
#else
// 1. Parse he command-line options.
int ref_levels = 3;
@@ -636,11 +636,11 @@ int main(int argc, char *argv[])
cout << "Mesh size dx: ";
if (itype != IntegrationType::Volumetric1D)
{
cout << 3.2 / pow(2., (double)ref_levels) << endl;
cout << 3.2 / pow(2., (real_t)ref_levels) << endl;
}
else
{
cout << .25 / pow(2., (double)ref_levels) << endl;
cout << .25 / pow(2., (real_t)ref_levels) << endl;
}
if (itype == IntegrationType::Surface2D
|| itype == IntegrationType::Volumetric2D)
@@ -652,7 +652,7 @@ int main(int argc, char *argv[])
cout << "============================================" << endl;
cout << "Computed value of surface integral: " << surface.Sum() << endl;
cout << "True value of surface integral: " << Surface() << endl;
cout << "Absolut Error (Surface): ";
cout << "Absolute Error (Surface): ";
cout << abs(surface.Sum() - Surface()) << endl;
cout << "Relative Error (Surface): ";
cout << abs(surface.Sum() - Surface()) / Surface() << endl;
@@ -663,7 +663,7 @@ int main(int argc, char *argv[])
cout << "--------------------------------------------" << endl;
cout << "Computed value of volume integral: " << volume.Sum() << endl;
cout << "True value of volume integral: " << Volume() << endl;
cout << "Absolut Error (Volume): ";
cout << "Absolute Error (Volume): ";
cout << abs(volume.Sum() - Volume()) << endl;
cout << "Relative Error (Volume): ";
cout << abs(volume.Sum() - Volume()) / Volume() << endl;
+285
View File
@@ -0,0 +1,285 @@
// MFEM Example 39
//
// Compile with: make ex39
//
// Sample runs: ex39
// ex39 -ess "Southern Boundary"
// ex39 -src Base
//
// Description: This example code demonstrates the use of named attribute
// sets in MFEM to specify material regions, boundary regions,
// or source regions by name rather than attribute numbers. It
// also demonstrates how new named attribute sets may be created
// from arbitrary groupings of attribute numbers and used as a
// convenient shorthand to refer to those groupings in other
// portions of the application or through the command line.
//
// The particular problem being solved here is nearly the same
// as that in example 1 i.e. a simple finite element
// discretization of the Laplace problem -Delta u = 1 with
// homogeneous Dirichlet boundary conditions and, in this case,
// an inhomogeneous diffusion coefficient. The diffusion
// coefficient is given a small default value throughout the
// domain which is increased by two separate amounts in two named
// regions.
//
// This example makes use of a specific input mesh, "compass.msh",
// containing named domain and boundary regions generated by Gmsh
// and stored in their "msh" format (version 2.2). This file
// defines eight boundary regions corresponding to eight compass
// headings; "ENE", "NNE", "NNW", "WSW", "SSW", "SSE", and "ESE".
// It also defines nine domain regions; "Base", "N Even", "N Odd",
// "W Even", "W Odd", "S Even", "S Odd", "E Even", and "E Odd".
// These regions split the four compass pointers into two halves
// each and also label the remaining elements as "Base". Starting
// with these named regions we test the construction of named
// sets as well as reading and writing these named groupings from
// and to mesh files.
//
// The example highlights the use of named attribute sets for
// both subdomains and boundaries in different contexts as well
// as basic methods to create named sets from existing attributes.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
const char *mesh_file = "../data/compass.msh";
int order = 1;
string source_name = "Rose Even";
string ess_name = "Boundary";
bool visualization = true;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) or -1 for"
" isoparametric space.");
args.AddOption(&source_name,"-src","--source-attr-name",
"Name of attribute set containing source.");
args.AddOption(&ess_name,"-ess","--ess-attr-name",
"Name of attribute set containing essential BC.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.ParseCheck();
// 2. Read the mesh from the given mesh file. We can handle triangular,
// quadrilateral, tetrahedral, hexahedral, surface and volume meshes with
// the same code.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
// 3. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
// largest number that gives a final mesh with no more than 50,000
// elements.
{
int ref_levels =
(int)floor(log(50000./mesh.GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
{
mesh.UniformRefinement();
}
}
// 4a. Display attribute set names contained in the initial mesh
AttributeSets &attr_sets = mesh.attribute_sets;
AttributeSets &bdr_attr_sets = mesh.bdr_attribute_sets;
{
std::set<string> names = attr_sets.GetAttributeSetNames();
cout << "Element Attribute Set Names: ";
for (auto const &set_name : names)
{
cout << " \"" << set_name << "\"";
}
cout << endl;
std::set<string> bdr_names = bdr_attr_sets.GetAttributeSetNames();
cout << "Boundary Attribute Set Names: ";
for (auto const &bdr_set_name : bdr_names)
{
cout << " \"" << bdr_set_name << "\"";
}
cout << endl;
}
// 4b. Define new regions based on existing attribute sets
{
Array<int> & Na = attr_sets.GetAttributeSet("N Even");
Array<int> & Nb = attr_sets.GetAttributeSet("N Odd");
Array<int> & Sa = attr_sets.GetAttributeSet("S Even");
Array<int> & Sb = attr_sets.GetAttributeSet("S Odd");
Array<int> & Ea = attr_sets.GetAttributeSet("E Even");
Array<int> & Eb = attr_sets.GetAttributeSet("E Odd");
Array<int> & Wa = attr_sets.GetAttributeSet("W Even");
Array<int> & Wb = attr_sets.GetAttributeSet("W Odd");
// Create a new set spanning the North point
attr_sets.SetAttributeSet("North", Na);
attr_sets.AddToAttributeSet("North", Nb);
// Create a new set spanning the South point
attr_sets.SetAttributeSet("South", Sa);
attr_sets.AddToAttributeSet("South", Sb);
// Create a new set spanning the East point
attr_sets.SetAttributeSet("East", Ea);
attr_sets.AddToAttributeSet("East", Eb);
// Create a new set spanning the West point
attr_sets.SetAttributeSet("West", Wa);
attr_sets.AddToAttributeSet("West", Wb);
// Create a new set consisting of the "a" sides of the compass rose
attr_sets.SetAttributeSet("Rose Even", Na);
attr_sets.AddToAttributeSet("Rose Even", Sa);
attr_sets.AddToAttributeSet("Rose Even", Ea);
attr_sets.AddToAttributeSet("Rose Even", Wa);
// Create a new set consisting of the "b" sides of the compass rose
attr_sets.SetAttributeSet("Rose Odd", Nb);
attr_sets.AddToAttributeSet("Rose Odd", Sb);
attr_sets.AddToAttributeSet("Rose Odd", Eb);
attr_sets.AddToAttributeSet("Rose Odd", Wb);
// Create a new set consisting of the full compass rose
Array<int> & Ra = attr_sets.GetAttributeSet("Rose Even");
Array<int> & Rb = attr_sets.GetAttributeSet("Rose Odd");
attr_sets.SetAttributeSet("Rose", Ra);
attr_sets.AddToAttributeSet("Rose", Rb);
}
// 4c. Define new boundary regions based on existing boundary attribute sets
{
Array<int> & NNE = bdr_attr_sets.GetAttributeSet("NNE");
Array<int> & NNW = bdr_attr_sets.GetAttributeSet("NNW");
Array<int> & ENE = bdr_attr_sets.GetAttributeSet("ENE");
Array<int> & ESE = bdr_attr_sets.GetAttributeSet("ESE");
Array<int> & SSE = bdr_attr_sets.GetAttributeSet("SSE");
Array<int> & SSW = bdr_attr_sets.GetAttributeSet("SSW");
Array<int> & WNW = bdr_attr_sets.GetAttributeSet("WNW");
Array<int> & WSW = bdr_attr_sets.GetAttributeSet("WSW");
bdr_attr_sets.SetAttributeSet("Northern Boundary", NNE);
bdr_attr_sets.AddToAttributeSet("Northern Boundary", NNW);
bdr_attr_sets.SetAttributeSet("Southern Boundary", SSE);
bdr_attr_sets.AddToAttributeSet("Southern Boundary", SSW);
bdr_attr_sets.SetAttributeSet("Eastern Boundary", ENE);
bdr_attr_sets.AddToAttributeSet("Eastern Boundary", ESE);
bdr_attr_sets.SetAttributeSet("Western Boundary", WNW);
bdr_attr_sets.AddToAttributeSet("Western Boundary", WSW);
bdr_attr_sets.SetAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Northern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Southern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Eastern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Western Boundary"));
}
// 5. Define a finite element space on the mesh. Here we use continuous
// Lagrange finite elements of the specified order.
H1_FECollection fec(order, mesh.Dimension());
FiniteElementSpace fespace(&mesh, &fec);
cout << "Number of finite element unknowns: "
<< fespace.GetTrueVSize() << endl;
// 6. Determine the list of true (i.e. conforming) essential boundary dofs.
// In this example, the boundary conditions are defined by marking all
// the boundary regions corresponding to the boundary attributes
// contained in the set named "ess_name" as essential (Dirichlet) and
// converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (bdr_attr_sets.AttributeSetExists(ess_name))
{
Array<int> ess_bdr_marker = bdr_attr_sets.GetAttributeSetMarker(ess_name);
fespace.GetEssentialTrueDofs(ess_bdr_marker, ess_tdof_list);
}
// 7. Set up the linear form b(.) which corresponds to the right-hand side of
// the FEM linear system, which in this case is (1_s,phi_i) where phi_i
// are the basis functions in fespace and 1_s is an indicator function
// equal to 1 on the region defined by the named set "source_name" and
// zero elsewhere.
Array<int> source_marker = attr_sets.GetAttributeSetMarker(source_name);
LinearForm b(&fespace);
ConstantCoefficient one(1.0);
b.AddDomainIntegrator(new DomainLFIntegrator(one), source_marker);
b.Assemble();
// 8. Define the solution vector x as a finite element grid function
// corresponding to fespace. Initialize x with initial guess of zero,
// which satisfies the boundary conditions.
GridFunction x(&fespace);
x = 0.0;
// 9. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the Laplacian operator -Delta, by adding the
// Diffusion domain integrator.
BilinearForm a(&fespace);
ConstantCoefficient defaultCoef(1.0e-6);
ConstantCoefficient baseCoef(1.0);
ConstantCoefficient roseCoef(2.0);
Array<int> base_marker = attr_sets.GetAttributeSetMarker("Base");
Array<int> rose_marker = attr_sets.GetAttributeSetMarker("Rose Even");
// Impose a very small diffusion coefficient across the entire mesh
a.AddDomainIntegrator(new DiffusionIntegrator(defaultCoef));
// Impose an additional, stronger diffusion coefficient in select regions
a.AddDomainIntegrator(new DiffusionIntegrator(baseCoef), base_marker);
a.AddDomainIntegrator(new DiffusionIntegrator(roseCoef), rose_marker);
// 10. Assemble the bilinear form and the corresponding linear system,
// applying any necessary transformations.
a.Assemble();
SparseMatrix A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
cout << "Size of linear system: " << A.Height() << endl;
// 11. Solve the system using PCG with symmetric Gauss-Seidel preconditioner.
GSSmoother M(A);
PCG(A, M, B, X, 1, 800, 1e-12, 0.0);
// 12. Recover the solution as a finite element grid function.
a.RecoverFEMSolution(X, b, x);
// 13. Save the refined mesh and the solution. This output can be viewed
// later using GLVis: "glvis -m refined.mesh -g sol.gf".
mesh.Save("refined.mesh");
x.Save("sol.gf");
// 14. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock(vishost, visport);
sol_sock.precision(8);
sol_sock << "solution\n" << mesh << x << "keys Rjmm" << flush;
}
return 0;
}
+314
View File
@@ -0,0 +1,314 @@
// MFEM Example 39 - Parallel Version
//
// Compile with: make ex39p
//
// Sample runs: mpirun -np 4 ex39p
// mpirun -np 4 ex39p -ess "Southern Boundary"
// mpirun -np 4 ex39p -src Base
//
// Description: This example code demonstrates the use of named attribute
// sets in MFEM to specify material regions, boundary regions,
// or source regions by name rather than attribute numbers. It
// also demonstrates how new named attribute sets may be created
// from arbitrary groupings of attribute numbers and used as a
// convenient shorthand to refer to those groupings in other
// portions of the application or through the command line.
//
// The particular problem being solved here is nearly the same
// as that in example 1 i.e. a simple finite element
// discretization of the Laplace problem -Delta u = 1 with
// homogeneous Dirichlet boundary conditions and, in this case,
// an inhomogeneous diffusion coefficient. The diffusion
// coefficient is given a small default value throughout the
// domain which is increased by two separate amounts in two named
// regions.
//
// This example makes use of a specific input mesh, "compass.msh",
// containing named domain and boundary regions generated by Gmsh
// and stored in their "msh" format (version 2.2). This file
// defines eight boundary regions corresponding to eight compass
// headings; "ENE", "NNE", "NNW", "WSW", "SSW", "SSE", and "ESE".
// It also defines nine domain regions; "Base", "N Even", "N Odd",
// "W Even", "W Odd", "S Even", "S Odd", "E Even", and "E Odd".
// These regions split the four compass pointers into two halves
// each and also label the remaining elements as "Base". Starting
// with these named regions we test the construction of named
// sets as well as reading and writing these named groupings from
// and to mesh files.
//
// The example highlights the use of named attribute sets for
// both subdomains and boundaries in different contexts as well
// as basic methods to create named sets from existing attributes.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
Mpi::Init();
Hypre::Init();
// 2. Parse command-line options.
const char *mesh_file = "../data/compass.msh";
int order = 1;
string source_name = "Rose Even";
string ess_name = "Boundary";
bool visualization = true;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) or -1 for"
" isoparametric space.");
args.AddOption(&source_name,"-src","--source-attr-name",
"Name of attribute set containing source.");
args.AddOption(&ess_name,"-ess","--ess-attr-name",
"Name of attribute set containing essential BC.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.ParseCheck();
// 3. Read the serial mesh from the given mesh file.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
// 4. Refine the serial mesh on all processors to increase the resolution. In
// this example we do 'ref_levels' of uniform refinement. We choose
// 'ref_levels' to be the largest number that gives a final mesh with no
// more than 10,000 elements.
{
int ref_levels =
(int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
{
mesh.UniformRefinement();
}
}
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted.
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
{
int par_ref_levels = 2;
for (int l = 0; l < par_ref_levels; l++)
{
pmesh.UniformRefinement();
}
}
// 6a. Display attribute set names contained in the initial mesh
AttributeSets &attr_sets = pmesh.attribute_sets;
AttributeSets &bdr_attr_sets = pmesh.bdr_attribute_sets;
if (Mpi::Root())
{
std::set<string> names = attr_sets.GetAttributeSetNames();
cout << "Element Attribute Set Names: ";
for (auto const &set_name : names)
{
cout << " \"" << set_name << "\"";
}
cout << endl;
std::set<string> bdr_names = bdr_attr_sets.GetAttributeSetNames();
cout << "Boundary Attribute Set Names: ";
for (auto const &bdr_set_name : bdr_names)
{
cout << " \"" << bdr_set_name << "\"";
}
cout << endl;
}
// 6b. Define new regions based on existing attribute sets
{
Array<int> & Na = attr_sets.GetAttributeSet("N Even");
Array<int> & Nb = attr_sets.GetAttributeSet("N Odd");
Array<int> & Sa = attr_sets.GetAttributeSet("S Even");
Array<int> & Sb = attr_sets.GetAttributeSet("S Odd");
Array<int> & Ea = attr_sets.GetAttributeSet("E Even");
Array<int> & Eb = attr_sets.GetAttributeSet("E Odd");
Array<int> & Wa = attr_sets.GetAttributeSet("W Even");
Array<int> & Wb = attr_sets.GetAttributeSet("W Odd");
// Create a new set spanning the North point
attr_sets.SetAttributeSet("North", Na);
attr_sets.AddToAttributeSet("North", Nb);
// Create a new set spanning the South point
attr_sets.SetAttributeSet("South", Sa);
attr_sets.AddToAttributeSet("South", Sb);
// Create a new set spanning the East point
attr_sets.SetAttributeSet("East", Ea);
attr_sets.AddToAttributeSet("East", Eb);
// Create a new set spanning the West point
attr_sets.SetAttributeSet("West", Wa);
attr_sets.AddToAttributeSet("West", Wb);
// Create a new set consisting of the "a" sides of the compass rose
attr_sets.SetAttributeSet("Rose Even", Na);
attr_sets.AddToAttributeSet("Rose Even", Sa);
attr_sets.AddToAttributeSet("Rose Even", Ea);
attr_sets.AddToAttributeSet("Rose Even", Wa);
// Create a new set consisting of the "b" sides of the compass rose
attr_sets.SetAttributeSet("Rose Odd", Nb);
attr_sets.AddToAttributeSet("Rose Odd", Sb);
attr_sets.AddToAttributeSet("Rose Odd", Eb);
attr_sets.AddToAttributeSet("Rose Odd", Wb);
// Create a new set consisting of the full compass rose
Array<int> & Ra = attr_sets.GetAttributeSet("Rose Even");
Array<int> & Rb = attr_sets.GetAttributeSet("Rose Odd");
attr_sets.SetAttributeSet("Rose", Ra);
attr_sets.AddToAttributeSet("Rose", Rb);
}
// 6c. Define new boundary regions based on existing boundary attribute sets
{
Array<int> & NNE = bdr_attr_sets.GetAttributeSet("NNE");
Array<int> & NNW = bdr_attr_sets.GetAttributeSet("NNW");
Array<int> & ENE = bdr_attr_sets.GetAttributeSet("ENE");
Array<int> & ESE = bdr_attr_sets.GetAttributeSet("ESE");
Array<int> & SSE = bdr_attr_sets.GetAttributeSet("SSE");
Array<int> & SSW = bdr_attr_sets.GetAttributeSet("SSW");
Array<int> & WNW = bdr_attr_sets.GetAttributeSet("WNW");
Array<int> & WSW = bdr_attr_sets.GetAttributeSet("WSW");
bdr_attr_sets.SetAttributeSet("Northern Boundary", NNE);
bdr_attr_sets.AddToAttributeSet("Northern Boundary", NNW);
bdr_attr_sets.SetAttributeSet("Southern Boundary", SSE);
bdr_attr_sets.AddToAttributeSet("Southern Boundary", SSW);
bdr_attr_sets.SetAttributeSet("Eastern Boundary", ENE);
bdr_attr_sets.AddToAttributeSet("Eastern Boundary", ESE);
bdr_attr_sets.SetAttributeSet("Western Boundary", WNW);
bdr_attr_sets.AddToAttributeSet("Western Boundary", WSW);
bdr_attr_sets.SetAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Northern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Southern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Eastern Boundary"));
bdr_attr_sets.AddToAttributeSet("Boundary",
bdr_attr_sets.GetAttributeSet
("Western Boundary"));
}
// 7. Define a parallel finite element space on the parallel mesh. Here we
// use continuous Lagrange finite elements of the specified order. If
// order < 1, we instead use an isoparametric/isogeometric space.
H1_FECollection fec(order, dim);
ParFiniteElementSpace fespace(&pmesh, &fec);
HYPRE_BigInt size = fespace.GlobalTrueVSize();
if (Mpi::Root())
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 8. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary regions corresponding to the boundary
// attributes contained in the set named "ess_name" as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (bdr_attr_sets.AttributeSetExists(ess_name))
{
Array<int> ess_bdr_marker = bdr_attr_sets.GetAttributeSetMarker(ess_name);
fespace.GetEssentialTrueDofs(ess_bdr_marker, ess_tdof_list);
}
// 9. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system, which in this case is
// (1_s,phi_i) where phi_i are the basis functions in fespace and 1_s
// is an indicator function equal to 1 on the region defined by the
// named set "source_name" and zero elsewhere.
Array<int> source_marker = attr_sets.GetAttributeSetMarker(source_name);
ParLinearForm b(&fespace);
ConstantCoefficient one(1.0);
b.AddDomainIntegrator(new DomainLFIntegrator(one), source_marker);
b.Assemble();
// 10. Define the solution vector x as a parallel finite element grid
// function corresponding to fespace. Initialize x with initial guess of
// zero, which satisfies the boundary conditions.
ParGridFunction x(&fespace);
x = 0.0;
// 11. Set up the parallel bilinear form a(.,.) on the finite element space
// corresponding to the Laplacian operator -Delta, by adding the
// Diffusion domain integrator.
ParBilinearForm a(&fespace);
ConstantCoefficient defaultCoef(1.0e-6);
ConstantCoefficient baseCoef(1.0);
ConstantCoefficient roseCoef(2.0);
Array<int> base_marker = attr_sets.GetAttributeSetMarker("Base");
Array<int> rose_marker = attr_sets.GetAttributeSetMarker("Rose Even");
// Impose a very small diffusion coefficient across the entire mesh
a.AddDomainIntegrator(new DiffusionIntegrator(defaultCoef));
// Impose an additional, stronger diffusion coefficient in select regions
a.AddDomainIntegrator(new DiffusionIntegrator(baseCoef), base_marker);
a.AddDomainIntegrator(new DiffusionIntegrator(roseCoef), rose_marker);
// 12. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations.
a.Assemble();
HypreParMatrix A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
// 13. Solve the system using PCG with hypre's BoomerAMG preconditioner.
HypreBoomerAMG M(A);
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(1e-12);
cg.SetMaxIter(2000);
cg.SetPrintLevel(1);
cg.SetPreconditioner(M);
cg.SetOperator(A);
cg.Mult(B, X);
// 14. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a.RecoverFEMSolution(X, b, x);
// 15. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
pmesh.Save("mesh");
x.Save("sol");
// 16. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
int num_procs = Mpi::WorldSize();
int myid = Mpi::WorldRank();
socketstream sol_sock(vishost, visport);
sol_sock << "parallel " << num_procs << " " << myid << "\n";
sol_sock.precision(8);
sol_sock << "solution\n" << pmesh << x << "keys Rjmm" << flush;
}
return 0;
}
+2 -2
View File
@@ -55,7 +55,7 @@ using namespace mfem;
// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int dim;
int main(int argc, char *argv[])
@@ -263,7 +263,7 @@ int main(int argc, char *argv[])
// 15. Compute and print the L^2 norm of the error.
{
double error = x.ComputeL2Error(E);
real_t error = x.ComputeL2Error(E);
if (myid == 0)
{
cout << "\n|| E_h - E ||_{L^2} = " << error << '\n' << endl;
+8 -8
View File
@@ -54,7 +54,7 @@ using namespace mfem;
// Exact solution, F, and r.h.s., f. See below for implementation.
void F_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -269,9 +269,9 @@ void F_exact(const Vector &p, Vector &F)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0; // Uncomment if F is changed to depend on z
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if F is changed to depend on z
F(0) = cos(kappa*x)*sin(kappa*y);
F(1) = cos(kappa*y)*sin(kappa*x);
@@ -286,11 +286,11 @@ void f_exact(const Vector &p, Vector &f)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0; // Uncomment if f is changed to depend on z
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if f is changed to depend on z
double temp = 1 + 2*kappa*kappa;
real_t temp = 1 + 2*kappa*kappa;
f(0) = temp*cos(kappa*x)*sin(kappa*y);
f(1) = temp*cos(kappa*y)*sin(kappa*x);
+411
View File
@@ -0,0 +1,411 @@
// MFEM Example 40
//
// Compile with: make ex40
//
// Sample runs: ex40 -o 2
// ex40 -o 2 -r 4
//
// Description: This example code demonstrates to how to use MFEM to solve
// the MongeAmpère equation
//
// det(∇²u) = f in Ω, u = 0 on ∂Ω.
//
// This example highlights the ExponentialMatrixCoefficient
// class, which is used in Newton's method to solve the
// variational formulation
//
// Find M ∈ H₀(div,Ω)ⁿ and u ∈ H₀¹(Ω) such that
// (exp(M), N) + (∇u, ∇⋅N) = 0 ∀ N ∈ H₀(div,Ω)ⁿ
// (tr(M), v) = (ln f, v) ∀ v ∈ H₀¹(Ω)
//
// where n is the spatial dimension of the domain Ω.
//
//
// The linearized subproblem is
//
// Find δM ∈ H₀(div,Ω)ⁿ and u ∈ H₀¹(Ω) such that
// (exp(M) δM, N) + (∇u, ∇⋅N) = -(exp(M), N) ∀ N ∈ H₀(div,Ω)ⁿ
// (tr(δM), v) = (ln f - tr(M), v) ∀ v ∈ H₀¹(Ω)
//
//
// (exp(M) δM, N) ::: VectorFEMassIntegrator
// (∇u, ∇⋅N) ::: MixedGradDivIntegrator
// (tr(δM), v) ::: MixedDotProductIntegrator
// (exp(M), N) ::: VectorFEDomainLFIntegrator
// (ln f - tr(M), v) ::: DomainLFIntegrator
//
//
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
real_t exact_solution(const Vector &pt);
void exact_solution_gradient(const Vector &pt, Vector &grad);
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
const char *mesh_file = "../data/disc-nurbs.mesh";
// const char *mesh_file = "../data/star.mesh";
int order = 2;
int max_it = 10;
int ref_levels = 1;
real_t tol = 1e-5;
bool visualization = true;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&ref_levels, "-r", "--refs",
"Number of h-refinements.");
args.AddOption(&max_it, "-mi", "--max-it",
"Maximum number of iterations");
args.AddOption(&tol, "-tol", "--tol",
"Stopping criteria based on the difference between"
"successive solution updates");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
args.PrintOptions(cout);
// 2. Read the mesh from the mesh file.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
if (dim != 2)
{
MFEM_ABORT("Example 40 currently only supports 2D problems")
}
// 3. Postprocess the mesh.
// 3A. Refine the mesh to increase the resolution.
for (int l = 0; l < ref_levels; l++)
{
mesh.UniformRefinement();
}
// 3B. Interpolate the geometry after refinement to control geometry error.
// NOTE: Minimum second-order interpolation is used to improve the accuracy.
int curvature_order = max(order,2);
mesh.SetCurvature(curvature_order);
// 4. Define the necessary finite element spaces on the mesh.
H1_FECollection H1fec(order, dim);
FiniteElementSpace H1fes(&mesh, &H1fec);
RT_FECollection RTfec(order-1, dim);
FiniteElementSpace RTfes(&mesh, &RTfec);
cout << "Number of H¹ degrees of freedom: "
<< H1fes.GetTrueVSize() << endl;
cout << "Number of H(div) degrees of freedom: "
<< RTfes.GetTrueVSize() * dim << endl;
Array<int> offsets(4);
offsets[0] = 0;
offsets[1] = RTfes.GetVSize();
offsets[2] = RTfes.GetVSize();
offsets[3] = H1fes.GetVSize();
offsets.PartialSum();
BlockVector x(offsets), rhs(offsets);
x = 0.0; rhs = 0.0;
// 5. Determine the list of true (i.e., conforming) essential boundary dofs.
Array<int> ess_bdr;
if (mesh.bdr_attributes.Size())
{
ess_bdr.SetSize(mesh.bdr_attributes.Max());
ess_bdr = 1;
}
// 6. Define constants to be used later.
ConstantCoefficient one(1.0);
ConstantCoefficient neg_one(-1.0);
ConstantCoefficient zero(0.0);
Vector V1(2), V2(2);
V1(0) = 1.0; V1(1) = 0.0;
V2(0) = 0.0; V2(1) = 1.0;
VectorConstantCoefficient onezero(V1);
VectorConstantCoefficient zeroone(V2);
ScalarVectorProductCoefficient neg_onezero(-1.0, onezero);
ScalarVectorProductCoefficient neg_zeroone(-1.0, zeroone);
// 7. Define the solution vectors as finite element grid functions
// corresponding to the fespaces.
GridFunction delta_M1_gf, delta_M2_gf, delta_u_gf;
delta_M1_gf.MakeRef(&RTfes,x,offsets[0]);
delta_M2_gf.MakeRef(&RTfes,x,offsets[1]);
delta_u_gf.MakeRef(&H1fes,x,offsets[2]);
GridFunction M1_gf(&RTfes);
GridFunction M2_gf(&RTfes);
GridFunction u_gf(&H1fes);
// 8. Define the function coefficients for the solution and use them to
// initialize the initial guess
FunctionCoefficient exact_coef(exact_solution);
VectorFunctionCoefficient exact_grad_coef(dim,exact_solution_gradient);
ConstantCoefficient ln_rhs_coef(0.0);
u_gf.ProjectCoefficient(exact_coef);
// u_gf.ProjectCoefficient(zero);
M1_gf = 0.0;
M2_gf = 0.0;
delta_M1_gf = 0.0;
delta_M2_gf = 0.0;
delta_u_gf = 0.0;
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock;
if (visualization)
{
sol_sock.open(vishost,visport);
sol_sock.precision(8);
}
// 10. Iterate
int k;
for (k = 0; k < max_it; k++)
{
mfem::out << "\nITERATION " << k+1 << endl;
LinearForm b0,b1,b2;
b0.Update(&RTfes,rhs.GetBlock(0),0);
b1.Update(&RTfes,rhs.GetBlock(1),0);
b2.Update(&H1fes,rhs.GetBlock(2),0);
VectorGridFunctionCoefficient M1(&M1_gf);
VectorGridFunctionCoefficient M2(&M2_gf);
MatrixArrayVectorCoefficient M(dim);
M.Set(0, &M1, false);
M.Set(1, &M2, false);
ExponentialMatrixCoefficient exp_M(M);
MatrixVectorProductCoefficient exp_M1(exp_M, onezero);
MatrixVectorProductCoefficient exp_M2(exp_M, zeroone);
InnerProductCoefficient exp_M11(exp_M1, onezero);
InnerProductCoefficient exp_M12(exp_M1, zeroone);
InnerProductCoefficient exp_M21(exp_M2, onezero);
InnerProductCoefficient exp_M22(exp_M2, zeroone);
GradientGridFunctionCoefficient grad_u(&u_gf);
InnerProductCoefficient neg_dudx(neg_onezero, grad_u);
ScalarVectorProductCoefficient neg_exp_M1(-1.0, exp_M1);
b0.AddDomainIntegrator(new VectorFEDomainLFDivIntegrator(neg_dudx));
b0.AddDomainIntegrator(new VectorFEDomainLFIntegrator(neg_exp_M1));
b0.Assemble();
InnerProductCoefficient neg_dudy(neg_zeroone, grad_u);
b1.AddDomainIntegrator(new VectorFEDomainLFDivIntegrator(neg_dudy));
ScalarVectorProductCoefficient neg_exp_M2(-1.0, exp_M2);
b1.AddDomainIntegrator(new VectorFEDomainLFIntegrator(neg_exp_M2));
b1.Assemble();
InnerProductCoefficient M11(M1, onezero);
InnerProductCoefficient M22(M2, zeroone);
SumCoefficient trace_M(M11, M22);
SumCoefficient rhs2(ln_rhs_coef, trace_M, 1.0, -1.0);
b2.AddDomainIntegrator(new DomainLFIntegrator(rhs2));
b2.Assemble();
cout << "b0.Norml2() = " << b0.Norml2() << endl;
cout << "b1.Norml2() = " << b1.Norml2() << endl;
cout << "b2.Norml2() = " << b2.Norml2() << endl;
BilinearForm a00(&RTfes);
a00.AddDomainIntegrator(new VectorFEMassIntegrator());
// a00.AddDomainIntegrator(new VectorFEMassIntegrator(exp_M11));
a00.Assemble();
a00.EliminateEssentialBC(ess_bdr,x.GetBlock(0),rhs.GetBlock(0),mfem::Operator::DIAG_ONE);
a00.Finalize();
SparseMatrix &A00 = a00.SpMat();
BilinearForm a01(&RTfes);
a01.AddDomainIntegrator(new VectorFEMassIntegrator(zero));
// a01.AddDomainIntegrator(new VectorFEMassIntegrator(exp_M12));
a01.Assemble();
a01.EliminateEssentialBC(ess_bdr,mfem::Operator::DIAG_ZERO);
a01.Finalize();
SparseMatrix &A01 = a01.SpMat();
MixedBilinearForm a02(&H1fes,&RTfes);
a02.AddDomainIntegrator(new MixedGradDivIntegrator(neg_onezero));
a02.Assemble(false);
a02.EliminateTrialDofs(ess_bdr,x.GetBlock(2),rhs.GetBlock(0));
a02.EliminateTestDofs(ess_bdr);
a02.Finalize();
SparseMatrix &A02 = a02.SpMat();
BilinearForm a10(&RTfes);
a10.AddDomainIntegrator(new VectorFEMassIntegrator(zero));
// a10.AddDomainIntegrator(new VectorFEMassIntegrator(exp_M21));
a10.Assemble();
a10.EliminateEssentialBC(ess_bdr,mfem::Operator::DIAG_ZERO);
a10.Finalize();
SparseMatrix &A10 = a10.SpMat();
BilinearForm a11(&RTfes);
a11.AddDomainIntegrator(new VectorFEMassIntegrator());
// a11.AddDomainIntegrator(new VectorFEMassIntegrator(exp_M22));
a11.Assemble();
a11.EliminateEssentialBC(ess_bdr,x.GetBlock(1),rhs.GetBlock(1),mfem::Operator::DIAG_ONE);
a11.Finalize();
SparseMatrix &A11 = a11.SpMat();
MixedBilinearForm a12(&H1fes,&RTfes);
a12.AddDomainIntegrator(new MixedGradDivIntegrator(neg_zeroone));
a12.Assemble(false);
a12.EliminateTrialDofs(ess_bdr,x.GetBlock(2),rhs.GetBlock(1));
a12.EliminateTestDofs(ess_bdr);
a12.Finalize();
SparseMatrix &A12 = a12.SpMat();
MixedBilinearForm a20(&RTfes,&H1fes);
a20.AddDomainIntegrator(new MixedDotProductIntegrator(onezero));
a20.Assemble();
a20.EliminateTrialDofs(ess_bdr,x.GetBlock(0),rhs.GetBlock(2));
a20.EliminateTestDofs(ess_bdr);
a20.Finalize();
SparseMatrix &A20 = a20.SpMat();
MixedBilinearForm a21(&RTfes,&H1fes);
a21.AddDomainIntegrator(new MixedDotProductIntegrator(zeroone));
a21.Assemble();
a21.EliminateTrialDofs(ess_bdr,x.GetBlock(1),rhs.GetBlock(2));
a21.EliminateTestDofs(ess_bdr);
a21.Finalize();
SparseMatrix &A21 = a21.SpMat();
BilinearForm a22(&H1fes);
// a22.AddDomainIntegrator(new MassIntegrator(neg_one));
a22.AddDomainIntegrator(new MassIntegrator(zero));
a22.Assemble(false);
a22.EliminateEssentialBC(ess_bdr,x.GetBlock(2),rhs.GetBlock(2),mfem::Operator::DIAG_ONE);
a22.Finalize();
SparseMatrix &A22 = a22.SpMat();
cout << "b0.Norml2() = " << b0.Norml2() << endl;
cout << "b1.Norml2() = " << b1.Norml2() << endl;
cout << "b2.Norml2() = " << b2.Norml2() << endl;
// BlockOperator A(offsets);
// A.SetBlock(0,0,&A00);
// A.SetBlock(0,1,&A01);
// A.SetBlock(0,2,&A02);
// A.SetBlock(1,0,&A10);
// A.SetBlock(1,1,&A11);
// A.SetBlock(1,2,&A12);
// A.SetBlock(2,0,&A20);
// A.SetBlock(2,1,&A21);
// A.SetBlock(2,2,&A22);
// BlockDiagonalPreconditioner prec(offsets);
// prec.SetDiagonalBlock(0,new GSSmoother(A00));
// prec.SetDiagonalBlock(1,new GSSmoother(A11));
// prec.SetDiagonalBlock(1,new GSSmoother(A22));
// prec.owns_blocks = 1;
// GMRES(A,prec,rhs,x,1,10000,500,1e-12,0.0);
BlockMatrix A(offsets);
A.SetBlock(0,0,&A00);
A.SetBlock(0,1,&A01);
A.SetBlock(0,2,&A02);
A.SetBlock(1,0,&A10);
A.SetBlock(1,1,&A11);
A.SetBlock(1,2,&A12);
A.SetBlock(2,0,&A20);
A.SetBlock(2,1,&A21);
A.SetBlock(2,2,&A22);
SparseMatrix * A_mono = A.CreateMonolithic();
UMFPackSolver umf(*A_mono);
umf.Mult(rhs,x);
delta_M1_gf.MakeRef(&RTfes, x.GetBlock(0), 0);
delta_M2_gf.MakeRef(&RTfes, x.GetBlock(1), 0);
delta_u_gf.MakeRef(&H1fes, x.GetBlock(2), 0);
real_t Newton_update_size = delta_u_gf.ComputeL2Error(zero);
real_t gamma = 0.3;
delta_M1_gf *= gamma;
delta_M2_gf *= gamma;
delta_u_gf *= gamma;
M1_gf += delta_M1_gf;
M2_gf += delta_M2_gf;
u_gf += delta_u_gf;
if (visualization)
{
// sol_sock << "solution\n" << mesh << delta_M1_gf << "window_title 'Discrete solution'"
sol_sock << "solution\n" << mesh << u_gf << "window_title 'Discrete solution'"
<< flush;
mfem::out << "Increment (|| uₕ - uₕ_prvs||) = " << Newton_update_size <<
endl;
}
// if (Newton_update_size < tol || k == max_it-1)
// {
// break;
// }
real_t H1_error = u_gf.ComputeH1Error(&exact_coef,&exact_grad_coef);
real_t L2_error = u_gf.ComputeL2Error(exact_coef);
mfem::out << "L2-error (|| u - uₕᵏ||) = " << L2_error << endl;
// mfem::out << "H1-error (|| u - uₕᵏ||) = " << H1_error << endl;
cin.get();
}
mfem::out << "\n Total iterations: " << k+1
<< "\n Total dofs: " << RTfes.GetTrueVSize() * 2 + H1fes.GetTrueVSize()
<< endl;
// 11. Exact solution.
// if (visualization)
// {
// socketstream err_sock(vishost, visport);
// err_sock.precision(8);
// GridFunction error_gf(&H1fes);
// error_gf.ProjectCoefficient(exact_coef);
// error_gf -= u_gf;
// err_sock << "solution\n" << mesh << error_gf << "window_title 'Error'" <<
// flush;
// }
return 0;
}
real_t exact_solution(const Vector &pt)
{
real_t x = pt(0), y = pt(1);
return (x*x + y*y) / 2.0 - 4.0;
}
void exact_solution_gradient(const Vector &pt, Vector &grad)
{
real_t x = pt(0), y = pt(1);
grad(0) = x;
grad(1) = y;
}
+9 -9
View File
@@ -54,7 +54,7 @@ using namespace mfem;
// Exact solution, F, and r.h.s., f. See below for implementation.
void F_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -255,7 +255,7 @@ int main(int argc, char *argv[])
// 15. Compute and print the L^2 norm of the error.
{
double error = x.ComputeL2Error(F);
real_t error = x.ComputeL2Error(F);
if (myid == 0)
{
cout << "\n|| F_h - F ||_{L^2} = " << error << '\n' << endl;
@@ -311,9 +311,9 @@ void F_exact(const Vector &p, Vector &F)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0; // Uncomment if F is changed to depend on z
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if F is changed to depend on z
F(0) = cos(kappa*x)*sin(kappa*y);
F(1) = cos(kappa*y)*sin(kappa*x);
@@ -328,11 +328,11 @@ void f_exact(const Vector &p, Vector &f)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0; // Uncomment if f is changed to depend on z
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if f is changed to depend on z
double temp = 1 + 2*kappa*kappa;
real_t temp = 1 + 2*kappa*kappa;
f(0) = temp*cos(kappa*x)*sin(kappa*y);
f(1) = temp*cos(kappa*y)*sin(kappa*x);
+18 -18
View File
@@ -45,10 +45,10 @@ using namespace mfem;
// Define the analytical solution and forcing terms / boundary conditions
void uFun_ex(const Vector & x, Vector & u);
double pFun_ex(const Vector & x);
real_t pFun_ex(const Vector & x);
void fFun(const Vector & x, Vector & f);
double gFun(const Vector & x);
double f_natural(const Vector & x);
real_t gFun(const Vector & x);
real_t f_natural(const Vector & x);
int main(int argc, char *argv[])
{
@@ -270,8 +270,8 @@ int main(int argc, char *argv[])
// 11. Solve the linear system with MINRES.
// Check the norm of the unpreconditioned residual.
int maxIter(1000);
double rtol(1.e-6);
double atol(1.e-10);
real_t rtol(1.e-6);
real_t atol(1.e-10);
chrono.Clear();
chrono.Start();
@@ -313,10 +313,10 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double err_u = u.ComputeL2Error(ucoeff, irs);
double norm_u = ComputeLpNorm(2., ucoeff, *mesh, irs);
double err_p = p.ComputeL2Error(pcoeff, irs);
double norm_p = ComputeLpNorm(2., pcoeff, *mesh, irs);
real_t err_u = u.ComputeL2Error(ucoeff, irs);
real_t norm_u = ComputeLpNorm(2., ucoeff, *mesh, irs);
real_t err_p = p.ComputeL2Error(pcoeff, irs);
real_t norm_p = ComputeLpNorm(2., pcoeff, *mesh, irs);
std::cout << "|| u_h - u_ex || / || u_ex || = " << err_u / norm_u << "\n";
std::cout << "|| p_h - p_ex || / || p_ex || = " << err_p / norm_p << "\n";
@@ -391,9 +391,9 @@ int main(int argc, char *argv[])
void uFun_ex(const Vector & x, Vector & u)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
zi = x(2);
@@ -409,11 +409,11 @@ void uFun_ex(const Vector & x, Vector & u)
}
// Change if needed
double pFun_ex(const Vector & x)
real_t pFun_ex(const Vector & x)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
@@ -428,7 +428,7 @@ void fFun(const Vector & x, Vector & f)
f = 0.0;
}
double gFun(const Vector & x)
real_t gFun(const Vector & x)
{
if (x.Size() == 3)
{
@@ -440,7 +440,7 @@ double gFun(const Vector & x)
}
}
double f_natural(const Vector & x)
real_t f_natural(const Vector & x)
{
return (-pFun_ex(x));
}
+18 -18
View File
@@ -46,10 +46,10 @@ using namespace mfem;
// Define the analytical solution and forcing terms / boundary conditions
void uFun_ex(const Vector & x, Vector & u);
double pFun_ex(const Vector & x);
real_t pFun_ex(const Vector & x);
void fFun(const Vector & x, Vector & f);
double gFun(const Vector & x);
double f_natural(const Vector & x);
real_t gFun(const Vector & x);
real_t f_natural(const Vector & x);
int main(int argc, char *argv[])
{
@@ -326,8 +326,8 @@ int main(int argc, char *argv[])
// 13. Solve the linear system with MINRES.
// Check the norm of the unpreconditioned residual.
int maxIter(pa ? 1000 : 500);
double rtol(1.e-6);
double atol(1.e-10);
real_t rtol(1.e-6);
real_t atol(1.e-10);
chrono.Clear();
chrono.Start();
@@ -371,10 +371,10 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double err_u = u->ComputeL2Error(ucoeff, irs);
double norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs);
double err_p = p->ComputeL2Error(pcoeff, irs);
double norm_p = ComputeGlobalLpNorm(2, pcoeff, *pmesh, irs);
real_t err_u = u->ComputeL2Error(ucoeff, irs);
real_t norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs);
real_t err_p = p->ComputeL2Error(pcoeff, irs);
real_t norm_p = ComputeGlobalLpNorm(2, pcoeff, *pmesh, irs);
if (verbose)
{
@@ -493,9 +493,9 @@ int main(int argc, char *argv[])
void uFun_ex(const Vector & x, Vector & u)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
zi = x(2);
@@ -511,11 +511,11 @@ void uFun_ex(const Vector & x, Vector & u)
}
// Change if needed
double pFun_ex(const Vector & x)
real_t pFun_ex(const Vector & x)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
@@ -530,7 +530,7 @@ void fFun(const Vector & x, Vector & f)
f = 0.0;
}
double gFun(const Vector & x)
real_t gFun(const Vector & x)
{
if (x.Size() == 3)
{
@@ -542,7 +542,7 @@ double gFun(const Vector & x)
}
}
double f_natural(const Vector & x)
real_t f_natural(const Vector & x)
{
return (-pFun_ex(x));
}
+8 -8
View File
@@ -28,8 +28,8 @@ using namespace std;
using namespace mfem;
// Exact solution and r.h.s., see below for implementation.
double analytic_solution(const Vector &x);
double analytic_rhs(const Vector &x);
real_t analytic_solution(const Vector &x);
real_t analytic_rhs(const Vector &x);
void SnapNodes(Mesh &mesh);
int main(int argc, char *argv[])
@@ -81,7 +81,7 @@ int main(int argc, char *argv[])
if (elem_type == 0) // inscribed octahedron
{
const double tri_v[6][3] =
const real_t tri_v[6][3] =
{
{ 1, 0, 0}, { 0, 1, 0}, {-1, 0, 0},
{ 0, -1, 0}, { 0, 0, 1}, { 0, 0, -1}
@@ -105,7 +105,7 @@ int main(int argc, char *argv[])
}
else // inscribed cube
{
const double quad_v[8][3] =
const real_t quad_v[8][3] =
{
{-1, -1, -1}, {+1, -1, -1}, {+1, +1, -1}, {-1, +1, -1},
{-1, -1, +1}, {+1, -1, +1}, {+1, +1, +1}, {-1, +1, +1}
@@ -249,15 +249,15 @@ int main(int argc, char *argv[])
return 0;
}
double analytic_solution(const Vector &x)
real_t analytic_solution(const Vector &x)
{
double l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
real_t l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
return x(0)*x(1)/l2;
}
double analytic_rhs(const Vector &x)
real_t analytic_rhs(const Vector &x)
{
double l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
real_t l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
return 7*x(0)*x(1)/l2;
}
+9 -9
View File
@@ -28,8 +28,8 @@ using namespace std;
using namespace mfem;
// Exact solution and r.h.s., see below for implementation.
double analytic_solution(const Vector &x);
double analytic_rhs(const Vector &x);
real_t analytic_solution(const Vector &x);
real_t analytic_rhs(const Vector &x);
void SnapNodes(Mesh &mesh);
int main(int argc, char *argv[])
@@ -101,7 +101,7 @@ int main(int argc, char *argv[])
if (elem_type == 0) // inscribed octahedron
{
const double tri_v[6][3] =
const real_t tri_v[6][3] =
{
{ 1, 0, 0}, { 0, 1, 0}, {-1, 0, 0},
{ 0, -1, 0}, { 0, 0, 1}, { 0, 0, -1}
@@ -125,7 +125,7 @@ int main(int argc, char *argv[])
}
else // inscribed cube
{
const double quad_v[8][3] =
const real_t quad_v[8][3] =
{
{-1, -1, -1}, {+1, -1, -1}, {+1, +1, -1}, {-1, +1, -1},
{-1, -1, +1}, {+1, -1, +1}, {+1, +1, +1}, {-1, +1, +1}
@@ -281,7 +281,7 @@ int main(int argc, char *argv[])
delete b;
// 12. Compute and print the L^2 norm of the error.
double error = x.ComputeL2Error(sol_coef);
real_t error = x.ComputeL2Error(sol_coef);
if (myid == 0)
{
cout << "\nL2 norm of error: " << error << endl;
@@ -323,15 +323,15 @@ int main(int argc, char *argv[])
return 0;
}
double analytic_solution(const Vector &x)
real_t analytic_solution(const Vector &x)
{
double l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
real_t l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
return x(0)*x(1)/l2;
}
double analytic_rhs(const Vector &x)
real_t analytic_rhs(const Vector &x)
{
double l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
real_t l2 = x(0)*x(0) + x(1)*x(1) + x(2)*x(2);
return 7*x(0)*x(1)/l2;
}
+2 -2
View File
@@ -206,7 +206,7 @@ int main(int argc, char *argv[])
SparseMatrix * Shat = RAP(matBhat, matSinv, matBhat);
#ifndef MFEM_USE_SUITESPARSE
const double prec_rtol = 1e-3;
const real_t prec_rtol = 1e-3;
const int prec_maxit = 200;
CGSolver *S0inv = new CGSolver;
S0inv->SetOperator(matS0);
@@ -240,7 +240,7 @@ int main(int argc, char *argv[])
Vector LSres(s_test);
B.Mult(x, LSres);
LSres -= F;
double res = sqrt(matSinv.InnerProduct(LSres, LSres));
real_t res = sqrt(matSinv.InnerProduct(LSres, LSres));
cout << "\n|| B0*x0 + Bhat*xhat - F ||_{S^-1} = " << res << endl;
}
+1 -1
View File
@@ -283,7 +283,7 @@ int main(int argc, char *argv[])
B.Mult(x, LSres);
LSres -= *trueF;
matSinv->Mult(LSres, tmp);
double res = sqrt(InnerProduct(LSres, tmp));
real_t res = sqrt(InnerProduct(LSres, tmp));
if (myid == 0)
{
cout << "\n|| B0*x0 + Bhat*xhat - F ||_{S^-1} = " << res << endl;
+25 -25
View File
@@ -58,10 +58,10 @@ int problem;
void velocity_function(const Vector &x, Vector &v);
// Initial condition
double u0_function(const Vector &x);
real_t u0_function(const Vector &x);
// Inflow boundary condition
double inflow_function(const Vector &x);
real_t inflow_function(const Vector &x);
// Mesh bounding box
Vector bb_min, bb_max;
@@ -72,7 +72,7 @@ private:
SparseMatrix &M, &K, A;
GMRESSolver linear_solver;
BlockILU prec;
double dt;
real_t dt;
public:
DG_Solver(SparseMatrix &M_, SparseMatrix &K_, const FiniteElementSpace &fes)
: M(M_),
@@ -89,7 +89,7 @@ public:
linear_solver.SetPreconditioner(prec);
}
void SetTimeStep(double dt_)
void SetTimeStep(real_t dt_)
{
if (dt_ != dt)
{
@@ -135,7 +135,7 @@ public:
FE_Evolution(BilinearForm &M_, BilinearForm &K_, const Vector &b_);
virtual void Mult(const Vector &x, Vector &y) const;
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &x, Vector &k);
virtual ~FE_Evolution();
};
@@ -153,8 +153,8 @@ int main(int argc, char *argv[])
bool fa = false;
const char *device_config = "cpu";
int ode_solver_type = 4;
double t_final = 10.0;
double dt = 0.01;
real_t t_final = 10.0;
real_t dt = 0.01;
bool visualization = true;
bool visit = false;
bool paraview = false;
@@ -293,7 +293,7 @@ int main(int argc, char *argv[])
k.SetAssemblyLevel(AssemblyLevel::FULL);
}
m.AddDomainIntegrator(new MassIntegrator);
constexpr double alpha = -1.0;
constexpr real_t alpha = -1.0;
k.AddDomainIntegrator(new ConvectionIntegrator(velocity, alpha));
k.AddInteriorFaceIntegrator(
new NonconservativeDGTraceIntegrator(velocity, alpha));
@@ -393,14 +393,14 @@ int main(int argc, char *argv[])
// iterations, ti, with a time-step dt).
FE_Evolution adv(m, k, b);
double t = 0.0;
real_t t = 0.0;
adv.SetTime(t);
ode_solver->Init(adv);
bool done = false;
for (int ti = 0; !done; )
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(u, t, dt_real);
ti++;
@@ -482,7 +482,7 @@ void FE_Evolution::Mult(const Vector &x, Vector &y) const
M_solver.Mult(z, y);
}
void FE_Evolution::ImplicitSolve(const double dt, const Vector &x, Vector &k)
void FE_Evolution::ImplicitSolve(const real_t dt, const Vector &x, Vector &k)
{
MFEM_VERIFY(dg_solver != NULL,
"Implicit time integration is not supported with partial assembly");
@@ -507,7 +507,7 @@ void velocity_function(const Vector &x, Vector &v)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -529,7 +529,7 @@ void velocity_function(const Vector &x, Vector &v)
case 2:
{
// Clockwise rotation in 2D around the origin
const double w = M_PI/2;
const real_t w = M_PI/2;
switch (dim)
{
case 1: v(0) = 1.0; break;
@@ -541,8 +541,8 @@ void velocity_function(const Vector &x, Vector &v)
case 3:
{
// Clockwise twisting rotation in 2D around the origin
const double w = M_PI/2;
double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
const real_t w = M_PI/2;
real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
d = d*d;
switch (dim)
{
@@ -556,7 +556,7 @@ void velocity_function(const Vector &x, Vector &v)
}
// Initial condition
double u0_function(const Vector &x)
real_t u0_function(const Vector &x)
{
int dim = x.Size();
@@ -564,7 +564,7 @@ double u0_function(const Vector &x)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -580,28 +580,28 @@ double u0_function(const Vector &x)
case 2:
case 3:
{
double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
if (dim == 3)
{
const double s = (1. + 0.25*cos(2*M_PI*X(2)));
const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
rx *= s;
ry *= s;
}
return ( erfc(w*(X(0)-cx-rx))*erfc(-w*(X(0)-cx+rx)) *
erfc(w*(X(1)-cy-ry))*erfc(-w*(X(1)-cy+ry)) )/16;
return ( std::erfc(w*(X(0)-cx-rx))*std::erfc(-w*(X(0)-cx+rx)) *
std::erfc(w*(X(1)-cy-ry))*std::erfc(-w*(X(1)-cy+ry)) )/16;
}
}
}
case 2:
{
double x_ = X(0), y_ = X(1), rho, phi;
rho = hypot(x_, y_);
real_t x_ = X(0), y_ = X(1), rho, phi;
rho = std::hypot(x_, y_);
phi = atan2(y_, x_);
return pow(sin(M_PI*rho),2)*sin(3*phi);
}
case 3:
{
const double f = M_PI;
const real_t f = M_PI;
return sin(f*X(0))*sin(f*X(1));
}
}
@@ -609,7 +609,7 @@ double u0_function(const Vector &x)
}
// Inflow boundary condition (zero for the problems considered in this example)
double inflow_function(const Vector &x)
real_t inflow_function(const Vector &x)
{
switch (problem)
{
+25 -25
View File
@@ -59,10 +59,10 @@ int problem;
void velocity_function(const Vector &x, Vector &v);
// Initial condition
double u0_function(const Vector &x);
real_t u0_function(const Vector &x);
// Inflow boundary condition
double inflow_function(const Vector &x);
real_t inflow_function(const Vector &x);
// Mesh bounding box
Vector bb_min, bb_max;
@@ -135,7 +135,7 @@ private:
HypreParMatrix *A;
GMRESSolver linear_solver;
Solver *prec;
double dt;
real_t dt;
public:
DG_Solver(HypreParMatrix &M_, HypreParMatrix &K_, const FiniteElementSpace &fes,
PrecType prec_type)
@@ -169,7 +169,7 @@ public:
M.GetDiag(M_diag);
}
void SetTimeStep(double dt_)
void SetTimeStep(real_t dt_)
{
if (dt_ != dt)
{
@@ -224,7 +224,7 @@ public:
PrecType prec_type);
virtual void Mult(const Vector &x, Vector &y) const;
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &x, Vector &k);
virtual ~FE_Evolution();
};
@@ -249,8 +249,8 @@ int main(int argc, char *argv[])
bool fa = false;
const char *device_config = "cpu";
int ode_solver_type = 4;
double t_final = 10.0;
double dt = 0.01;
real_t t_final = 10.0;
real_t dt = 0.01;
bool visualization = true;
bool visit = false;
bool paraview = false;
@@ -425,7 +425,7 @@ int main(int argc, char *argv[])
}
m->AddDomainIntegrator(new MassIntegrator);
constexpr double alpha = -1.0;
constexpr real_t alpha = -1.0;
k->AddDomainIntegrator(new ConvectionIntegrator(velocity, alpha));
k->AddInteriorFaceIntegrator(
new NonconservativeDGTraceIntegrator(velocity, alpha));
@@ -566,14 +566,14 @@ int main(int argc, char *argv[])
// iterations, ti, with a time-step dt).
FE_Evolution adv(*m, *k, *B, prec_type);
double t = 0.0;
real_t t = 0.0;
adv.SetTime(t);
ode_solver->Init(adv);
bool done = false;
for (int ti = 0; !done; )
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(*U, t, dt_real);
ti++;
@@ -704,7 +704,7 @@ FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
// u_t = M^{-1}(Ku + b),
// by solving associated linear system
// (M - dt*K) d = K*u + b
void FE_Evolution::ImplicitSolve(const double dt, const Vector &x, Vector &k)
void FE_Evolution::ImplicitSolve(const real_t dt, const Vector &x, Vector &k)
{
K->Mult(x, z);
z += b;
@@ -736,7 +736,7 @@ void velocity_function(const Vector &x, Vector &v)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -758,7 +758,7 @@ void velocity_function(const Vector &x, Vector &v)
case 2:
{
// Clockwise rotation in 2D around the origin
const double w = M_PI/2;
const real_t w = M_PI/2;
switch (dim)
{
case 1: v(0) = 1.0; break;
@@ -770,8 +770,8 @@ void velocity_function(const Vector &x, Vector &v)
case 3:
{
// Clockwise twisting rotation in 2D around the origin
const double w = M_PI/2;
double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
const real_t w = M_PI/2;
real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
d = d*d;
switch (dim)
{
@@ -785,7 +785,7 @@ void velocity_function(const Vector &x, Vector &v)
}
// Initial condition
double u0_function(const Vector &x)
real_t u0_function(const Vector &x)
{
int dim = x.Size();
@@ -793,7 +793,7 @@ double u0_function(const Vector &x)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -809,28 +809,28 @@ double u0_function(const Vector &x)
case 2:
case 3:
{
double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
if (dim == 3)
{
const double s = (1. + 0.25*cos(2*M_PI*X(2)));
const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
rx *= s;
ry *= s;
}
return ( erfc(w*(X(0)-cx-rx))*erfc(-w*(X(0)-cx+rx)) *
erfc(w*(X(1)-cy-ry))*erfc(-w*(X(1)-cy+ry)) )/16;
return ( std::erfc(w*(X(0)-cx-rx))*std::erfc(-w*(X(0)-cx+rx)) *
std::erfc(w*(X(1)-cy-ry))*std::erfc(-w*(X(1)-cy+ry)) )/16;
}
}
}
case 2:
{
double x_ = X(0), y_ = X(1), rho, phi;
rho = hypot(x_, y_);
real_t x_ = X(0), y_ = X(1), rho, phi;
rho = std::hypot(x_, y_);
phi = atan2(y_, x_);
return pow(sin(M_PI*rho),2)*sin(3*phi);
}
case 3:
{
const double f = M_PI;
const real_t f = M_PI;
return sin(f*X(0))*sin(f*X(1));
}
}
@@ -838,7 +838,7 @@ double u0_function(const Vector &x)
}
// Inflow boundary condition (zero for the problems considered in this example)
double inflow_function(const Vector &x)
real_t inflow_function(const Vector &x)
{
switch (problem)
{
+3 -3
View File
@@ -23,11 +23,11 @@ MFEM_LIB_FILE = mfem_is_not_built
SEQ_EXAMPLES = ex0 ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 \
ex17 ex18 ex19 ex20 ex21 ex22 ex23 ex24 ex25 ex26 ex27 ex28 ex29 ex30 \
ex31 ex33 ex34 ex36 ex37
ex31 ex33 ex34 ex36 ex37 ex38 ex39 ex40
PAR_EXAMPLES = ex0p ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p \
ex12p ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex21p ex22p ex24p \
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p \
ex37p
ex37p ex39p ex40p
SEQ_DEVICE_EXAMPLES = ex1 ex3 ex4 ex5 ex6 ex9 ex22 ex24 ex25 ex26 ex34
PAR_DEVICE_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex9p ex13p ex22p \
ex24p ex25p ex26p ex34p ex35p
@@ -187,11 +187,11 @@ clean-exec:
@rm -f deformed.* velocity.* elastic_energy.* mode_* mode_deriv_* flux.*
@rm -f ex5-p-*.bp ex9-p-*.bp ex12-p-*.bp ex16-p-*.bp
@rm -f ex16.mesh ex16-mesh.* ex16-init.* ex16-final.*
@rm -f vortex-mesh.* vortex.mesh vortex-?-init.* vortex-?-final.*
@rm -f deformation.* pressure.*
@rm -f ex20.dat ex20p_?????.dat gnuplot_ex20.inp gnuplot_ex20p.inp
@rm -f ex21*.mesh ex21*.sol ex21p_*.*
@rm -f ex23.mesh ex23-*.gf
@rm -f ex25.mesh ex25-*.gf ex25p-*.*
@rm -f euler-?-final.* euler-?-init.* euler-mesh-final.* euler-mesh.*
@rm -rf ex28_* ex28p_*
@rm -rf cond.* cond_mesh.* cond_j.* dsol.* port_mesh.* port_mode.*
+6 -5
View File
@@ -81,7 +81,8 @@ set(EX1_ARGS_HIPAMG -m ../../data/star.mesh --usepetsc --device hip --petscopts
set(EX2_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p)
set(EX2_ARGS_BDDC -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc)
set(EX2_ARGS_ASM -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm)
set(EX3_ARGS -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
set(EX3_ARGS_BDDC_2D -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
set(EX3_ARGS_BDDC_3D -m ../../data/amr-hex.mesh -rs 1 -rp 0 -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
set(EX4_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping)
set(EX4_HYB_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping --hybridization)
set(EX5_BDDC_LB_ARGS -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping --local-bdr)
@@ -109,10 +110,10 @@ endif()
# Add the tests: one test per command-line-variable.
if (MFEM_ENABLE_TESTING)
set(TEST_OPTIONS_VARS
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX2_ARGS_BDDC EX2_ARGS_ASM EX3_ARGS
EX4_ARGS EX4_HYB_ARGS EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS
EX6_ARGS EX6_NONOVL_ARGS EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS
EX10_MF_ARGS EX10_MFOP_ARGS EX10_JFNK_ARGS)
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX2_ARGS_BDDC EX2_ARGS_ASM EX3_ARGS_BDDC_2D
EX3_ARGS_BDDC_3D EX4_ARGS EX4_HYB_ARGS EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS
EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS
EX10_ARGS EX10_MF_ARGS EX10_MFOP_ARGS EX10_JFNK_ARGS)
if (MFEM_USE_SLEPC)
list(APPEND TEST_OPTIONS_VARS
EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
+41 -35
View File
@@ -68,7 +68,7 @@ protected:
ParBilinearForm M, S;
ParNonlinearForm H;
double viscosity;
real_t viscosity;
HyperelasticModel *model;
HypreParMatrix *Mmat; // Mass matrix from ParallelAssemble()
@@ -96,17 +96,17 @@ protected:
public:
HyperelasticOperator(ParFiniteElementSpace &f, Array<int> &ess_bdr,
double visc, double mu, double K,
real_t visc, real_t mu, real_t K,
bool use_petsc, bool petsc_use_jfnk);
/// Compute the right-hand side of the ODE system.
virtual void Mult(const Vector &vx, Vector &dvx_dt) const;
/** Solve the Backward-Euler equation: k = f(x + dt*k, t), for the unknown k.
This is the only requirement for high-order SDIRK implicit integration.*/
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
virtual void ImplicitSolve(const real_t dt, const Vector &x, Vector &k);
double ElasticEnergy(const ParGridFunction &x) const;
double KineticEnergy(const ParGridFunction &v) const;
real_t ElasticEnergy(const ParGridFunction &x) const;
real_t KineticEnergy(const ParGridFunction &v) const;
void GetElasticEnergyDensity(const ParGridFunction &x,
ParGridFunction &w) const;
@@ -123,7 +123,7 @@ private:
ParBilinearForm *M, *S;
ParNonlinearForm *H;
mutable HypreParMatrix *Jacobian;
double dt;
real_t dt;
const Vector *v, *x;
mutable Vector w, z;
const Array<int> &ess_tdof_list;
@@ -133,7 +133,7 @@ public:
ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
/// Set current dt, v, x values - needed to compute action and Jacobian.
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
void SetParameters(real_t dt_, const Vector *v_, const Vector *x_);
/// Compute y = H(x + dt (v + dt k)) + M k + S (v + dt k).
virtual void Mult(const Vector &k, Vector &y) const;
@@ -170,7 +170,7 @@ private:
public:
ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
: model(m), x(x_) { }
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip);
virtual ~ElasticEnergyCoefficient() { }
};
@@ -196,11 +196,11 @@ int main(int argc, char *argv[])
int par_ref_levels = 0;
int order = 2;
int ode_solver_type = 3;
double t_final = 300.0;
double dt = 3.0;
double visc = 1e-2;
double mu = 0.25;
double K = 5.0;
real_t t_final = 300.0;
real_t dt = 3.0;
real_t visc = 1e-2;
real_t mu = 0.25;
real_t K = 5.0;
bool visualization = true;
int vis_steps = 1;
bool use_petsc = true;
@@ -387,8 +387,8 @@ int main(int argc, char *argv[])
}
}
double ee0 = oper->ElasticEnergy(x_gf);
double ke0 = oper->KineticEnergy(v_gf);
real_t ee0 = oper->ElasticEnergy(x_gf);
real_t ke0 = oper->KineticEnergy(v_gf);
if (myid == 0)
{
cout << "initial elastic energy (EE) = " << ee0 << endl;
@@ -396,7 +396,7 @@ int main(int argc, char *argv[])
cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
}
double t = 0.0;
real_t t = 0.0;
oper->SetTime(t);
ode_solver->Init(*oper);
@@ -405,7 +405,7 @@ int main(int argc, char *argv[])
bool last_step = false;
for (int ti = 1; !last_step; ti++)
{
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(vx, t, dt_real);
@@ -415,8 +415,8 @@ int main(int argc, char *argv[])
{
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
double ee = oper->ElasticEnergy(x_gf);
double ke = oper->KineticEnergy(v_gf);
real_t ee = oper->ElasticEnergy(x_gf);
real_t ke = oper->KineticEnergy(v_gf);
if (myid == 0)
{
@@ -515,7 +515,7 @@ ReducedSystemOperator::ReducedSystemOperator(
ess_tdof_list(ess_tdof_list_)
{ }
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
void ReducedSystemOperator::SetParameters(real_t dt_, const Vector *v_,
const Vector *x_)
{
dt = dt_; v = v_; x = x_;
@@ -555,18 +555,24 @@ ReducedSystemOperator::~ReducedSystemOperator()
HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
Array<int> &ess_bdr, double visc,
double mu, double K, bool use_petsc,
Array<int> &ess_bdr, real_t visc,
real_t mu, real_t K, bool use_petsc,
bool use_petsc_factory)
: TimeDependentOperator(2*f.TrueVSize(), 0.0), fespace(f),
: TimeDependentOperator(2*f.TrueVSize(), static_cast<real_t>(0.0)), fespace(f),
M(&fespace), S(&fespace), H(&fespace),
viscosity(visc), M_solver(f.GetComm()),
newton_solver(f.GetComm()), pnewton_solver(NULL), z(height/2)
{
const double rel_tol = 1e-8;
#if defined(MFEM_USE_DOUBLE)
const real_t rel_tol = 1e-8;
const real_t newton_abs_tol = 0.0;
#elif defined(MFEM_USE_SINGLE)
const real_t rel_tol = 1e-3;
const real_t newton_abs_tol = 1e-4;
#endif
const int skip_zero_entries = 0;
const double ref_density = 1.0; // density in the reference configuration
const real_t ref_density = 1.0; // density in the reference configuration
ConstantCoefficient rho0(ref_density);
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
M.Assemble(skip_zero_entries);
@@ -617,7 +623,7 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
newton_solver.SetOperator(*reduced_oper);
newton_solver.SetPrintLevel(1); // print Newton iterations
newton_solver.SetRelTol(rel_tol);
newton_solver.SetAbsTol(0.0);
newton_solver.SetAbsTol(newton_abs_tol);
newton_solver.SetMaxIter(10);
}
else
@@ -638,7 +644,7 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
}
pnewton_solver->SetPrintLevel(1); // print Newton iterations
pnewton_solver->SetRelTol(rel_tol);
pnewton_solver->SetAbsTol(0.0);
pnewton_solver->SetAbsTol(newton_abs_tol);
pnewton_solver->SetMaxIter(10);
}
}
@@ -664,7 +670,7 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
dx_dt = v;
}
void HyperelasticOperator::ImplicitSolve(const double dt,
void HyperelasticOperator::ImplicitSolve(const real_t dt,
const Vector &vx, Vector &dvx_dt)
{
int sc = height/2;
@@ -696,16 +702,16 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
add(v, dt, dv_dt, dx_dt);
}
double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
real_t HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
{
return H.GetEnergy(x);
}
double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
real_t HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
{
double loc_energy = 0.5*M.InnerProduct(v, v);
double energy;
MPI_Allreduce(&loc_energy, &energy, 1, MPI_DOUBLE, MPI_SUM,
real_t loc_energy = 0.5*M.InnerProduct(v, v);
real_t energy;
MPI_Allreduce(&loc_energy, &energy, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
fespace.GetComm());
return energy;
}
@@ -742,7 +748,7 @@ Solver* PreconditionerFactory::NewPreconditioner(const mfem::OperatorHandle& oh)
return new PetscPreconditioner(*pP,"jfnk_");
}
double ElasticEnergyCoefficient::Eval(ElementTransformation &T,
real_t ElasticEnergyCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
model.SetTransformation(T);
@@ -762,7 +768,7 @@ void InitialDeformation(const Vector &x, Vector &y)
void InitialVelocity(const Vector &x, Vector &v)
{
const int dim = x.Size();
const double s = 0.1/64.;
const real_t s = 0.1/64.;
v = 0.0;
v(dim-1) = s*x(0)*x(0)*(8.0-x(0));
+2 -2
View File
@@ -207,7 +207,7 @@ int main(int argc, char *argv[])
m->AddDomainIntegrator(new MassIntegrator(one));
m->Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<real_t>::min());
m->Finalize();
PetscParMatrix *pA = NULL, *pM = NULL;
@@ -317,7 +317,7 @@ int main(int argc, char *argv[])
// 9. Compute the eigenmodes and extract the array of eigenvalues. Define a
// parallel grid function to represent each of the eigenmodes returned by
// the solver.
Array<double> eigenvalues;
Array<real_t> eigenvalues;
if (!use_slepc)
{
lobpcg->Solve();
+2 -1
View File
@@ -58,6 +58,8 @@ int main(int argc, char *argv[])
// 2. Parse command-line options.
const char *mesh_file = "../../data/beam-tri.mesh";
int ser_ref_levels = -1;
int par_ref_levels = 1;
int order = 1;
bool static_cond = false;
bool visualization = 1;
@@ -65,7 +67,6 @@ int main(int argc, char *argv[])
bool use_petsc = true;
const char *petscrc_file = "";
bool use_nonoverlapping = false;
int ser_ref_levels = -1, par_ref_levels = 1;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
+23 -6
View File
@@ -40,7 +40,7 @@ using namespace mfem;
// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int dim;
int main(int argc, char *argv[])
@@ -53,6 +53,8 @@ int main(int argc, char *argv[])
// 2. Parse command-line options.
const char *mesh_file = "../../data/beam-tet.mesh";
int ser_ref_levels = -1;
int par_ref_levels = 2;
int order = 1;
bool static_cond = false;
bool visualization = 1;
@@ -63,6 +65,10 @@ int main(int argc, char *argv[])
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial.");
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
@@ -103,6 +109,16 @@ int main(int argc, char *argv[])
// and volume meshes with the same code.
Mesh *mesh = new Mesh(mesh_file, 1, 1);
dim = mesh->Dimension();
#if PETSC_VERSION_LT(3,21,0)
if (dim == 3 && use_petsc && use_nonoverlapping)
{
cout << "\nFor three-dimensional runs you need a version of PETSc greater or equal 3.21.\n\n";
delete mesh;
MFEMFinalizePetsc();
Mpi::Finalize();
return MFEM_SKIP_RETURN_VALUE;
}
#endif
int sdim = mesh->SpaceDimension();
// 4. Refine the serial mesh on all processors to increase the resolution. In
@@ -110,9 +126,11 @@ int main(int argc, char *argv[])
// 'ref_levels' to be the largest number that gives a final mesh with no
// more than 1,000 elements.
{
int ref_levels =
(int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
if (ser_ref_levels < 0)
{
ser_ref_levels = (int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
}
for (int l = 0; l < ser_ref_levels; l++)
{
mesh->UniformRefinement();
}
@@ -124,7 +142,6 @@ int main(int argc, char *argv[])
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
int par_ref_levels = 2;
for (int l = 0; l < par_ref_levels; l++)
{
pmesh->UniformRefinement();
@@ -261,7 +278,7 @@ int main(int argc, char *argv[])
// 14. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(E);
real_t err = x.ComputeL2Error(E);
if (myid == 0)
{
cout << "\n|| E_h - E ||_{L^2} = " << err << '\n' << endl;
+22 -14
View File
@@ -36,7 +36,7 @@ using namespace mfem;
// Exact solution, F, and r.h.s., f. See below for implementation.
void F_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
real_t freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -48,6 +48,8 @@ int main(int argc, char *argv[])
// 2. Parse command-line options.
const char *mesh_file = "../../data/star.mesh";
int ser_ref_levels = -1;
int par_ref_levels = 2;
int order = 1;
bool set_bc = true;
bool static_cond = false;
@@ -60,6 +62,10 @@ int main(int argc, char *argv[])
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial.");
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
@@ -111,9 +117,11 @@ int main(int argc, char *argv[])
// 'ref_levels' to be the largest number that gives a final mesh with no
// more than 1,000 elements.
{
int ref_levels =
(int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
if (ser_ref_levels < 0)
{
ser_ref_levels = (int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
}
for (int l = 0; l < ser_ref_levels; l++)
{
mesh->UniformRefinement();
}
@@ -125,7 +133,6 @@ int main(int argc, char *argv[])
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
int par_ref_levels = 2;
for (int l = 0; l < par_ref_levels; l++)
{
pmesh->UniformRefinement();
@@ -252,7 +259,8 @@ int main(int argc, char *argv[])
if (use_nonoverlapping)
{
ParFiniteElementSpace *prec_fespace =
(a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
(a->StaticCondensationIsEnabled() ? a->SCParFESpace() :
(hfes ? NULL : fespace));
// Auxiliary class for BDDC customization
PetscBDDCSolverParams opts;
@@ -280,7 +288,7 @@ int main(int argc, char *argv[])
// 14. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(F);
real_t err = x.ComputeL2Error(F);
if (myid == 0)
{
cout << "\n|| F_h - F ||_{L^2} = " << err << '\n' << endl;
@@ -337,9 +345,9 @@ void F_exact(const Vector &p, Vector &F)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0;
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0;
F(0) = cos(kappa*x)*sin(kappa*y);
F(1) = cos(kappa*y)*sin(kappa*x);
@@ -354,11 +362,11 @@ void f_exact(const Vector &p, Vector &f)
{
int dim = p.Size();
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0;
real_t x = p(0);
real_t y = p(1);
// real_t z = (dim == 3) ? p(2) : 0.0;
double temp = 1 + 2*kappa*kappa;
real_t temp = 1 + 2*kappa*kappa;
f(0) = temp*cos(kappa*x)*sin(kappa*y);
f(1) = temp*cos(kappa*y)*sin(kappa*x);
+18 -18
View File
@@ -41,10 +41,10 @@ using namespace mfem;
// Define the analytical solution and forcing terms / boundary conditions
void uFun_ex(const Vector & x, Vector & u);
double pFun_ex(const Vector & x);
real_t pFun_ex(const Vector & x);
void fFun(const Vector & x, Vector & f);
double gFun(const Vector & x);
double f_natural(const Vector & x);
real_t gFun(const Vector & x);
real_t f_natural(const Vector & x);
int main(int argc, char *argv[])
{
@@ -356,8 +356,8 @@ int main(int argc, char *argv[])
// Check the norm of the unpreconditioned residual.
int maxIter(500);
double rtol(1.e-6);
double atol(1.e-10);
real_t rtol(1.e-6);
real_t atol(1.e-10);
chrono.Clear();
chrono.Start();
@@ -454,10 +454,10 @@ int main(int argc, char *argv[])
irs[i] = &(IntRules.Get(i, order_quad));
}
double err_u = u->ComputeL2Error(ucoeff, irs);
double norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs);
double err_p = p->ComputeL2Error(pcoeff, irs);
double norm_p = ComputeGlobalLpNorm(2, pcoeff, *pmesh, irs);
real_t err_u = u->ComputeL2Error(ucoeff, irs);
real_t norm_u = ComputeGlobalLpNorm(2, ucoeff, *pmesh, irs);
real_t err_p = p->ComputeL2Error(pcoeff, irs);
real_t norm_p = ComputeGlobalLpNorm(2, pcoeff, *pmesh, irs);
if (verbose)
{
@@ -551,9 +551,9 @@ int main(int argc, char *argv[])
void uFun_ex(const Vector & x, Vector & u)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
zi = x(2);
@@ -569,11 +569,11 @@ void uFun_ex(const Vector & x, Vector & u)
}
// Change if needed
double pFun_ex(const Vector & x)
real_t pFun_ex(const Vector & x)
{
double xi(x(0));
double yi(x(1));
double zi(0.0);
real_t xi(x(0));
real_t yi(x(1));
real_t zi(0.0);
if (x.Size() == 3)
{
@@ -588,7 +588,7 @@ void fFun(const Vector & x, Vector & f)
f = 0.0;
}
double gFun(const Vector & x)
real_t gFun(const Vector & x)
{
if (x.Size() == 3)
{
@@ -600,7 +600,7 @@ double gFun(const Vector & x)
}
}
double f_natural(const Vector & x)
real_t f_natural(const Vector & x)
{
return (-pFun_ex(x));
}
+1 -1
View File
@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
// The system will be solved for true (unconstrained/unique) DOFs only.
Array<int> ess_tdof_list;
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
double time;
real_t time;
const int copy_interior = 1;
if (use_petsc)
+19 -19
View File
@@ -49,10 +49,10 @@ int problem;
void velocity_function(const Vector &x, Vector &v);
// Initial condition
double u0_function(const Vector &x);
real_t u0_function(const Vector &x);
// Inflow boundary condition
double inflow_function(const Vector &x);
real_t inflow_function(const Vector &x);
// Mesh bounding box
Vector bb_min, bb_max;
@@ -87,7 +87,7 @@ public:
virtual void Mult(const Vector &x, Vector &y) const;
virtual Operator& GetExplicitGradient(const Vector &x) const;
virtual Operator& GetImplicitGradient(const Vector &x, const Vector &xp,
double shift) const;
real_t shift) const;
virtual ~FE_Evolution() { delete iJacobian; delete rJacobian; }
};
@@ -153,8 +153,8 @@ int main(int argc, char *argv[])
bool fa = false;
const char *device_config = "cpu";
int ode_solver_type = 4;
double t_final = 10.0;
double dt = 0.01;
real_t t_final = 10.0;
real_t dt = 0.01;
bool visualization = true;
bool visit = false;
bool binary = false;
@@ -431,7 +431,7 @@ int main(int argc, char *argv[])
// 10. Define the time-dependent evolution operator describing the ODE
FE_Evolution *adv = new FE_Evolution(*m, *k, *B, implicit);
double t = 0.0;
real_t t = 0.0;
adv->SetTime(t);
if (use_petsc)
{
@@ -451,7 +451,7 @@ int main(int argc, char *argv[])
{
// We cannot match exactly the time history of the Run method
// since we are explicitly telling PETSc to use a time step
double dt_real = min(dt, t_final - t);
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(*U, t, dt_real);
ti++;
@@ -621,7 +621,7 @@ Operator& FE_Evolution::GetExplicitGradient(const Vector &x) const
// LHS Jacobian, evaluated as shift*F_du/dt + F_u
Operator& FE_Evolution::GetImplicitGradient(const Vector &x, const Vector &xp,
double shift) const
real_t shift) const
{
Operator::Type otype = (MAlev == AssemblyLevel::LEGACY ?
Operator::PETSC_MATAIJ : Operator::ANY_TYPE);
@@ -648,7 +648,7 @@ void velocity_function(const Vector &x, Vector &v)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -670,7 +670,7 @@ void velocity_function(const Vector &x, Vector &v)
case 2:
{
// Clockwise rotation in 2D around the origin
const double w = M_PI/2;
const real_t w = M_PI/2;
switch (dim)
{
case 1: v(0) = 1.0; break;
@@ -682,8 +682,8 @@ void velocity_function(const Vector &x, Vector &v)
case 3:
{
// Clockwise twisting rotation in 2D around the origin
const double w = M_PI/2;
double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
const real_t w = M_PI/2;
real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
d = d*d;
switch (dim)
{
@@ -697,7 +697,7 @@ void velocity_function(const Vector &x, Vector &v)
}
// Initial condition
double u0_function(const Vector &x)
real_t u0_function(const Vector &x)
{
int dim = x.Size();
@@ -705,7 +705,7 @@ double u0_function(const Vector &x)
Vector X(dim);
for (int i = 0; i < dim; i++)
{
double center = (bb_min[i] + bb_max[i]) * 0.5;
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
@@ -721,10 +721,10 @@ double u0_function(const Vector &x)
case 2:
case 3:
{
double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
if (dim == 3)
{
const double s = (1. + 0.25*cos(2*M_PI*X(2)));
const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
rx *= s;
ry *= s;
}
@@ -735,14 +735,14 @@ double u0_function(const Vector &x)
}
case 2:
{
double x_ = X(0), y_ = X(1), rho, phi;
real_t x_ = X(0), y_ = X(1), rho, phi;
rho = hypot(x_, y_);
phi = atan2(y_, x_);
return pow(sin(M_PI*rho),2)*sin(3*phi);
}
case 3:
{
const double f = M_PI;
const real_t f = M_PI;
return sin(f*X(0))*sin(f*X(1));
}
}
@@ -750,7 +750,7 @@ double u0_function(const Vector &x)
}
// Inflow boundary condition (zero for the problems considered in this example)
double inflow_function(const Vector &x)
real_t inflow_function(const Vector &x)
{
switch (problem)
{
+4 -2
View File
@@ -83,7 +83,8 @@ EX1_ARGS_HIPAMG := -m ../../data/star.mesh --usepetsc --device hip --petsc
EX2_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p
EX2_ARGS_BDDC := -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc
EX2_ARGS_ASM := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm
EX3_ARGS := -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping
EX3_ARGS_BDDC_2D := -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping
EX3_ARGS_BDDC_3D := -m ../../data/amr-hex.mesh -rs 1 -rp 0 -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping
EX4_ARGS := -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping
EX4_HYB_ARGS := -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping --hybridization
EX5_BDDC_LB_ARGS := -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping --local-bdr
@@ -122,7 +123,8 @@ ex2p-test-par: ex2p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX2_ARGS_BDDC))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX2_ARGS_ASM))
ex3p-test-par: ex3p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX3_ARGS))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX3_ARGS_BDDC_2D))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX3_ARGS_BDDC_3D))
ex4p-test-par: ex4p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX4_ARGS))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX4_HYB_ARGS))
+2
View File
@@ -4,7 +4,9 @@
-ksp_converged_reason
# Internal use (don't remove it)
# It is duplicated because we support older versions of PETSc
-matis_convert_local_nest
-mat_is_convert_local_nest
# PCBDDC options

Some files were not shown because too many files have changed in this diff Show More