Compare commits

...
Author SHA1 Message Date
Will Pazner 088ef1b667 Fix another makefile bug 2019-03-08 14:25:10 -08:00
Will Pazner ad21b3e8fc Update makefile 2019-03-08 14:04:14 -08:00
Will Pazner 82f75c3a05 Use MFEM build configuration 2019-03-05 14:47:56 -08:00
Will Pazner 4fba9c2575 Merge branch 'cons-law-dev' of github.com:mfem/mfem into cons-law-dev 2019-02-06 17:07:52 -08:00
Will Pazner 916ed1b2c3 make style 2019-02-06 17:06:52 -08:00
Will Pazner acaf6ad484 Adding DG partial assembly conservation law mini-app 2019-02-06 17:06:28 -08:00
Will Pazner e20e323ea5 Adding DG partial assembly conservation law mini-app 2019-02-06 16:59:03 -08:00
Veselin Dobrev 3e9a86cecf Merge pull request #681 from najlkin/pr5
Fixed BlockVector Update method [najlkin:pr5]
2019-02-05 17:00:20 -08:00
Tzanio Kolev da7b500db5 Merge pull request #693 from mfem/derefine-vector-spaces
Add support for derefinement of vector (RT + ND) spaces [derefine-vector-spaces]
2019-01-18 16:24:36 -08:00
Tzanio Kolev 7cfb879a17 Merge pull request #635 from mfem/periodic-nurbs-v2-dev
Adding C_0 continuous periodicity to NURBS meshes [periodic-nurbs-v2-dev]
2019-01-18 16:21:54 -08:00
Jan Nikl 9e4e3b2e10 Fixed the new logic of BlockVector::Update() for the case when the offsets are shifted. 2019-01-11 06:18:34 +01:00
Veselin Dobrev 3b4a080565 Use 'mfem::out' instead of 'cout'. 2019-01-10 15:03:43 -08:00
Veselin Dobrev 83de2dfd76 Tweak a bit the logic in BlockVector::Update(). 2019-01-10 13:14:08 -08:00
Jan Nikl 58b708713f The new offsets in BlockVector::Update() are compared with the real sizes of the blocks. 2019-01-10 10:12:09 +01:00
Jan Nikl 3a977fb925 Revert "BlockVector::Update(): added a parameter to force reallocation."
This reverts commit dec82f7046.
2019-01-10 10:12:09 +01:00
Ido Akkerman b1e2aaf09d Fixing unused var and self reference 2019-01-09 15:53:20 +01:00
Veselin Dobrev 004e664f18 Fix valgrind warnings in:
* NodalFiniteElement::GetLocalRestriction(),
* VectorFiniteElement::LocalRestriction_RT(), and
* VectorFiniteElement::LocalRestriction_ND().
2019-01-08 11:57:15 -08:00
Veselin Dobrev 2ad5a65e02 Update a few comments in class BlockVector. 2018-12-21 18:11:10 -08:00
Veselin Dobrev f9e7fb2bd7 Add support for derefinement of Nedelec spaces (ND_FECollection) 2018-12-21 16:23:10 -08:00
Tzanio Kolev 4987e1132a Merge pull request #664 from mfem/tmop-lim-dev
TMOP extension for limiting [tmop-lim-dev]
2018-12-17 07:25:51 -08:00
Tzanio Kolev 1bb9998b13 Merge pull request #687 from mfem/tmop-skew-aspratio
TMOP metrics for skew and aspect ratio [tmop-skew-aspratio]
2018-12-17 07:25:30 -08:00
Vladimir Tomov 41205ed92f Moved the normalization computations inside TMOP_Integrator. 2018-12-12 16:35:36 -08:00
Veselin Dobrev 31ff80a137 A few small tweaks in (p)mesh-optimizer.cpp 2018-12-11 21:03:33 -08:00
Tzanio Kolev e17a73fa8b Merge pull request #639 from mfem/tests-phase1-dev
Add unit framework [tests-phase1-dev]
2018-12-11 06:27:39 -08:00
Tzanio Kolev 338a4767c2 Merge pull request #682 from mfem/cut-mesh-groups-fix
Fix ordering of cut mesh groups and orientation of shared edges/faces [cut-mesh-groups-fix]
2018-12-11 06:27:06 -08:00
Vladimir Tomov 7fe4b57a62 Merge branch 'tmop-lim-dev' of github.com:mfem/mfem into tmop-lim-dev 2018-12-10 11:40:56 -08:00
Vladimir Tomov f2b71d807f Restored the usual behavior when normalization is off. 2018-12-10 11:40:02 -08:00
Veselin Dobrev 5b8ae39c88 Some small tweaks in the classes TMOP_LimiterFunction,
TMOP_QuadraticLimiter, and TMOP_Integrator.

In TMOP_Integrator::GetElementEnergy, add a FIXME remark about the
computation of the weight Coefficients in physical coordinates.
2018-12-06 21:51:29 -08:00
Vladimir Tomov da43f83a1d Merge branch 'tmop-skew-aspratio' of github.com:mfem/mfem into tmop-skew-aspratio 2018-12-06 19:01:19 -08:00
Vladimir Tomov d2f4e745e2 Small edits. 2018-12-06 19:00:36 -08:00
Veselin Dobrev 634d9431d8 Add support for parallel non-conforming meshes in class
ZienkiewiczZhuEstimator.

This support is based on the update in ParGridFunction::ComputeFlux
which, in turn, is based on the support for GroupCommunicators in
ParFiniteElementSpaces on non-conforming meshes.
2018-12-05 20:11:57 -08:00
Tzanio 79cddce644 Mentioned in CHANGELOG 2018-12-05 14:47:37 -08:00
Tzanio Kolev 5e6dabb3c8 Merge pull request #691 from mfem/hypre-part-comment-dev
HYPRE partitioning array comments [hypre-part-comment-dev]
2018-12-03 09:17:04 -08:00
Tzanio Kolev 903d51e78f Merge pull request #686 from mfem/mesh-reorder-elem-fix
Fix a bug in Mesh::ReorderElements [mesh-reorder-elem-fix]
2018-12-03 09:16:24 -08:00
Tzanio Kolev 83cef85c1d Merge pull request #680 from mfem/stefanozampini/small-additions
Stefanozampini/small additions
2018-12-03 09:15:28 -08:00
Veselin Dobrev ffaa2ed259 Few small updates related to the renamed unit test executable. 2018-11-30 22:06:27 -08:00
Veselin Dobrev 6a2d288ece In tests/unit/makefile, always use the full path to the source
files - this is needed as a workaround for an issue in Coveralls
when run in Travis CI.
2018-11-30 21:22:16 -08:00
Veselin Dobrev 7bf1c95e26 Update a message string in the top-level makefile. 2018-11-30 17:36:35 -08:00
Veselin Dobrev 62182060e9 In tests/unit, define target 'test' in the GNU makefile, similar
to the makefiles in the examples and miniapps directories.

In the top-level makefile:
* the target 'all' will also build the unit tests
* the target 'test' will also run the unit tests
* removed the target 'alltest' (now it is the same as 'test')

In .travis.yml, since the 'test' target will run the unit tests,
remove the special Travis CI build that just runs the unit tests.
2018-11-30 17:28:07 -08:00
Veselin Dobrev d44aa186d2 Add the unit tests to the CMake build system. 2018-11-30 16:17:25 -08:00
Tzanio 3fd08ddc67 Typos and minor styling 2018-11-30 09:31:21 -08:00
Veselin Dobrev 1a0976dc17 Add support for building and running the unit tests in
out-of-source builds with GNU make.

Clean the unit tests directory when 'make clean' is invoked at
the top level.
2018-11-29 22:23:47 -08:00
Veselin Dobrev fde408ec95 Use a doxygen @anchor and @ref commands to point to the hypre
partitioning array description, instead of using the name of the
method where the description can be found.

Some other small doxygen tweaks in hypre.hpp.
2018-11-29 20:34:45 -08:00
Stowell, Mark L 9776ebe890 Adding comments describing the partitioning arrays in HYPRE vector and matrix classes 2018-11-29 14:25:28 -08:00
Tzanio 63c03920b3 make style 2018-11-28 17:31:24 -08:00
Tzanio 56059b4672 make style 2018-11-28 17:29:31 -08:00
Tzanio 2b14832192 make style 2018-11-28 17:28:33 -08:00
Aaron Fisher 8d6669b83f Merge branch 'master' into tests-phase1-dev 2018-11-28 15:59:30 -08:00
Aaron Fisher 91e47a804f Removed the 'smoke' tests. 2018-11-28 15:58:33 -08:00
Vladimir Tomov 4e22e0f772 Legacy version of EnableLimiting to maintain the old interface.
It will be removed after apps are updated.
2018-11-28 11:32:00 -08:00
Tzanio 605a535c0f Fixed a compiler warning. 2018-11-27 22:10:37 -08:00
Veselin Dobrev 884abe71b5 Fix a bug in Mesh::ReorderElements. 2018-11-27 21:07:05 -08:00
Veselin Dobrev 9807f9dba6 Add support for derefinement of spaces using RT_FECollection. 2018-11-27 19:46:49 -08:00
Vladimir Tomov 61cce4d4bc Merge branch 'master' into tmop-lim-dev 2018-11-27 18:20:21 -08:00
Vladimir Tomov ced7c47558 Virtual destructor of TMOP_Integrator. 2018-11-27 18:19:26 -08:00
Veselin Dobrev bb55232c49 Fix a doxygen warning in class PetscParVector. 2018-11-27 15:50:32 -08:00
Tzanio Kolev 87f86d45c9 Merge pull request #674 from mfem/empty-procs-dev
A few small tweaks related to mesh partitioning [empty-procs-dev]
2018-11-26 16:45:57 -08:00
Tzanio Kolev 144635c3d8 Merge pull request #568 from mfem/shared-integ-dev
Consistent c'tors for [Par][Mixed]BilinearForm/[Par]LinearForm [shared-integ-dev]
2018-11-26 08:33:26 -08:00
Tzanio Kolev 3c674d72fd Merge pull request #675 from mfem/small-updates
A few small updates [small-updates]
2018-11-26 08:31:51 -08:00
Jakub Červený 1dd1300812 Face orientations work too. 2018-11-22 13:53:22 +01:00
Jakub Červený fba0fd6187 Edge orientations fixed in ParNCMesh conforming groups. 2018-11-22 13:16:23 +01:00
Jan Nikl f8fdf24246 Fixed BlockVector Update method, where the change of the offsets array was ignored in the case the offsets were identical, but just the location in memory differed.
The check if the offsets are identical cannot guarantee the offsets will be identical in the future. There may be a good reason why the user calls this method like rewriting or deallocating the original array. The pointer must be changed even if the forced reallocation is not performed (but it may be reconsidered if it is really needed).
2018-11-22 10:26:02 +01:00
Jakub Červený f015b94c89 Updated ParNCMesh::MemoryUsage and PrintMemoryUsage. 2018-11-22 09:19:55 +01:00
Vladimir Tomov ede020977c Update CHANGELOG 2018-11-21 13:02:37 -08:00
Vladimir Tomov b92d1d37ba Merge branch 'master' into tmop-lim-dev 2018-11-21 13:02:04 -08:00
Vladimir Tomov 9dd9189563 Update CHANGELOG 2018-11-21 12:58:12 -08:00
Vladimir Tomov 6beb052e86 Updated the serial miniapp. 2018-11-21 12:55:12 -08:00
Veselin Dobrev 25f8e3f3f4 In class LinearForm, initialize 'extern_lfs' in the default
constructor.
2018-11-21 12:27:39 -08:00
Veselin Dobrev 92ab0429f2 In linalg/petsc.hpp, small adjustments of #include directives. 2018-11-21 15:14:53 +03:00
Tzanio 9a9c29e03f make style 2018-11-21 15:14:53 +03:00
Stefano Zampini 7c9bf81d17 Prevent from having petsc.h being include from MFEM source codes if not desired 2018-11-21 15:14:53 +03:00
Stefano Zampini f94b099e40 Added convenience functions to initialize/finalize PETSc without the need of including petsc.h 2018-11-21 15:14:53 +03:00
Stefano Zampini 777c6d98f7 Move the GetComm() methods implementation for PETSc to the cpp file 2018-11-21 15:14:53 +03:00
Stefano Zampini 367503651e Added PetscSolver::GetComm() method 2018-11-21 15:14:53 +03:00
Stefano Zampini 03f2898985 PetscODESolver: the Init method should reset to the initial state in any case 2018-11-21 15:14:53 +03:00
Stefano Zampini 6ca447ec36 Added some methods to PetscParMatrix to scale rows and columns and to shift the diagonal terms 2018-11-21 15:14:53 +03:00
Stefano Zampini 493c8b1e63 PetscParMatrix: added conversion constructor for SparseMatrix 2018-11-21 15:14:53 +03:00
Stefano Zampini 7724bdf9c4 make style 2018-11-21 15:14:53 +03:00
Stefano Zampini 7e72e7f559 Added default constructor for {Vector,}GridFunctionCoefficient 2018-11-21 15:14:53 +03:00
Stefano Zampini ddba68f2be MatISGetMPIXAIJ is deprecated in 3.10 in favor of MatConvert 2018-11-21 15:14:53 +03:00
Stefano Zampini 8f601776cd Added RAP operation with A Hypre mat and P PETSc
Fix documentation regarding PETSC_MATHYPRE
2018-11-21 15:14:53 +03:00
Stefano Zampini 9457962d33 PetscSolver: extended monitoring framework
Add a user callback to monitor the solver (defaults to no-hop)

fixed a bug in ex1p.cpp
2018-11-21 15:14:53 +03:00
Stefano Zampini 560697884d Added method to customize the line search
- use an objective function to drive the line search
- run a method after the PETSc's linesearch has been done to further refine it
2018-11-21 15:14:53 +03:00
Stefano Zampini eb578c55a0 Added method to zero only the rows of a PetscParMatrix 2018-11-21 15:14:53 +03:00
Stefano Zampini 9fa65e6412 Added ParMult method to PetscParMatrix 2018-11-21 15:14:53 +03:00
Stefano Zampini f3c2fae804 Fix bug in ConvertOperator 2018-11-21 15:14:53 +03:00
Stefano Zampini ea81393011 Added method to change the inner Mat of a PetscParMatrix 2018-11-21 15:14:53 +03:00
Stefano Zampini 7b6ddb6227 Added SetValues and AddValues to PetscParVector 2018-11-21 15:14:53 +03:00
Stefano Zampini 72bd63a556 Added copy argument to constructor 2018-11-21 15:14:53 +03:00
Stefano Zampini 7f40802a83 PetscBCHandler: added method to apply the BC in place 2018-11-21 15:14:53 +03:00
Stefano Zampini 04983d747e PetscODESolver: added the special function TSComputeSplitJacobians_C
This special function is used in the branch stefano_zampini/feature-continuousadjoint to enable PDE constrained optimization
If that branch will not get merged into PETSc, I'll will do my own library and this function will be still needed.
2018-11-21 15:14:53 +03:00
Stefano Zampini 795c758dd4 PetscParMatrix: added customization of the diagonal entry when eliminating rows and columns 2018-11-21 15:14:53 +03:00
Stefano Zampini 94f7568165 PetscParMatrix: add -= operator 2018-11-21 15:14:53 +03:00
Stefano Zampini c8e0a5ae00 PetscParVector: added few operators and default case for Randomize() 2018-11-21 15:14:53 +03:00
Stefano Zampini f1eb664f58 make style 2018-11-21 15:14:53 +03:00
Stefano Zampini 7934db1a9c PetscODESolver::Run: Run reset Jacobian caching
This method may be invoked multiple times, each time with a different parametrization of the TimeDependentOperator
2018-11-21 15:14:53 +03:00
Stefano Zampini 34cc491b19 PetscBCHandler: remove hideous setup requirement and do lazy setup 2018-11-21 15:14:53 +03:00
Stefano Zampini 6d2680cde6 Make EvalDelta a virtual method 2018-11-21 15:14:53 +03:00
Stefano Zampini ff6bfe3808 Add constructor with conversion 2018-11-21 15:14:53 +03:00
Veselin Dobrev 9be3b415aa A few small tweaks in the doxygen documentation of class
LinearForm.
2018-11-20 19:26:39 -08:00
Veselin Dobrev b7557d4664 Re-introduce the copy assignment operator in the class
GridFunction, which was incorrectly removed in PR #628 --
this was my mistake.

Add the copy assignment operators in the classes ParGridFunction,
and (Par)LinearForm.

Add copy constructors in the classes QuadratureFunction and
ParGridFunction.

Disallow copy construction of the classes (Par)LinearForm by
declaring their copy constructors as private.

Improve the doxygen documentation in the above mentioned classes.
2018-11-20 19:06:56 -08:00
Veselin Dobrev 6d9f041bc7 Disallow the copy construction and copy assignment in the
classes (Par)BilinearForm, (Par)MixedBilinearForm and
(Par)DiscreteLinearOperator.

This is achieved by declaring their copy constructors and copy
assignment operators as private.

Also, improved the doxygen documentation of the same classes.
2018-11-20 19:01:13 -08:00
Veselin Dobrev 562434aabb Simplify the implementation of one of the LinearForm ctors. 2018-11-20 18:58:55 -08:00
Vladimir Tomov e8d7299091 Added space-dependent physical distance to the limiting interface.
(this changes the interface).
2018-11-20 18:23:24 -08:00
Vladimir Tomov 8499dee89d Merge branch 'tmop-lim-dev' of github.com:mfem/mfem into tmop-lim-dev 2018-11-19 19:28:22 -08:00
Vladimir Tomov 4155b591a4 Normalization of the objective function in pmesh-optimizer. 2018-11-19 17:03:01 -08:00
Jakub Červený e8c31c884d ParNCMesh conforming groups globally consistent ordering works. TODO: orientations 2018-11-19 21:38:50 +01:00
Stefano Zampini e69f787149 PetscODESolver: added method to set the type of solver at a later stage 2018-11-18 11:28:36 +03:00
Stefano Zampini ab7b1609a9 PetscParMatrix: add method to get local ownership of rows and columns 2018-11-18 11:28:36 +03:00
Stefano Zampini bc9f74fddd PetscParMatrix: added constructor for submatrix 2018-11-18 11:28:36 +03:00
Vladimir Tomov 492133825a Merge branch 'master' into tmop-skew-aspratio 2018-11-16 15:25:27 -08:00
Jakub Červený 588548b13d WIP fix order of shared entities in ParMesh compatibility groups. 2018-11-16 17:30:50 +01:00
Veselin Dobrev 3d0ffe65e4 Remove the 'shaper' miniapp from config/sample-runs.sh -- it
requires user input.

In the build systems, fix/update the value of MFEM_LIB_FILE exported
in the generated file config.mk.
2018-11-15 20:57:32 -08:00
Veselin Dobrev 721ee611c4 In L2ZZErrorEstimator, support processors without elements.
In Mesh::GeneratePartitioning, use a simple partitioning when
the number of partitions is larger than or equal to the number
of elements.

In the mesh-explorer miniapp, in the partitioning sub-menu,
indicate which partitioning method is the default.
2018-11-15 14:02:36 -08:00
Tzanio Kolev 4cb8d2cbc1 Merge pull request #582 from mfem/elasticity-flux
Add ComputeElementFlux method to ElasticityIntegrator [elasticity-flux]
2018-11-14 08:49:27 -06:00
Tzanio 7ca6676475 Merge branch 'master' into elasticity-flux
Conflicts:
	CHANGELOG
2018-11-14 08:48:54 -06:00
Tzanio Kolev 35cd561675 Merge pull request #590 from mfem/derived-coefs-dev
Coefficients derived from other coefficients [derived-coefs-dev]
2018-11-14 08:46:10 -06:00
Tzanio Kolev 190c605bc1 Merge pull request #660 from mfem/laghos-amr-dev
Laghos AMR changes [laghos-amr-dev]
2018-11-14 08:45:36 -06:00
Vladimir Tomov a2ace42dc4 3D skew and aspect ratio. 2018-11-12 16:26:00 -08:00
Tzanio Kolev 668a7cc3b9 Merge pull request #661 from vikramsg/master
Adding Euclid preconditioner wrappers for ILU preconditioning options [vikramsg:master]
2018-11-12 18:13:14 -06:00
Tzanio Kolev bc3189d560 Update hypre.cpp 2018-11-12 18:12:56 -06:00
Vladimir Tomov d13ea5fe0d Added skew-only and aspect_ratio-only metrics. 2018-11-09 19:31:01 -08:00
Aaron Fisher beb5994616 Renamed the test dirs and fixed some text that had an old version of the directories. 2018-11-09 16:28:51 -08:00
Tzanio 7eea20baef Updated CHANGELOG 2018-11-09 15:08:39 -08:00
Jakub Červený 572d447033 Added mesh rebalancing in ex22p. 2018-11-09 13:58:42 +01:00
Veselin Dobrev ae1a01df4b Added some more documentation to classes (Mixed)BilinearForm.
Also, made small tweaks in their implementation.
2018-11-08 22:13:21 -08:00
Veselin Dobrev e3ad48d930 Merge branch 'master' into tests-phase1-dev 2018-11-08 18:44:25 -08:00
Veselin Dobrev 8eb9de562d Revert style changes in mesh/mesh.cpp 2018-11-08 18:27:03 -08:00
Stowell, Mark L 1d66080c77 Merge remote-tracking branch 'origin/master' into derived-coefs-dev 2018-11-08 18:03:37 -08:00
Stowell, Mark L ccc5883cca Merge remote-tracking branch 'origin/master' into shared-integ-dev 2018-11-08 18:02:44 -08:00
Tzanio bd9f831a0b Fix in CHANGELOG 2018-11-08 17:23:21 -08:00
Tzanio 93c8be74d3 Mentioned in doc/CodeDocumentation.dox 2018-11-08 17:21:07 -08:00
Tzanio 7b39339fab Updated CHANGELOG. Small typos. 2018-11-08 17:19:08 -08:00
Tzanio 14e3a3d2d7 Merge branch 'elasticity-flux' of github.com:mfem/mfem into elasticity-flux 2018-11-08 16:48:06 -08:00
Veselin Dobrev 0b6783959a Update CHANGELOG 2018-11-08 16:46:47 -08:00
Veselin Dobrev c7118efe7e Revert example 1p to the 'master' version. 2018-11-08 16:30:54 -08:00
Tzanio ea33141aae Merge branch 'master' into elasticity-flux 2018-11-08 15:32:15 -08:00
Tzanio 80fa382b53 make style; updated CHANGELOG 2018-11-08 15:19:36 -08:00
Tzanio 125bafebc8 make style 2018-11-08 15:14:53 -08:00
Tzanio b270dc8323 PMATRIX_STATS -> MFEM_PMATRIX_STATS; Some typos 2018-11-08 14:48:06 -08:00
Jakub Červený ff43f75b5b Replaced std::cout with mfem::out. 2018-11-08 21:03:24 +01:00
Jakub Červený a922078a11 Removed changes in RK4Solver::Step. 2018-11-08 21:02:41 +01:00
Veselin Dobrev 797370ec97 Fix a copy-paste bug in GridFunction::AccumulateAndCountBdrValues 2018-11-07 21:20:30 -08:00
Veselin Dobrev 46cc41c0c9 Add description for the methods ComputeElementFlux and
ComputeFluxEnergy in the base class BilinearFormIntegrator.
2018-11-07 20:57:29 -08:00
Veselin Dobrev 9306ffc841 Added example 22/22p to the CMake build system. 2018-11-07 19:31:40 -08:00
Veselin Dobrev 2ae23b17d2 Added parallel version of example 22.
Enhanced class VectorMassIntegrator to support user specified
number of components using the new method SetVDim().

Tweaked the function L2ZZErrorEstimator() to support flux spaces
with any number of components; this is only supported when the
smooth flux space is a Cartesian power of a scalar space.

Updated and tested all sample runs in ex22/ex22p.
2018-11-07 19:21:04 -08:00
VSingh f90f1ac989 Euclid components now located next to PARASAILS. Some additional documentation. 2018-11-07 12:43:40 +02:00
Veselin Dobrev 58ca57f0f3 In class ZienkiewiczZhuEstimator, add an option (set using the
method SetFluxAveraging) that corresponds to the optional
parameter 'with_subdomains' of the function ZZErrorEstimator().

In ex22, add a command line flag to set the new flux-averaging
option in class ZienkiewiczZhuEstimator; also, save the reference
and deformed meshes and displacement field at the end of the
adaptivity loop.
2018-11-06 19:46:36 -08:00
Tzanio 0c31381de8 Mentioned in CHANGELOG 2018-11-06 17:42:56 -08:00
Vladimir Tomov 7277e0ad01 Option for user-defined limiting terms. 2018-11-06 16:52:56 -08:00
Tzanio Kolev 73a4ddfb61 Merge pull request #658 from mfem/fgmres-dev
FGMRES alter Iteration/Pass counts to match those in GMRES [fgmres-dev]
2018-11-06 07:28:15 -08:00
Tzanio Kolev c55788c526 Merge pull request #508 from cwsmith/cwsmith/cmake_create_config.mk
CMake creates config.mk and installs config.mk and test.mk [cwsmith/cmake_create_config.mk]
2018-11-05 09:36:51 -08:00
VSingh ab4f2b0ffc Adding more parameters for Euclid 2018-11-05 13:58:30 +02:00
VSingh 3665a96d52 Adding Euclid preconditioner wrappers for ILU preconditioning options 2018-11-04 14:41:06 +02:00
Veselin Dobrev 6262ac25b8 In class ElasticityIntegrator, update the methods ComputeElementFlux
and ComputeFluxEnergy to work with flux (stress) that stores just the
symmetric part of the stress, i.e. dim*(dim+1)/2 components instead
of dim*dim components. Also, update ComputeFluxEnergy to compute the
element integral of the strain energy density, instead of the
Frobenius norm of the stress squared.

Several small additions and tweaks in ex22_proposed.cpp.
2018-11-02 20:46:52 -07:00
Veselin Dobrev d5d51cee9b In classes GridFunction and ParGridFunction, add method
ProjectBdrCoefficient for VectorCoefficients.
2018-11-02 20:44:12 -07:00
Aaron Fisher d2c885fd1d Reran make style with the proper version of astyle installed. 2018-11-02 15:28:38 -07:00
Aaron Fisher da3ad902f4 Added a test subdirectory for general and put a simple test in there to get the system up and running. 2018-11-02 15:05:43 -07:00
Aaron Fisher 95fce28de1 Added a travis build that will run the unittests. 2018-11-02 14:19:19 -07:00
Aaron Fisher d4c7a4bf0b Added all of the run test scripts. Not sure what we should call these tests, it's kinda a smorgasboard. 2018-11-02 14:08:41 -07:00
Stowell, Mark L 367929f415 Adding example code to test ElasticityIntegrator::ComputeElementFlux method 2018-11-02 11:20:41 -07:00
Jakub Červený b560030f32 Removed debugging code. 2018-11-02 15:59:05 +01:00
Veselin Dobrev dd22e6bbf3 Fix a typo in miniapps/nurbs/ex1.cpp 2018-11-01 22:54:49 -07:00
Veselin Dobrev 21fa41f0f6 In miniapps/nurbs, add the new test run from CMake to GNU make. 2018-11-01 21:54:18 -07:00
Tzanio 0aa13c973b Updated CHANGELOG 2018-11-01 21:04:07 -07:00
Tzanio d4ce263c08 Merge branch 'master' into fgmres-dev 2018-11-01 21:02:20 -07:00
Aaron Fisher ec07fc2dbe Merge branch 'tests-phase1-dev' of https://github.com/mfem/mfem into tests-phase1-dev 2018-11-01 17:05:13 -07:00
Aaron Fisher ce7b66f5be Changed the test directory to tests and added the tests to the make style target. 2018-11-01 17:03:57 -07:00
Stowell, Mark L fc3c0743ae Altering FGMRES to use the same iteration/pass numbers used in GMRES 2018-11-01 16:05:03 -07:00
Stowell, Mark L 684fbcb2e6 Changing to FGMRES to work with no preconditioner (Yes, I know... why not just use GMRES if you don't have a preconditioner?) 2018-11-01 15:44:06 -07:00
Jakub Cerveny dec82f7046 BlockVector::Update(): added a parameter to force reallocation. 2018-11-01 16:39:35 +01:00
Jakub Cerveny 195a77e959 Merge branch 'master' into laghos-amr-dev 2018-11-01 11:46:52 +01:00
Jean-Sylvain CAMIER 81a359dc6d Merge pull request #656 from mfem/mesh-tetrahedron-MarkEdge
Remove the MarkEdge method
2018-10-30 17:35:34 -07:00
Veselin Dobrev c20960c50a Apply 'make style' 2018-10-30 16:48:30 -07:00
Veselin Dobrev 265006d59f Remove the method MarkEdge(DenseMatrix &) from the base class
Element - it is only used by class Triangle.

A few more tweaks to suppress compiler warnings.
2018-10-30 16:40:31 -07:00
camierjs 26bfd8b757 Add the missing (not implemented) MarkEdge function 2018-10-30 15:06:52 -07:00
Veselin Dobrev e8fc6fcdb2 In the CMake build system, use CMAKE_SHARED_LIBRARY_CXX_FLAGS to
get the PIC compiler flag instead of the hardcoded '-fPIC' value.

Suggested by: @cwsmith
2018-10-29 17:05:03 -07:00
Tzanio 48469e8e10 Merge branch 'master' into periodic-nurbs-v2-dev 2018-10-28 14:54:35 -07:00
Tzanio 2019606947 Merge branch 'master' into elasticity-flux 2018-10-28 14:51:59 -07:00
Tzanio 8bfa269825 Merge branch 'master' into tests-phase1-dev 2018-10-28 14:48:11 -07:00
Tzanio Kolev d19ec0aad0 Merge pull request #650 from mfem/license-fix
Small edits in LICENSE and CHANGELOG
2018-10-26 12:49:08 -07:00
Jakub Cerveny 00227e56ad Merge branch 'master' into laghos-amr-dev 2018-10-26 11:18:10 +02:00
Tzanio cfdc9322b3 Reorganized + updated CHANGELOG. 2018-10-25 21:51:09 -07:00
Tzanio cf694b4492 Removing whitespace differences with the LGPL-2.1 LICENSE file, so GitHub
hopefully recognizes it at https://github.com/mfem/mfem.
2018-10-25 21:34:04 -07:00
Tzanio Kolev 43cf4fb2f5 Merge pull request #646 from mfem/print-as-one-fix
Fix a bug in ParMesh::PrintAsOne [print-as-one-fix]
2018-10-23 17:50:39 -07:00
Veselin Dobrev 3b69137064 Move the code for generating 'config.mk' from CMakeLists.txt to
a function in MfemCmakeUtilities.cmake, applying various tweaks.

Use the new cmake variable MFEM_MPI_NP when running the parallel
tests.

Remove the config variable MFEM_CPPFLAGS - it is not really used
anywhere. Also, remove the variables MFEM_MPIEXEC and
MFEM_MPIEXEC_NP since these values are autodetected by CMake.

Fix a warning in ex18.hpp.

In the makefile buidl system set MFEM_LIB_FILE to the versioned
shared library (when building shared) instead of the non-versioned
link.
2018-10-23 17:35:49 -07:00
Veselin Dobrev 9032dd3c9a Fix a bug in ParMesh::PrintAsOne
Reported by: @Dan2997925
2018-10-23 16:34:34 -07:00
Tzanio Kolev abe79bb2f3 Merge pull request #609 from mfem/cut-mesh-groups-dev-3
ParMesh groups communicaton for NC meshes [cut-mesh-groups-dev-3]
2018-10-23 11:27:01 -07:00
Tzanio Kolev 264770d21f Merge pull request #642 from mfem/mesh-load-patch-topo-fix
Fix an issue in Mesh::LoadPatchTopo introduced in 'prism-dev' [mesh-load-patch-topo-fix]
2018-10-23 08:38:37 -07:00
Tzanio Kolev 24cebb3b13 Merge pull request #641 from mfem/mesh-doxygen-tweak
Tweak the doxygen documentation for Mesh::UniformRefinement [mesh-doxygen-tweak]
2018-10-22 09:12:12 -07:00
Tzanio Kolev 54bb55bc32 Merge pull request #136 from mfem/hamiltonian-dev
Symplectic Integration for Hamiltonian Systems [hamiltonian-dev]
2018-10-22 07:23:14 -07:00
Tzanio Kolev 18994df30a Merge pull request #318 from IdoAkkerman/form_marker_dev
Boundary integrals only on indicated boundaries [form_marker_dev]
2018-10-22 07:22:29 -07:00
Tzanio Kolev daad02cbe3 Merge pull request #638 from mfem/test_gzstream
Add support for compressed saves in Mesh Explorer [test_gzstream]
2018-10-22 07:22:06 -07:00
Tzanio Kolev 559acc05fc Merge pull request #628 from mfem/bugfix-linearform-equal-dev
Adding LinearForm::operator=() methods [bugfix-linearform-equal-dev]
2018-10-22 07:21:25 -07:00
Tzanio Kolev 36cd32306f Merge pull request #633 from mfem/vs2013-workaround
Workaround for a bug in the Visual Studio 2013 compiler [vs2013-workaround]
2018-10-22 07:20:47 -07:00
Tzanio Kolev c819aa09ad Merge pull request #637 from mfem/bugfix-projectGF
Fixed a bug [bugfix-projectGF]
2018-10-22 07:20:17 -07:00
Jakub Cerveny ba60c07379 Merge branch 'master' into cut-mesh-groups-dev-3 2018-10-19 16:54:49 -07:00
Jakub Cerveny f7ab960d24 Cleaning up the examples directory. 2018-10-19 16:53:34 -07:00
Veselin Dobrev 0d6e920cc7 Add checks to ensure the mesh is conforming in the methods
ParGridFunction::ParallelAverage.

Remove a check for non-conforming mesh in the method
ParFiniteElementSpace::Synchronize which now should work for
NC meshes too.

A few additions to the doxygen documentation of class
ParFiniteElementSpace.
2018-10-19 15:31:49 -07:00
Tzanio Kolev 665d58bab6 Merge pull request #629 from mfem/pos-vector-basis-dev
Implementing Project method for vector coefficients [pos-vector-basis-dev]
2018-10-19 11:05:46 -07:00
Jakub Cerveny 52a3e70765 Removed unused parameter in ParMesh::FindSharedVertices. 2018-10-18 17:46:59 -07:00
Jakub Cerveny 895b935807 Fixed a problem for slave DOFs in ParFESpace::DivideByGroupSize. 2018-10-18 17:24:37 -07:00
Veselin Dobrev 6f9a5585c8 Fix an issue in Mesh::LoadPatchTopo introduced in 'prism-dev'. 2018-10-18 14:57:22 -07:00
Veselin Dobrev c95b1de846 Tweak the doxygen documentation for Mesh::UniformRefinement 2018-10-18 14:13:43 -07:00
Veselin Dobrev 4307149838 A few tweaks in the methods GridFunction::GetGradients. 2018-10-17 13:07:32 -07:00
Stowell, Mark L f065090fa7 Removing GetIntPoint/SetIntPoint calls 2018-10-17 10:39:51 -07:00
Stowell, Mark L 10ce20447b Adding GridFunction::GetGradients(ElementTransformation &T, ...) 2018-10-17 10:34:58 -07:00
Veselin Dobrev 6c6ac7ea6b Small optimization of some GridFunction methods.
The optimization is to use the (potentially cached) inverse Jacobian
matrix from the ElementTransformation class instead of computing
it from the Jacobian.
2018-10-16 17:44:25 -07:00
Veselin Dobrev 2a1a3a33b4 Add Doxygen documentation of the Eval methods in all base
coefficient classes: Coefficient, VectorCoefficient, and
MatrixCoefficient.
2018-10-16 17:30:52 -07:00
Aaron Fisher 877bae7623 Added unittest outputs to .gitignore and pulled unit testing out of the LLNL only section of the contribuiting.md 2018-10-16 16:07:41 -07:00
Veselin Dobrev a11f53ce43 Add examples 20/20p to config/sample-runs.sh 2018-10-16 16:03:30 -07:00
Aaron Fisher eeb60aff40 Conected the unit tests up to the make system and updated the changelog and contributing.md. 2018-10-16 15:58:18 -07:00
Veselin Dobrev 6e9fb6abb0 Update the error message in LinearForm::Assemble for the case of
boundary face integrators.
2018-10-16 14:54:42 -07:00
Mark C. Miller 251021cbe1 Add support for compressed saves 2018-10-16 13:59:15 -07:00
Aaron Fisher b74e81edc3 Dropped our unit tests into MFEM and added all of the copyright headers. Still need to hook it all up. 2018-10-16 11:07:43 -07:00
Tzanio 4f25a377b4 Minor styling 2018-10-16 11:01:56 -07:00
Tzanio 72003a06b1 Updated CHANGELOG 2018-10-16 10:44:18 -07:00
Tzanio eb5dd736f7 Merge branch 'master' into periodic-nurbs-v2-dev 2018-10-16 10:40:50 -07:00
Tzanio 6c54949cb7 make style 2018-10-16 10:40:12 -07:00
Tzanio 7095d4b7e0 Updated CHANGELOG 2018-10-16 10:27:22 -07:00
Tzanio 556e55fc37 Merge branch 'master' into elasticity-flux 2018-10-16 10:26:05 -07:00
Stowell, Mark L 32793336bd Removing unneeded operator= operload 2018-10-15 14:30:50 -07:00
Vladimir Tomov 40534e4f48 Fixed a bug. 2018-10-15 10:42:51 -07:00
Tzanio Kolev 14808f8cab Merge pull request #591 from mfem/xsdk-cmake-options-dev
Bring us in compliance with M1 of the XSDK [xsdk-cmake-options-dev]
2018-10-15 07:45:13 -07:00
Ido Akkerman d1fb866651 Add periodic test case 2018-10-15 10:14:59 +02:00
Ido Akkerman e79074c938 Add read/write periodic capability 2018-10-15 10:14:30 +02:00
Ido Akkerman 7053c05338 Add periodicity to NURBS 2018-10-15 10:14:06 +02:00
Veselin Dobrev a14ff8d866 Workaround for a bug in the Visual Studio 2013 compiler. 2018-10-14 13:41:27 -07:00
Aaron Fisher 4f3c122233 Merge branch 'master' into xsdk-cmake-options-dev 2018-10-12 10:05:15 -07:00
Aaron Fisher c3ea170328 Moved the aliased TPL variables into the XSDKDefaults.cmake file. 2018-10-12 10:02:53 -07:00
Jakub Cerveny cc9df02fe5 Merge branch 'master' into cut-mesh-groups-dev-3 2018-10-12 17:03:22 +02:00
Stowell, Mark L 46c7a80c65 Merge remote-tracking branch 'origin/master' into pos-vector-basis-dev 2018-10-10 21:27:06 -07:00
Stowell, Mark L 6b4f41f626 Merge remote-tracking branch 'origin/master' into shared-integ-dev 2018-10-10 21:16:24 -07:00
Stowell, Mark L c8b9e434a5 Merge remote-tracking branch 'origin/master' into hamiltonian-dev
# Conflicts:
#	CHANGELOG
2018-10-10 21:13:46 -07:00
Stowell, Mark L c52ce95c6b Merge remote-tracking branch 'origin/master' into derived-coefs-dev 2018-10-10 21:06:13 -07:00
Stowell, Mark L 481174fd4c Duplicating ParGridFunction::operator=() methods in ParLinearForm 2018-10-10 20:50:09 -07:00
Stowell, Mark L 5d5b483b6a Adding ParGridFunction::operator=(ParGridFunction&) method just to be certain 2018-10-10 20:49:42 -07:00
Stowell, Mark L 696694f124 Duplicating GridFunction::operator=() methods in LinearForm 2018-10-10 20:48:24 -07:00
Tzanio Kolev 7b0c974fe8 Merge pull request #554 from mfem/prism-dev
Adding Prisms and Mixed Mesh Support [prism-dev]
2018-10-10 19:16:10 -07:00
Tzanio b8ffb74c52 Small fix in doc/CodeDocumentation.dox 2018-10-10 18:53:55 -07:00
Tzanio 9b657d5303 Edited CHANGELOG 2018-10-10 18:35:47 -07:00
Tzanio 9bd8f77f10 Minor editing 2018-10-10 18:35:24 -07:00
Tzanio ba983bd37e Added Toroid and Shaper to config/sample-runs.sh 2018-10-10 18:34:49 -07:00
Tzanio 203fe01f87 Added Extruder to doc/CodeDocumentation.dox 2018-10-10 18:34:10 -07:00
Tzanio bdc5415de9 Added VTK versions of some mixed and wedge meshes 2018-10-10 18:31:57 -07:00
Tzanio b1537b5648 Small edits 2018-10-10 17:54:26 -07:00
Tzanio 357b925738 hexahedrons, hexahedrals -> hexahedra 2018-10-10 17:47:35 -07:00
Veselin Dobrev f168dfe1c7 A small tweak in the toroid meshing miniapp. 2018-10-03 19:39:43 -07:00
Veselin Dobrev 030544c2d9 Fix a typo in Mesh::PrintElementsByGeometry: 'cout' -> 'out' 2018-10-02 17:03:54 -07:00
Veselin Dobrev 88c8b70b45 In Mesh::CheckBdrElementOrientation, in 2D, generate the edge/face
internal data, if not already generated.
2018-10-02 16:39:52 -07:00
Veselin Dobrev 3af6c5bfb4 Merge pull request #617 from mfem/prism-dev-dev-2
Additions and modification for #554 [prism-dev-dev-2 -> prism-dev]
2018-10-01 16:04:44 -07:00
Stowell, Mark L f049206f6c Implementing PositiveFiniteElement::Project for vector coefficients 2018-10-01 13:56:18 -07:00
Stowell, Mark L 54125a350d merging with prism-dev 2018-09-30 10:47:52 -07:00
Veselin Dobrev 38feeb08a4 Fix a debug check for non-orientable surfaces.
At the end of Mesh::Finalize, perform the face orientation check only
when Dim == spaceDim, since a surface may be non-orientable.
2018-09-29 20:02:05 -07:00
Veselin Dobrev aa2a8eb687 Update CHANGELOG 2018-09-29 17:48:02 -07:00
Veselin Dobrev 102f7833c7 Make the method ParMesh::ExchangeFaceNbrData(Table*, int*) protected. 2018-09-29 17:46:03 -07:00
Veselin Dobrev 65cf48ccc2 Synchronize PUMI classes with the updated Mesh/ParMesh classes
Also, made some simplifications and tweaks in the ParPumiMesh ctor.
2018-09-29 14:38:20 -07:00
Veselin Dobrev f4b7cc883c Rename the Mesh method FinalizeMixedMesh to FinalizeMesh and
replace its implementation with two calls: to FinalizeTopology
and Finalize.

Some small edits in the doxygen documentation in class Mesh.
2018-09-28 17:29:46 -07:00
Veselin Dobrev 3b5986bcd4 Add support for reading wedge elements from a VTK mesh.
Both linear and quadratic elements are supported.

In the mesh-explorer miniapp, add a menu option to save the mesh
in VTK format - works for linear and quadratic elements only.
2018-09-28 12:07:54 -07:00
Veselin Dobrev da2fb88a17 Improved uniform refinement of tetrahedral meshes
In class Mesh/ParMesh:
  * Move the serial implementation of UniformRefinement3D to a new
    method: UniformRefinement3D_base. The implementations of the virtual
    method UniformRefinement3D (which now have no parameters) use the
    new UniformRefinement3D_base method.
  * In UniformRefinement3D_base, implemented two algorithms for choosing
    how to split the middle octahedron when refining a tetrahedron by
    cutting off its four corner tets. (These four tets have the same
    shape as the original tet and half the edge-length.) The choice of
    the algorithm is hard-coded in a const variable for now.
  * Add an optional parameter to UniformRefinement which is used to
    choose how to refine tet-only meshes: the default choice is to use
    the new algorithm defined by UniformRefinement3D; the second option
    is to use the old default - call LocalRefinement (marking all
    elements) to perform 3 levels of bisection. The new algorithm
    always produces elements with better shape (aspect ratio) than the
    old default (at least for the meshes in the data/ directory and a
    few other meshes).
  * Make the method Finalize virtual - its implementation in parallel
    requires updates in the ParMesh data.
  * Add a consistency check in ParMesh::ReorientTetMesh that verifies
    the assumption made in the method about the update of the shared
    triangles.
  * Simplify implementation of some methods in class ParMesh by
    separating common code in a new protected method: FinalizeParTopo.

Other updates:
  * In the examples and miniapps, when using a tet-only mesh which is
    first refined uniformly and then locally, it is now necessary to
    call the method Mesh::Finalize(true) (which is now virtual) in order
    to mark the elements for local refinement after the uniform
    refinement.
  * In example 12p, use better random seed values.
  * In examples 3/3p, add a sample run with order=2 on a tet mesh - this
    will test the methods {Mesh,ParMesh}::ReorientTetMesh. Previously,
    these were only tested by one sample run in example 4p.
  * In the mesh-explorer miniapp, add a refinement option to perform
    uniform refinement of tet-only meshes using bisection.
  * In the MFEM_LOCATION macro print the <file> and <line> location
    using a standard format: <file>:<line>, as used by most compilers
    when reporting warnings and errors.
  * Remove FIXME comments about mesh format v1.0.1.
2018-09-27 21:04:58 -07:00
Stowell, Mark L 110998255b Merge remote-tracking branch 'origin/master' into shared-integ-dev 2018-09-25 13:27:48 -07:00
Stowell, Mark L e8382c0b75 Merge remote-tracking branch 'origin/master' into prism-dev 2018-09-25 13:26:26 -07:00
Stowell, Mark L ed6ea98bb8 Merge remote-tracking branch 'origin/master' into hamiltonian-dev 2018-09-25 13:24:14 -07:00
Stowell, Mark L 4c96ac94ef Merge remote-tracking branch 'origin/master' into derived-coefs-dev 2018-09-25 13:20:27 -07:00
Tzanio Kolev 9dc443e3d3 Merge pull request #606 from mfem/project-bdr-coeff-fix
Fix an issue in ProjectBdrCoefficient [project-bdr-coeff-fix]
2018-09-25 12:07:45 -07:00
Tzanio Kolev 1218f51995 Merge pull request #572 from mfem/elementwise-error-dev
Adding methods which compute element-wise Lp errors [elementwise-error-dev]
2018-09-25 11:53:43 -07:00
Cameron Smith 851d075a14 fix shared and static lib inclusion
static and shared libs were being incorrectly added to the MFEM_LIBS list
2018-09-21 09:06:12 -04:00
Veselin Dobrev 46d92466fa Simplify the uniform-refinement mesh methods.
In the classes Mesh and ParMesh:

* Small optimization in Mixed3DUniformRefinement for hex-only meshes.
* In Mixed3DUniformRefinement, use marker array instead of std::map.
* Rename the methods Mixed{2D,3D}UniformRefinement to
  UniformRefinement{2D,3D}.
* Remove the methods {Quad,Hex,Wedge}UniformRefinement and use
  UniformRefinement{2D,3D} instead. In terms of performance, the
  difference was negligible.
2018-09-20 20:17:30 -07:00
Veselin Dobrev debea3cff7 Fix a bug in the boudary projection methods in ParGridFunction.
Specifically, in class ParGridFunction, in the methods
ProjectBdrCoefficient and ProjectBdrCoefficientTangent, add missing
average computation in the case of a nonconforming mesh.
2018-09-20 16:51:52 -07:00
Tzanio Kolev 15bc58dd2a Merge pull request #601 from mfem/sdc-mem-leak
SidreDataCollection: free memory in `attr_map` [sdc-mem-leak]
2018-09-20 14:47:17 -07:00
Jakub Cerveny 200c906e3c Merge branch 'master' into cut-mesh-groups-dev-3 2018-09-19 20:32:26 +02:00
Tzanio d74316144e Styling 2018-09-18 16:18:46 -07:00
Veselin Dobrev 1ddbc1e719 Fix an issue with ParGridFunction::ProjectBdrCoefficientTangent.
This fixes is the same issue is in ProjectBdrCoefficient which was
fixed by the previous commit.

An outstanding issue is the handling of nonconforming meshes in these
two methods - I left 'FIXME' comments there as reminders.
2018-09-18 15:47:47 -07:00
Veselin Dobrev 0f828353da Rework the changes in the parallel mesh format methods in ParMesh.
The goal was to preserve the parallel format from 'master' while
supporting the new features in this branch, prism-dev/prism-dev-dev-2.
2018-09-18 14:42:42 -07:00
Tzanio Kolev 2b24600f82 Merge pull request #605 from mfem/issue-463-fix
Preserve the global attribute lists after parallel derefinement [issue-463-fix]
2018-09-18 14:12:12 -07:00
Tzanio fd809f84f8 Minor 2018-09-18 14:09:34 -07:00
Jakub Cerveny b995f44a41 Added GetConformingSharedStructures call to ParMesh::NonconformingDerefinement. 2018-09-18 21:16:08 +02:00
Veselin Dobrev d791e2bf26 In ex11p, add a better random seed for the sample run with
inline-wedge.mesh.
2018-09-17 15:35:34 -07:00
Tzanio 419aa43306 Minor 2018-09-17 15:30:24 -07:00
Stowell, Mark L 20086252cf Merge remote-tracking branch 'origin/prism-dev' into prism-dev-dev-2 2018-09-17 15:28:36 -07:00
Tzanio fef3d1c3a3 Minor 2018-09-17 14:53:27 -07:00
Veselin Dobrev e47d652a88 Bugfix in the ParMesh constructor from serial Mesh.
The issue was: in the transition from serial to parallel mesh, a
shared triangle face was rotated (marked for bisection refinement)
if its processor-local adjacent element was a tetrahedron with a
non-zero refinement flag. This led to inconsistent shared triangles
in the two neighbor processors when the other adjacent element was
a wedge.

The solution is to apply the shared triangle rotation only when
we have a tet-only mesh (globally).
2018-09-16 16:40:06 -07:00
Veselin Dobrev f9694c3c2b Simplified data structures in class ParMesh
In class ParMesh:

* Introduced internal struct's Vert3 and Vert4 holding 3 and 4
  integers, respectively.

* Replaced 'shared_faces' with two separate arrays 'shared_trias'
  and 'shared_quads' with types Array<Vert3> and Array<Vert4>,
  respectively.

* Removed the arrays 'stria_lface', 'squad_lface', 'stria_sface',
  'squad_sface', and 'sface_stype'.

* Restore the array 'sface_lface' used previously. Shared face
  indices are shred triangle / quad indices offset by 0 / "number
  of shared triangles", respectively.

* Made the two RefineGroups methods protected.

* Added two new protected methods: UniformRefineGroups2D and
  UniformRefineGroups3D. These two methods simplify the
  implementations of almost all uniform-refinement methods in
  the class.

* Fixed a bug in ReorderTetMesh that was causing ex8p to fail with
  fichera-mixed.mesh.

* Updated the implementations of all ParMesh methods as necessary
  due to the above changes.

In class Triangle, add a static method MarkEdge that works on a
given array of 3 indices.

In class Array, add a method CopyTo - implemented using std::copy.
2018-09-16 14:30:09 -07:00
Jakub Cerveny 26a77da393 Added TODO. 2018-09-16 21:00:26 +02:00
Jakub Cerveny f1601bd24f Simplified group_map in ParNCMesh::GetConformingSharedStructures. 2018-09-16 20:53:03 +02:00
Jakub Cerveny 3506544b42 ParNCMesh cannot take prescribed partitioning (at the moment).
Reorganized and added a warning.
2018-09-16 20:42:13 +02:00
Jakub Cerveny 132cd5d316 Fixed merging errors, removed TODOs. 2018-09-16 20:41:15 +02:00
Jakub Cerveny 2bec165a83 Trying to reorder refactored methods to minimize diff to master. 2018-09-16 19:19:10 +02:00
Jakub Cerveny 3bc5c3f1f3 More cleanup. 2018-09-16 19:07:46 +02:00
Jakub Cerveny 93349a068d Cleaning up. 2018-09-16 12:08:22 +02:00
Jakub Cerveny f1cde22573 Fixed bug in initialization of pmesh.shared_faces. 2018-09-16 12:06:36 +02:00
Jakub Cerveny d372d76336 Removed debugging code. 2018-09-16 12:05:49 +02:00
Jakub Cerveny b11335c3ab ParMesh compatibility: creating shared_edges, shared_faces. 2018-09-14 20:20:55 +02:00
Jakub Cerveny b4d3473dab Conforming groups (ParallelAverage) seem to work for linear elements. 2018-09-14 16:45:15 +02:00
Jakub Cerveny 766d90c942 ParNCMesh: initialization of ParMesh::group_* 2018-09-14 09:19:44 +02:00
Veselin Dobrev 1fd822cfb5 Merge branch 'prism-dev' into prism-dev-dev-2 2018-09-13 17:29:08 -07:00
Veselin Dobrev 2ecebf912f In ParGridFunction::ProjectBdrCoefficient, add temporary
workaround for nonconforming meshes.

The workaround is to disable the parallel synchronization.
Also, added a debug check that all boundary dofs are set.
2018-09-13 16:53:02 -07:00
Stowell, Mark L d144057b23 Small typo in a comment 2018-09-13 15:52:32 -07:00
Stowell, Mark L 400e6fc422 Adding sample runs with mixed or wedge meshes 2018-09-13 15:35:53 -07:00
Tzanio d80c92ec54 Style 2018-09-13 09:23:28 -07:00
Veselin Dobrev 4f059c1898 Merge branch 'prism-dev' into prism-dev-dev-2 2018-09-12 21:46:11 -07:00
Veselin Dobrev e9176049bf Fix for an issue in the method ProjectBdrCoefficient in
class GridFunction when used in parallel.

The issue appears when the master processor for a boundary DOF does
not own any of the boundary elements adjacent to that DOF.

The method ProjectBdrCoefficientTangent is probably affected by the
same issue, however, it is not addressed by this commit.
2018-09-12 21:18:01 -07:00
Stowell, Mark L 5cce8731af Bugfix: missing indirection in element lookup 2018-09-12 21:17:27 -07:00
Veselin Dobrev bed70d3ca9 When derefining a mesh in parallel preserve the global
attribute lists.

Currently, the global attribute lists are replaced with
the local lists.
2018-09-12 21:01:00 -07:00
Veselin Dobrev 7c0b8c3147 Merge branch 'prism-dev' into prism-dev-dev-2 2018-09-12 17:31:49 -07:00
Veselin Dobrev 3dae180160 In Mesh::UniformRefinement, use the 'meshgen' field which
is global instead of the local GeometryList class.
2018-09-12 17:25:32 -07:00
Stowell, Mark L 74813abf09 Merging group_stria and group_squad within ParMesh::ExchangeFaceNbrData when necessary 2018-09-11 15:18:25 -07:00
Veselin Dobrev e3c83134f1 Merge branch 'prism-dev' into prism-dev-dev-2 2018-09-10 18:58:38 -07:00
Veselin Dobrev 9f854aa078 Merge branch 'master' into prism-dev 2018-09-10 18:57:37 -07:00
Veselin Dobrev bbac26bffe Merge pull request #598 from mfem/miniapps-sample-runs-fix
Fix the out-of-source build for the miniapps sample runs
2018-09-10 18:49:59 -07:00
Veselin Dobrev 0d6d850e09 Updates related to wedge/prism elements and mixed meshes.
List of changes and additions:

* In class Mesh:
  * Replaced the data fields BaseGeom, BaseBdrGeom, and BaseFaceGeom
    with a new data field: mesh_geoms that is a bitwise mask for all
    Geometry::Types found in the (local) Mesh including entities of
    lower dimensions.
  * The new data field mesh_geoms is set by the method SetMeshGen.
  * Removed the (protected) method InitBaseGeom.
  * Add new methods: HasGeometry, GetNumGeometries, and GetGeometries
    that can be used to query the content of mesh_geoms. Also, added
    class Mesh::GeometryList that can simplify such queries too.
  * The methods GetFaceBaseGeometry, GetElementBaseGeometry, and
    GetBdrElementBaseGeometry no longer have a default value for
    their input parameter (the entity index) and accept only values
    within their respective ranges.
  * Removed the parameter of the method GetRefinementTransforms.
  * Updated the methods PrepareNodeReorder and DoNodeReorder to
    support mixed meshes.
  * In parallel, the data field meshgen is now required to represent
    information about the global mesh - updated relevant ParMesh
    methods.
  * Made any required changes outside of class Mesh due to the above
    changes.
  * Made various tweaks and improvements in the following methods:
      CheckBdrElementOrientation, Mixed2DUniformRefinement,
      Mixed3DUniformRefinement, UniformRefinement, and
      GeneralRefinement.
  * Updated the method PrintCharacteristics to print the types of
    elements, boundary elements and faces used in the mesh.
  * In the method ReadInlineMesh, replace remaining "pri" strings
    with "wedge".
  * In the mesh reader method ReadGmshMesh, recover the term "prism"
    in the comments - it was replaced, unintentionally, I assume,
    by "wedge".

* Add support for refinement of curvilinear mixed meshes:
  * In class FiniteElementSpace, updated the methods:
    GetLocalRefinementMatrices, GetLocalDerefinementMatrices,
    RefinementMatrix, RefinementMatrix_main, as well as class
    RefinementOperator to support mixed meshes.
  * Add two new meshes: star-mixed-p2.mesh and fichera-mixed-p2.mesh
    which represent examples of quadratic mixed meshes in 2D and 3D,
    respectively.
  * Add sample runs in ex1/ex1p using the new quadratic mixed meshes.

* In class Geometry:
  * In the enumeration Type: removed the constant MIXED and added
    new constant: NUM_GEOMETRIES.
  * Add new static data field: DimStart[] that indexes the Types by
    dimension: the Types of dimension 'd' are given by the range
    [ DimStart[d], DimStart[d+1] ).

* In class ParNCMesh, added method GetGhostFaceGeometry that,
  for now, returns Geometry::SQUARE.

* Update the return type of the method DofOrderForOrientation in
  class FiniteElementCollection (and all derived classes) from
  'int *' to 'const int *'.

* Removed the virtual method Element::GetRefinementFlag and made
  the only relevant derived version (in class Tetrahedron),
  non-virtual.

* In class Tetrahedron, added method Init.

* Added FIXME comments for some outstanding issues.

* In the mesh-explorer miniapp:
  * Added option to enable or disable the 'refine' parameter when
    reading a mesh from file.
  * In the 'jitter' menu option, ask the user if the boundary
    nodes should be moved or not.
  * In the 'Print sub-element stats' menu option, count and print
    bad/inverted elements by their Geometry::Type as well.
2018-09-10 14:22:14 -07:00
Veselin Dobrev cb6fcfd39d Suppress "extra semi-colon" warnings from "sidre.hpp" when the macro
MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC is defined.
2018-09-10 14:15:15 -07:00
Veselin Dobrev a8589359d1 Move a _WIN32 config option from the config.hpp.in files
(GNU make and CMake versions) to the common config.hpp.

Add new macro definition in config.hpp:
   MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
which is defined when pragmas of the form
   #pragma GCC diagnostic ...
are supported.
2018-09-10 14:10:36 -07:00
Veselin Dobrev 816985fe8e A few tweaks in the Conduit and Sidre data collection classes. 2018-09-10 14:08:11 -07:00
Veselin Dobrev bd02a23e70 In config/sample-runs.sh, add option '-d' that is equivalent to
setting the variable 'mfem_build_dir'.
2018-09-10 14:04:32 -07:00
Veselin Dobrev e59f42b926 Some small updates in the extruder miniapp and related files. 2018-09-10 14:02:21 -07:00
Thomas Stitt b40d28ffc6 free memory in attr_map 2018-09-10 14:02:03 -07:00
Stowell, Mark L 40a9f507e0 Merge remote-tracking branch 'origin/master' into prism-dev 2018-09-08 14:55:18 -07:00
Stowell, Mark L 472ec2906c Merge remote-tracking branch 'origin/master' into hamiltonian-dev 2018-09-08 14:54:33 -07:00
Stowell, Mark L d78ee29349 Merge remote-tracking branch 'origin/master' into elementwise-error-dev 2018-09-08 14:53:55 -07:00
Stowell, Mark L b78036c2c4 Merge remote-tracking branch 'origin/master' into derived-coefs-dev 2018-09-08 14:52:39 -07:00
Veselin Dobrev f0dcf0bee0 Merge pull request #579 from mfem/fe-coll-order-check-dev
Verifying order and dimension arguments in fe_coll [fe-col-order-check-dev]
2018-09-08 15:42:08 -06:00
Veselin Dobrev c3a5b8e18f Merge pull request #587 from mfem/parmesh-copy-ctor-dev
ParNCMesh copy constructor, copying of NC ParMesh.
2018-09-08 15:31:25 -06:00
Veselin Dobrev 2c9d06fcff Merge pull request #596 from mfem/test-mk-fix
Small tweak in test.mk
2018-09-08 15:29:52 -06:00
Stowell, Mark L d7162db2aa Adding "extruder" to the test and cmake build systems 2018-09-07 16:55:47 -07:00
Stowell, Mark L 06cc992b88 Cleaning up comments and style 2018-09-07 16:30:47 -07:00
Stowell, Mark L ea1e1dcec1 Controlling the order used for transformed meshes 2018-09-07 16:05:15 -07:00
Stowell, Mark L 0c201f9ee3 Fixed a bug in the extrusion of 2D curved meshes 2018-09-07 15:53:32 -07:00
Stowell, Mark L c992559c18 Adding sample runs and coordinate transformation to extruder minapp 2018-09-07 15:38:23 -07:00
Stowell, Mark L 91b97b617c Fixing a small typo 2018-09-07 15:37:55 -07:00
Stowell, Mark L 1f3214d7c5 Adding mesh extruder miniapp 2018-09-07 14:51:24 -07:00
Mark L. Stowell dc113bd29d Merge pull request #600 from mfem/prism-dev-dev
Veselin and I discussed these proposed changes last week and after one small modification I agree with his suggestions.
2018-09-07 14:29:09 -07:00
Stowell, Mark L 1f67431608 Reverting ex1p to its standard form 2018-09-07 14:23:54 -07:00
Stowell, Mark L a8880d7a57 Preserving fixed order Wedge FEs, as derived classes, to be consistent with the existence of similar classes for other element types 2018-09-07 14:05:57 -07:00
Jakub Cerveny db90716187 ParNCMesh::GetConformingSharedStructures: shared to local maps. 2018-09-07 21:35:39 +02:00
Jakub Cerveny 97ba008e3d WIP ParNCMesh method to fill out ParMesh groups. 2018-09-07 17:23:21 +02:00
Jakub Cerveny b9626e8f2b ParMesh: some const correctness and minor stuff. 2018-09-07 17:22:39 +02:00
Jakub Cerveny 6d815143b9 Adding some temporary debug code. 2018-09-07 17:21:34 +02:00
Jakub Cerveny bd5007e868 WIP trying to make ParallelAverage work for NCMeshes. 2018-09-06 16:54:17 +02:00
Stowell, Mark L 25e9030b08 Fixing vector dimension in vector grid functions 2018-09-05 10:16:34 -07:00
Stowell, Mark L fbf6a27447 Modifying VectorGridFunctionCoefs to accept NULL pointers 2018-09-03 11:07:08 -07:00
Veselin Dobrev 94b4f23664 In the makefile build system, ensure that the sample runs in
the miniapps directory can be run when using an out-of-source
build.
2018-09-02 14:58:34 -07:00
Veselin Dobrev aa5c29e7bd Merge branch 'prism-dev' into prism-dev-dev 2018-08-31 18:53:14 -07:00
Veselin Dobrev f948c724bc Fix an issue with quadratic VTK meshes. 2018-08-31 18:51:52 -07:00
Veselin Dobrev 7b09c91564 Merge branch 'prism-dev' into prism-dev-dev 2018-08-31 17:27:03 -07:00
Veselin Dobrev bd52c083e6 Bugfix in Mesh::UniformRefinement plus a few small tweaks 2018-08-31 17:25:10 -07:00
Stowell, Mark L 9ff454b959 Adding an Identity Matrix Coefficient 2018-08-31 16:50:40 -07:00
Veselin Dobrev c0cbe38b48 Apply 'make style' 2018-08-31 13:14:47 -07:00
Robert W. Anderson 6331f5c43d DivideByGroupSize is a valid operation now on the cut mesh 2018-08-31 10:46:39 -07:00
Robert W. Anderson de88f554fd construct vector group communicator in nc case that is usually constructed in ConstructTrueDofs 2018-08-30 22:01:24 -07:00
Veselin Dobrev b4c143c40d A number of proposed tweaks for merging into prism-dev.
* Removed the fixed low-order finite element classes for wedges.
* Replace more cases of 'int' variables with 'Geometry::Type',
  mainly in class FiniteElement and its derived classes.
* Use constants from BasisType (instead of Quadrature1D) in the
  parameters of the *WedgeElement finite element classes.
* Impose ordering on the construction of some global objects by
  moving them into the same translation unit: specifically, moved
  the objects 'TriangleFE', 'TetrahedronFE', 'WedgeFE', and
  'Geometries' into fem/fe.cpp.
* In switchs on 'Geometry::Type', move the 'Geometry::PRISM' case
  last - just to follow the order in the enumeration.
* Add a new method CoarseFineTransformations::GetPointMatrices
  that simplifies some code that uses CoarseFineTransformations.
* Removed the 'INVALID' and 'MIXED' constants from the enum
  Element::Type.
* Remove the static method Element::GeometryType.
* Tweak some doxygen comments in the classes Embedding and
  CoarseFineTransformations.
* Generate an error if the method Wedge::GetNFaces is called:
  its parameter 'nFaceVertices' does not make sense for wedges.
2018-08-30 16:57:23 -07:00
Veselin Dobrev 57557479c6 Tweak the timing command in config/test.mk for Mac - failures in the
test were causing wrong output.
2018-08-30 14:17:06 -07:00
Stowell, Mark L 2e0c5b927c Removing outdated Mesh::GetFaceBaseGeometry method 2018-08-30 10:43:26 -07:00
Jakub Červený 9ff338c6e4 Cosmetic changes done while studying the branch. 2018-08-30 14:44:18 +02:00
Stowell, Mark L 3ed45b3665 Merge remote-tracking branch 'origin/master' into shared-integ-dev 2018-08-29 09:32:50 -07:00
Stowell, Mark L e79afa5508 Merge remote-tracking branch 'origin/master' into fe-coll-order-check-dev 2018-08-29 09:30:53 -07:00
Stowell, Mark L c19c1284a5 Merge remote-tracking branch 'origin/master' into elementwise-error-dev 2018-08-29 09:29:43 -07:00
Stowell, Mark L e694c796f9 Merge remote-tracking branch 'origin/master' into hamiltonian-dev 2018-08-29 09:27:30 -07:00
Stowell, Mark L 96a7752e86 Merge remote-tracking branch 'origin/master' into prism-dev 2018-08-29 09:26:25 -07:00
Stowell, Mark L 5b334276a1 Merge remote-tracking branch 'origin/master' into derived-coefs-dev 2018-08-29 09:25:37 -07:00
Jakub Červený 1e9c62eb8d make style 2018-08-29 16:45:10 +02:00
Jakub Červený 723e2c2bbe Merge branch 'master' into cut-mesh-groups-dev-2 2018-08-29 16:43:00 +02:00
Stowell, Mark L ce8a0cd527 Adding various coefficients which are sums or products of other coefficients 2018-08-28 16:36:52 -07:00
Stowell, Mark L bba10888d1 make style 2018-08-28 16:36:41 -07:00
Stowell, Mark L 341064508e Adding coefficients to compute div, grad, or curl of grid functions. 2018-08-28 16:36:15 -07:00
Aaron Fisher e269582dbe Added optional xsdk variable aliases for all of the external libraries. 2018-08-28 15:43:24 -07:00
Stowell, Mark L b3c6177292 Changing one last occurrence of AddPri to AddWedge 2018-08-28 12:27:59 -07:00
Stowell, Mark L 75849bf3ea Merge remote-tracking branch 'origin/master' into fe-coll-order-check-dev 2018-08-28 10:08:17 -07:00
Stowell, Mark L 108eaa46f4 Merge remote-tracking branch 'origin/master' into hamiltonian-dev 2018-08-28 09:53:30 -07:00
Stowell, Mark L 1259e95425 Merge remote-tracking branch 'origin/master' into shared-integ-dev 2018-08-28 09:51:42 -07:00
Stowell, Mark L 20b07c3ca2 Merge remote-tracking branch 'origin/master' into elementwise-error-dev 2018-08-28 09:49:11 -07:00
Jakub Červený 450dc4cd8b Implemented ParNCMesh copy constructor, enabled copying NC ParMesh. 2018-08-28 13:42:52 +02:00
Robert W. Anderson b6df5d2805 add declarations needed for merged code 2018-08-27 16:10:29 -07:00
Robert W. Anderson c6f0d84b31 cherry pick 5caee from branch 2018-08-27 16:04:36 -07:00
Robert W. Anderson 3a8c0ddc5e merge eba6d48 from branch and resolve conflicts 2018-08-27 16:03:29 -07:00
Stowell, Mark L 5ebcda8f08 Removing dead code 2018-08-27 14:45:08 -07:00
Stowell, Mark L 79fd394f71 Adding prism related comments to CHANGELOG 2018-08-27 14:35:33 -07:00
Stowell, Mark L 960ba8a8c2 Changing "pri" to "wedge" or "wdg" is several places. 2018-08-27 14:23:11 -07:00
Veselin Dobrev 3309520ed6 In the ctor for H1_FECollection, allow dim=0 to support point meshes. 2018-08-24 15:21:06 -07:00
Andrew T. Barker ddda86a6d0 ElasticityIntegrator, move DenseMatrix initialization outside
integration point loop in ComputeElementFlux method.
2018-08-23 13:15:36 -07:00
Tzanio 057b688116 Merge branch 'master' into prism-dev 2018-08-22 17:53:35 -07:00
Andrew T. Barker 4bfdd59ac5 Add ComputeElementFlux method to ElasticityIntegrator
This can be seen as one step toward implementing a ZZ error
estimator for elasticity.
2018-08-22 12:01:00 -07:00
Stowell, Mark L d7f0640204 Inline wedge format now uses "wedge" rather than "pri". Also trying to increase code coverage by adding wedge example runs. 2018-08-18 10:31:05 -07:00
Stowell, Mark L a47d70cfba make style 2018-08-17 21:51:33 -07:00
Stowell, Mark L 1e100b3f26 Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	mesh/pmesh.cpp
2018-08-17 21:51:16 -07:00
Stowell, Mark L 7e8ac2f1d1 Fixing bug in LOR ParMesh construction 2018-08-17 21:02:16 -07:00
Stowell, Mark L 72c52af4c3 Changing method names to what was suggested... (oops) 2018-08-16 18:33:15 -07:00
Stowell, Mark L 196a193224 Changing the method names 2018-08-16 18:29:06 -07:00
Veselin Dobrev 8e21f7f5d0 Apply 'make style' 2018-08-16 17:11:11 -07:00
Tzanio cb2166b786 minor styling 2018-08-14 14:39:48 -07:00
Stowell, Mark L 82815d2cf4 Verifying order and dimension arguments in FiniteElementCollection base class constructors. 2018-08-14 14:03:42 -07:00
Stowell, Mark L 2fc7eb39ab Adding GridFunction methods which compute element-wise Lp errors (useful for visualization) 2018-08-07 16:27:26 -07:00
Stowell, Mark L 1faf3f3073 make style 2018-08-02 20:20:01 -07:00
Stowell, Mark L 3bf8a815b5 Adding Integrator copy Constructors to MixedBilinearForm and LinearForm. Also adding marker array copying 2018-08-02 17:55:05 -07:00
Stowell, Mark L 3b55f92b78 Merge with master Aug 2, 2018 2018-08-02 16:05:30 -07:00
Cameron Smith 6d8f70ba57 support pumi built with zoltan/parmetis/simmodsuite 2018-08-01 21:03:20 +00:00
Tzanio 0f0883c8c0 Renamed prismatic-torus -> toroid.
See https://en.wikipedia.org/wiki/Toroid.
2018-07-28 16:49:48 -07:00
Tzanio b924ac4518 A few changes related to the Prismatic Torus miniapp 2018-07-28 15:58:16 -07:00
Tzanio 0249dcf7d5 Updated CHANGELOG. 2018-07-27 16:31:37 -07:00
Tzanio 639a30c5fd make style 2018-07-27 15:32:14 -07:00
Stowell, Mark L 370552b3e2 Found one more line where "prism" should become "wedge" 2018-07-26 13:29:06 -07:00
Stowell, Mark L 7442982ac5 Changing "Prism" to "Wedge" in various places. Geometry::Type intentionally left as Geometry::PRISM 2018-07-25 19:51:40 -07:00
Stowell, Mark L e068bd6883 Adding new files to CMake files 2018-07-25 13:35:35 -07:00
Stowell, Mark L 4dd0799db8 Updating CHANGELOG with news of ex20 and ex20p 2018-07-25 09:36:31 -07:00
Tzanio 9d7b9e47fb Minor styling in Example 20.
Updates examples/CMakeLists.txt and .gitignore.
2018-07-24 19:53:59 -07:00
Stowell, Mark L aa98b92e8c Adding comments and new options to prismatic-torus miniapp 2018-07-24 17:06:54 -07:00
Stowell, Mark L 8d4948dc74 Moving Nedelec prism code to a sub-branch 2018-07-24 15:35:41 -07:00
Stowell, Mark L bf0b2be104 Merge remote-tracking branch 'origin/master' into prism-dev 2018-07-24 15:11:45 -07:00
Stowell, Mark L 959cd13211 make style 2018-07-24 14:51:47 -07:00
Stowell, Mark L 3466f991ca Adding comments commensurate with the other example codes 2018-07-24 10:05:13 -07:00
Stowell, Mark L 0c111ee4e1 Improving the comments for the new examples 2018-07-24 09:42:57 -07:00
Stowell, Mark L e4f26fa252 Merge remote-tracking branch 'origin/master' into hamiltonian-dev 2018-07-24 09:12:55 -07:00
Stowell, Mark L 3583cd8a83 Adding Mesh::FinalizeMixedMesh 2018-07-23 20:21:01 -07:00
Stowell, Mark L 0c087abe42 Fixing a typo 2018-07-23 16:07:20 -07:00
Stowell, Mark L 396969db0d Adding capability to extrude 2D meshes to ex1p (with new sample run) 2018-07-23 15:58:29 -07:00
Stowell, Mark L dd3991a0fc Adding sample runs using mixed meshes to ex1 and ex1p 2018-07-23 15:57:20 -07:00
Stowell, Mark L ff7ed2efc6 Adding prism mesh to sample runs in ex2 and ex2p 2018-07-23 15:25:31 -07:00
Stowell, Mark L d525f0a730 Adding support for mixed meshes in parallel 2018-07-23 15:01:08 -07:00
Stowell, Mark L cd7e2dcb4c Fixing a broken file 2018-07-21 13:52:27 -07:00
Stowell, Mark L 51ba4a9e13 Fixes to Mixed 2D meshes in parallel 2018-07-21 13:43:25 -07:00
Stowell, Mark L ecfc2b1360 make style 2018-07-20 19:34:26 -07:00
Stowell, Mark L 7658cbb6d4 Adding support for uniform refinement of mixed meshes in 3D 2018-07-20 16:57:49 -07:00
Stowell, Mark L 90968146bb Adding support for uniform refinement of mixed 2D meshes 2018-07-20 11:54:17 -07:00
Stowell, Mark L 7d1b1c51d3 Fixing point matrices for prisms 2018-07-20 00:21:10 -07:00
Stowell, Mark L c3e023deed Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	fem/fespace.cpp
2018-07-19 19:51:39 -07:00
Stowell, Mark L b7952fb8ed A few small edits 2018-07-19 19:27:33 -07:00
Stowell, Mark L 6db10d2147 Adding miniapp to generate test meshes 2018-07-19 16:29:31 -07:00
Stowell, Mark L 887788da68 Merge branch 'hamiltonian-dev' of github.com:mfem/mfem into hamiltonian-dev
# Conflicts:
#	doc/CodeDocumentation.dox
#	examples/ex20.cpp
#	examples/ex20p.cpp
#	examples/makefile
2018-07-19 09:10:56 -07:00
Jakub Cerveny 54c5582fbd Improved DOF partition stats. 2018-06-15 11:40:40 +02:00
Jakub Cerveny 0792af6c3e Merge branch 'master' into laghos-amr-dev 2018-06-14 16:36:30 +02:00
Jakub Cerveny 8aacc088ea Added method PrintPartitionStats. 2018-06-14 15:30:54 +02:00
Jakub Cerveny 76aeca77bd Merge branch 'pmatrix-stats-dev' into laghos-amr-dev 2018-06-14 13:16:22 +02:00
Cameron Smith 14143faa88 create config.mk, install config.mk and test.mk 2018-06-01 13:52:31 -05:00
Stowell, Mark L 612c828cf3 Overwriting ex18 with new one from master 2018-05-25 12:12:43 -07:00
Stowell, Mark L 8c4a3a7bf5 Adding example 20 2018-05-25 12:11:18 -07:00
Stowell, Mark L e472854dd0 Merge remote-tracking branch 'origin/master' into hamiltonian-dev
# Conflicts:
#	examples/ex18.cpp
#	examples/ex18p.cpp
#	examples/makefile
#	linalg/ode.cpp
#	linalg/ode.hpp
2018-05-25 12:10:22 -07:00
Tzanio f291244bc1 boundary face integrator -> boundary integrator 2018-05-07 17:57:47 -07:00
Tzanio 1a41951843 Merge branch 'master' into form_marker_dev 2018-05-07 17:51:37 -07:00
Jakub Cerveny 2767704cc6 ParFESpace: added DOF partitioning stats. 2018-05-04 18:40:29 +02:00
Jakub Cerveny 0958ac8644 P matrix construction: added collection of comm statistics. 2018-05-03 17:06:58 +02:00
Jakub Červený 253e1dc320 Added missing assert in Vector::AddElementVector (based on similar function). 2018-03-16 16:49:05 +01:00
Jakub Cerveny 761854a143 DebugDump helpers in DenseTensor and BilinearForm 2018-03-08 16:38:38 +01:00
Jakub Cerveny cfe0e0063f Support for laghos/amr-dev, this is kind of a companion branch. 2018-02-09 17:33:31 +01:00
Stowell, Mark L d0cecfba52 Fixing a vertex numbering issue related to the lack of new vertices on triangular faces of uniformly refined prisms 2018-02-01 17:17:42 -08:00
Stowell, Mark L 0545862005 Replacing code that was overwritten by merge with master 2018-02-01 10:16:26 -08:00
Stowell, Mark L ef17fa07e9 Switching int to enum type 2018-02-01 09:27:29 -08:00
Stowell, Mark L 8bf859381b Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	fem/fespace.cpp
#	fem/fespace.hpp
2018-02-01 09:15:25 -08:00
Stowell, Mark L dcebaab1ab Remove uniform face type assumption from ParFiniteElementSpace::GetGroupComm (thanks Veselin!) 2018-01-30 11:30:01 -08:00
Stowell, Mark L 132dd9724d make style 2018-01-30 11:29:04 -08:00
Stowell, Mark L e7f24c66f9 Remove unnecessary assumption 2018-01-30 11:28:48 -08:00
Stowell, Mark L 53f4b0423e Adding FinalizeTransformation to Mesh::GetLocalQuadToPriTransformation (thanks Veselin!) 2018-01-30 10:36:23 -08:00
Stowell, Mark L f19fafe71b Implementing Prism::GetFaceVertices 2018-01-27 12:14:15 -08:00
Stowell, Mark L 8adf1bf29c make style 2018-01-26 20:48:27 -08:00
Stowell, Mark L a0b21e9ec0 Switching to enumerated type 2018-01-26 20:45:12 -08:00
Stowell, Mark L bae718680d Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	fem/fespace.cpp
#	fem/pfespace.cpp
2018-01-26 20:44:48 -08:00
Stowell, Mark L f0b59a7371 Adding first draft of Nedelec basis for prisms 2018-01-26 11:24:41 -08:00
Stowell, Mark L 75c6486cdc Adding calls to FinalizeTransform 2018-01-26 11:24:03 -08:00
Stowell, Mark L 590c0d7f6a Merge remote-tracking branch 'origin/master' into prism-dev 2018-01-22 18:59:32 -08:00
Stowell, Mark L 7eaf351332 Adding debug output to an error message 2018-01-19 15:12:42 -08:00
Stowell, Mark L 0edcb4a6d6 make style 2018-01-17 21:53:17 -08:00
Stowell, Mark L cbb2b2b272 make style 2018-01-17 21:50:30 -08:00
Stowell, Mark L 35fc235ace Adding PRISM case to ProjectPoint 2018-01-17 21:46:42 -08:00
Stowell, Mark L d1a87f25d9 Adding PRISM case to fuzzy CheckPoint function 2018-01-17 21:41:08 -08:00
Stowell, Mark L 7518b5ce9d Caching the jacobian for the PRISM type 2018-01-17 21:36:13 -08:00
Stowell, Mark L 07158b29f6 Fix counter declaration after merge with master 2018-01-16 11:00:52 -08:00
Stowell, Mark L 6cfc1081d8 Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	fem/geom.hpp
#	mesh/mesh.cpp
#	mesh/mesh.hpp
2018-01-16 10:53:03 -08:00
Stowell, Mark L 6079f4674a Adding Extrude2D function to generate hex or prism meshes from quad or tri meshes respectively. 2018-01-12 15:06:15 -08:00
Stowell, Mark L 20d6e495ac Switching to GeomType enumeration in a few more places 2018-01-12 15:05:12 -08:00
Stowell, Mark L 8a5a250204 Merge remote-tracking branch 'origin/master' into prism-dev
# Conflicts:
#	fem/fe.cpp
#	fem/fe.hpp
#	fem/fe_coll.cpp
#	fem/geom.cpp
#	fem/geom.hpp
#	mesh/mesh.cpp
2018-01-12 11:36:49 -08:00
Stowell, Mark L 3e20045b56 Shared triangular faces may not belong to tetrahedra 2017-11-28 11:05:02 -08:00
Stowell, Mark L fb9921fac2 make style 2017-11-28 11:04:00 -08:00
Stowell, Mark L dd94a5ce4a Fixed a face orientation bug 2017-11-27 20:36:40 -08:00
Stowell, Mark L 77d0d01dd0 Adding L2 finite elements for prisms 2017-11-24 15:32:51 -08:00
Stowell, Mark L ca56e2e6b5 Using the proper function space type so that higher order integration rules will be used for prisms 2017-11-24 11:21:29 -08:00
Stowell, Mark L 9793b393c5 Defining nodes for H1 Prisms elements 2017-11-24 11:20:27 -08:00
Stowell, Mark L 1f58383468 Rotating face zero for prisms 2017-11-24 11:19:32 -08:00
Stowell, Mark L c72ecf9a9c Tweaking comments 2017-11-24 11:18:54 -08:00
Stowell, Mark L a3f7b4ab02 A few more instances of missing BaseFaceGeom 2017-11-22 19:56:46 -08:00
Stowell, Mark L 9dbde39b0c make style 2017-11-22 19:35:31 -08:00
Stowell, Mark L e5e80bb3a3 Propagating BaseFaceGeometry 2017-11-22 16:08:13 -08:00
Stowell, Mark L 3e7da90620 Fixing cut-n-paste error 2017-11-22 16:07:05 -08:00
Stowell, Mark L 2b296192ff Fixing a small oversight 2017-11-22 16:06:29 -08:00
Stowell, Mark L 032176f5c4 As this is implemented in a new way we should verify it. 2017-11-22 16:06:07 -08:00
Stowell, Mark L 1cc14aa4d8 Removing mixed mesh class 2017-11-21 14:58:52 -08:00
Stowell, Mark L 40c658b74f Adding inline prism mesh 2017-11-21 14:58:24 -08:00
Stowell, Mark L 6df61f337e Adding parallel uniform refinement for prism meshes (not yet working) 2017-11-21 10:14:32 -08:00
Stowell, Mark L 487975f952 Removing debugging output 2017-11-21 10:13:56 -08:00
Stowell, Mark L 90c123811e Fixed uniform refinement of prism meshes 2017-11-21 09:39:53 -08:00
Stowell, Mark L e8ecc20a2f Adding a uniform refinement scheme for prisms (not yet working...) 2017-11-20 17:05:36 -08:00
Stowell, Mark L 92d334277e make style 2017-11-20 17:05:01 -08:00
Stowell, Mark L 3ff130cd91 More int -> Geometry::Type changes 2017-11-19 22:08:59 -08:00
Stowell, Mark L c911b598e4 Adding an inline prism mesh 2017-11-19 22:05:30 -08:00
Stowell, Mark L 6a236ada82 Changing int to Geometry::Type 2017-11-19 20:14:42 -08:00
Stowell, Mark L d6ebac09c6 make style 2017-11-19 10:18:13 -08:00
Stowell, Mark L 6e443353df Adding integration rules for prisms 2017-11-19 10:16:16 -08:00
Stowell, Mark L aa754254f1 Implementing H1Pos_PrismElement following H1_PrismElement 2017-11-19 10:15:51 -08:00
Stowell, Mark L c9c6db3ef8 Implementing H1_PrismElement::CalcDShape 2017-11-19 10:15:20 -08:00
Stowell, Mark L fd356bcce7 make style 2017-11-18 15:43:56 -08:00
Stowell, Mark L 916f400575 Adding H1 and H1Pos finite elements for prisms 2017-11-18 15:43:22 -08:00
Stowell, Mark L 787607a273 Adding face to element transformations for prisms (not yet properly tested) 2017-11-17 20:14:46 -08:00
Stowell, Mark L c989798981 Adjusting orderings to avoid orientation errors 2017-11-17 20:13:12 -08:00
Stowell, Mark L 523a7cb9e2 Generalizing FiniteElementSpace::Construct 2017-11-17 10:47:06 -08:00
Stowell, Mark L 25b828001d Generalizing FiniteElementSpace::RefinementMatrix 2017-11-17 10:35:23 -08:00
Stowell, Mark L e234a6da94 Moving GetFaceBaseGeometry implementation to the header file 2017-11-16 13:53:35 -08:00
Stowell, Mark L 191a1fa470 Adding BaseFaceGeom because this can differ from BaseBdrGeom 2017-11-16 13:49:53 -08:00
Stowell, Mark L ccb36621f7 make style 2017-11-16 13:23:19 -08:00
Stowell, Mark L c8cee31d33 Removing assumption that all elements are the same . 2017-11-16 13:22:58 -08:00
Stowell, Mark L 5956e157c1 Switching more occurrences of "int" to Geometry::Type 2017-11-16 10:42:16 -08:00
Stowell, Mark L 00069e5914 Switching to Element::Type and Geometry::Type rather than "int" when relevant. 2017-11-15 15:34:31 -08:00
Stowell, Mark L be198061ce Adding test meshes for mixed meshes 2017-11-15 10:09:52 -08:00
Tzanio f5558d5054 make style 2017-11-10 17:14:18 -08:00
Tzanio 981629fac6 Merge branch 'master' into hamiltonian-dev 2017-11-10 17:13:57 -08:00
Stowell, Mark L cb7e52fcba Resolving linking problems 2017-11-10 15:39:01 -08:00
Stowell, Mark L e9f0bd9489 Returning a pair of face tables from GenerateElementToFaceTable 2017-11-10 15:38:33 -08:00
Stowell, Mark L 0e53b4ba9b MixedMesh now compiles but has many methods commented out 2017-11-09 11:11:36 -08:00
Stowell, Mark L 70dab69198 Continuing the transition to maps of Arrays 2017-11-08 21:20:29 -08:00
Stowell, Mark L 55a3f13bfd make style 2017-11-08 21:16:10 -08:00
Stowell, Mark L 10ac646d18 Adding INVALID and MIXED to the element type and geometry type enumerations. Also adding a static member function to map between the enumerations. 2017-11-08 21:09:18 -08:00
Stowell, Mark L 4e768e68e2 Modifying Elements to use their Element::Type enumeration rather than "int" 2017-11-08 17:22:48 -08:00
Stowell, Mark L 29c3baaea4 Adding an experimental MixedMesh class rather than editing Mesh itself. 2017-11-08 15:48:35 -08:00
Stowell, Mark L 201c51b7d1 Adding a piece-wise constant basis for prisms 2017-11-05 19:58:08 -08:00
Stowell, Mark L 81b041567b Adding prism class to mesh directory 2017-11-04 10:40:47 -07:00
Stowell, Mark L d7385c0db4 Adding a BiCubic3DFiniteElement for cubic Prisms 2017-11-03 21:18:23 -07:00
Stowell, Mark L ef7fcf7576 Adding Quadratic H1 basis for Prisms 2017-11-03 16:42:41 -07:00
Stowell, Mark L 344ee2f115 Initial changes to Mesh class to support Prism meshes. 2017-10-31 16:36:33 -07:00
Stowell, Mark L ec36b397b0 Adding a simple prism mesh for testing. 2017-10-31 11:32:11 -07:00
Stowell, Mark L bec7973784 Starting to add prism support to eltrans and fe_coll 2017-10-31 11:31:35 -07:00
Stowell, Mark L b0aa25c996 Using the new NodalFiniteElement class for prisms 2017-10-31 11:31:00 -07:00
Stowell, Mark L 8aa2941b55 Adding a NodalFiniteElement class for Prisms 2017-10-31 11:29:58 -07:00
Stowell, Mark L bb80432cd1 Fixing typos and adding a missing declaration 2017-10-31 09:37:19 -07:00
Stowell, Mark L 7a8deac838 make style 2017-10-30 18:15:14 -07:00
Stowell, Mark L 56ac6ec435 Adding PRISM case to the GeometryRefiner 2017-10-30 18:01:15 -07:00
Stowell, Mark L bf37988ec6 It seems we cannot insert a new entry into the Geometry::Type enumeration without redefining the mesh format. 2017-10-30 12:03:39 -07:00
Stowell, Mark L 16bacad76b Possible bug if 1-end.x is interpreted as an integer rather than a double. 2017-10-30 11:11:19 -07:00
Stowell, Mark L a92e32e388 Adding initial changes to support Prisms 2017-10-30 11:10:06 -07:00
Tzanio d9791934f8 Minor 2017-10-19 13:43:25 -07:00
Ido Akkerman 118e2fd469 Added boundary marker to bilinearform 2017-10-13 11:50:26 +02:00
Ido Akkerman 82f591d2df Added boundary marker to linearform 2017-10-13 11:50:15 +02:00
Veselin Dobrev a881380de7 A few small additions + edits. 2017-04-28 20:20:29 -07:00
Stowell, Mark L 3893845102 Adding comment blocks 2017-04-12 15:53:40 -07:00
Stowell, Mark L ca1e273afc Renaming example 19 to 18 2017-04-12 11:20:54 -07:00
Tzanio 7694a8e18f Merge branch 'master' into hamiltonian-dev 2017-04-12 09:37:31 -07:00
Stowell, Mark L f158b615c0 Adding 1D example codes to test Symplectic integrators 2017-02-25 22:08:39 -08:00
Stowell, Mark L b69699c133 Adding specialized ODE integrators for Hamiltonian systems 2017-02-25 22:07:28 -08:00
209 changed files with 41016 additions and 3689 deletions
+17
View File
@@ -45,6 +45,8 @@ examples/ex[1-9]
examples/ex[1-9]p
examples/ex1[04-9]
examples/ex1[0-9]p
examples/ex2[0-9]
examples/ex2[0-9]p
examples/refined.mesh
examples/displaced.mesh
@@ -76,6 +78,13 @@ examples/vortex-?-init.*
examples/vortex-?-final.*
examples/deformation.*
examples/pressure.*
examples/ex20.dat
examples/ex20p_?????.dat
examples/gnuplot_ex20.inp
examples/gnuplot_ex20p.inp
examples/ex22*.mesh
examples/ex22*.sol
examples/ex22p_*.*
examples/sundials/ex9
examples/sundials/ex1[06]
@@ -133,16 +142,20 @@ miniapps/electromagnetics/Joule_*
miniapps/meshing/mobius-strip
miniapps/meshing/klein-bottle
miniapps/meshing/toroid
miniapps/meshing/mesh-explorer
miniapps/meshing/shaper
miniapps/meshing/extruder
miniapps/meshing/mesh-optimizer
miniapps/meshing/pmesh-optimizer
miniapps/meshing/mobius-strip.mesh
miniapps/meshing/klein-bottle.mesh
miniapps/meshing/toroid-*.mesh
miniapps/meshing/mesh-explorer.mesh
miniapps/meshing/partitioning.txt
miniapps/meshing/shaper.mesh
miniapps/meshing/extruder.mesh
miniapps/meshing/optimized*
miniapps/meshing/perturbed*
@@ -165,3 +178,7 @@ miniapps/nurbs/mesh.*
miniapps/nurbs/sol.*
miniapps/nurbs/mode_*
miniapps/nurbs/Example1*
# Unit test binary and outputs
tests/unit/output_meshes
tests/unit/unit_tests
+102 -6
View File
@@ -10,15 +10,111 @@
Version 3.4.1 (development)
===========================
Support for wedge elements and meshes with mixed element types
--------------------------------------------------------------
- Added support for wedge shaped mesh elements of arbitrary order (with Geometry
type PRISM) which have two triangular faces and three quadrilateral faces.
Several examples of such meshes can be found in the data/ directory.
- Added H1 and L2 finite elements of arbitrary order for Wedge elements.
- Added support for mixed meshes containing triangles and quadrilaterals in 2D
or tetrahedra, wedges, and hexahedra in 3D. This includes support for uniform
refinement of such meshes. Several examples of such meshes can be found in the
data/ directory.
- Added support for reading and writing linear and quadratic meshes containing
wedge elements in VTK mesh format. Several examples of such meshes can be
found in the data/ directory.
Other meshing improvements
--------------------------
- Improved the uniform refinement of tetrahedral meshes (also part of the
uniform refinement of mixed 3D meshes). The previous refinement algorithm is
still available as an option in Mesh::UniformRefinement. Both can be used in
the updated Mesh Explorer miniapp.
- The local tetrahedral mesh refinement algorithm in serial and in parallel now
follows precisely the paper:
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
Using Bisection", SIAM J. Sci. Comput., 22(2), 431448.
This guarantees that the shape regularity of the elements will be preserved
under refinement.
- Added support for parallel communication groups on non-conforming meshes.
- A boundary in a NURBS mesh can now be connected with another boundary. Such a
periodic NURBS mesh is a simple way to impose periodic boundary conditions.
- Added support for reading linear and quadratic 2D quadrilateral and triangular
Cubit meshes.
- The tetrahedral mesh refinement algorithm in serial and in parallel now
follows precisely the paper:
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
Using Bisection", SIAM J. Sci. Comput., 22(2), 431448.
This guarantees that the shape regularity of the elements will be preserved
under refinement.
- The TMOP mesh optimization algorithms were extended to support user-defined
space-dependent limiting terms. Improved the TMOP objective functions by
more accurate normalization of the different terms.
Discretization improvements
---------------------------
- Added support for derefinement of vector (RT + ND) spaces.
- Added element flux, and flux energy computation in class ElasticityIntegrator,
allowing for the use of Zienkiewicz-Zhu type error estimators with the
integrator. For an illustration of this addition, see the new Example 22.
- Added a variety of coefficients which are sums or products of existing
coefficients as well as grid function coefficients which return the
divergence, gradient, or curl of their GridFunctions.
New and improved solvers and preconditioners
--------------------------------------------
- Added support for parallel ILU preconditioning via hypre's Euclid solver.
New and updated examples and miniapps
-------------------------------------
- Added a new meshing miniapp, Toroid, which can produce a variety of torus
shaped meshes by twisting a stack of wedges or hexahedra.
- Added a new meshing miniapp, Extruder, that demonstrates the capability to
produce 3D meshes by extruding 2D meshes.
- Added a new example, Example 20/20p, that solves a system of 1D ODEs derived
from a Hamiltonian. The example demonstrates the use of the variable order,
symplectic integration algorithm implemented in class SIAVSolver.
- Added a new example, Example 22/22p, that illustrates the use of AMR to solve
a linear elasticity problem. This is an extension of Example 2/2p.
Miscellaneous
-------------
- Added unit tests based on the Catch++ library.
- Altered the way FGMRES counts its iterations so that it matches GMRES.
- Various other simplifications, extensions, and bugfixes in the code.
API changes
-----------
- In multiple places, use Geometry::Type instead of int, where appropriate.
- In multiple places, use Element::Type instead of int, where appropriate.
- The Mesh methods GetElementBaseGeometry and GetBdrElementBaseGeometry no
longer have a default value for their parameter, they only work with an
explicitly given index.
- In class Mesh, added methods useful for queries regarding the types of
elements present in the mesh: HasGeometry, GetNumGeometries, GetGeometries,
and class Mesh::GeometryList.
- The struct CoarseFineTransformations (returned by the Mesh method
GetRefinementTransforms) now stores the embedding matrices separately for each
Geometry::Type.
- In class ParMesh, replaced the method GroupNFaces with two new methods:
GroupNTriangles and GroupNQuadrilaterals. Also, replaced GroupFace with two
methods: GroupTriangle and GroupQuadrilateral.
- In class ParMesh, made the two RefineGroups methods protected.
- Removed the virtual method Element::GetRefinementFlag, it is only used by the
derived class Tetrahedron.
- Added new methods: Array::CopyTo, Tetrahedron::Init.
Version 3.4, released on May 29, 2018
+13 -4
View File
@@ -312,9 +312,6 @@ message(STATUS "MFEM build type: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
message(STATUS "MFEM version: v${MFEM_VERSION_STRING}")
message(STATUS "MFEM git string: ${MFEM_GIT_STRING}")
# Windows specific
set(_USE_MATH_DEFINES ${WIN32})
#-------------------------------------------------------------------------------
# Define and configure the MFEM library
#-------------------------------------------------------------------------------
@@ -388,6 +385,9 @@ endif()
# Enable testing if required
if (MFEM_ENABLE_TESTING)
enable_testing()
set(MFEM_ALL_TESTS_TARGET_NAME tests)
add_mfem_target(${MFEM_ALL_TESTS_TARGET_NAME} OFF)
add_subdirectory(tests EXCLUDE_FROM_ALL)
endif()
# Define a target that all examples and miniapps will depend on.
@@ -407,7 +407,9 @@ add_subdirectory(miniapps EXCLUDE_FROM_ALL)
# Target to build all executables, i.e. everything.
add_custom_target(exec)
add_dependencies(exec
${MFEM_ALL_EXAMPLES_TARGET_NAME} ${MFEM_ALL_MINIAPPS_TARGET_NAME})
${MFEM_ALL_EXAMPLES_TARGET_NAME}
${MFEM_ALL_MINIAPPS_TARGET_NAME}
${MFEM_ALL_TESTS_TARGET_NAME})
# Here, we want to "add_dependencies(test exec)". However, dependencies for
# 'test' (and other built-in targets) can not be added with add_dependencies():
# - https://gitlab.kitware.com/cmake/cmake/issues/8438
@@ -543,3 +545,10 @@ install(FILES
# Install the export set for use with the install-tree
install(EXPORT ${PROJECT_NAME_UC}Targets
DESTINATION ${INSTALL_CMAKE_DIR})
#-------------------------------------------------------------------------------
# Create 'config.mk' from 'config.mk.in' for the build and install locations and
# define install rules for 'config.mk' and 'test.mk'
#-------------------------------------------------------------------------------
mfem_export_mk_files()
+18 -11
View File
@@ -90,13 +90,18 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
├── general
├── linalg
├── mesh
── miniapps
├── common
├── electromagnetics
├── meshing
├── nurbs
├── performance
└── tools
── miniapps
├── common
├── electromagnetics
├── meshing
├── nurbs
├── performance
└── tools
└── tests
├── unit
│ ├── ...
└── ...
```
- The main directories are `fem/`, `mesh/` and `linalg/` containing the C++
@@ -151,6 +156,9 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
in the simple example codes and more fully-featured mini applications in the
`examples/` and `miniapps/` directories.
- The `tests/` directory contains a unit test suite and will later contain more
tests that run example codes.
- See also the [code overview](http://mfem.org/code-overview/) section on the
MFEM website.
@@ -316,9 +324,9 @@ Before a PR can be merged, it should satisfy the following:
- [ ] Is this a new feature users need to be aware of? New or updated example or miniapp?
- [ ] Does it make sense to create a new section in the `CHANGELOG` to group with other related features?
- [ ] Update `INSTALL`:
- [ ] Has a new optional library been added? (*Make sure the external library is licensed under LGPL, not GPL!*)
- [ ] Had a new optional library been added? (*Make sure the external library is licensed under LGPL, not GPL!*)
- [ ] Does `make` or `cmake` have a new target?
- [ ] Did the requirements or the installation process change? *(rare)*.
- [ ] Did the requirements or the installation process change? *(rare)*
- [ ] Update `.gitignore`:
- [ ] Check if `make distclean; git status` shows any files that are generated from the source but we don't want to track in the repository.
- [ ] Add new patterns (just for the new files above) and re-run the above test.
@@ -358,10 +366,10 @@ Before a PR can be merged, it should satisfy the following:
- [ ] If this is a major new feature, consider mentioning in the short summary inside `README` *(rare)*.
- [ ] List major new classes in `doc/CodeDocumentation.dox` *(rare)*.
- [ ] Update this checklist, if the new pull request affects it.
- [ ] Run the unit tests and make sure they all pass `make unittest`.
- [ ] (LLNL only) Clone the `tests` repository and run the following tests, see `mfem/tests/README.md`:
- [ ] `compilers`
- [ ] `memcheck`
- [ ] `unit-test`
- [ ] `documentation`
- [ ] (LLNL only) After merging:
- [ ] Regenerate `README.html` files from companion documentation pull requests.
@@ -472,7 +480,6 @@ MFEM uses a `master`/`next`-branch workflow as described below:
- `mfem:gh-next` -- Bleeding-edge development version, may be broken, use at
your own risk.
## Automated Testing
MFEM has several levels of automated testing running on GitHub, as well as on
+11 -11
View File
@@ -1,5 +1,5 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
@@ -10,7 +10,7 @@
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -112,7 +112,7 @@ modification follow. Pay close attention to the difference between a
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
@@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
@@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -455,7 +455,7 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
@@ -485,7 +485,8 @@ convey the exclusion of warranty; and each file should have at least the
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
@@ -494,11 +495,10 @@ school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
+72
View File
@@ -180,3 +180,75 @@ IF (USE_XSDK_DEFAULTS)
ENDIF()
ENDIF()
IF (DEFINED TPL_ENABLE_MPI)
SET(MFEM_USE_MPI ${TPL_ENABLE_MPI} CACHE BOOL "Enable MPI parallel build" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_METIS)
SET(MFEM_USE_METIS ${TPL_ENABLE_METIS} CACHE BOOL "Enable METIS usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_GZSTREAM)
SET(MFEM_USE_GZSTREAM ${TPL_ENABLE_GZSTREAM} CACHE BOOL "Enable gzstream for compressed data streams." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_LIBUNWIND)
SET(MFEM_USE_LIBUNWIND ${TPL_ENABLE_LIBUNWIND} CACHE BOOL "Enable backtrace for errors." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_LAPACK)
SET(MFEM_USE_LAPACK ${TPL_ENABLE_LAPACK} CACHE BOOL "Enable LAPACK usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SUNDIALS)
SET(MFEM_USE_SUNDIALS ${TPL_ENABLE_SUNDIALS} CACHE BOOL "Enable SUNDIALS usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_MESQUITE)
SET(MFEM_USE_MESQUITE ${TPL_ENABLE_MESQUITE} CACHE BOOL "Enable MESQUITE usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SUITESPARSE)
SET(MFEM_USE_SUITESPARSE ${TPL_ENABLE_SUITESPARSE} CACHE BOOL "Enable SuiteSparse usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SUPERLU)
SET(MFEM_USE_SUPERLU ${TPL_ENABLE_SUPERLU} CACHE BOOL "Enable SuperLU_DIST usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_STRUMPACK)
SET(MFEM_USE_STRUMPACK ${TPL_ENABLE_STRUMPACK} CACHE BOOL "Enable STRUMPACK usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_GECKO)
SET(MFEM_USE_GECKO ${TPL_ENABLE_GECKO} CACHE BOOL "Enable GECKO usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_GNUTLS)
SET(MFEM_USE_GNUTLS ${TPL_ENABLE_GNUTLS} CACHE BOOL "Enable GNUTLS usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_NETCDF)
SET(MFEM_USE_NETCDF ${TPL_ENABLE_NETCDF} CACHE BOOL "Enable NETCDF usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_PETSC)
SET(MFEM_USE_PETSC ${TPL_ENABLE_PETSC} CACHE BOOL "Enable PETSc support." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_MPFR)
SET(MFEM_USE_MPFR ${TPL_ENABLE_MPFR} CACHE BOOL "Enable MPFR usage." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SIDRE)
SET(MFEM_USE_SIDRE ${TPL_ENABLE_SIDRE} CACHE BOOL "Enable Axom/Sidre usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_CONDUIT)
SET(MFEM_USE_CONDUIT ${TPL_ENABLE_CONDUIT} CACHE BOOL "Enable Conduit usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_PUMI)
SET(MFEM_USE_PUMI ${TPL_ENABLE_PUMI} CACHE BOOL "Enable PUMI" FORCE)
ENDIF()
-4
View File
@@ -109,10 +109,6 @@
// Enable MFEM functionality based on the SUNDIALS libraries.
#cmakedefine MFEM_USE_SUNDIALS
// Windows specific options
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
#cmakedefine _USE_MATH_DEFINES
// Version of HYPRE used for building MFEM.
#cmakedefine MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
@@ -229,6 +229,15 @@ endfunction(mfem_find_component)
function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
Lib IncDoc LibDoc)
# If we have the TPL_ versions of _INCLUDE_DIRS and _LIBRARIES then set the
# standard ${Prefix} versions
if (TPL_${Prefix}_INCLUDE_DIRS)
set(${Prefix}_INCLUDE_DIRS ${TPL_${Prefix}_INCLUDE_DIRS} CACHE STRING "TPL_${Prefix}_INCLUDE_DIRS was found." FORCE)
endif()
if (TPL_${Prefix}_LIBRARIES)
set(${Prefix}_LIBRARIES ${TPL_${Prefix}_LIBRARIES} CACHE STRING "TPL_${Prefix}_LIBRARIES was found." FORCE)
endif()
# Quick return
if (${Prefix}_FOUND)
return()
@@ -685,3 +694,162 @@ function(mfem_find_library Name Prefix Lib LibDoc CheckVar CheckSrc)
endif()
endfunction(mfem_find_library)
#
# Function that creates 'config.mk' from 'config.mk.in' for the both the
# build- and the install-locations and define install rules for 'config.mk'
# and 'test.mk'.
#
function(mfem_export_mk_files)
# Define a few auxiliary variables (not written to 'config.mk')
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
# CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG -> '-Wl,-rpath,'
set(shared_link_flag ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
if (NOT shared_link_flag)
set(shared_link_flag "-Wl,-rpath,")
endif()
# Convert Boolean vars to YES/NO without writting 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_GZSTREAM MFEM_USE_LIBUNWIND
MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_OPENMP MFEM_USE_MEMALLOC
MFEM_USE_SUNDIALS MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE MFEM_USE_SUPERLU
MFEM_USE_STRUMPACK MFEM_USE_GECKO MFEM_USE_GNUTLS MFEM_USE_NETCDF
MFEM_USE_PETSC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_CONDUIT
MFEM_USE_PUMI)
foreach(var ${CONFIG_MK_BOOL_VARS})
if (${var})
set(${var} YES)
else()
set(${var} NO)
endif()
endforeach()
set(MFEM_CXX ${CMAKE_CXX_COMPILER})
set(MFEM_CPPFLAGS "")
string(STRIP "${CMAKE_CXX_FLAGS_${BUILD_TYPE}} ${CMAKE_CXX_FLAGS}"
MFEM_CXXFLAGS)
set(MFEM_TPLFLAGS "")
foreach(dir ${MFEM_TPL_INCLUDE_DIRS})
set(MFEM_TPLFLAGS "${MFEM_TPLFLAGS} -I${dir}")
endforeach()
# TODO: MFEM_TPLFLAGS: add other TPL flags, in addition to the -I flags.
set(MFEM_INCFLAGS "-I\$(MFEM_INC_DIR) \$(MFEM_TPLFLAGS)")
set(MFEM_PICFLAG "")
if (BUILD_SHARED_LIBS)
set(MFEM_PICFLAG "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}")
endif()
set(MFEM_FLAGS "\$(MFEM_CPPFLAGS) \$(MFEM_CXXFLAGS) \$(MFEM_INCFLAGS)")
# TPL link flags: set below
set(MFEM_EXT_LIBS "")
if (BUILD_SHARED_LIBS)
set(MFEM_LIBS "${shared_link_flag}\$(MFEM_LIB_DIR) -L\$(MFEM_LIB_DIR)")
set(MFEM_LIBS "${MFEM_LIBS} -lmfem \$(MFEM_EXT_LIBS)")
if (APPLE)
set(SO_VER ".${mfem_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}")
else()
set(SO_VER "${CMAKE_SHARED_LIBRARY_SUFFIX}.${mfem_VERSION}")
endif()
set(MFEM_LIB_FILE "\$(MFEM_LIB_DIR)/libmfem${SO_VER}")
set(MFEM_SHARED YES)
set(MFEM_STATIC NO)
else()
set(MFEM_LIBS "-L\$(MFEM_LIB_DIR) -lmfem \$(MFEM_EXT_LIBS)")
set(MFEM_LIB_FILE "\$(MFEM_LIB_DIR)/libmfem.a")
set(MFEM_SHARED NO)
set(MFEM_STATIC YES)
endif()
set(MFEM_BUILD_TAG "${CMAKE_SYSTEM}")
set(MFEM_PREFIX "${CMAKE_INSTALL_PREFIX}")
# For the next 4 variable, these are the values for the build-tree version of
# 'config.mk'
set(MFEM_INC_DIR "${PROJECT_BINARY_DIR}")
set(MFEM_LIB_DIR "${PROJECT_BINARY_DIR}")
set(MFEM_TEST_MK "${PROJECT_SOURCE_DIR}/config/test.mk")
set(MFEM_CONFIG_EXTRA "MFEM_BUILD_DIR ?= ${PROJECT_BINARY_DIR}")
set(MFEM_MPIEXEC ${MPIEXEC})
if (NOT MFEM_MPIEXEC)
set(MFEM_MPIEXEC "mpirun")
endif()
set(MFEM_MPIEXEC_NP ${MPIEXEC_NUMPROC_FLAG})
if (NOT MFEM_MPIEXEC_NP)
set(MFEM_MPIEXEC_NP "-np")
endif()
# MFEM_MPI_NP is already set
# Define the variable 'MFEM_EXT_LIBS': handle PUMI libs
if ("${MFEM_USE_PUMI}" STREQUAL "YES")
message(STATUS "simmodsuite_dir = '${SIMMODSUITE_DIR}'")
get_target_property(liblist ${PUMI_LIBRARIES} INTERFACE_LINK_LIBRARIES)
set(pumi_dep_libs "${liblist}")
foreach(pumilib ${liblist})
get_target_property(libdeps ${pumilib} INTERFACE_LINK_LIBRARIES)
if (NOT "${libdeps}" MATCHES "libdeps-NOTFOUND")
list(APPEND pumi_dep_libs ${libdeps})
endif()
endforeach()
list(REMOVE_DUPLICATES pumi_dep_libs)
foreach(pumilib ${pumi_dep_libs})
unset(lib CACHE)
string(REGEX REPLACE "^SCOREC::" "" libname ${pumilib})
string(FIND "${pumilib}" ".a" staticlib)
string(FIND "${pumilib}" ".so" sharedlib)
find_library(lib ${libname} PATHS ${PUMI_DIR}/lib NO_DEFUALT_PATH)
if (NOT "${sharedlib}" MATCHES "-1" OR
NOT "${staticlib}" MATCHES "-1" )
set(MFEM_EXT_LIBS "${pumilib} ${MFEM_EXT_LIBS}")
elseif (NOT "${lib}" MATCHES "lib-NOTFOUND")
set(MFEM_EXT_LIBS "${lib} ${MFEM_EXT_LIBS}")
elseif ("${lib}" MATCHES "lib-NOTFOUND" AND
NOT "${libname}" MATCHES "can" AND
NOT "${libname}" MATCHES "pthread")
message(FATAL_ERROR "SCOREC lib ${libname} not found")
endif()
endforeach()
endif()
# Define the variable 'MFEM_EXT_LIBS': handle other (not PUMI) libs
foreach(lib ${TPL_LIBRARIES})
get_filename_component(suffix ${lib} EXT)
# handle interfaces (e.g., SCOREC::apf)
if ("${lib}" MATCHES "SCOREC::.*")
elseif (NOT "${lib}" MATCHES "SCOREC::.*" AND "${lib}" MATCHES ".*::.*")
message(FATAL_ERROR "***** interface lib found ... exiting *****")
# handle static and shared libs
elseif ("${suffix}" STREQUAL "${CMAKE_SHARED_LIBRARY_SUFFIX}")
get_filename_component(dir ${lib} DIRECTORY)
get_filename_component(fullLibName ${lib} NAME_WE)
string(REGEX REPLACE "^lib" "" libname ${fullLibName})
set(MFEM_EXT_LIBS
"${MFEM_EXT_LIBS} ${shared_link_flag}${dir} -L${dir} -l${libname}")
else()
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} ${lib}")
endif()
endforeach()
# Create the build-tree version of 'config.mk'
configure_file(
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
"${PROJECT_BINARY_DIR}/config/config.mk")
# Copy 'test.mk' from the source-tree to the build-tree
configure_file(
"${PROJECT_SOURCE_DIR}/config/test.mk"
"${PROJECT_BINARY_DIR}/config/test.mk" COPYONLY)
# Update variables for the install-tree version of 'config.mk'
set(MFEM_INC_DIR "${CMAKE_INSTALL_PREFIX}/include")
set(MFEM_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
set(MFEM_TEST_MK "${CMAKE_INSTALL_PREFIX}/share/mfem/test.mk")
set(MFEM_CONFIG_EXTRA "")
# Create the install-tree version of 'config.mk'
configure_file(
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
"${PROJECT_BINARY_DIR}/config/config-install.mk")
# Install rules for 'config.mk' and 'test.mk'
install(FILES ${PROJECT_SOURCE_DIR}/config/test.mk
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/)
install(FILES ${PROJECT_BINARY_DIR}/config/config-install.mk
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/ RENAME config.mk)
endfunction()
+12
View File
@@ -23,6 +23,18 @@
#include "_config.hpp"
#endif
// Common configuration macros
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)
#define MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
#endif
// Windows specific options
#ifdef _WIN32
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
#define _USE_MATH_DEFINES
#endif
// Check dependencies:
// Options that require MPI
-6
View File
@@ -112,12 +112,6 @@
// Enable MFEM functionality based on the PUMI library
// #define MFEM_USE_PUMI
// Windows specific options
#ifdef _WIN32
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
#define _USE_MATH_DEFINES
#endif
// Version of HYPRE used for building MFEM.
// #define MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
+2
View File
@@ -42,6 +42,8 @@ option(MFEM_USE_SIDRE "Enable Axom/Sidre usage" OFF)
option(MFEM_USE_CONDUIT "Enable Conduit usage" OFF)
option(MFEM_USE_PUMI "Enable PUMI" OFF)
set(MFEM_MPI_NP 4 CACHE STRING "Number of processes used for MPI tests")
# Allow a user to disable testing, examples, and/or miniapps at CONFIGURE TIME
# if they don't want/need them (e.g. if MFEM is "just a dependency" and all they
# need is the library, building all that stuff adds unnecessary overhead). Note
+16 -7
View File
@@ -30,7 +30,7 @@ groups_serial=(
'"examples"
"Examples:"
"examples"
"ex{,1}[0-9].cpp"'
"ex{,1,2}[0-9].cpp"'
# "ex1.cpp"'
'"sundials"
"SUNDIALS examples:"
@@ -44,14 +44,15 @@ groups_serial=(
'"meshing"
"Meshing miniapps:"
"miniapps/meshing"
"mobius-strip.cpp klein-bottle.cpp mesh-optimizer.cpp"'
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
mesh-optimizer.cpp"'
)
# Parallel groups
groups_parallel=(
'"examples"
"Examples:"
"examples"
"ex{,1}[0-9]p.cpp"'
"ex{,1,2}[0-9]p.cpp"'
# "ex1p.cpp"'
'"sundials"
"SUNDIALS examples:"
@@ -81,7 +82,7 @@ groups_all=(
'"examples"
"Examples:"
"examples"
"ex\"{,1}[0-9]\"{,p}.cpp"'
"ex\"{,1,2}[0-9]\"{,p}.cpp"'
'"sundials"
"SUNDIALS examples:"
"examples/sundials"
@@ -97,7 +98,8 @@ groups_all=(
'"meshing"
"Meshing miniapps:"
"miniapps/meshing"
"mobius-strip.cpp klein-bottle.cpp {,p}mesh-optimizer.cpp"'
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
{,p}mesh-optimizer.cpp"'
'"electromagnetics"
"Electromagnetics miniapps:"
"miniapps/electromagnetics"
@@ -170,6 +172,9 @@ function help_message()
-v Enable valgrind
-o <dir> [${output_dir:-"<empty>: output goes to stdout"}]
If not empty, save output to files inside <dir>
-d <dir> [${mfem_build_dir}]
If <dir> is different from <mfem_dir> then use an
out-of-source build in <dir>
-j <np> [${make_j}] Specify the number of jobs to use for building
-c|-color Always use colors for the status messages: OK, FAILED, etc
-b|-built Do NOT rebuild the library and the executables
@@ -196,8 +201,8 @@ function help_message()
Their values can also set using the respective uppercase environment
variable
mfem_build_dir [${mfem_build_dir}]
Set this variable to something different from <mfem_dir> to use an
out-of-source build
Same as '-d': set this variable to something different from <mfem_dir>
to use an out-of-source build
For other valid variables, see the script source.
@@ -266,6 +271,10 @@ case "$1" in
shift
output_dir="$1"
;;
-d)
shift
mfem_build_dir="$1"
;;
-j)
shift
make_j="-j $1"
+3 -2
View File
@@ -38,7 +38,7 @@ export TIME='%es %MkB %x'; \
set -- $$($(1) $(SHELL) -c "$(2)" 2>&1); while [ "$$#" -gt 3 ]; do shift; done
endef
define TIMECMD.NOTGNU
set -- $$($(1) -l $(SHELL) -c "$(2)" 2>&1; echo $$?); \
set -- $$($(1) -l $(SHELL) -c "{ $(2); } > /dev/null 2>&1" 2>&1; echo $$?); \
set -- "$$1"s "$$(($$7/1024))"kB "$${60}"
endef
define TIMECMD.BASH
@@ -60,7 +60,8 @@ endif
# Test runs of the examples/miniapps with parameters - check exit code
mfem-test = \
printf " $(3) [$(2) $(1) ... ]: "; \
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) -no-vis $(4) > $(1).stderr 2>&1); \
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) $(if $(5),,-no-vis )$(4) \
> $(1).stderr 2>&1); \
if [ "$$3" = 0 ]; \
then $(PRINT_OK); else $(PRINT_FAILED); cat $(1).stderr; fi; \
rm -f $(1).stderr; exit $$3
+87
View File
@@ -0,0 +1,87 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
8
1 6 0 9 18 1 10 19
1 6 1 10 19 2 11 20
1 6 2 11 20 3 12 21
1 6 3 12 21 4 13 22
2 6 4 13 22 5 14 23
2 6 5 14 23 6 15 24
2 6 6 15 24 7 16 25
2 6 7 16 25 8 17 26
boundary
26
1 2 0 18 9
2 2 8 17 26
3 3 0 9 10 1
3 3 1 10 11 2
3 3 2 11 12 3
3 3 3 12 13 4
3 3 4 13 14 5
3 3 5 14 15 6
3 3 6 15 16 7
3 3 7 16 17 8
3 3 18 0 1 19
3 3 19 1 2 20
3 3 20 2 3 21
3 3 21 3 4 22
3 3 22 4 5 23
3 3 23 5 6 24
3 3 24 6 7 25
3 3 25 7 8 26
3 3 9 18 19 10
3 3 10 19 20 11
3 3 11 20 21 12
3 3 12 21 22 13
3 3 13 22 23 14
3 3 14 23 24 15
3 3 15 24 25 16
3 3 16 25 26 17
vertices
27
3
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0
8 0 0
0 1 0
1 1 0
2 1 0
3 1 0
4 1 0
5 1 0
6 1 0
7 1 0
8 1 0
0 0.5 1
1 0.5 1
2 0.5 1
3 0.5 1
4 0.5 1
5 0.5 1
6 0.5 1
7 0.5 1
8 0.5 1
+61
View File
@@ -0,0 +1,61 @@
# vtk DataFile Version 3.0
Generated by MFEM
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 27 double
0 0 0
1 0 0
2 0 0
3 0 0
4 0 0
5 0 0
6 0 0
7 0 0
8 0 0
0 1 0
1 1 0
2 1 0
3 1 0
4 1 0
5 1 0
6 1 0
7 1 0
8 1 0
0 0.5 1
1 0.5 1
2 0.5 1
3 0.5 1
4 0.5 1
5 0.5 1
6 0.5 1
7 0.5 1
8 0.5 1
CELLS 8 56
6 0 9 18 1 10 19
6 1 10 19 2 11 20
6 2 11 20 3 12 21
6 3 12 21 4 13 22
6 4 13 22 5 14 23
6 5 14 23 6 15 24
6 6 15 24 7 16 25
6 7 16 25 8 17 26
CELL_TYPES 8
13
13
13
13
13
13
13
13
CELL_DATA 8
SCALARS material int
LOOKUP_TABLE default
1
1
1
1
2
2
2
2
+192
View File
@@ -0,0 +1,192 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
14
1 4 13 15 21 25
1 4 15 13 21 12
1 4 21 13 25 22
1 4 15 21 25 24
1 4 13 15 25 16
1 5 0 1 4 3 9 10 13 12
1 5 8 9 12 11 17 18 21 20
1 5 2 3 6 5 11 12 15 14
1 6 3 4 6 12 13 15
1 6 4 7 6 13 16 15
1 6 12 13 21 9 10 18
1 6 13 22 21 10 19 18
1 6 11 14 20 12 15 21
1 6 15 21 24 14 20 23
boundary
30
1 3 5 6 3 2
2 2 6 4 3
2 2 4 6 7
3 3 3 4 1 0
4 3 11 12 9 8
5 3 2 3 12 11
6 3 0 1 10 9
7 2 10 18 9
7 2 18 10 19
8 3 8 9 18 17
9 3 1 4 13 10
10 3 4 7 16 13
11 2 25 13 16
11 2 13 25 22
12 3 10 13 22 19
13 3 7 6 15 16
14 3 6 5 14 15
15 3 15 14 23 24
16 2 15 25 16
16 2 25 15 24
17 3 5 2 11 14
18 3 3 0 9 12
19 3 11 8 17 20
20 2 20 14 11
20 2 14 20 23
21 3 17 18 21 20
22 3 18 19 22 21
23 2 25 21 22
23 2 21 25 24
24 3 20 21 24 23
vertices
26
nodes
FiniteElementSpace
FiniteElementCollection: H1_3D_P2
VDim: 3
Ordering: 1
0.028213666146621 -1.0129124616273 -1.0197422793601
0.99151103207842 -0.97408353323117 -1.0219424221199
-0.98628834960982 -0.048291393648833 -1.0334530425724
-0.045286384224892 -0.028259630873799 -0.95961592583917
1.0351351283956 0.016103611653671 -1.0465984194074
-0.97963495329022 0.975340601895 -0.95050375238061
-0.016565482225269 0.98394050155766 -1.0119900547434
0.98232264800655 1.0061312792241 -0.97468885016611
-1.0111163694877 -1.0328216757625 -0.033904406474903
-0.031359497737139 -0.95907832225785 -0.02936147605069
1.0216721775476 -0.95571139678359 -0.041445003869012
-0.96617995956913 0.013420177670196 -0.047073400672525
0.03735491973348 0.024136644229293 -0.035419858060777
0.99844568660483 -0.023344853520393 0.043047091318294
-1.0075354852248 0.95110015915707 0.040374961402267
-0.018023004801944 0.98735854397528 0.035048884851858
0.96496833880778 0.98624407089765 0.029059857856424
-0.95618249163963 -0.95913625303656 0.99699592567049
0.010523111699149 -1.0380611987319 1.0054330066312
1.0131589291349 -0.99133288586241 1.0510169859154
-0.9992929702159 -0.016950021823868 1.0209834648762
-0.030905270343646 -0.024878516234457 0.96677784407511
1.0369556044533 0.036727200814101 0.97476146325791
-1.0268666699025 0.99100244478387 0.95557046163574
0.032850918109418 0.9761234538078 0.99340013005027
0.96517252528448 1.018590816239 0.96241486393546
0.52641251369336 0.53453492783232 -0.046831832639522
0.54842095679127 0.012466884090474 0.52264325135947
1.0546647359835 0.51503200008771 0.47661895657821
0.008193729444779 0.46320342579585 0.51330736048101
0.48446121998846 1.0366433051979 0.46910527980021
0.50338134740858 0.53372671722279 1.0016026703109
-0.0026805294677615 0.54834160562605 -0.022633473388851
0.4992129677441 -0.027650739811361 -0.025983834639192
-0.010308592952788 0.043478553090245 0.54404251929373
0.52373361142037 0.017260625417003 1.0190168930687
0.95156254112601 0.024917951411289 0.48927665714905
1.0114961385777 0.53988309084877 0.98077339629239
0.01429600397056 1.0255897320394 0.44945099394948
-0.0037663174125072 0.46114195337251 0.98693741812483
0.53955416269275 0.95254191223583 0.99345054396648
1.0344137934711 0.51549308419917 0.0019079259000746
0.4635900873147 1.0074141174823 -0.025796540646941
1.0393698821347 0.99823230649269 0.53561992818844
0.54910938213579 -1.0186136680655 -1.0399189315271
0.98251790353097 -0.52159510049969 -1.0488538759761
0.51290647936985 0.019199261348695 -1.0180139709264
0.039190890220925 -0.51870735888369 -1.0145805133507
0.54531239252537 -1.0346180800814 -0.026071808021516
1.0111227696296 -0.45961035727523 0.028725982550532
-0.0024106570985168 -0.51591348233633 0.042102640075609
0.019072471559048 -1.0489699664991 -0.53822694290429
1.0197706996463 -1.0138504981995 -0.48532295548357
0.97708769380115 0.012869927892461 -0.49512141938321
-0.0056951441802084 -0.018287890031934 -0.46456751856022
-0.48628377295099 -0.97137148869224 -0.040609835088253
-0.52949825478718 0.022831952339038 0.036623532185331
-0.9682938832324 -0.51529484749772 0.039498377451673
-0.45076946932822 -0.98247022288851 1.0229644412175
-0.036635886738077 -0.53934830226935 0.97308384231292
-0.47986206617206 -0.041745604947209 0.98161771683954
-0.95103283049539 -0.5087813614402 1.0116585971788
-0.95395673410967 -0.95082942959853 0.50977751370519
0.030673310998827 -0.97366141136736 0.47265974627808
-1.0076441270299 0.025157339498401 0.51940553779714
-0.45112570035271 0.030354945734143 -1.0244264173787
-0.034796683816239 0.47213521944359 -1.0233666383661
-0.52309081116691 1.0127369282767 -1.030445962213
-1.0052867605351 0.54541603662074 -0.99267176855355
-0.53441363093443 1.0101050069556 0.034852372528985
-1.0361742412671 0.51952713127248 -0.0075041593052447
-1.0224051106721 0.037305149668828 -0.51234883274883
-0.0468317149207 0.99936735257506 -0.53290488454513
-1.0323944162577 1.0470460939221 -0.49629869163036
0.50827771586097 0.51091354087276 -0.96143114171132
0.97860428203942 0.53881222049291 -1.0227558970328
0.54899092558423 1.0449853148062 -1.0290394971016
0.98149990118493 1.0265442789565 -0.45402792714566
0.47938502309767 -0.95321110021154 0.46438798044786
0.98893120098231 -1.0252040218394 0.52866776747387
0.46061993861414 -0.973998097143 0.95264651015888
0.98858339184873 -0.49578777734639 0.97955980177082
-0.95322811676761 0.49312524158842 0.46350421594559
-0.9670648949319 0.52720408663568 1.0147400701319
-0.95970724064157 0.9966338243727 0.47198853459547
-0.55076990539437 0.95548113087191 1.0002298586837
0.48237521727569 -0.51972299404442 -0.98436066769063
0.45025863721967 -1.0030842470471 -0.53693975312635
0.95356930759735 -0.4606471833773 -0.49721032292582
0.48610299886204 0.033102156873792 -0.45204877182841
0.016292646434158 -0.4694908623118 -0.53292224425822
0.47584088565782 -0.54223454683088 -0.036028525792062
-0.53143287785351 -0.4923779387027 0.0039846746250987
-0.52957315347157 -1.0359902368858 0.51208876920864
-0.024055424472317 -0.49951890320517 0.48579422575422
-0.45644746879116 -0.012607240816578 0.51010388839059
-0.98394734906033 -0.50309513998218 0.47998268660158
-0.53098605261184 -0.48258609846234 0.97544367099181
-0.51822144156322 0.45223189569078 -1.0385291075334
-0.45871022404172 -0.042734754644334 -0.54302125046961
0.041843411838636 0.46222349074669 -0.5097909247037
-0.45607118047774 1.0116704457439 -0.45481789885089
-1.0244252419565 0.4849586374592 -0.50017994958907
-0.52441235366277 0.50157218999229 0.023797604069114
0.46467856940869 0.54693057615002 -0.46251054922067
0.98669286111723 0.51824862516758 -0.45168929326637
0.54790127868275 0.98589193659248 -0.51421705686245
0.54233705943277 -0.4508773840935 0.45025142266283
1.0203662623874 -0.5304726794563 0.52365051237419
0.48446453821555 -0.47976663671026 1.043945324572
-0.48793381256969 0.50247088679532 0.48323828733422
-0.52670996575095 0.50194146344506 1.0026980744777
-0.47523256142428 0.97748358070477 0.48234451559035
0.45616661459208 -0.50770850274712 -0.4568053398747
-0.52734654471278 -0.51337681044824 0.47594708297402
-0.45737625267357 0.47732204026543 -0.54846904515289
+168
View File
@@ -0,0 +1,168 @@
# vtk DataFile Version 3.0
Generated by MFEM
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 116 double
0.028213666146621 -1.0129124616273 -1.0197422793601
0.99151103207842 -0.97408353323117 -1.0219424221199
-0.98628834960982 -0.048291393648833 -1.0334530425724
-0.045286384224892 -0.028259630873799 -0.95961592583917
1.0351351283956 0.016103611653671 -1.0465984194074
-0.97963495329022 0.975340601895 -0.95050375238061
-0.016565482225269 0.98394050155766 -1.0119900547434
0.98232264800655 1.0061312792241 -0.97468885016611
-1.0111163694877 -1.0328216757625 -0.033904406474903
-0.031359497737139 -0.95907832225785 -0.02936147605069
1.0216721775476 -0.95571139678359 -0.041445003869012
-0.96617995956913 0.013420177670196 -0.047073400672525
0.03735491973348 0.024136644229293 -0.035419858060777
0.99844568660483 -0.023344853520393 0.043047091318294
-1.0075354852248 0.95110015915707 0.040374961402267
-0.018023004801944 0.98735854397528 0.035048884851858
0.96496833880778 0.98624407089765 0.029059857856424
-0.95618249163963 -0.95913625303656 0.99699592567049
0.010523111699149 -1.0380611987319 1.0054330066312
1.0131589291349 -0.99133288586241 1.0510169859154
-0.9992929702159 -0.016950021823868 1.0209834648762
-0.030905270343646 -0.024878516234457 0.96677784407511
1.0369556044533 0.036727200814101 0.97476146325791
-1.0268666699025 0.99100244478387 0.95557046163574
0.032850918109418 0.9761234538078 0.99340013005027
0.96517252528448 1.018590816239 0.96241486393546
0.50338134740858 0.53372671722279 1.0016026703109
0.54842095679127 0.012466884090474 0.52264325135947
0.008193729444779 0.46320342579585 0.51330736048101
1.0546647359835 0.51503200008771 0.47661895657821
0.48446121998846 1.0366433051979 0.46910527980021
0.52641251369336 0.53453492783232 -0.046831832639522
-0.0026805294677615 0.54834160562605 -0.022633473388851
0.4992129677441 -0.027650739811361 -0.025983834639192
-0.010308592952788 0.043478553090245 0.54404251929373
1.0114961385777 0.53988309084877 0.98077339629239
0.52373361142037 0.017260625417003 1.0190168930687
0.95156254112601 0.024917951411289 0.48927665714905
-0.0037663174125072 0.46114195337251 0.98693741812483
0.53955416269275 0.95254191223583 0.99345054396648
0.01429600397056 1.0255897320394 0.44945099394948
1.0344137934711 0.51549308419917 0.0019079259000746
0.4635900873147 1.0074141174823 -0.025796540646941
1.0393698821347 0.99823230649269 0.53561992818844
0.54910938213579 -1.0186136680655 -1.0399189315271
0.98251790353097 -0.52159510049969 -1.0488538759761
0.51290647936985 0.019199261348695 -1.0180139709264
0.039190890220925 -0.51870735888369 -1.0145805133507
0.54531239252537 -1.0346180800814 -0.026071808021516
1.0111227696296 -0.45961035727523 0.028725982550532
-0.0024106570985168 -0.51591348233633 0.042102640075609
0.019072471559048 -1.0489699664991 -0.53822694290429
1.0197706996463 -1.0138504981995 -0.48532295548357
0.97708769380115 0.012869927892461 -0.49512141938321
-0.0056951441802084 -0.018287890031934 -0.46456751856022
-0.48628377295099 -0.97137148869224 -0.040609835088253
-0.52949825478718 0.022831952339038 0.036623532185331
-0.9682938832324 -0.51529484749772 0.039498377451673
-0.45076946932822 -0.98247022288851 1.0229644412175
-0.036635886738077 -0.53934830226935 0.97308384231292
-0.47986206617206 -0.041745604947209 0.98161771683954
-0.95103283049539 -0.5087813614402 1.0116585971788
-0.95395673410967 -0.95082942959853 0.50977751370519
0.030673310998827 -0.97366141136736 0.47265974627808
-1.0076441270299 0.025157339498401 0.51940553779714
-0.45112570035271 0.030354945734143 -1.0244264173787
-0.034796683816239 0.47213521944359 -1.0233666383661
-0.52309081116691 1.0127369282767 -1.030445962213
-1.0052867605351 0.54541603662074 -0.99267176855355
-0.53441363093443 1.0101050069556 0.034852372528985
-1.0361742412671 0.51952713127248 -0.0075041593052447
-1.0224051106721 0.037305149668828 -0.51234883274883
-0.0468317149207 0.99936735257506 -0.53290488454513
-1.0323944162577 1.0470460939221 -0.49629869163036
0.50827771586097 0.51091354087276 -0.96143114171132
0.97860428203942 0.53881222049291 -1.0227558970328
0.54899092558423 1.0449853148062 -1.0290394971016
0.98149990118493 1.0265442789565 -0.45402792714566
0.47938502309767 -0.95321110021154 0.46438798044786
0.98893120098231 -1.0252040218394 0.52866776747387
0.46061993861414 -0.973998097143 0.95264651015888
0.98858339184873 -0.49578777734639 0.97955980177082
-0.95322811676761 0.49312524158842 0.46350421594559
-0.9670648949319 0.52720408663568 1.0147400701319
-0.95970724064157 0.9966338243727 0.47198853459547
-0.55076990539437 0.95548113087191 1.0002298586837
0.48237521727569 -0.51972299404442 -0.98436066769063
0.45025863721967 -1.0030842470471 -0.53693975312635
0.95356930759735 -0.4606471833773 -0.49721032292582
0.48610299886204 0.033102156873792 -0.45204877182841
0.016292646434158 -0.4694908623118 -0.53292224425822
0.47584088565782 -0.54223454683088 -0.036028525792062
-0.53143287785351 -0.4923779387027 0.0039846746250987
-0.52957315347157 -1.0359902368858 0.51208876920864
-0.024055424472317 -0.49951890320517 0.48579422575422
-0.45644746879116 -0.012607240816578 0.51010388839059
-0.98394734906033 -0.50309513998218 0.47998268660158
-0.53098605261184 -0.48258609846234 0.97544367099181
-0.51822144156322 0.45223189569078 -1.0385291075334
-0.45871022404172 -0.042734754644334 -0.54302125046961
0.041843411838636 0.46222349074669 -0.5097909247037
-0.45607118047774 1.0116704457439 -0.45481789885089
-1.0244252419565 0.4849586374592 -0.50017994958907
-0.52441235366277 0.50157218999229 0.023797604069114
0.46467856940869 0.54693057615002 -0.46251054922067
0.98669286111723 0.51824862516758 -0.45168929326637
0.54790127868275 0.98589193659248 -0.51421705686245
0.54233705943277 -0.4508773840935 0.45025142266283
1.0203662623874 -0.5304726794563 0.52365051237419
0.48446453821555 -0.47976663671026 1.043945324572
-0.48793381256969 0.50247088679532 0.48323828733422
-0.52670996575095 0.50194146344506 1.0026980744777
-0.47523256142428 0.97748358070477 0.48234451559035
0.45616661459208 -0.50770850274712 -0.4568053398747
-0.52734654471278 -0.51337681044824 0.47594708297402
-0.45737625267357 0.47732204026543 -0.54846904515289
CELLS 14 253
10 21 25 13 15 26 29 27 28 30 31
10 15 13 21 12 31 27 28 32 33 34
10 25 21 13 22 26 27 29 35 36 37
10 21 25 15 24 26 30 28 38 39 40
10 13 15 25 16 31 30 29 41 42 43
27 0 1 4 3 9 10 13 12 44 45 46 47 48 49 33 50 51 52 53 54 90 88 87 89 86 91 113
27 8 9 12 11 17 18 21 20 55 50 56 57 58 59 60 61 62 63 34 64 96 94 93 95 92 97 114
27 2 3 6 5 11 12 15 14 65 66 67 68 56 32 69 70 71 54 72 73 102 100 99 101 98 103 115
18 3 6 4 12 15 13 66 74 46 32 31 33 54 72 53 100 104 89
18 4 6 7 13 15 16 74 76 75 31 42 41 53 72 77 104 106 105
18 12 21 13 9 18 10 34 27 33 63 78 48 50 59 49 94 107 91
18 13 21 22 10 18 19 27 36 37 78 80 79 49 59 81 107 109 108
18 11 20 14 12 21 15 64 82 70 34 28 32 56 60 69 95 110 103
18 15 24 21 14 23 20 40 38 28 84 83 82 69 85 60 112 111 110
CELL_TYPES 14
24
24
24
24
24
29
29
29
32
32
32
32
32
32
CELL_DATA 14
SCALARS material int
LOOKUP_TABLE default
1
1
1
1
1
1
1
1
1
1
1
1
1
1
+96
View File
@@ -0,0 +1,96 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
14
1 4 13 15 21 25
1 4 12 13 15 21
1 4 13 21 22 25
1 4 15 24 21 25
1 4 13 15 25 16
1 5 0 1 4 3 9 10 13 12
1 5 8 9 12 11 17 18 21 20
1 5 2 3 6 5 11 12 15 14
1 6 3 4 6 12 13 15
1 6 4 7 6 13 16 15
1 6 12 13 21 9 10 18
1 6 13 22 21 10 19 18
1 6 11 14 20 12 15 21
1 6 15 21 24 14 20 23
boundary
30
1 3 5 6 3 2
2 2 3 6 4
2 2 4 6 7
3 3 3 4 1 0
4 3 11 12 9 8
5 3 2 3 12 11
6 3 0 1 10 9
7 2 9 10 18
7 2 10 19 18
8 3 8 9 18 17
9 3 1 4 13 10
10 3 4 7 16 13
11 2 13 16 25
11 2 13 25 22
12 3 10 13 22 19
13 3 7 6 15 16
14 3 6 5 14 15
15 3 15 14 23 24
16 2 16 15 25
16 2 15 24 25
17 3 5 2 11 14
18 3 3 0 9 12
19 3 11 8 17 20
20 2 11 20 14
20 2 14 20 23
21 3 17 18 21 20
22 3 18 19 22 21
23 2 21 22 25
23 2 21 25 24
24 3 20 21 24 23
vertices
26
3
0 -1 -1
1 -1 -1
-1 0 -1
0 0 -1
1 0 -1
-1 1 -1
0 1 -1
1 1 -1
-1 -1 0
0 -1 0
1 -1 0
-1 0 0
0 0 0
1 0 0
-1 1 0
0 1 0
1 1 0
-1 -1 1
0 -1 1
1 -1 1
-1 0 1
0 0 1
1 0 1
-1 1 1
0 1 1
1 1 1
+9
View File
@@ -0,0 +1,9 @@
MFEM INLINE mesh v1.0
type = wedge
nx = 4
ny = 4
nz = 4
sx = 1.0
sy = 1.0
sz = 1.0
+182
View File
@@ -0,0 +1,182 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
#
dimension
2
elements
30
1 3 0 11 26 14
1 3 0 14 27 17
1 3 0 17 28 20
1 3 0 20 29 23
1 3 0 23 30 11
1 2 1 26 11
1 2 26 1 12
1 3 26 12 3 13
1 2 2 26 13
1 2 26 2 14
1 2 2 27 14
1 2 27 2 15
1 3 27 15 5 16
1 2 4 27 16
1 2 27 4 17
1 2 4 28 17
1 2 28 4 18
1 3 28 18 7 19
1 2 6 28 19
1 2 28 6 20
1 2 6 29 20
1 2 29 6 21
1 3 29 21 9 22
1 2 8 29 22
1 2 29 8 23
1 2 8 30 23
1 2 30 8 24
1 3 30 24 10 25
1 2 1 30 25
1 2 30 1 11
boundary
20
1 1 13 2
1 1 12 3
1 1 16 4
1 1 15 5
1 1 19 6
1 1 18 7
1 1 22 8
1 1 21 9
1 1 25 1
1 1 24 10
1 1 3 13
1 1 1 12
1 1 5 16
1 1 2 15
1 1 7 19
1 1 4 18
1 1 9 22
1 1 6 21
1 1 10 25
1 1 8 24
vertices
31
nodes
FiniteElementSpace
FiniteElementCollection: H1_2D_P2
VDim: 2
Ordering: 1
0.01350768617383 -0.0075500592639684
1 0
0.309017 0.951057
1.30902 0.951057
-0.809017 0.587785
-0.5 1.53884
-0.809017 -0.587785
-1.61803 0
0.309017 -0.951057
-0.5 -1.53884
1.30902 -0.951057
0.4935497789318 -0.012882964767041
1.15451 0.475529
0.809019 0.951057
0.17136163619581 0.48175756223348
-0.0954915 1.24495
-0.654508 1.06331
-0.41734925397369 0.28726550311701
-1.21352 0.293893
-1.21352 -0.293892
-0.39460365124056 -0.30156877530663
-0.654508 -1.06331
-0.0954915 -1.24495
0.14399901886801 -0.48762042397771
0.809019 -0.951057
1.15451 -0.475529
0.6498356311584 0.48434918539882
-0.24288407581812 0.75594729997554
-0.8152592767797 0.0028387384025541
-0.22754482186326 -0.77540708661379
0.672255499984 -0.48174474211839
0.22829595615988 0.0021164169942289
0.60101450815825 0.21860266792331
0.41883194868682 0.47605389684094
0.07343165966527 0.21396989328966
-0.02571592547416 0.63942139993498
-0.32229829912758 0.53827901417123
-0.17873676879185 0.14412581843398
-0.6182337454462 0.14256917811499
-0.59596471744054 -0.16569961862581
-0.19439899436461 -0.12390276596268
-0.33986575323528 -0.53331120777067
-0.064647379830725 -0.60235938684263
0.091924539036435 -0.25440885597942
0.40469418107844 -0.47549896605132
0.59442400974309 -0.23815570080881
0.83567929699787 0.25605757828544
0.73491944894413 -0.013500778246483
1.077255 0.2377645
0.88696375569985 0.49133008726061
1.231765 0.713293
1.0590195 0.951057
0.72725653289275 0.73104100472096
0.50225974659165 0.6904536152084
0.559018 0.951057
0.23657516510421 0.69857072686934
0.011561493903121 0.87524541641085
0.10676275 1.0980035
-0.17127243181091 0.99863326833074
-0.29774575 1.391895
-0.577254 1.301075
-0.45323351407757 0.93490604288187
-0.55200861955087 0.66792304985565
-0.7317625 0.8255475
-0.58327877079184 0.4240660861124
-0.81465656906104 0.28713104760848
-1.0112685 0.440839
-0.99771272279525 0.1592736885552
-1.415775 0.1469465
-1.415775 -0.146946
-1.0166887889241 -0.16866723370018
-0.80412516287867 -0.29582734656
-1.0112685 -0.4408385
-0.6073309356422 -0.45826153759998
-0.55501395481483 -0.68914767547246
-0.7317625 -0.8255475
-0.45240617124569 -0.93833106759189
-0.577254 -1.301075
-0.29774575 -1.391895
-0.1923419715726 -1.0285844005569
0.031614306262131 -0.83601077226744
0.10676275 -1.0980035
0.22112358843745 -0.69009711121629
0.50046759811715 -0.72837571286759
0.559018 -0.951057
0.71074483315985 -0.70826931724532
1.0590195 -0.951057
1.231765 -0.713293
0.89135027612826 -0.46226040977064
0.84948897506491 -0.23986695857234
1.077255 -0.2377645
0.31586449185434 0.2462788698702
-0.13788918217579 0.40149150514309
-0.40416548945856 0.0027692745957735
-0.14861804521337 -0.3698676302047
0.33007376541085 -0.24598293851351
0.99473757603443 0.69214841080247
-0.38122249894249 1.1629329119286
-1.208195003484 -0.0026998371675556
-0.35890854853443 -1.1361244276705
0.9901912195942 -0.73640851058427
+201
View File
@@ -0,0 +1,201 @@
# vtk DataFile Version 3.0
Generated by MFEM
ASCII
DATASET UNSTRUCTURED_GRID
POINTS 101 double
0.01350768617383 -0.0075500592639684 0
1 0 0
0.309017 0.951057 0
1.30902 0.951057 0
-0.809017 0.587785 0
-0.5 1.53884 0
-0.809017 -0.587785 0
-1.61803 0 0
0.309017 -0.951057 0
-0.5 -1.53884 0
1.30902 -0.951057 0
0.4935497789318 -0.012882964767041 0
1.15451 0.475529 0
0.809019 0.951057 0
0.17136163619581 0.48175756223348 0
-0.0954915 1.24495 0
-0.654508 1.06331 0
-0.41734925397369 0.28726550311701 0
-1.21352 0.293893 0
-1.21352 -0.293892 0
-0.39460365124056 -0.30156877530663 0
-0.654508 -1.06331 0
-0.0954915 -1.24495 0
0.14399901886801 -0.48762042397771 0
0.809019 -0.951057 0
1.15451 -0.475529 0
0.6498356311584 0.48434918539882 0
-0.24288407581812 0.75594729997554 0
-0.8152592767797 0.0028387384025541 0
-0.22754482186326 -0.77540708661379 0
0.672255499984 -0.48174474211839 0
0.22829595615988 0.0021164169942289 0
0.60101450815825 0.21860266792331 0
0.41883194868682 0.47605389684094 0
0.07343165966527 0.21396989328966 0
-0.02571592547416 0.63942139993498 0
-0.32229829912758 0.53827901417123 0
-0.17873676879185 0.14412581843398 0
-0.6182337454462 0.14256917811499 0
-0.59596471744054 -0.16569961862581 0
-0.19439899436461 -0.12390276596268 0
-0.33986575323528 -0.53331120777067 0
-0.064647379830725 -0.60235938684263 0
0.091924539036435 -0.25440885597942 0
0.40469418107844 -0.47549896605132 0
0.59442400974309 -0.23815570080881 0
0.83567929699787 0.25605757828544 0
0.73491944894413 -0.013500778246483 0
1.077255 0.2377645 0
0.88696375569985 0.49133008726061 0
1.231765 0.713293 0
1.0590195 0.951057 0
0.72725653289275 0.73104100472096 0
0.50225974659165 0.6904536152084 0
0.559018 0.951057 0
0.23657516510421 0.69857072686934 0
0.011561493903121 0.87524541641085 0
0.10676275 1.0980035 0
-0.17127243181091 0.99863326833074 0
-0.29774575 1.391895 0
-0.577254 1.301075 0
-0.45323351407757 0.93490604288187 0
-0.55200861955087 0.66792304985565 0
-0.7317625 0.8255475 0
-0.58327877079184 0.4240660861124 0
-0.81465656906104 0.28713104760848 0
-1.0112685 0.440839 0
-0.99771272279525 0.1592736885552 0
-1.415775 0.1469465 0
-1.415775 -0.146946 0
-1.0166887889241 -0.16866723370018 0
-0.80412516287867 -0.29582734656 0
-1.0112685 -0.4408385 0
-0.6073309356422 -0.45826153759998 0
-0.55501395481483 -0.68914767547246 0
-0.7317625 -0.8255475 0
-0.45240617124569 -0.93833106759189 0
-0.577254 -1.301075 0
-0.29774575 -1.391895 0
-0.1923419715726 -1.0285844005569 0
0.031614306262131 -0.83601077226744 0
0.10676275 -1.0980035 0
0.22112358843745 -0.69009711121629 0
0.50046759811715 -0.72837571286759 0
0.559018 -0.951057 0
0.71074483315985 -0.70826931724532 0
1.0590195 -0.951057 0
1.231765 -0.713293 0
0.89135027612826 -0.46226040977064 0
0.84948897506491 -0.23986695857234 0
1.077255 -0.2377645 0
0.31586449185434 0.2462788698702 0
-0.13788918217579 0.40149150514309 0
-0.40416548945856 0.0027692745957735 0
-0.14861804521337 -0.3698676302047 0
0.33007376541085 -0.24598293851351 0
0.99473757603443 0.69214841080247 0
-0.38122249894249 1.1629329119286 0
-1.208195003484 -0.0026998371675556 0
-0.35890854853443 -1.1361244276705 0
0.9901912195942 -0.73640851058427 0
CELLS 30 240
9 0 11 26 14 31 32 33 34 91
9 0 14 27 17 34 35 36 37 92
9 0 17 28 20 37 38 39 40 93
9 0 20 29 23 40 41 42 43 94
9 0 23 30 11 43 44 45 31 95
6 1 26 11 46 32 47
6 26 1 12 46 48 49
9 26 12 3 13 49 50 51 52 96
6 2 26 13 53 52 54
6 26 2 14 53 55 33
6 2 27 14 56 35 55
6 27 2 15 56 57 58
9 27 15 5 16 58 59 60 61 97
6 4 27 16 62 61 63
6 27 4 17 62 64 36
6 4 28 17 65 38 64
6 28 4 18 65 66 67
9 28 18 7 19 67 68 69 70 98
6 6 28 19 71 70 72
6 28 6 20 71 73 39
6 6 29 20 74 41 73
6 29 6 21 74 75 76
9 29 21 9 22 76 77 78 79 99
6 8 29 22 80 79 81
6 29 8 23 80 82 42
6 8 30 23 83 44 82
6 30 8 24 83 84 85
9 30 24 10 25 85 86 87 88 100
6 1 30 25 89 88 90
6 30 1 11 89 47 45
CELL_TYPES 30
28
28
28
28
28
22
22
28
22
22
22
22
28
22
22
22
22
28
22
22
22
22
28
22
22
22
22
28
22
22
CELL_DATA 30
SCALARS material int
LOOKUP_TABLE default
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
+107
View File
@@ -0,0 +1,107 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
2
elements
30
1 3 0 11 26 14
1 3 0 14 27 17
1 3 0 17 28 20
1 3 0 20 29 23
1 3 0 23 30 11
1 2 11 1 26
1 2 1 12 26
1 3 26 12 3 13
1 2 26 13 2
1 2 14 26 2
1 2 14 2 27
1 2 2 15 27
1 3 27 15 5 16
1 2 27 16 4
1 2 17 27 4
1 2 17 4 28
1 2 4 18 28
1 3 28 18 7 19
1 2 28 19 6
1 2 20 28 6
1 2 20 6 29
1 2 6 21 29
1 3 29 21 9 22
1 2 29 22 8
1 2 23 29 8
1 2 23 8 30
1 2 8 24 30
1 3 30 24 10 25
1 2 30 25 1
1 2 11 30 1
boundary
20
1 1 13 2
1 1 12 3
1 1 16 4
1 1 15 5
1 1 19 6
1 1 18 7
1 1 22 8
1 1 21 9
1 1 25 1
1 1 24 10
1 1 3 13
1 1 1 12
1 1 5 16
1 1 2 15
1 1 7 19
1 1 4 18
1 1 9 22
1 1 6 21
1 1 10 25
1 1 8 24
vertices
31
2
0 0
1 0
0.309017 0.951057
1.30902 0.951057
-0.809017 0.587785
-0.5 1.53884
-0.809017 -0.587785
-1.61803 0
0.309017 -0.951057
-0.5 -1.53884
1.30902 -0.951057
0.5 0
1.15451 0.475529
0.809019 0.951057
0.154508 0.475529
-0.0954915 1.24495
-0.654508 1.06331
-0.404508 0.293893
-1.21352 0.293893
-1.21352 -0.293892
-0.404508 -0.293893
-0.654508 -1.06331
-0.0954915 -1.24495
0.154508 -0.475529
0.809019 -0.951057
1.15451 -0.475529
0.654509 0.475529
-0.25 0.769421
-0.809016 0
-0.25 -0.76942
0.654509 -0.475529
+350
View File
@@ -0,0 +1,350 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
6
1 5 0 1 2 3 4 5 6 7
1 5 4 5 6 7 8 9 10 11
1 5 8 9 10 11 12 13 14 15
1 5 12 13 14 15 16 17 18 19
1 5 16 17 18 19 20 21 22 23
1 5 20 21 22 23 3 0 1 2
boundary
24
1 3 0 1 5 4
1 3 1 2 6 5
1 3 2 3 7 6
1 3 3 0 4 7
1 3 4 5 9 8
1 3 5 6 10 9
1 3 6 7 11 10
1 3 7 4 8 11
1 3 8 9 13 12
1 3 9 10 14 13
1 3 10 11 15 14
1 3 11 8 12 15
1 3 12 13 17 16
1 3 13 14 18 17
1 3 14 15 19 18
1 3 15 12 16 19
1 3 16 17 21 20
1 3 17 18 22 21
1 3 18 19 23 22
1 3 19 16 20 23
1 3 20 21 0 3
1 3 21 22 1 0
1 3 22 23 2 1
1 3 23 20 3 2
vertices
24
nodes
FiniteElementSpace
FiniteElementCollection: H1_3D_P3
VDim: 3
Ordering: 1
0.71715729 -1.7565288e-16 -0.28284271
0.71715729 -1.7565288e-16 0.28284271
1.2828427 -3.1420584e-16 0.28284271
1.2828427 -3.1420584e-16 -0.28284271
0.3 0.51961524 -2.7755576e-17
0.5 0.8660254 0.4
0.7 1.2124356 2.7755576e-17
0.5 0.8660254 -0.4
-0.35857864 0.62107643 0.28284271
-0.64142136 1.1109744 0.28284271
-0.64142136 1.1109744 -0.28284271
-0.35857864 0.62107643 -0.28284271
-1 1.2246468e-16 0.4
-1.4 1.7145055e-16 2.7755576e-17
-1 1.2246468e-16 -0.4
-0.6 7.3478808e-17 -2.7755576e-17
-0.64142136 -1.1109744 0.28284271
-0.64142136 -1.1109744 -0.28284271
-0.35857864 -0.62107643 -0.28284271
-0.35857864 -0.62107643 0.28284271
0.7 -1.2124356 8.3266727e-17
0.5 -0.8660254 -0.4
0.3 -0.51961524 -8.3266727e-17
0.5 -0.8660254 0.4
0.71715729 -1.7565288e-16 -0.12649111
0.71715729 -1.7565288e-16 0.12649111
0.87350889 -2.1394797e-16 0.28284271
1.1264911 -2.7591075e-16 0.28284271
1.2828427 -3.1420584e-16 0.12649111
1.2828427 -3.1420584e-16 -0.12649111
0.87350889 -2.1394797e-16 -0.28284271
1.1264911 -2.7591075e-16 -0.28284271
0.35527864 0.61536066 0.11055728
0.44472136 0.77027999 0.28944272
0.55527864 0.96177082 0.28944272
0.64472136 1.1166902 0.11055728
0.64472136 1.1166902 -0.11055728
0.55527864 0.96177082 -0.28944272
0.35527864 0.61536066 -0.11055728
0.44472136 0.77027999 -0.28944272
0.63530452 0.18919442 -0.21528657
0.44264573 0.41882944 -0.086151128
0.75207276 0.22396814 0.33712267
0.66379961 0.62808427 0.39061232
1.2815042 0.38163342 0.21528657
1.01011 0.95576166 0.086151128
1.1647359 0.3468597 -0.33712267
0.78895615 0.74650684 -0.39061232
-0.43675445 0.75648089 0.28284271
-0.56324555 0.97556992 0.28284271
-0.64142136 1.1109744 0.12649111
-0.64142136 1.1109744 -0.12649111
-0.56324555 0.97556992 -0.28284271
-0.43675445 0.75648089 -0.28284271
-0.35857864 0.62107643 0.12649111
-0.35857864 0.62107643 -0.12649111
0.14139407 0.59275717 0.086151128
-0.15380509 0.64478706 0.21528657
0.25201581 1.0565095 0.39061232
-0.28197865 1.1821208 0.33712267
0.32265887 1.3526618 -0.086151128
-0.31024785 1.3006319 -0.21528657
0.21203713 0.88890945 -0.39061232
-0.18207429 0.76329818 -0.33712267
-1.1105573 1.3600404e-16 0.28944272
-1.2894427 1.5791119e-16 0.11055728
-1.2894427 1.5791119e-16 -0.11055728
-1.1105573 1.3600404e-16 -0.28944272
-0.88944272 1.0892532e-16 -0.28944272
-0.71055728 8.701817e-17 -0.11055728
-0.88944272 1.0892532e-16 0.28944272
-0.71055728 8.701817e-17 0.11055728
-0.56999848 0.53933005 0.33712267
-0.87583673 0.26082519 0.39061232
-0.97125633 0.91899846 0.21528657
-1.3327689 0.39690011 0.086151128
-0.88275728 0.83526106 -0.33712267
-1.040972 0.31000265 -0.39061232
-0.48149943 0.45559264 -0.21528657
-0.5840398 0.17392773 -0.086151128
-0.64142136 -1.1109744 0.12649111
-0.64142136 -1.1109744 -0.12649111
-0.56324555 -0.97556992 -0.28284271
-0.43675445 -0.75648089 -0.28284271
-0.35857864 -0.62107643 -0.12649111
-0.35857864 -0.62107643 0.12649111
-0.56324555 -0.97556992 0.28284271
-0.43675445 -0.75648089 0.28284271
-1.040972 -0.31000265 0.39061232
-0.88275728 -0.83526106 0.33712267
-1.3327689 -0.39690011 -0.086151128
-0.97125633 -0.91899846 -0.21528657
-0.87583673 -0.26082519 -0.39061232
-0.56999848 -0.53933005 -0.33712267
-0.5840398 -0.17392773 0.086151128
-0.48149943 -0.45559264 0.21528657
0.64472136 -1.1166902 -0.11055728
0.55527864 -0.96177082 -0.28944272
0.44472136 -0.77027999 -0.28944272
0.35527864 -0.61536066 -0.11055728
0.35527864 -0.61536066 0.11055728
0.44472136 -0.77027999 0.28944272
0.64472136 -1.1166902 0.11055728
0.55527864 -0.96177082 0.28944272
-0.31024785 -1.3006319 0.21528657
0.32265887 -1.3526618 0.086151128
-0.28197865 -1.1821208 -0.33712267
0.25201581 -1.0565095 -0.39061232
-0.15380509 -0.64478706 -0.21528657
0.14139407 -0.59275717 -0.086151128
-0.18207429 -0.76329818 0.33712267
0.21203713 -0.88890945 0.39061232
1.2815042 -0.38163342 -0.21528657
1.01011 -0.95576166 -0.086151128
0.75207276 -0.22396814 -0.33712267
0.66379961 -0.62808427 -0.39061232
0.63530452 -0.18919442 0.21528657
0.44264573 -0.41882944 0.086151128
1.1647359 -0.3468597 0.33712267
0.78895615 -0.74650684 0.39061232
1.1264911 -2.7591075e-16 -0.12649111
1.1264911 -2.7591075e-16 0.12649111
0.87350889 -2.1394797e-16 -0.12649111
0.87350889 -9.8977972e-16 0.12649111
0.66757847 0.19880564 -0.062604414
0.71979881 0.21435692 0.18444051
0.50377116 0.47666605 0.045623048
0.60267418 0.57024766 0.25883814
0.89840401 0.26754575 0.303448
1.1351729 0.33805581 0.24896124
0.75951745 0.71865207 0.30646131
0.91439218 0.86519386 0.17030213
1.2492302 0.3720222 0.062604414
1.1970099 0.35647092 -0.18444051
0.9489846 0.89792505 -0.045623048
0.85008158 0.80434345 -0.25883814
1.0184047 0.30328209 -0.303448
0.78163576 0.23277203 -0.24896124
0.69323831 0.65593903 -0.30646131
0.53836358 0.50939725 -0.17030213
0.41055728 0.71110607 -1.3877788e-17
0.5 0.8660254 0.17888544
0.5 0.8660254 -0.17888544
0.58944272 1.0209447 1.3877788e-17
0.17196917 0.72093516 0.17030213
0.22144071 0.9283315 0.30646131
-0.18923139 0.79330244 0.24896124
-0.24655235 1.0336054 0.303448
0.27154107 1.138364 0.25883814
0.30313361 1.2708073 0.045623048
-0.28979207 1.2148764 0.18444051
-0.30243444 1.2678762 -0.062604414
0.29208377 1.2244838 -0.17030213
0.24261222 1.0170874 -0.30646131
-0.27482155 1.1521165 -0.24896124
-0.21750059 0.91181357 -0.303448
0.19251187 0.80705498 -0.25883814
0.16091933 0.67461165 -0.045623048
-0.17426087 0.73054252 -0.18444051
-0.1616185 0.67754273 0.062604414
-0.43675445 0.75648089 0.12649111
-0.56324555 0.97556992 0.12649111
-0.43675445 0.75648089 -0.12649111
-0.56324555 0.97556992 -0.12649111
-0.68090342 0.64426782 0.303448
-0.86035138 0.81406069 0.24896124
-1.0021297 0.29843537 0.30646131
-1.2064759 0.35928993 0.17030213
-0.94679579 0.89585401 0.062604414
-0.90721782 0.85840551 -0.18444051
-1.2521182 0.37288224 -0.045623048
-1.1216227 0.33402052 -0.25883814
-0.77185234 0.73032329 -0.303448
-0.59240437 0.56053041 -0.24896124
-0.91467902 0.27239247 -0.30646131
-0.71033275 0.21153791 -0.17030213
-0.50595997 0.47873709 -0.062604414
-0.54553794 0.5161856 0.18444051
-0.66469049 0.19794559 0.045623048
-0.79518604 0.23680732 0.25883814
-1 1.2246468e-16 0.17888544
-1.1788854 1.4437183e-16 1.3877788e-17
-0.82111456 1.0055753e-16 -1.3877788e-17
-1 5.6655389e-16 -0.17888544
-1.1216227 -0.33402052 0.25883814
-1.2521182 -0.37288224 0.045623048
-0.90721782 -0.85840551 0.18444051
-0.94679579 -0.89585401 -0.062604414
-1.2064759 -0.35928993 -0.17030213
-1.0021297 -0.29843537 -0.30646131
-0.86035138 -0.81406069 -0.24896124
-0.68090342 -0.64426782 -0.303448
-0.79518604 -0.23680732 -0.25883814
-0.66469049 -0.19794559 -0.045623048
-0.54553794 -0.5161856 -0.18444051
-0.50595997 -0.47873709 0.062604414
-0.71033275 -0.21153791 0.17030213
-0.91467902 -0.27239247 0.30646131
-0.59240437 -0.56053041 0.24896124
-0.77185234 -0.73032329 0.303448
-0.56324555 -0.97556992 0.12649111
-0.56324555 -0.97556992 -0.12649111
-0.43675445 -0.75648089 0.12649111
-0.43675445 -0.75648089 -0.12649111
-0.30243444 -1.2678762 0.062604414
-0.28979207 -1.2148764 -0.18444051
0.30313361 -1.2708073 -0.045623048
0.27154107 -1.138364 -0.25883814
-0.24655235 -1.0336054 -0.303448
-0.18923139 -0.79330244 -0.24896124
0.22144071 -0.9283315 -0.30646131
0.17196917 -0.72093516 -0.17030213
-0.1616185 -0.67754273 -0.062604414
-0.17426087 -0.73054252 0.18444051
0.16091933 -0.67461165 0.045623048
0.19251187 -0.80705498 0.25883814
-0.21750059 -0.91181357 0.303448
-0.27482155 -1.1521165 0.24896124
0.24261222 -1.0170874 0.30646131
0.29208377 -1.2244838 0.17030213
0.58944272 -1.0209447 2.7755576e-17
0.5 -0.8660254 -0.17888544
0.5 -0.8660254 0.17888544
0.41055728 -0.71110607 -2.7755576e-17
0.91439218 -0.86519386 -0.17030213
0.75951745 -0.71865207 -0.30646131
1.1351729 -0.33805581 -0.24896124
0.89840401 -0.26754575 -0.303448
0.60267418 -0.57024766 -0.25883814
0.50377116 -0.47666605 -0.045623048
0.71979881 -0.21435692 -0.18444051
0.66757847 -0.19880564 0.062604414
0.53836358 -0.50939725 0.17030213
0.69323831 -0.65593903 0.30646131
0.78163576 -0.23277203 0.24896124
1.0184047 -0.30328209 0.303448
0.85008158 -0.80434345 0.25883814
0.9489846 -0.89792505 0.045623048
1.1970099 -0.35647092 0.18444051
1.2492302 -0.3720222 -0.062604414
0.81390971 0.24238325 -0.096279082
0.86613006 0.25793453 0.15076584
1.0506786 0.31289331 -0.15076584
1.102899 0.32844459 0.096279082
0.59948901 0.56723386 -0.038527956
0.69839202 0.66081546 0.17468714
0.75436373 0.71377565 -0.17468714
0.85326675 0.80735725 0.038527956
0.19149443 0.80278964 0.038527956
0.24096597 1.010186 0.17468714
0.22308696 0.93523296 -0.17468714
0.27255851 1.1426293 -0.038527956
-0.1970448 0.82605811 0.096279082
-0.25436576 1.066361 0.15076584
-0.20968717 0.8790579 -0.15076584
-0.26700813 1.1193608 -0.096279082
-0.65644288 0.62112337 0.15076584
-0.83589085 0.79091624 0.096279082
-0.61686491 0.58367486 -0.096279082
-0.79631287 0.75346774 -0.15076584
-0.92147899 0.2744175 0.17468714
-1.1258253 0.33527206 0.038527956
-0.79098343 0.23555578 -0.038527956
-0.99532971 0.29641033 -0.17468714
-0.99532971 -0.29641033 0.17468714
-1.1258253 -0.33527206 -0.038527956
-0.79098343 -0.23555578 0.038527956
-0.92147899 -0.2744175 -0.17468714
-0.79631287 -0.75346774 0.15076584
-0.83589085 -0.79091624 -0.096279082
-0.61686491 -0.58367486 0.096279082
-0.65644288 -0.62112337 -0.15076584
-0.26700813 -1.1193608 0.096279082
-0.25436576 -1.066361 -0.15076584
-0.20968717 -0.8790579 0.15076584
-0.1970448 -0.82605811 -0.096279082
0.27255851 -1.1426293 0.038527956
0.24096597 -1.010186 -0.17468714
0.22308696 -0.93523296 0.17468714
0.19149443 -0.80278964 -0.038527956
0.85326675 -0.80735725 -0.038527956
0.69839202 -0.66081546 -0.17468714
0.75436373 -0.71377565 0.17468714
0.59948901 -0.56723386 0.038527956
1.102899 -0.32844459 -0.096279082
0.86613006 -0.25793453 -0.15076584
1.0506786 -0.31289331 0.15076584
0.81390971 -0.24238325 0.096279082
+236
View File
@@ -0,0 +1,236 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
6
1 6 0 1 2 3 4 5
1 6 3 4 5 6 7 8
1 6 6 7 8 9 10 11
1 6 9 10 11 12 13 14
1 6 12 13 14 15 16 17
1 6 15 16 17 0 1 2
boundary
18
1 3 0 1 4 3
1 3 1 2 5 4
1 3 2 0 3 5
1 3 3 4 7 6
1 3 4 5 8 7
1 3 5 3 6 8
1 3 6 7 10 9
1 3 7 8 11 10
1 3 8 6 9 11
1 3 9 10 13 12
1 3 10 11 14 13
1 3 11 9 12 14
1 3 12 13 16 15
1 3 13 14 17 16
1 3 14 12 15 17
1 3 15 16 1 0
1 3 16 17 2 1
1 3 17 15 0 2
vertices
18
nodes
FiniteElementSpace
FiniteElementCollection: H1_3D_P3
VDim: 3
Ordering: 1
0.6 -1.4695762e-16 -9.7971744e-17
1.2 -2.9391523e-16 0.34641016
1.2 -1.3597293e-15 -0.34641016
0.4 0.69282032 0.34641016
0.7 1.2124356 2.7755576e-17
0.4 0.69282032 -0.34641016
-0.6 1.0392305 0.34641016
-0.6 1.0392305 -0.34641016
-0.3 0.51961524 -3.8651415e-16
-1.4 1.7145055e-16 4.8985872e-17
-0.8 9.7971744e-17 -0.34641016
-0.8 4.5324311e-16 0.34641016
-0.6 -1.0392305 -0.34641016
-0.3 -0.51961524 -2.220446e-16
-0.6 -1.0392305 0.34641016
0.4 -0.69282032 -0.34641016
0.4 -0.69282032 0.34641016
0.7 -1.2124356 7.7509221e-16
0.76583592 -8.6777464e-16 0.095745414
1.0341641 2.5022695e-15 0.25066475
1.2 -1.3597293e-15 0.15491933
1.2 -2.9391523e-16 -0.15491933
0.76583592 4.9262324e-16 -0.095745414
1.0341641 3.4207917e-15 -0.25066475
0.48291796 0.83643844 0.25066475
0.61708204 1.0688174 0.095745414
0.61708204 1.0688174 -0.095745414
0.48291796 0.83643844 -0.25066475
0.4 0.69282032 0.15491933
0.4 0.69282032 -0.15491933
0.59098879 0.17599714 0.11416557
0.51532795 0.48760104 0.27491822
1.2368698 0.36834126 0.27491822
1.0048434 0.95077837 0.11416557
1.0473544 0.31190335 -0.38908379
0.65896232 0.62350725 -0.38908379
-0.6 1.0392305 0.15491933
-0.6 1.0392305 -0.15491933
-0.51708204 0.89561236 -0.25066475
-0.38291796 0.66323336 -0.095745414
-0.51708204 0.89561236 0.25066475
-0.38291796 0.66323336 0.095745414
0.21049196 0.88243173 0.38908379
-0.25356098 1.0629872 0.38908379
0.32097654 1.3456091 -0.11416557
-0.29944203 1.2553313 -0.27491822
0.16461091 0.69008761 -0.27491822
-0.1430764 0.59980988 -0.11416557
-1.2341641 6.9922046e-16 -0.095745414
-0.96583592 -1.1684711e-15 -0.25066475
-0.8 4.5324311e-16 -0.15491933
-0.8 9.7971744e-17 0.15491933
-1.2341641 -3.9693744e-16 0.095745414
-0.96583592 -1.5973885e-15 0.25066475
-0.93742781 0.88699007 0.27491822
-1.3258199 0.3948307 0.11416557
-0.79379344 0.75108386 -0.38908379
-0.86945428 0.25892449 -0.38908379
-0.44791239 0.42381273 0.11416557
-0.67993886 0.20248658 0.27491822
-0.51708204 -0.89561236 -0.25066475
-0.38291796 -0.66323336 -0.095745414
-0.38291796 -0.66323336 0.095745414
-0.51708204 -0.89561236 0.25066475
-0.6 -1.0392305 -0.15491933
-0.6 -1.0392305 0.15491933
-1.3258199 -0.3948307 -0.11416557
-0.93742781 -0.88699007 -0.27491822
-0.67993886 -0.20248658 -0.27491822
-0.44791239 -0.42381273 -0.11416557
-0.86945428 -0.25892449 0.38908379
-0.79379344 -0.75108386 0.38908379
0.4 -0.69282032 -0.15491933
0.4 -0.69282032 0.15491933
0.48291796 -0.83643844 0.25066475
0.61708204 -1.0688174 0.095745414
0.48291796 -0.83643844 -0.25066475
0.61708204 -1.0688174 -0.095745414
-0.25356098 -1.0629872 -0.38908379
0.21049196 -0.88243173 -0.38908379
-0.1430764 -0.59980988 0.11416557
0.16461091 -0.69008761 0.27491822
-0.29944203 -1.2553313 0.27491822
0.32097654 -1.3456091 0.11416557
0.59098879 -0.17599714 -0.11416557
0.51532795 -0.48760104 -0.27491822
1.0473544 -0.31190335 0.38908379
0.65896232 -0.62350725 0.38908379
1.2368698 -0.36834126 -0.27491822
1.0048434 -0.95077837 -0.11416557
1 2.4196059e-15 -1.3788671e-16
0.5 0.8660254 -8.6542076e-17
0.76950592 0.22915975 0.15859651
1.0583527 0.31517866 0.23048728
0.65062668 0.6156201 0.23048728
0.86954463 0.8227593 0.15859651
1.1844891 0.35274221 0.091392579
1.0997352 0.32750241 -0.20555815
0.9092442 0.86032286 -0.024929133
0.75456149 0.71396276 -0.24998909
0.92121806 0.2743398 -0.24998909
0.71712515 0.2135607 -0.024929133
0.61926276 0.5859437 -0.20555815
0.55502751 0.52516459 0.091392579
-0.5 0.8660254 5.1344633e-17
0.24102914 1.0104508 0.24998909
0.29043935 1.21759 0.024929133
-0.26624219 1.1161498 0.20555815
-0.28676082 1.2021687 -0.091392579
0.27775814 1.1644274 -0.15859651
0.20782931 0.87126929 -0.23048728
-0.25622363 1.0741497 -0.23048728
-0.1862948 0.78099155 -0.15859651
0.17729212 0.74325022 -0.091392579
0.19781075 0.82926913 0.20555815
-0.17361359 0.72782894 0.024929133
-0.22302379 0.93496814 0.24998909
-1 -1.2098029e-15 1.3788671e-16
-0.89772824 0.84942651 0.091392579
-0.833493 0.78864741 -0.20555815
-1.1996835 0.35726714 -0.024929133
-0.99559063 0.29648804 -0.24998909
-0.69819427 0.66062834 -0.24998909
-0.54351156 0.51426825 -0.024929133
-0.8170735 0.24332543 -0.20555815
-0.73231963 0.21808563 0.091392579
-0.58321113 0.5518318 0.15859651
-0.80212907 0.758971 0.23048728
-0.85845599 0.25564918 0.23048728
-1.1473028 0.34166809 0.15859651
-0.5 -0.8660254 8.6542076e-17
-1.1473028 -0.34166809 -0.15859651
-0.85845599 -0.25564918 -0.23048728
-0.80212907 -0.758971 -0.23048728
-0.58321113 -0.5518318 -0.15859651
-0.73231963 -0.21808563 -0.091392579
-0.8170735 -0.24332543 0.20555815
-0.54351156 -0.51426825 0.024929133
-0.69819427 -0.66062834 0.24998909
-0.99559063 -0.29648804 0.24998909
-1.1996835 -0.35726714 0.024929133
-0.833493 -0.78864741 0.20555815
-0.89772824 -0.84942651 -0.091392579
0.5 -0.8660254 -5.1344633e-17
-0.22302379 -0.93496814 -0.24998909
-0.17361359 -0.72782894 -0.024929133
0.19781075 -0.82926913 -0.20555815
0.17729212 -0.74325022 0.091392579
-0.1862948 -0.78099155 0.15859651
-0.25622363 -1.0741497 0.23048728
0.20782931 -0.87126929 0.23048728
0.27775814 -1.1644274 0.15859651
-0.28676082 -1.2021687 0.091392579
-0.26624219 -1.1161498 -0.20555815
0.29043935 -1.21759 -0.024929133
0.24102914 -1.0104508 -0.24998909
0.55502751 -0.52516459 -0.091392579
0.61926276 -0.5859437 0.20555815
0.71712515 -0.2135607 0.024929133
0.92121806 -0.2743398 0.24998909
0.75456149 -0.71396276 0.24998909
0.9092442 -0.86032286 0.024929133
1.0997352 -0.32750241 0.20555815
1.1844891 -0.35274221 -0.091392579
0.86954463 -0.8227593 -0.15859651
0.65062668 -0.6156201 -0.23048728
1.0583527 -0.31517866 -0.23048728
0.76950592 -0.22915975 -0.15859651
0.95840435 0.28541392 -1.3795119e-16
0.72637788 0.68729555 -1.1412456e-16
0.23202647 0.97270947 -5.1760042e-17
-0.23202647 0.97270947 1.2226691e-17
-0.72637788 0.68729555 8.6191148e-17
-0.95840435 0.28541392 1.2635125e-16
-0.95840435 -0.28541392 1.3795119e-16
-0.72637788 -0.68729555 1.1412456e-16
-0.23202647 -0.97270947 5.1760042e-17
0.23202647 -0.97270947 -1.2226691e-17
0.72637788 -0.68729555 -8.6191148e-17
0.95840435 -0.28541392 -1.2635125e-16
+6
View File
@@ -71,6 +71,10 @@ namespace mfem {
* - <a class="el" href="ex18p_8cpp_source.html">Example 18p</a>: parallel Discontinuous Galerkin (DG) for the Euler equations
* - <a class="el" href="ex19_8cpp_source.html">Example 19</a>: incompressible nonlinear elasticity
* - <a class="el" href="ex19p_8cpp_source.html">Example 19p</a>: parallel incompressible nonlinear elasticity
* - <a class="el" href="ex20_8cpp_source.html">Example 20</a>: symplectic ODE integration
* - <a class="el" href="ex20p_8cpp_source.html">Example 20p</a>: parallel symplectic ODE integration
* - <a class="el" href="ex22_8cpp_source.html">Example 22</a>: adaptive mesh refinement for linear elasticity
* - <a class="el" href="ex22p_8cpp_source.html">Example 22p</a>: parallel adaptive mesh refinement for linear elasticity
*
* <H4>SUNDIALS Examples</H4>
* - Variants of Examples
@@ -112,7 +116,9 @@ namespace mfem {
* - <a class="el" href="joule_8cpp_source.html">Joule</a>: transient magnetics and Joule heating miniapp
* - <a class="el" href="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
* - <a class="el" href="toroid_8cpp_source.html">Toroid</a>: generate simple toroidal meshes
* - <a class="el" href="shaper_8cpp_source.html">Shaper</a>: resolve material interfaces by mesh refinement
* - <a class="el" href="extruder_8cpp_source.html">Extruder</a>: extrude a low-dimensional mesh into a higher dimension
* - <a class="el" href="mesh-explorer_8cpp_source.html">Mesh Explorer</a>: visualize and manipulate meshes
* - <a class="el" href="mesh-optimizer_8cpp_source.html">Mesh Optimizer</a>: optimize high-order meshes, <a class="el" href="mesh-optimizer_8cpp_source.html">serial</a> and <a class="el" href="pmesh-optimizer_8cpp_source.html">parallel</a> versions
* - <a class="el" href="display-basis_8cpp_source.html">Display Basis</a>: visualize finite element basis functions
+5 -1
View File
@@ -26,6 +26,8 @@ list(APPEND ALL_EXE_SRCS
ex17.cpp
ex18.cpp
ex19.cpp
ex20.cpp
ex22.cpp
)
if (MFEM_USE_MPI)
@@ -49,6 +51,8 @@ if (MFEM_USE_MPI)
ex17p.cpp
ex18p.cpp
ex19p.cpp
ex20p.cpp
ex22p.cpp
)
endif()
@@ -75,7 +79,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
else()
add_test(NAME ${TEST_NAME}_np=4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
${MPIEXEC_POSTFLAGS})
+5
View File
@@ -4,13 +4,18 @@
//
// Sample runs: ex1 -m ../data/square-disc.mesh
// ex1 -m ../data/star.mesh
// ex1 -m ../data/star-mixed.mesh
// ex1 -m ../data/escher.mesh
// ex1 -m ../data/fichera.mesh
// ex1 -m ../data/fichera-mixed.mesh
// ex1 -m ../data/toroid-wedge.mesh
// ex1 -m ../data/square-disc-p2.vtk -o 2
// ex1 -m ../data/square-disc-p3.mesh -o 3
// ex1 -m ../data/square-disc-nurbs.mesh -o -1
// ex1 -m ../data/star-mixed-p2.mesh -o 2
// ex1 -m ../data/disc-nurbs.mesh -o -1
// ex1 -m ../data/pipe-nurbs.mesh -o -1
// ex1 -m ../data/fichera-mixed-p2.mesh -o 2
// ex1 -m ../data/star-surf.mesh
// ex1 -m ../data/square-disc-surf.mesh
// ex1 -m ../data/inline-segment.mesh
+1
View File
@@ -7,6 +7,7 @@
// ex10 -m ../data/beam-tri.mesh -s 3 -r 2 -o 2 -dt 3
// ex10 -m ../data/beam-hex.mesh -s 2 -r 1 -o 2 -dt 3
// ex10 -m ../data/beam-tet.mesh -s 2 -r 1 -o 2 -dt 3
// ex10 -m ../data/beam-wedge.mesh -s 2 -r 1 -o 2 -dt 3
// ex10 -m ../data/beam-quad.mesh -s 14 -r 2 -o 2 -dt 0.03 -vs 20
// ex10 -m ../data/beam-hex.mesh -s 14 -r 1 -o 2 -dt 0.05 -vs 20
// ex10 -m ../data/beam-quad-amr.mesh -s 3 -r 2 -o 2 -dt 3
+1
View File
@@ -7,6 +7,7 @@
// mpirun -np 4 ex10p -m ../data/beam-tri.mesh -s 3 -rs 2 -dt 3
// mpirun -np 4 ex10p -m ../data/beam-hex.mesh -s 2 -rs 1 -dt 3
// mpirun -np 4 ex10p -m ../data/beam-tet.mesh -s 2 -rs 1 -dt 3
// mpirun -np 4 ex10p -m ../data/beam-wedge.mesh -s 2 -rs 1 -dt 3
// mpirun -np 4 ex10p -m ../data/beam-quad.mesh -s 14 -rs 2 -dt 0.03 -vs 20
// mpirun -np 4 ex10p -m ../data/beam-hex.mesh -s 14 -rs 1 -dt 0.05 -vs 20
// mpirun -np 4 ex10p -m ../data/beam-quad-amr.mesh -s 3 -rs 2 -dt 3
+8
View File
@@ -4,8 +4,11 @@
//
// Sample runs: mpirun -np 4 ex11p -m ../data/square-disc.mesh
// mpirun -np 4 ex11p -m ../data/star.mesh
// mpirun -np 4 ex11p -m ../data/star-mixed.mesh
// mpirun -np 4 ex11p -m ../data/escher.mesh
// mpirun -np 4 ex11p -m ../data/fichera.mesh
// mpirun -np 4 ex11p -m ../data/fichera-mixed.mesh
// mpirun -np 4 ex11p -m ../data/toroid-wedge.mesh -o 2
// mpirun -np 4 ex11p -m ../data/square-disc-p2.vtk -o 2
// mpirun -np 4 ex11p -m ../data/square-disc-p3.mesh -o 3
// mpirun -np 4 ex11p -m ../data/square-disc-nurbs.mesh -o -1
@@ -15,6 +18,11 @@
// mpirun -np 4 ex11p -m ../data/star-surf.mesh
// mpirun -np 4 ex11p -m ../data/square-disc-surf.mesh
// mpirun -np 4 ex11p -m ../data/inline-segment.mesh
// mpirun -np 4 ex11p -m ../data/inline-quad.mesh
// mpirun -np 4 ex11p -m ../data/inline-tri.mesh
// mpirun -np 4 ex11p -m ../data/inline-hex.mesh
// mpirun -np 4 ex11p -m ../data/inline-tet.mesh
// mpirun -np 4 ex11p -m ../data/inline-wedge.mesh -s 83
// mpirun -np 4 ex11p -m ../data/amr-quad.mesh
// mpirun -np 4 ex11p -m ../data/amr-hex.mesh
// mpirun -np 4 ex11p -m ../data/mobius-strip.mesh -n 8
+3 -2
View File
@@ -5,9 +5,10 @@
// Sample runs:
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -n 10 -o 2 -elast
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 79 -n 10 -o 2 -elast
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3876
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -o 2 -sys
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 79
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -s 3876 -o 2 -sys
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -s 4526 -n 6 -o 3 -elast
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
// mpirun -np 4 ex12p -m ../data/beam-hex-nurbs.mesh
+2
View File
@@ -4,8 +4,10 @@
//
// Sample runs: ex14 -m ../data/inline-quad.mesh -o 0
// ex14 -m ../data/star.mesh -r 4 -o 2
// ex14 -m ../data/star-mixed.mesh -r 4 -o 2
// ex14 -m ../data/escher.mesh -s 1
// ex14 -m ../data/fichera.mesh -s 1 -k 1
// ex14 -m ../data/fichera-mixed.mesh -s 1 -k 1
// ex14 -m ../data/square-disc-p2.vtk -r 3 -o 2
// ex14 -m ../data/square-disc-p3.mesh -r 2 -o 3
// ex14 -m ../data/square-disc-nurbs.mesh -o 1
+2
View File
@@ -4,8 +4,10 @@
//
// Sample runs: mpirun -np 4 ex14p -m ../data/inline-quad.mesh -o 0
// mpirun -np 4 ex14p -m ../data/star.mesh -o 2
// mpirun -np 4 ex14p -m ../data/star-mixed.mesh -o 2
// mpirun -np 4 ex14p -m ../data/escher.mesh -s 1
// mpirun -np 4 ex14p -m ../data/fichera.mesh -s 1 -k 1
// mpirun -np 4 ex14p -m ../data/fichera-mixed.mesh -s 1 -k 1
// mpirun -np 4 ex14p -m ../data/square-disc-p2.vtk -o 2
// mpirun -np 4 ex14p -m ../data/square-disc-p3.mesh -o 3
// mpirun -np 4 ex14p -m ../data/square-disc-nurbs.mesh -o 1
+2
View File
@@ -135,6 +135,8 @@ int main(int argc, char *argv[])
{
mesh.UniformRefinement();
}
// Make sure tet-only meshes are marked for local refinement.
mesh.Finalize(true);
// 4. All boundary attributes will be used for essential (Dirichlet) BC.
MFEM_VERIFY(mesh.bdr_attributes.Size() > 0,
+2
View File
@@ -151,6 +151,8 @@ int main(int argc, char *argv[])
{
mesh->UniformRefinement();
}
// Make sure tet-only meshes are marked for local refinement.
mesh->Finalize(true);
// 5. Define a parallel mesh by partitioning the serial mesh. Once the
// parallel mesh is defined, the serial mesh can be deleted.
+1
View File
@@ -10,6 +10,7 @@
// ex16 -s 3 -a 0.5 -k 0.5 -o 4
// ex16 -s 14 -dt 1.0e-4 -tf 4.0e-2 -vs 40
// ex16 -m ../data/fichera-q2.mesh
// ex16 -m ../data/fichera-mixed.mesh
// ex16 -m ../data/escher.mesh
// ex16 -m ../data/beam-tet.mesh -tf 10 -dt 0.1
// ex16 -m ../data/amr-quad.mesh -o 4 -r 0
+1
View File
@@ -10,6 +10,7 @@
// mpirun -np 8 ex16p -s 3 -a 0.5 -k 0.5 -o 4
// mpirun -np 4 ex16p -s 14 -dt 1.0e-4 -tf 4.0e-2 -vs 40
// mpirun -np 16 ex16p -m ../data/fichera-q2.mesh
// mpirun -np 16 ex16p -m ../data/fichera-mixed.mesh
// mpirun -np 16 ex16p -m ../data/escher-p2.mesh
// mpirun -np 8 ex16p -m ../data/beam-tet.mesh -tf 10 -dt 0.1
// mpirun -np 4 ex16p -m ../data/amr-quad.mesh -o 4 -rs 0 -rp 0
+1
View File
@@ -8,6 +8,7 @@
// ex17 -m ../data/beam-quad.mesh
// ex17 -m ../data/beam-tet.mesh
// ex17 -m ../data/beam-hex.mesh
// ex17 -m ../data/beam-wedge.mesh
// ex17 -m ../data/beam-quad.mesh -r 2 -o 3
// ex17 -m ../data/beam-quad.mesh -r 2 -o 2 -a 1 -k 1
// ex17 -m ../data/beam-hex.mesh -r 2 -o 2
+1
View File
@@ -8,6 +8,7 @@
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh
// mpirun -np 4 ex17p -m ../data/beam-tet.mesh
// mpirun -np 4 ex17p -m ../data/beam-hex.mesh
// mpirun -np 4 ex17p -m ../data/beam-wedge.mesh
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh -rs 2 -rp 2 -o 3 -elast
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh -rs 2 -rp 3 -o 2 -a 1 -k 1
// mpirun -np 4 ex17p -m ../data/beam-hex.mesh -rs 2 -rp 1 -o 2
+1 -2
View File
@@ -509,8 +509,7 @@ bool StateIsPhysical(const Vector &state, const int dim)
// Initial condition
void InitialCondition(const Vector &x, Vector &y)
{
const int dim = x.Size();
MFEM_ASSERT(dim == 2, "");
MFEM_ASSERT(x.Size() == 2, "");
double radius = 0, Minf = 0, beta = 0;
if (problem == 1)
+1
View File
@@ -7,6 +7,7 @@
// ex19 -m ../data/beam-tri.mesh
// ex19 -m ../data/beam-hex.mesh
// ex19 -m ../data/beam-tet.mesh
// ex19 -m ../data/beam-wedge.mesh
//
// Description: This examples solves a quasi-static incompressible nonlinear
// elasticity problem of the form 0 = H(x), where H is an
+1
View File
@@ -7,6 +7,7 @@
// mpirun -np 2 ex19p -m ../data/beam-tri.mesh
// mpirun -np 2 ex19p -m ../data/beam-hex.mesh
// mpirun -np 2 ex19p -m ../data/beam-tet.mesh
// mpirun -np 2 ex19p -m ../data/beam-wedge.mesh
//
// Description: This examples solves a quasi-static incompressible nonlinear
// elasticity problem of the form 0 = H(x), where H is an
+5
View File
@@ -4,14 +4,19 @@
//
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
// mpirun -np 4 ex1p -m ../data/star.mesh
// mpirun -np 4 ex1p -m ../data/star-mixed.mesh
// mpirun -np 4 ex1p -m ../data/escher.mesh
// mpirun -np 4 ex1p -m ../data/fichera.mesh
// mpirun -np 4 ex1p -m ../data/fichera-mixed.mesh
// mpirun -np 4 ex1p -m ../data/toroid-wedge.mesh
// mpirun -np 4 ex1p -m ../data/square-disc-p2.vtk -o 2
// mpirun -np 4 ex1p -m ../data/square-disc-p3.mesh -o 3
// mpirun -np 4 ex1p -m ../data/square-disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/star-mixed-p2.mesh -o 2
// mpirun -np 4 ex1p -m ../data/disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/pipe-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/ball-nurbs.mesh -o 2
// mpirun -np 4 ex1p -m ../data/fichera-mixed-p2.mesh -o 2
// mpirun -np 4 ex1p -m ../data/star-surf.mesh
// mpirun -np 4 ex1p -m ../data/square-disc-surf.mesh
// mpirun -np 4 ex1p -m ../data/inline-segment.mesh
+1
View File
@@ -6,6 +6,7 @@
// ex2 -m ../data/beam-quad.mesh
// ex2 -m ../data/beam-tet.mesh
// ex2 -m ../data/beam-hex.mesh
// ex2 -m ../data/beam-wedge.mesh
// ex2 -m ../data/beam-quad.mesh -o 3 -sc
// ex2 -m ../data/beam-quad-nurbs.mesh
// ex2 -m ../data/beam-hex-nurbs.mesh
+298
View File
@@ -0,0 +1,298 @@
// MFEM Example 20
//
// Compile with: make ex20
//
// Sample runs: ex20
//
// Description: This example demonstrates the use of the variable order,
// symplectic ODE integration algorithm. Symplectic integration
// algorithms are designed to conserve energy when integrating, in
// time, systems of ODEs which are derived from Hamiltonian
// systems.
//
// Hamiltonian systems define the energy of a system as a function
// of time (t), a set of generalized coordinates (q), and their
// corresponding generalized momenta (p).
//
// H(q,p,t) = T(p) + V(q,t)
//
// Hamilton's equations then specify how q and p evolve in time:
//
// dq/dt = dH/dp
// dp/dt = -dH/dq
//
// To use the symplectic integration classes we need to define an
// mfem::Operator P which evaluates the action of dH/dp, and an
// mfem::TimeDependentOperator F which computes -dH/dq.
//
// This example offers five simple 1D Hamiltonians:
// 0) Simple Harmonic Oscillator (mass on a spring)
// H = ( p^2 / m + q^2 / k ) / 2
// 1) Pendulum
// H = ( p^2 / m - k ( 1 - cos(q) ) ) / 2
// 2) Gaussian Potential Well
// H = ( p^2 / m ) / 2 - k exp(-q^2 / 2)
// 3) Quartic Potential
// H = ( p^2 / m + k ( 1 + q^2 ) q^2 ) / 2
// 4) Negative Quartic Potential
// H = ( p^2 / m + k ( 1 - q^2 /8 ) q^2 ) / 2
//
// In all cases these Hamiltonians are shifted by constant values
// so that the energy will remain positive. The mean and standard
// deviation of the computed energies at each time step are
// displayed upon completion.
//
// We then use GLVis to visualize the results in a non-standard way
// by defining the axes to be q, p, and t rather than x, y, and z.
// In this space we build a ribbon-like mesh with nodes at (0,0,t)
// and (q,p,t). Finally we plot the energy as a function of time
// as a scalar field on this ribbon-like mesh.
//
// For a more traditional plot of the results, including q, p, and
// H, can be obtained by selecting the "-gp" option. This creates
// a data file and input deck for the GnuPlot application (not
// included with MFEM). To visualize these results on most Linux
// systems type the command "gnuplot gnuplot_ex20.inp". The data
// file, named "ex20.dat", should be simple enough to display with
// other plotting programs as well.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
// Constants used in the Hamiltonian
static int prob_ = 0;
static double m_ = 1.0;
static double k_ = 1.0;
// Hamiltonian functional, see below for implementation
double hamiltonian(double q, double p, double t);
class GradT : public Operator
{
public:
GradT() : Operator(1) {}
void Mult(const Vector &x, Vector &y) const { y.Set(1.0/m_, x); }
};
class NegGradV : public TimeDependentOperator
{
public:
NegGradV() : TimeDependentOperator(1) {}
void Mult(const Vector &x, Vector &y) const;
};
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
int order = 1;
int nsteps = 100;
double dt = 0.1;
bool visualization = true;
bool gnuplot = false;
OptionsParser args(argc, argv);
args.AddOption(&order, "-o", "--order",
"Time integration order.");
args.AddOption(&prob_, "-p", "--problem-type",
"Problem Type:\n"
"\t 0 - Simple Harmonic Oscillator\n"
"\t 1 - Pendulum\n"
"\t 2 - Gaussian Potential Well\n"
"\t 3 - Quartic Potential\n"
"\t 4 - Negative Quartic Potential");
args.AddOption(&nsteps, "-n", "--number-of-steps",
"Number of time steps.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step size.");
args.AddOption(&m_, "-m", "--mass",
"Mass.");
args.AddOption(&k_, "-k", "--spring-const",
"Spring constant.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&gnuplot, "-gp", "--gnuplot", "-no-gp", "--no-gnuplot",
"Enable or disable GnuPlot visualization.");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
args.PrintOptions(cout);
// 2. Create and Initialize the Symplectic Integration Solver
SIAVSolver siaSolver(order);
GradT P;
NegGradV F;
siaSolver.Init(P,F);
// 3. Set the initial conditions
double t = 0.0;
Vector q(1), p(1);
Vector e(nsteps+1);
q(0) = 0.0;
p(0) = 1.0;
// 4. Prepare GnuPlot output file if needed
ofstream ofs;
if (gnuplot)
{
ofs.open("ex20.dat");
ofs << t << "\t" << q(0) << "\t" << p(0) << endl;
}
// 5. Create a Mesh for visualization in phase space
int nverts = (visualization) ? 2*(nsteps+1) : 0;
int nelems = (visualization) ? nsteps : 0;
Mesh mesh(2, nverts, nelems, 0, 3);
int v[4];
Vector x0(3); x0 = 0.0;
Vector x1(3); x1 = 0.0;
// 6. Perform time-stepping
double e_mean = 0.0;
for (int i = 0; i < nsteps; i++)
{
// 6a. Record initial state
if (i == 0)
{
e[0] = hamiltonian(q(0),p(0),t);
e_mean += e[0];
if (visualization)
{
x1[0] = q(0);
x1[1] = p(0);
x1[2] = 0.0;
mesh.AddVertex(x0);
mesh.AddVertex(x1);
}
}
// 6b. Advance the state of the system
siaSolver.Step(q,p,t,dt);
e[i+1] = hamiltonian(q(0),p(0),t);
e_mean += e[i+1];
// 6c. Record the state of the system
if (gnuplot)
{
ofs << t << "\t" << q(0) << "\t" << p(0) << "\t" << e[i+1] << endl;
}
// 6d. Add results to GLVis visualization
if (visualization)
{
x0[2] = t;
x1[0] = q(0);
x1[1] = p(0);
x1[2] = t;
mesh.AddVertex(x0);
mesh.AddVertex(x1);
v[0] = 2*i;
v[1] = 2*(i+1);
v[2] = 2*(i+1)+1;
v[3] = 2*i+1;
mesh.AddQuad(v);
}
}
// 7. Compute and display mean and standard deviation of the energy
e_mean /= (nsteps + 1);
double 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);
cout << endl << "Mean and standard deviation of the energy" << endl;
cout << e_mean << "\t" << e_sd << endl;
// 8. Finalize the GnuPlot output
if (gnuplot)
{
ofs.close();
ofs.open("gnuplot_ex20.inp");
ofs << "plot 'ex20.dat' using 1:2 w l t 'q', "
<< "'ex20.dat' using 1:3 w l t 'p', "
<< "'ex20.dat' using 1:4 w l t 'H'" << endl;
ofs.close();
}
// 9. Finalize the GLVis output
if (visualization)
{
H1_FECollection fec(order = 1, 2);
FiniteElementSpace fespace(&mesh, &fec);
GridFunction energy(&fespace);
energy = 0.0;
for (int i = 0; i <= nsteps; i++)
{
energy[2*i+0] = e[i];
energy[2*i+1] = e[i];
}
char vishost[] = "localhost";
int visport = 19916;
socketstream sock(vishost, visport);
sock.precision(8);
sock << "solution\n" << mesh << energy
<< "window_title 'Energy in Phase Space'\n"
<< "keys\n maac\n" << "axis_labels 'q' 'p' 't'\n"<< flush;
}
}
double hamiltonian(double q, double p, double t)
{
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
switch (prob_)
{
case 1:
h += k_ * (1.0 - cos(q));
break;
case 2:
h += k_ * (1.0 - exp(-0.5 * q * q));
break;
case 3:
h += 0.5 * k_ * (1.0 + q * q) * q * q;
break;
case 4:
h += 0.5 * k_ * (1.0 - 0.125 * q * q) * q * q;
break;
default:
h += 0.5 * k_ * q * q;
break;
}
return h;
}
void NegGradV::Mult(const Vector &x, Vector &y) const
{
switch (prob_)
{
case 1:
y(0) = - k_* sin(x(0));
break;
case 2:
y(0) = - k_ * x(0) * exp(-0.5 * x(0) * x(0));
break;
case 3:
y(0) = - k_ * (1.0 + 2.0 * x(0) * x(0)) * x(0);
break;
case 4:
y(0) = - k_ * (1.0 - 0.25 * x(0) * x(0)) * x(0);
break;
default:
y(0) = - k_ * x(0);
break;
};
}
+364
View File
@@ -0,0 +1,364 @@
// MFEM Example 20 - Parallel Version
//
// Compile with: make ex20p
//
// Sample runs: mpirun -np 4 ex20p
//
// Description: This example demonstrates the use of the variable order,
// symplectic ODE integration algorithm. Symplectic integration
// algorithms are designed to conserve energy when integrating, in
// time, systems of ODEs which are derived from Hamiltonian
// systems.
//
// Hamiltonian systems define the energy of a system as a function
// of time (t), a set of generalized coordinates (q), and their
// corresponding generalized momenta (p).
//
// H(q,p,t) = T(p) + V(q,t)
//
// Hamilton's equations then specify how q and p evolve in time:
//
// dq/dt = dH/dp
// dp/dt = -dH/dq
//
// To use the symplectic integration classes we need to define an
// mfem::Operator P which evaluates the action of dH/dp, and an
// mfem::TimeDependentOperator F which computes -dH/dq.
//
// This example offers five simple 1D Hamiltonians:
// 0) Simple Harmonic Oscillator (mass on a spring)
// H = ( p^2 / m + q^2 / k ) / 2
// 1) Pendulum
// H = ( p^2 / m - k ( 1 - cos(q) ) ) / 2
// 2) Gaussian Potential Well
// H = ( p^2 / m ) / 2 - k exp(-q^2 / 2)
// 3) Quartic Potential
// H = ( p^2 / m + k ( 1 + q^2 ) q^2 ) / 2
// 4) Negative Quartic Potential
// H = ( p^2 / m + k ( 1 - q^2 /8 ) q^2 ) / 2
//
// In all cases these Hamiltonians are shifted by constant values
// so that the energy will remain positive. The mean and standard
// deviation of the computed energies at each time step are
// displayed upon completion. When run in parallel the same
// Hamiltonian system is evolved on each processor but starting
// from different initial conditions.
//
// We then use GLVis to visualize the results in a non-standard way
// by defining the axes to be q, p, and t rather than x, y, and z.
// In this space we build a ribbon-like mesh on each processor with
// nodes at (0,0,t) and (q,p,t). When these ribbons are bonded
// together on the t-axis they resemble a Rotini pasta. Finally we
// plot the energy as a function of time as a scalar field on this
// Rotini-like mesh.
//
// For a more traditional plot of the results, including q, p, and
// H from each processor, can be obtained by selecting the "-gp"
// option. This creates a collection of data files and an input
// deck for the GnuPlot application (not included with MFEM). To
// visualize these results on most linux systems type the command
// "gnuplot gnuplot_ex20p.inp". The data files, named
// "ex20p_?????.dat", should be simple enough to display with other
// plotting programs as well.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
// Constants used in the Hamiltonian
static int prob_ = 0;
static double m_ = 1.0;
static double k_ = 1.0;
// Hamiltonian functional, see below for implementation
double hamiltonian(double q, double p, double t);
class GradT : public Operator
{
public:
GradT() : Operator(1) {}
void Mult(const Vector &x, Vector &y) const { y.Set(1.0/m_, x); }
};
class NegGradV : public TimeDependentOperator
{
public:
NegGradV() : TimeDependentOperator(1) {}
void Mult(const Vector &x, Vector &y) const;
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Comm comm = MPI_COMM_WORLD;
MPI_Init(&argc, &argv);
MPI_Comm_size(comm, &num_procs);
MPI_Comm_rank(comm, &myid);
// 2. Parse command-line options.
int order = 1;
int nsteps = 100;
double dt = 0.1;
bool visualization = true;
bool gnuplot = false;
OptionsParser args(argc, argv);
args.AddOption(&order, "-o", "--order",
"Time integration order.");
args.AddOption(&prob_, "-p", "--problem-type",
"Problem Type:\n"
"\t 0 - Simple Harmonic Oscillator\n"
"\t 1 - Pendulum\n"
"\t 2 - Gaussian Potential Well\n"
"\t 3 - Quartic Potential\n"
"\t 4 - Negative Quartic Potential");
args.AddOption(&nsteps, "-n", "--number-of-steps",
"Number of time steps.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step size.");
args.AddOption(&m_, "-m", "--mass",
"Mass.");
args.AddOption(&k_, "-k", "--spring-const",
"Spring constant.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&gnuplot, "-gp", "--gnuplot", "-no-gp", "--no-gnuplot",
"Enable or disable GnuPlot visualization.");
args.Parse();
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
MPI_Finalize();
return 1;
}
if (myid == 0)
{
args.PrintOptions(cout);
}
// 3. Create and Initialize the Symplectic Integration Solver
SIAVSolver siaSolver(order);
GradT P;
NegGradV F;
siaSolver.Init(P,F);
// 4. Set the initial conditions
double 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);
// 5. Prepare GnuPlot output file if needed
ostringstream oss;
ofstream ofs;
if (gnuplot)
{
oss << "ex20p_" << setfill('0') << setw(5) << myid << ".dat";
ofs.open(oss.str().c_str());
ofs << t << "\t" << q(0) << "\t" << p(0) << endl;
}
// 6. Create a Mesh for visualization in phase space
int nverts = (visualization) ? (num_procs+1)*(nsteps+1) : 0;
int nelems = (visualization) ? (nsteps * num_procs) : 0;
Mesh mesh(2, nverts, nelems, 0, 3);
int *part = (visualization) ? (new int[nelems]) : NULL;
int v[4];
Vector x0(3); x0 = 0.0;
Vector x1(3); x1 = 0.0;
// 7. Perform time-stepping
double e_mean = 0.0;
for (int i = 0; i < nsteps; i++)
{
// 7a. Record initial state
if (i == 0)
{
e[0] = hamiltonian(q(0),p(0),t);
e_mean += e[0];
if (visualization)
{
mesh.AddVertex(x0);
for (int j = 0; j < num_procs; j++)
{
x1[0] = q(0);
x1[1] = p(0);
x1[2] = 0.0;
mesh.AddVertex(x1);
}
}
}
// 7b. Advance the state of the system
siaSolver.Step(q,p,t,dt);
e[i+1] = hamiltonian(q(0),p(0),t);
e_mean += e[i+1];
// 7c. Record the state of the system
if (gnuplot)
{
ofs << t << "\t" << q(0) << "\t" << p(0) << "\t" << e[i+1] << endl;
}
// 7d. Add results to GLVis visualization
if (visualization)
{
x0[2] = t;
mesh.AddVertex(x0);
for (int j = 0; j < num_procs; j++)
{
x1[0] = q(0);
x1[1] = p(0);
x1[2] = t;
mesh.AddVertex(x1);
v[0] = (num_procs + 1) * i;
v[1] = (num_procs + 1) * (i + 1);
v[2] = (num_procs + 1) * (i + 1) + j + 1;
v[3] = (num_procs + 1) * i + j + 1;
mesh.AddQuad(v);
part[num_procs * i + j] = j;
}
}
}
// 8. Compute and display mean and standard deviation of the energy
e_mean /= (nsteps + 1);
double 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);
if (myid == 0)
{
cout << endl << "Mean and standard deviation of the energy" << endl;
}
for (int i = 0; i < num_procs; i++)
{
if (myid == i)
{
cout << myid << ": " << e_mean << "\t" << e_sd << endl;
}
MPI_Barrier(comm);
}
// 9. Finalize the GnuPlot output
if (gnuplot)
{
ofs.close();
if (myid == 0)
{
ofs.open("gnuplot_ex20p.inp");
for (int i = 0; i < num_procs; i++)
{
ostringstream ossi;
ossi << "ex20p_" << setfill('0') << setw(5) << i << ".dat";
if (i == 0)
{
ofs << "plot";
}
ofs << " '" << ossi.str() << "' using 1:2 w l t 'q" << i << "',"
<< " '" << ossi.str() << "' using 1:3 w l t 'p" << i << "',"
<< " '" << ossi.str() << "' using 1:4 w l t 'H" << i << "'";
if (i < num_procs-1)
{
ofs << ",";
}
else
{
ofs << ";" << endl;
}
}
ofs.close();
}
}
// 10. Finalize the GLVis output
if (visualization)
{
mesh.FinalizeQuadMesh(1);
ParMesh pmesh(comm, mesh, part);
delete [] part;
H1_FECollection fec(order = 1, 2);
ParFiniteElementSpace fespace(&pmesh, &fec);
ParGridFunction energy(&fespace);
energy = 0.0;
for (int i = 0; i <= nsteps; i++)
{
energy[2*i+0] = e[i];
energy[2*i+1] = e[i];
}
char vishost[] = "localhost";
int visport = 19916;
socketstream sock(vishost, visport);
sock.precision(8);
sock << "parallel " << num_procs << " " << myid << "\n"
<< "solution\n" << pmesh << energy
<< "window_title 'Energy in Phase Space'\n"
<< "keys\n maac\n" << "axis_labels 'q' 'p' 't'\n"<< flush;
}
MPI_Finalize();
}
double hamiltonian(double q, double p, double t)
{
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
switch (prob_)
{
case 1:
h += k_ * (1.0 - cos(q));
break;
case 2:
h += k_ * (1.0 - exp(-0.5 * q * q));
break;
case 3:
h += 0.5 * k_ * (1.0 + q * q) * q * q;
break;
case 4:
h += 0.5 * k_ * (1.0 - 0.125 * q * q) * q * q;
break;
default:
h += 0.5 * k_ * q * q;
break;
}
return h;
}
void NegGradV::Mult(const Vector &x, Vector &y) const
{
switch (prob_)
{
case 1:
y(0) = - k_* sin(x(0));
break;
case 2:
y(0) = - k_ * x(0) * exp(-0.5 * x(0) * x(0));
break;
case 3:
y(0) = - k_ * (1.0 + 2.0 * x(0) * x(0)) * x(0);
break;
case 4:
y(0) = - k_ * (1.0 - 0.25 * x(0) * x(0)) * x(0);
break;
default:
y(0) = - k_ * x(0);
break;
};
}
+310
View File
@@ -0,0 +1,310 @@
// MFEM Example 22
//
// Compile with: make ex22
//
// Sample runs: ex22
// ex22 -o 3
// ex22 -m ../data/beam-quad.mesh
// ex22 -m ../data/beam-quad.mesh -o 3
// ex22 -m ../data/beam-quad.mesh -o 3 -f 1
// ex22 -m ../data/beam-tet.mesh
// ex22 -m ../data/beam-tet.mesh -o 2
// ex22 -m ../data/beam-hex.mesh
// ex22 -m ../data/beam-hex.mesh -o 2
//
// Description: This is a version of Example 2 with a simple adaptive mesh
// refinement loop. The problem being solved is again the linear
// elasticity describing a multi-material cantilever beam.
// The problem is solved on a sequence of meshes which
// are locally refined in a conforming (triangles, tetrahedrons)
// or non-conforming (quadrilaterals, hexahedra) manner according
// to a simple ZZ error estimator.
//
// The example demonstrates MFEM's capability to work with both
// conforming and nonconforming refinements, in 2D and 3D, on
// linear and curved meshes. Interpolation of functions from
// coarse to fine meshes, as well as persistent GLVis
// visualization are also illustrated.
//
// We recommend viewing Examples 2 and 6 before viewing this
// example.
#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/beam-tri.mesh";
int order = 1;
bool static_cond = false;
int flux_averaging = 0;
bool visualization = 1;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&flux_averaging, "-f", "--flux-averaging",
"Flux averaging: 0 - global, 1 - by mesh attribute.");
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 given mesh file. We can handle triangular,
// quadrilateral, tetrahedral, and hexahedral meshes with the same code.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
MFEM_VERIFY(mesh.SpaceDimension() == dim, "invalid mesh");
if (mesh.attributes.Max() < 2 || mesh.bdr_attributes.Max() < 2)
{
cerr << "\nInput mesh should have at least two materials and "
<< "two boundary attributes! (See schematic in ex2.cpp)\n"
<< endl;
return 3;
}
// 3. Since a NURBS mesh can currently only be refined uniformly, we need to
// convert it to a piecewise-polynomial curved mesh. First we refine the
// NURBS mesh a bit more and then project the curvature to quadratic Nodes.
if (mesh.NURBSext)
{
for (int i = 0; i < 2; i++)
{
mesh.UniformRefinement();
}
mesh.SetCurvature(2);
}
// 4. Define a finite element space on the mesh. The polynomial order is
// one (linear) by default, but this can be changed on the command line.
H1_FECollection fec(order, dim);
FiniteElementSpace fespace(&mesh, &fec, dim);
// 5. As in Example 2, we set up the linear form b(.) which corresponds to
// the right-hand side of the FEM linear system. In this case, b_i equals
// the boundary integral of f*phi_i where f represents a "pull down"
// force on the Neumann part of the boundary and phi_i are the basis
// functions in the finite element fespace. The force is defined by the
// VectorArrayCoefficient object f, which is a vector of Coefficient
// objects. The fact that f is non-zero on boundary attribute 2 is
// indicated by the use of piece-wise constants coefficient for its last
// component. We don't assemble the discrete problem yet, this will be
// done in the main loop.
VectorArrayCoefficient f(dim);
for (int i = 0; i < dim-1; i++)
{
f.Set(i, new ConstantCoefficient(0.0));
}
{
Vector pull_force(mesh.bdr_attributes.Max());
pull_force = 0.0;
pull_force(1) = -1.0e-2;
f.Set(dim-1, new PWConstCoefficient(pull_force));
}
LinearForm b(&fespace);
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
// 6. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the linear elasticity integrator with piece-wise
// constants coefficient lambda and mu.
Vector lambda(mesh.attributes.Max());
lambda = 1.0;
lambda(0) = lambda(1)*50;
PWConstCoefficient lambda_func(lambda);
Vector mu(mesh.attributes.Max());
mu = 1.0;
mu(0) = mu(1)*50;
PWConstCoefficient mu_func(mu);
BilinearForm a(&fespace);
BilinearFormIntegrator *integ =
new ElasticityIntegrator(lambda_func,mu_func);
a.AddDomainIntegrator(integ);
if (static_cond) { a.EnableStaticCondensation(); }
// 7. The solution vector x and the associated finite element grid function
// will be maintained over the AMR iterations. We initialize it to zero.
Vector zero_vec(dim);
zero_vec = 0.0;
VectorConstantCoefficient zero_vec_coeff(zero_vec);
GridFunction x(&fespace);
x = 0.0;
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
// In this example, the boundary conditions are defined by marking only
// boundary attribute 1 from the mesh as essential and converting it to a
// list of true dofs. The conversion to true dofs will be done in the
// main loop.
Array<int> ess_bdr(mesh.bdr_attributes.Max());
ess_bdr = 0;
ess_bdr[0] = 1;
// 9. Connect to GLVis.
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock;
if (visualization)
{
sol_sock.open(vishost, visport);
sol_sock.precision(8);
}
// 10. Set up an error estimator. Here we use the Zienkiewicz-Zhu estimator
// that uses the ComputeElementFlux method of the ElasticityIntegrator to
// recover a smoothed flux (stress) that is subtracted from the element
// flux to get an error indicator. We need to supply the space for the
// smoothed flux: an (H1)^tdim (i.e., vector-valued) space is used here.
// Here, tdim represents the number of components for a symmetric (dim x
// dim) tensor.
const int tdim = dim*(dim+1)/2;
FiniteElementSpace flux_fespace(&mesh, &fec, tdim);
ZienkiewiczZhuEstimator estimator(*integ, x, flux_fespace);
estimator.SetFluxAveraging(flux_averaging);
// 11. A refiner selects and refines elements based on a refinement strategy.
// The strategy here is to refine elements with errors larger than a
// fraction of the maximum element error. Other strategies are possible.
// The refiner will call the given error estimator.
ThresholdRefiner refiner(estimator);
refiner.SetTotalErrorFraction(0.7);
// 12. The main AMR loop. In each iteration we solve the problem on the
// current mesh, visualize the solution, and refine the mesh.
const int max_dofs = 50000;
const int max_amr_itr = 20;
for (int it = 0; it <= max_amr_itr; it++)
{
int cdofs = fespace.GetTrueVSize();
cout << "\nAMR iteration " << it << endl;
cout << "Number of unknowns: " << cdofs << endl;
// 13. Assemble the stiffness matrix and the right-hand side.
a.Assemble();
b.Assemble();
// 14. Set Dirichlet boundary values in the GridFunction x.
// Determine the list of Dirichlet true DOFs in the linear system.
Array<int> ess_tdof_list;
x.ProjectBdrCoefficient(zero_vec_coeff, ess_bdr);
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
// 15. Create the linear system: eliminate boundary conditions, constrain
// hanging nodes and possibly apply other transformations. The system
// will be solved for true (unconstrained) DOFs only.
SparseMatrix A;
Vector B, X;
const int copy_interior = 1;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
#ifndef MFEM_USE_SUITESPARSE
// 16. Define a simple symmetric Gauss-Seidel preconditioner and use it to
// solve the linear system with PCG.
GSSmoother M(A);
PCG(A, M, B, X, 3, 2000, 1e-12, 0.0);
#else
// 16. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the
// the linear system.
UMFPackSolver umf_solver;
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
umf_solver.SetOperator(A);
umf_solver.Mult(B, X);
#endif
// 17. After solving the linear system, reconstruct the solution as a
// finite element GridFunction. Constrained nodes are interpolated
// from true DOFs (it may therefore happen that x.Size() >= X.Size()).
a.RecoverFEMSolution(X, b, x);
// 18. Send solution by socket to the GLVis server.
if (visualization && sol_sock.good())
{
GridFunction nodes(&fespace), *nodes_p = &nodes;
mesh.GetNodes(nodes);
nodes += x;
int own_nodes = 0;
mesh.SwapNodes(nodes_p, own_nodes);
x.Neg(); // visualize the backward displacement
sol_sock << "solution\n" << mesh << x << flush;
x.Neg();
mesh.SwapNodes(nodes_p, own_nodes);
if (it == 0)
{
sol_sock << "keys '" << ((dim == 2) ? "Rjl" : "") << "m'" << endl;
}
sol_sock << "window_title 'AMR iteration: " << it << "'\n"
<< "pause" << endl;
cout << "Visualization paused. "
"Press <space> in the GLVis window to continue." << endl;
}
if (cdofs > max_dofs)
{
cout << "Reached the maximum number of dofs. Stop." << endl;
break;
}
// 19. Call the refiner to modify the mesh. The refiner calls the error
// estimator to obtain element errors, then it selects elements to be
// refined and finally it modifies the mesh. The Stop() method can be
// used to determine if a stopping criterion was met.
refiner.Apply(mesh);
if (refiner.Stop())
{
cout << "Stopping criterion satisfied. Stop." << endl;
break;
}
// 20. Update the space to reflect the new state of the mesh. Also,
// interpolate the solution x so that it lies in the new space but
// represents the same function. This saves solver iterations later
// since we'll have a good initial guess of x in the next step.
// Internally, FiniteElementSpace::Update() calculates an
// interpolation matrix which is then used by GridFunction::Update().
fespace.Update();
x.Update();
// 21. Inform also the bilinear and linear forms that the space has
// changed.
a.Update();
b.Update();
}
{
ofstream mesh_ref_out("ex22_reference.mesh");
mesh_ref_out.precision(16);
mesh.Print(mesh_ref_out);
ofstream mesh_out("ex22_deformed.mesh");
mesh_out.precision(16);
GridFunction nodes(&fespace), *nodes_p = &nodes;
mesh.GetNodes(nodes);
nodes += x;
int own_nodes = 0;
mesh.SwapNodes(nodes_p, own_nodes);
mesh.Print(mesh_out);
mesh.SwapNodes(nodes_p, own_nodes);
ofstream x_out("ex22_displacement.sol");
x_out.precision(16);
x.Save(x_out);
}
return 0;
}
+366
View File
@@ -0,0 +1,366 @@
// MFEM Example 22
//
// Compile with: make ex22p
//
// Sample runs: mpirun -np 4 ex22p
// mpirun -np 4 ex22p -o 3
// mpirun -np 4 ex22p -m ../data/beam-quad.mesh
// mpirun -np 4 ex22p -m ../data/beam-quad.mesh -o 3
// mpirun -np 4 ex22p -m ../data/beam-tet.mesh
// mpirun -np 4 ex22p -m ../data/beam-tet.mesh -o 2
// mpirun -np 4 ex22p -m ../data/beam-hex.mesh
// mpirun -np 4 ex22p -m ../data/beam-hex.mesh -o 2
//
// Description: This is a version of Example 2p with a simple adaptive mesh
// refinement loop. The problem being solved is again the linear
// elasticity describing a multi-material cantilever beam.
// The problem is solved on a sequence of meshes which
// are locally refined in a conforming (triangles, tetrahedrons)
// or non-conforming (quadrilaterals, hexahedra) manner according
// to a simple ZZ error estimator.
//
// The example demonstrates MFEM's capability to work with both
// conforming and nonconforming refinements, in 2D and 3D, on
// linear and curved meshes. Interpolation of functions from
// coarse to fine meshes, as well as persistent GLVis
// visualization are also illustrated.
//
// We recommend viewing Examples 2p and 6p before viewing this
// example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 0. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// 1. Parse command-line options.
const char *mesh_file = "../data/beam-tri.mesh";
int serial_ref_levels = 0;
int order = 1;
bool static_cond = false;
bool visualization = 1;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&serial_ref_levels, "-rs", "--refine-serial",
"Number of uniform serial refinements (before parallel"
" partitioning)");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
MPI_Finalize();
return 1;
}
if (myid == 0)
{
args.PrintOptions(cout);
}
// 2. Read the mesh from the given mesh file. We can handle triangular,
// quadrilateral, tetrahedral, and hexahedral meshes with the same code.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
MFEM_VERIFY(mesh.SpaceDimension() == dim, "invalid mesh");
if (mesh.attributes.Max() < 2 || mesh.bdr_attributes.Max() < 2)
{
cerr << "\nInput mesh should have at least two materials and "
<< "two boundary attributes! (See schematic in ex2.cpp)\n"
<< endl;
MPI_Finalize();
return 3;
}
// 3. Refine the mesh before parallel partitioning. Since a NURBS mesh can
// currently only be refined uniformly, we need to convert it to a
// piecewise-polynomial curved mesh. First we refine the NURBS mesh a bit
// more and then project the curvature to quadratic Nodes.
if (mesh.NURBSext && serial_ref_levels == 0)
{
serial_ref_levels = 2;
}
for (int i = 0; i < serial_ref_levels; i++)
{
mesh.UniformRefinement();
}
if (mesh.NURBSext)
{
mesh.SetCurvature(2);
}
mesh.EnsureNCMesh();
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
// 4. Define a finite element space on the mesh. The polynomial order is
// one (linear) by default, but this can be changed on the command line.
H1_FECollection fec(order, dim);
ParFiniteElementSpace fespace(&pmesh, &fec, dim);
// 5. As in Example 2, we set up the linear form b(.) which corresponds to
// the right-hand side of the FEM linear system. In this case, b_i equals
// the boundary integral of f*phi_i where f represents a "pull down"
// force on the Neumann part of the boundary and phi_i are the basis
// functions in the finite element fespace. The force is defined by the
// VectorArrayCoefficient object f, which is a vector of Coefficient
// objects. The fact that f is non-zero on boundary attribute 2 is
// indicated by the use of piece-wise constants coefficient for its last
// component. We don't assemble the discrete problem yet, this will be
// done in the main loop.
VectorArrayCoefficient f(dim);
for (int i = 0; i < dim-1; i++)
{
f.Set(i, new ConstantCoefficient(0.0));
}
{
Vector pull_force(pmesh.bdr_attributes.Max());
pull_force = 0.0;
pull_force(1) = -1.0e-2;
f.Set(dim-1, new PWConstCoefficient(pull_force));
}
ParLinearForm b(&fespace);
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
// 6. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the linear elasticity integrator with piece-wise
// constants coefficient lambda and mu.
Vector lambda(pmesh.attributes.Max());
lambda = 1.0;
lambda(0) = lambda(1)*50;
PWConstCoefficient lambda_func(lambda);
Vector mu(pmesh.attributes.Max());
mu = 1.0;
mu(0) = mu(1)*50;
PWConstCoefficient mu_func(mu);
ParBilinearForm a(&fespace);
BilinearFormIntegrator *integ =
new ElasticityIntegrator(lambda_func,mu_func);
a.AddDomainIntegrator(integ);
if (static_cond) { a.EnableStaticCondensation(); }
// 7. The solution vector x and the associated finite element grid function
// will be maintained over the AMR iterations. We initialize it to zero.
Vector zero_vec(dim);
zero_vec = 0.0;
VectorConstantCoefficient zero_vec_coeff(zero_vec);
ParGridFunction x(&fespace);
x = 0.0;
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
// In this example, the boundary conditions are defined by marking only
// boundary attribute 1 from the mesh as essential and converting it to a
// list of true dofs. The conversion to true dofs will be done in the
// main loop.
Array<int> ess_bdr(pmesh.bdr_attributes.Max());
ess_bdr = 0;
ess_bdr[0] = 1;
// 9. GLVis visualization.
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock;
// 10. Set up an error estimator. Here we use the Zienkiewicz-Zhu estimator
// that uses the ComputeElementFlux method of the ElasticityIntegrator to
// recover a smoothed flux (stress) that is subtracted from the element
// flux to get an error indicator. We need to supply the space for the
// smoothed flux: an (H1)^tdim (i.e., vector-valued) space is used here.
// Here, tdim represents the number of components for a symmetric (dim x
// dim) tensor.
const int tdim = dim*(dim+1)/2;
L2_FECollection flux_fec(order, dim);
ParFiniteElementSpace flux_fespace(&pmesh, &flux_fec, tdim);
ParFiniteElementSpace smooth_flux_fespace(&pmesh, &fec, tdim);
L2ZienkiewiczZhuEstimator estimator(*integ, x, flux_fespace,
smooth_flux_fespace);
// 11. A refiner selects and refines elements based on a refinement strategy.
// The strategy here is to refine elements with errors larger than a
// fraction of the maximum element error. Other strategies are possible.
// The refiner will call the given error estimator.
ThresholdRefiner refiner(estimator);
refiner.SetTotalErrorFraction(0.7);
// 12. The main AMR loop. In each iteration we solve the problem on the
// current mesh, visualize the solution, and refine the mesh.
const int max_dofs = 50000;
const int max_amr_itr = 20;
for (int it = 0; it <= max_amr_itr; it++)
{
HYPRE_Int global_dofs = fespace.GlobalTrueVSize();
if (myid == 0)
{
cout << "\nAMR iteration " << it << endl;
cout << "Number of unknowns: " << global_dofs << endl;
}
// 13. Assemble the stiffness matrix and the right-hand side.
a.Assemble();
b.Assemble();
// 14. Set Dirichlet boundary values in the GridFunction x.
// Determine the list of Dirichlet true DOFs in the linear system.
Array<int> ess_tdof_list;
x.ProjectBdrCoefficient(zero_vec_coeff, ess_bdr);
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
// 15. Create the linear system: eliminate boundary conditions, constrain
// hanging nodes and possibly apply other transformations. The system
// will be solved for true (unconstrained) DOFs only.
HypreParMatrix A;
Vector B, X;
const int copy_interior = 1;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
// 16. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
// preconditioner from hypre.
HypreBoomerAMG amg;
amg.SetPrintLevel(0);
// amg.SetSystemsOptions(dim); // optional
CGSolver pcg(A.GetComm());
pcg.SetPreconditioner(amg);
pcg.SetOperator(A);
pcg.SetRelTol(1e-6);
pcg.SetMaxIter(500);
pcg.SetPrintLevel(3); // print the first and the last iterations only
pcg.Mult(B, X);
// 17. After solving the linear system, reconstruct the solution as a
// finite element GridFunction. Constrained nodes are interpolated
// from true DOFs (it may therefore happen that x.Size() >= X.Size()).
a.RecoverFEMSolution(X, b, x);
// 18. Send solution by socket to the GLVis server.
if (visualization && it == 0)
{
sol_sock.open(vishost, visport);
sol_sock.precision(8);
}
if (visualization && sol_sock.good())
{
GridFunction nodes(&fespace), *nodes_p = &nodes;
pmesh.GetNodes(nodes);
nodes += x;
int own_nodes = 0;
pmesh.SwapNodes(nodes_p, own_nodes);
x.Neg(); // visualize the backward displacement
sol_sock << "parallel " << num_procs << ' ' << myid << '\n';
sol_sock << "solution\n" << pmesh << x << flush;
x.Neg();
pmesh.SwapNodes(nodes_p, own_nodes);
if (it == 0)
{
sol_sock << "keys '" << ((dim == 2) ? "Rjl" : "") << "m'" << endl;
}
sol_sock << "window_title 'AMR iteration: " << it << "'\n"
<< "pause" << endl;
if (myid == 0)
{
cout << "Visualization paused. "
"Press <space> in the GLVis window to continue." << endl;
}
}
if (global_dofs > max_dofs)
{
if (myid == 0)
{
cout << "Reached the maximum number of dofs. Stop." << endl;
}
break;
}
// 19. Call the refiner to modify the mesh. The refiner calls the error
// estimator to obtain element errors, then it selects elements to be
// refined and finally it modifies the mesh. The Stop() method can be
// used to determine if a stopping criterion was met.
refiner.Apply(pmesh);
if (refiner.Stop())
{
if (myid == 0)
{
cout << "Stopping criterion satisfied. Stop." << endl;
}
break;
}
// 20. Update the space to reflect the new state of the mesh. Also,
// interpolate the solution x so that it lies in the new space but
// represents the same function. This saves solver iterations later
// since we'll have a good initial guess of x in the next step.
// Internally, FiniteElementSpace::Update() calculates an
// interpolation matrix which is then used by GridFunction::Update().
fespace.Update();
x.Update();
// 21. Load balance the mesh, and update the space and solution. Currently
// available only for nonconforming meshes.
if (pmesh.Nonconforming())
{
pmesh.Rebalance();
// Update the space and the GridFunction. This time the update matrix
// redistributes the GridFunction among the processors.
fespace.Update();
x.Update();
}
// 22. Inform also the bilinear and linear forms that the space has
// changed.
a.Update();
b.Update();
}
{
ostringstream mref_name, mesh_name, sol_name;
mref_name << "ex22p_reference_mesh." << setfill('0') << setw(6) << myid;
mesh_name << "ex22p_deformed_mesh." << setfill('0') << setw(6) << myid;
sol_name << "ex22p_displacement." << setfill('0') << setw(6) << myid;
ofstream mesh_ref_out(mref_name.str().c_str());
mesh_ref_out.precision(16);
pmesh.Print(mesh_ref_out);
ofstream mesh_out(mesh_name.str().c_str());
mesh_out.precision(16);
GridFunction nodes(&fespace), *nodes_p = &nodes;
pmesh.GetNodes(nodes);
nodes += x;
int own_nodes = 0;
pmesh.SwapNodes(nodes_p, own_nodes);
pmesh.Print(mesh_out);
pmesh.SwapNodes(nodes_p, own_nodes);
ofstream x_out(sol_name.str().c_str());
x_out.precision(16);
x.Save(x_out);
}
MPI_Finalize();
return 0;
}
+1
View File
@@ -6,6 +6,7 @@
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh
// mpirun -np 4 ex2p -m ../data/beam-tet.mesh
// mpirun -np 4 ex2p -m ../data/beam-hex.mesh
// mpirun -np 4 ex2p -m ../data/beam-wedge.mesh
// mpirun -np 4 ex2p -m ../data/beam-tri.mesh -o 2 -sys
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh -o 3 -elast
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh -o 3 -sc
+1
View File
@@ -7,6 +7,7 @@
// ex3 -m ../data/beam-tet.mesh
// ex3 -m ../data/beam-hex.mesh
// ex3 -m ../data/escher.mesh
// ex3 -m ../data/escher.mesh -o 2
// ex3 -m ../data/fichera.mesh
// ex3 -m ../data/fichera-q2.vtk
// ex3 -m ../data/fichera-q3.mesh
+1
View File
@@ -7,6 +7,7 @@
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
// mpirun -np 4 ex3p -m ../data/escher.mesh
// mpirun -np 4 ex3p -m ../data/escher.mesh -o 2
// mpirun -np 4 ex3p -m ../data/fichera.mesh
// mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
// mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
+1 -1
View File
@@ -20,7 +20,7 @@
// equation -Delta u = 1 with homogeneous Dirichlet boundary
// conditions. The problem is solved on a sequence of meshes which
// are locally refined in a conforming (triangles, tetrahedrons)
// or non-conforming (quadrilateral, hexahedrons) manner according
// or non-conforming (quadrilaterals, hexahedra) manner according
// to a simple ZZ error estimator.
//
// The example demonstrates MFEM's capability to work with both
+1 -1
View File
@@ -20,7 +20,7 @@
// equation -Delta u = 1 with homogeneous Dirichlet boundary
// conditions. The problem is solved on a sequence of meshes which
// are locally refined in a conforming (triangles, tetrahedrons)
// or non-conforming (quadrilateral, hexahedrons) manner according
// or non-conforming (quadrilaterals, hexahedra) manner according
// to a simple ZZ error estimator.
//
// The example demonstrates MFEM's capability to work with both
+2
View File
@@ -4,8 +4,10 @@
//
// Sample runs: ex8 -m ../data/square-disc.mesh
// ex8 -m ../data/star.mesh
// ex8 -m ../data/star-mixed.mesh
// ex8 -m ../data/escher.mesh
// ex8 -m ../data/fichera.mesh
// ex8 -m ../data/fichera-mixed.mesh
// ex8 -m ../data/square-disc-p2.vtk
// ex8 -m ../data/square-disc-p3.mesh
// ex8 -m ../data/star-surf.mesh -o 2
+6
View File
@@ -4,8 +4,10 @@
//
// Sample runs: mpirun -np 4 ex8p -m ../data/square-disc.mesh
// mpirun -np 4 ex8p -m ../data/star.mesh
// mpirun -np 4 ex8p -m ../data/star-mixed.mesh
// mpirun -np 4 ex8p -m ../data/escher.mesh
// mpirun -np 4 ex8p -m ../data/fichera.mesh
// mpirun -np 4 ex8p -m ../data/fichera-mixed.mesh
// mpirun -np 4 ex8p -m ../data/square-disc-p2.vtk
// mpirun -np 4 ex8p -m ../data/square-disc-p3.mesh
// mpirun -np 4 ex8p -m ../data/star-surf.mesh -o 2
@@ -123,9 +125,13 @@ int main(int argc, char *argv[])
test_order++;
}
if (test_order < trial_order)
{
if (myid == 0)
{
cerr << "Warning, test space not enriched enough to handle primal"
<< " trial space\n";
}
}
FiniteElementCollection *x0_fec, *xhat_fec, *test_fec;
+1
View File
@@ -10,6 +10,7 @@
// ex9 -m ../data/periodic-hexagon.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex9 -m ../data/amr-quad.mesh -p 1 -r 2 -dt 0.002 -tf 9
// ex9 -m ../data/star-q3.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex9 -m ../data/star-mixed.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex9 -m ../data/disc-nurbs.mesh -p 1 -r 3 -dt 0.005 -tf 9
// ex9 -m ../data/disc-nurbs.mesh -p 2 -r 3 -dt 0.005 -tf 9
// ex9 -m ../data/periodic-square.mesh -p 3 -r 4 -dt 0.0025 -tf 9 -vs 20
+1
View File
@@ -10,6 +10,7 @@
// mpirun -np 4 ex9p -m ../data/periodic-hexagon.mesh -p 1 -dt 0.005 -tf 9
// mpirun -np 4 ex9p -m ../data/amr-quad.mesh -p 1 -rp 1 -dt 0.002 -tf 9
// mpirun -np 4 ex9p -m ../data/star-q3.mesh -p 1 -rp 1 -dt 0.004 -tf 9
// mpirun -np 4 ex9p -m ../data/star-mixed.mesh -p 1 -rp 1 -dt 0.004 -tf 9
// mpirun -np 4 ex9p -m ../data/disc-nurbs.mesh -p 1 -rp 1 -dt 0.005 -tf 9
// mpirun -np 4 ex9p -m ../data/disc-nurbs.mesh -p 2 -rp 1 -dt 0.005 -tf 9
// mpirun -np 4 ex9p -m ../data/periodic-square.mesh -p 3 -rp 2 -dt 0.0025 -tf 9 -vs 20
+4 -2
View File
@@ -22,9 +22,9 @@ MFEM_LIB_FILE = mfem_is_not_built
-include $(CONFIG_MK)
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 ex17\
ex18 ex19
ex18 ex19 ex20 ex22
PAR_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p ex12p\
ex13p ex14p ex15p ex16p ex17p ex18p ex19p
ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex22p
ifeq ($(MFEM_USE_MPI),NO)
EXAMPLES = $(SEQ_EXAMPLES)
@@ -118,3 +118,5 @@ clean-exec:
@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 ex22*.mesh ex22*.sol ex22p_*.*
+1 -1
View File
@@ -96,7 +96,7 @@ foreach(TEST_OPTIONS_VAR
# All PETSC tests are parallel.
if (MFEM_USE_MPI)
add_test(NAME ${TEST_NAME_FULL}_np=4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:${TEST_NAME}> ${TEST_OPTIONS}
${MPIEXEC_POSTFLAGS})
+2 -2
View File
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
// 2b. We initialize PETSc
if (use_petsc)
{
PetscInitialize(NULL,NULL,petscrc_file,NULL);
MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL);
}
// 3. Read the serial mesh from the given mesh file on all processors. We can
@@ -446,7 +446,7 @@ int main(int argc, char *argv[])
delete oper;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
+2 -3
View File
@@ -123,7 +123,7 @@ int main(int argc, char *argv[])
}
// 2b. We initialize PETSc
PetscInitialize(NULL,NULL,petscrc_file,NULL);
MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL);
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
@@ -266,7 +266,6 @@ int main(int argc, char *argv[])
if (visualization && petscmonitor)
{
pcg->SetMonitor(&mymon);
pcg->SetPrintLevel(4);
pcg->iterative_mode = true;
X.Randomize();
}
@@ -314,7 +313,7 @@ int main(int argc, char *argv[])
delete pmesh;
// We finalize PETSc
PetscFinalize();
MFEMFinalizePetsc();
MPI_Finalize();
+2 -2
View File
@@ -101,7 +101,7 @@ int main(int argc, char *argv[])
}
// 2b. We initialize PETSc
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
@@ -359,7 +359,7 @@ int main(int argc, char *argv[])
delete pmesh;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
+2 -2
View File
@@ -96,7 +96,7 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
// 2b. We initialize PETSc
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
kappa = freq * M_PI;
// 3. Read the (serial) mesh from the given mesh file on all processors. We
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
delete pmesh;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
+2 -2
View File
@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
// 2b. We initialize PETSc
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
kappa = freq * M_PI;
// 3. Read the (serial) mesh from the given mesh file on all processors. We
@@ -330,7 +330,7 @@ int main(int argc, char *argv[])
delete pmesh;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
+2 -2
View File
@@ -105,7 +105,7 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
// 2b. We initialize PETSc
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
@@ -544,7 +544,7 @@ int main(int argc, char *argv[])
delete pmesh;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
+3 -3
View File
@@ -12,7 +12,7 @@
// equation -Delta u = 1 with homogeneous Dirichlet boundary
// conditions. The problem is solved on a sequence of meshes which
// are locally refined in a conforming (triangles, tetrahedrons)
// or non-conforming (quadrilateral, hexahedrons) manner according
// or non-conforming (quadrilaterals, hexahedra) manner according
// to a simple ZZ error estimator.
//
// The example demonstrates MFEM's capability to work with both
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
// 2b. We initialize PETSc
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
@@ -315,7 +315,7 @@ int main(int argc, char *argv[])
}
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
return 0;
+2 -2
View File
@@ -248,7 +248,7 @@ int main(int argc, char *argv[])
{
// When using PETSc, we just create the ODE solver. We use command line
// customization to select a specific solver.
PetscInitialize(NULL, NULL, petscrc_file, NULL);
MFEMInitializePetsc(NULL, NULL, petscrc_file, NULL);
ode_solver = pode_solver = new PetscODESolver(MPI_COMM_WORLD);
}
@@ -481,7 +481,7 @@ int main(int argc, char *argv[])
delete pmon;
// We finalize PETSc
if (use_petsc) { PetscFinalize(); }
if (use_petsc) { MFEMFinalizePetsc(); }
MPI_Finalize();
return 0;
+2 -1
View File
@@ -40,7 +40,8 @@ add_mfem_examples(PUMI_EXAMPLES_SRCS ${PFX} "" test_pumi)
# Command line options for the tests.
# TODO...
# Set the number of processors for the parallel examples.
# Set the number of processors for the parallel examples. The value of
# MFEM_MPI_NP is ignored.
set(EX1_TEST_NP 1)
set(EX1P_TEST_NP 8)
set(EX2_TEST_NP 1)
+3 -3
View File
@@ -209,15 +209,15 @@ int main(int argc, char *argv[])
Transform(Geometries.GetCenter(mesh->GetElementBaseGeometry(el)),cent);
if (cent(0) <= -0.05)
{
mesh->SetAttribute(el , 1);
mesh->SetAttribute(el, 1);
}
else if (cent(0) >= 0.05)
{
mesh->SetAttribute(el , 2);
mesh->SetAttribute(el, 2);
}
else
{
mesh->SetAttribute(el , 3);
mesh->SetAttribute(el, 3);
}
}
mesh->SetAttributes();
+1 -1
View File
@@ -68,7 +68,7 @@ foreach(SRC_FILE ${SUNDIALS_EXAMPLES_SRCS})
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
else()
add_test(NAME ${TEST_NAME}_np=4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
${MPIEXEC_POSTFLAGS})
+31 -32
View File
@@ -79,9 +79,6 @@ BilinearForm::BilinearForm (FiniteElementSpace * f)
BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
: Matrix (f->GetVSize())
{
int i;
Array<BilinearFormIntegrator*> *bfi;
fes = f;
sequence = f->GetSequence();
mat_e = NULL;
@@ -92,33 +89,16 @@ BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
precompute_sparsity = ps;
diag_policy = DIAG_KEEP;
bfi = bf->GetDBFI();
dbfi.SetSize (bfi->Size());
for (i = 0; i < bfi->Size(); i++)
{
dbfi[i] = (*bfi)[i];
}
// Copy the pointers to the integrators
dbfi = bf->dbfi;
bfi = bf->GetBBFI();
bbfi.SetSize (bfi->Size());
for (i = 0; i < bfi->Size(); i++)
{
bbfi[i] = (*bfi)[i];
}
bbfi = bf->bbfi;
bbfi_marker = bf->bbfi_marker;
bfi = bf->GetFBFI();
fbfi.SetSize (bfi->Size());
for (i = 0; i < bfi->Size(); i++)
{
fbfi[i] = (*bfi)[i];
}
fbfi = bf->fbfi;
bfi = bf->GetBFBFI();
bfbfi.SetSize (bfi->Size());
for (i = 0; i < bfi->Size(); i++)
{
bfbfi[i] = (*bfi)[i];
}
bfbfi = bf->bfbfi;
bfbfi_marker = bf->bfbfi_marker;
AllocMat();
}
@@ -941,6 +921,23 @@ MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
trial_fes = tr_fes;
test_fes = te_fes;
mat = NULL;
extern_bfs = 0;
}
MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
FiniteElementSpace *te_fes,
MixedBilinearForm * mbf)
: Matrix(te_fes->GetVSize(), tr_fes->GetVSize())
{
trial_fes = tr_fes;
test_fes = te_fes;
mat = NULL;
extern_bfs = 1;
// Copy the pointers to the integrators
dom = mbf->dom;
bdr = mbf->bdr;
skt = mbf->skt;
}
double & MixedBilinearForm::Elem (int i, int j)
@@ -1177,12 +1174,14 @@ void MixedBilinearForm::Update()
MixedBilinearForm::~MixedBilinearForm()
{
int i;
if (mat) { delete mat; }
for (i = 0; i < dom.Size(); i++) { delete dom[i]; }
for (i = 0; i < bdr.Size(); i++) { delete bdr[i]; }
for (i = 0; i < skt.Size(); i++) { delete skt[i]; }
if (!extern_bfs)
{
int i;
for (i = 0; i < dom.Size(); i++) { delete dom[i]; }
for (i = 0; i < bdr.Size(); i++) { delete bdr[i]; }
for (i = 0; i < skt.Size(); i++) { delete skt[i]; }
}
}
+133 -40
View File
@@ -29,19 +29,21 @@ namespace mfem
class BilinearForm : public Matrix
{
protected:
/// Sparse matrix to be associated with the form.
/// Sparse matrix to be associated with the form. Owned.
SparseMatrix *mat;
/// Matrix used to eliminate b.c.
/// Matrix used to eliminate b.c. Owned.
SparseMatrix *mat_e;
/// FE space on which the form lives.
/// FE space on which the form lives. Not owned.
FiniteElementSpace *fes;
/// Indicates the Mesh::sequence corresponding to the current state of the
/// BilinearForm.
long sequence;
/** @brief Indicates the BilinearFormIntegrator%s stored in #dbfi, #bbfi,
#fbfi, and #bfbfi are owned by another BilinearForm. */
int extern_bfs;
/// Set of Domain Integrators to be applied.
@@ -49,22 +51,22 @@ protected:
/// Set of Boundary Integrators to be applied.
Array<BilinearFormIntegrator*> bbfi;
Array<Array<int>*> bbfi_marker;
Array<Array<int>*> bbfi_marker; ///< Entries are not owned.
/// Set of interior face Integrators to be applied.
Array<BilinearFormIntegrator*> fbfi;
/// Set of boundary face Integrators to be applied.
Array<BilinearFormIntegrator*> bfbfi;
Array<Array<int>*> bfbfi_marker;
Array<Array<int>*> bfbfi_marker; ///< Entries are not owned.
DenseMatrix elemmat;
Array<int> vdofs;
DenseTensor *element_matrices;
DenseTensor *element_matrices; ///< Owned.
StaticCondensation *static_cond;
Hybridization *hybridization;
StaticCondensation *static_cond; ///< Owned.
Hybridization *hybridization; ///< Owned.
/**
* This member allows one to specify what should be done
@@ -89,10 +91,28 @@ protected:
diag_policy = DIAG_KEEP;
}
private:
/// Copy construction is not supported; body is undefined.
BilinearForm(const BilinearForm &);
/// Copy assignment is not supported; body is undefined.
BilinearForm &operator=(const BilinearForm &);
public:
/// Creates bilinear form associated with FE space @a *f.
/** The pointer @a f is not owned by the newly constructed object. */
BilinearForm(FiniteElementSpace *f);
/** @brief Create a BilinearForm on the FiniteElementSpace @a f, using the
same integrators as the BilinearForm @a bf.
The pointer @a f is not owned by the newly constructed object.
The integrators in @a bf are copied as pointers and they are not owned by
the newly constructed BilinearForm.
The optional parameter @a ps is used to initialize the internal flag
#precompute_sparsity, see UsePrecomputedSparsity() for details. */
BilinearForm(FiniteElementSpace *f, BilinearForm *bf, int ps = 0);
/// Get the size of the BilinearForm as a square matrix.
@@ -143,13 +163,25 @@ public:
finalized) and the entries are initialized with zeros. */
void AllocateMatrix() { if (mat == NULL) { AllocMat(); } }
/// Access all integrators added with AddDomainIntegrator().
Array<BilinearFormIntegrator*> *GetDBFI() { return &dbfi; }
/// Access all integrators added with AddBoundaryIntegrator().
Array<BilinearFormIntegrator*> *GetBBFI() { return &bbfi; }
/** @brief Access all boundary markers added with AddBoundaryIntegrator().
If no marker was specified when the integrator was added, the
corresponding pointer (to Array<int>) will be NULL. */
Array<Array<int>*> *GetBBFI_Marker() { return &bbfi_marker; }
/// Access all integrators added with AddInteriorFaceIntegrator().
Array<BilinearFormIntegrator*> *GetFBFI() { return &fbfi; }
/// Access all integrators added with AddBdrFaceIntegrator().
Array<BilinearFormIntegrator*> *GetBFBFI() { return &bfbfi; }
/** @brief Access all boundary markers added with AddBdrFaceIntegrator().
If no marker was specified when the integrator was added, the
corresponding pointer (to Array<int>) will be NULL. */
Array<Array<int>*> *GetBFBFI_Marker() { return &bfbfi_marker; }
const double &operator()(int i, int j) { return (*mat)(i,j); }
@@ -175,10 +207,10 @@ public:
const double a = 1.0) const
{ mat->AddMultTranspose(x, y, a); }
void FullAddMultTranspose (const Vector & x, Vector & y) const
void FullAddMultTranspose(const Vector & x, Vector & y) const
{ mat->AddMultTranspose(x, y); mat_e->AddMultTranspose(x, y); }
virtual void MultTranspose (const Vector & x, Vector & y) const
virtual void MultTranspose(const Vector & x, Vector & y) const
{ y = 0.0; AddMultTranspose (x, y); }
double InnerProduct(const Vector &x, const Vector &y) const
@@ -215,25 +247,31 @@ public:
return *mat_e;
}
/// Adds new Domain Integrator.
/// Adds new Domain Integrator. Assumes ownership of @a bfi.
void AddDomainIntegrator(BilinearFormIntegrator *bfi);
/// Adds new Boundary Integrator.
/// Adds new Boundary Integrator. Assumes ownership of @a bfi.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi);
/** @brief Adds new Boundary Integrator, restricted to specific boundary
attributes. */
void AddBoundaryIntegrator(BilinearFormIntegrator * bfi,
attributes.
Assumes ownership of @a bfi. The array @a bdr_marker is stored internally
as a pointer to the given Array<int> object. */
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi,
Array<int> &bdr_marker);
/// Adds new interior Face Integrator.
/// Adds new interior Face Integrator. Assumes ownership of @a bfi.
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi);
/// Adds new boundary Face Integrator.
/// Adds new boundary Face Integrator. Assumes ownership of @a bfi.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi);
/** @brief Adds new boundary Face Integrator, restricted to specific boundary
attributes. */
attributes.
Assumes ownership of @a bfi. The array @a bdr_marker is stored internally
as a pointer to the given Array<int> object. */
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi,
Array<int> &bdr_marker);
@@ -393,36 +431,68 @@ public:
class MixedBilinearForm : public Matrix
{
protected:
SparseMatrix *mat;
SparseMatrix *mat; ///< Owned.
FiniteElementSpace *trial_fes, *test_fes;
FiniteElementSpace *trial_fes, ///< Not owned
*test_fes; ///< Not owned
/** @brief Indicates the BilinearFormIntegrator%s stored in #dom, #bdr, and
#skt are owned by another MixedBilinearForm. */
int extern_bfs;
/// Domain integrators.
Array<BilinearFormIntegrator*> dom;
/// Boundary integrators.
Array<BilinearFormIntegrator*> bdr;
Array<BilinearFormIntegrator*> skt; // trace face integrators
/// Trace face (skeleton) integrators.
Array<BilinearFormIntegrator*> skt;
private:
/// Copy construction is not supported; body is undefined.
MixedBilinearForm(const MixedBilinearForm &);
/// Copy assignment is not supported; body is undefined.
MixedBilinearForm &operator=(const MixedBilinearForm &);
public:
MixedBilinearForm (FiniteElementSpace *tr_fes,
FiniteElementSpace *te_fes);
/** @brief Construct a MixedBilinearForm on the given trial, @a tr_fes, and
test, @a te_fes, FiniteElementSpace%s. */
/** The pointers @a tr_fes and @a te_fes are not owned by the newly
constructed object. */
MixedBilinearForm(FiniteElementSpace *tr_fes,
FiniteElementSpace *te_fes);
virtual double& Elem (int i, int j);
/** @brief Create a MixedBilinearForm on the given trial, @a tr_fes, and
test, @a te_fes, FiniteElementSpace%s, using the same integrators as the
MixedBilinearForm @a mbf.
virtual const double& Elem (int i, int j) const;
The pointers @a tr_fes and @a te_fes are not owned by the newly
constructed object.
virtual void Mult (const Vector & x, Vector & y) const;
The integrators in @a mbf are copied as pointers and they are not owned
by the newly constructed MixedBilinearForm. */
MixedBilinearForm(FiniteElementSpace *tr_fes,
FiniteElementSpace *te_fes,
MixedBilinearForm *mbf);
virtual void AddMult (const Vector & x, Vector & y,
const double a = 1.0) const;
virtual double &Elem(int i, int j);
virtual void AddMultTranspose (const Vector & x, Vector & y,
const double a = 1.0) const;
virtual const double &Elem(int i, int j) const;
virtual void MultTranspose (const Vector & x, Vector & y) const
virtual void Mult(const Vector & x, Vector & y) const;
virtual void AddMult(const Vector & x, Vector & y,
const double a = 1.0) const;
virtual void AddMultTranspose(const Vector & x, Vector & y,
const double a = 1.0) const;
virtual void MultTranspose(const Vector & x, Vector & y) const
{ y = 0.0; AddMultTranspose (x, y); }
virtual MatrixInverse * Inverse() const;
virtual MatrixInverse *Inverse() const;
virtual void Finalize (int skip_zeros = 1);
virtual void Finalize(int skip_zeros = 1);
/** Extract the associated matrix as SparseMatrix blocks. The number of
block rows and columns is given by the vector dimensions (vdim) of the
@@ -433,24 +503,31 @@ public:
SparseMatrix &SpMat() { return *mat; }
SparseMatrix *LoseMat() { SparseMatrix *tmp = mat; mat = NULL; return tmp; }
void AddDomainIntegrator (BilinearFormIntegrator * bfi);
/// Adds a domain integrator. Assumes ownership of @a bfi.
void AddDomainIntegrator(BilinearFormIntegrator *bfi);
void AddBoundaryIntegrator (BilinearFormIntegrator * bfi);
/// Adds a boundary integrator. Assumes ownership of @a bfi.
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi);
/** Add a trace face integrator. This type of integrator assembles terms
over all faces of the mesh using the face FE from the trial space and the
two adjacent volume FEs from the test space. */
void AddTraceFaceIntegrator (BilinearFormIntegrator * bfi);
/** @brief Add a trace face integrator. Assumes ownership of @a bfi.
This type of integrator assembles terms over all faces of the mesh using
the face FE from the trial space and the two adjacent volume FEs from the
test space. */
void AddTraceFaceIntegrator(BilinearFormIntegrator *bfi);
/// Access all integrators added with AddDomainIntegrator().
Array<BilinearFormIntegrator*> *GetDBFI() { return &dom; }
/// Access all integrators added with AddBoundaryIntegrator().
Array<BilinearFormIntegrator*> *GetBBFI() { return &bdr; }
/// Access all integrators added with AddTraceFaceIntegrator().
Array<BilinearFormIntegrator*> *GetTFBFI() { return &skt; }
void operator= (const double a) { *mat = a; }
void operator=(const double a) { *mat = a; }
void Assemble (int skip_zeros = 1);
void Assemble(int skip_zeros = 1);
/** For partially conforming trial and/or test FE spaces, complete the
assembly process by performing A := P2^t A P1 where A is the internal
@@ -505,19 +582,35 @@ public:
*/
class DiscreteLinearOperator : public MixedBilinearForm
{
private:
/// Copy construction is not supported; body is undefined.
DiscreteLinearOperator(const DiscreteLinearOperator &);
/// Copy assignment is not supported; body is undefined.
DiscreteLinearOperator &operator=(const DiscreteLinearOperator &);
public:
/** @brief Construct a DiscreteLinearOperator on the given
FiniteElementSpace%s @a domain_fes and @a range_fes. */
/** The pointers @a domain_fes and @a range_fes are not owned by the newly
constructed object. */
DiscreteLinearOperator(FiniteElementSpace *domain_fes,
FiniteElementSpace *range_fes)
: MixedBilinearForm(domain_fes, range_fes) { }
/// Adds a domain interpolator. Assumes ownership of @a di.
void AddDomainInterpolator(DiscreteInterpolator *di)
{ AddDomainIntegrator(di); }
/// Adds a trace face interpolator. Assumes ownership of @a di.
void AddTraceFaceInterpolator(DiscreteInterpolator *di)
{ AddTraceFaceIntegrator(di); }
/// Access all interpolators added with AddDomainInterpolator().
Array<BilinearFormIntegrator*> *GetDI() { return &dom; }
/** @brief Construct the internal matrix representation of the discrete
linear operator. */
virtual void Assemble(int skip_zeros = 1);
};
+235 -55
View File
@@ -962,8 +962,8 @@ void VectorMassIntegrator::AssembleElementMatrix
double norm;
// Get vdim from VQ, MQ, or the space dimension
int vdim = (VQ) ? (VQ -> GetVDim()) : ((MQ) ? (MQ -> GetVDim()) : spaceDim);
// If vdim is not set, set it to the space dimension
vdim = (vdim == -1) ? spaceDim : vdim;
elmat.SetSize(nd*vdim);
shape.SetSize(nd);
@@ -1041,13 +1041,11 @@ void VectorMassIntegrator::AssembleElementMatrix2(
{
int tr_nd = trial_fe.GetDof();
int te_nd = test_fe.GetDof();
int dim = trial_fe.GetDim();
int vdim;
double norm;
// Get vdim from the ElementTransformation Trans ?
vdim = (VQ) ? (VQ -> GetVDim()) : ((MQ) ? (MQ -> GetVDim()) : (dim));
// If vdim is not set, set it to the space dimension
vdim = (vdim == -1) ? Trans.GetSpaceDim() : vdim;
elmat.SetSize(te_nd*vdim, tr_nd*vdim);
shape.SetSize(tr_nd);
@@ -2180,11 +2178,12 @@ void ElasticityIntegrator::AssembleElementMatrix(
int dim = el.GetDim();
double w, L, M;
MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
#ifdef MFEM_THREAD_SAFE
DenseMatrix dshape(dof, dim), Jinv(dim), gshape(dof, dim), pelmat(dof);
DenseMatrix dshape(dof, dim), gshape(dof, dim), pelmat(dof);
Vector divshape(dim*dof);
#else
Jinv.SetSize(dim);
dshape.SetSize(dof, dim);
gshape.SetSize(dof, dim);
pelmat.SetSize(dof);
@@ -2210,8 +2209,7 @@ void ElasticityIntegrator::AssembleElementMatrix(
Trans.SetIntPoint(&ip);
w = ip.weight * Trans.Weight();
CalcInverse(Trans.Jacobian(), Jinv);
Mult(dshape, Jinv, gshape);
Mult(dshape, Trans.InverseJacobian(), gshape);
MultAAt(gshape, pelmat);
gshape.GradToDiv (divshape);
@@ -2246,14 +2244,184 @@ void ElasticityIntegrator::AssembleElementMatrix(
{
for (int k = 0; k < dof; k++)
for (int l = 0; l < dof; l++)
{
elmat(dof*i+k, dof*j+l) +=
(M * w) * gshape(k, j) * gshape(l, i);
// + (L * w) * gshape(k, i) * gshape(l, j)
}
}
}
}
}
void ElasticityIntegrator::ComputeElementFlux(
const mfem::FiniteElement &el, ElementTransformation &Trans,
Vector &u, const mfem::FiniteElement &fluxelem, Vector &flux,
int with_coef)
{
const int dof = el.GetDof();
const int dim = el.GetDim();
const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
double L, M;
MFEM_ASSERT(dim == 2 || dim == 3,
"dimension is not supported: dim = " << dim);
MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
MFEM_ASSERT(fluxelem.GetMapType() == FiniteElement::VALUE, "");
MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(&fluxelem), "");
#ifdef MFEM_THREAD_SAFE
DenseMatrix dshape(dof, dim);
#else
dshape.SetSize(dof, dim);
#endif
double gh_data[9], grad_data[9];
DenseMatrix gh(gh_data, dim, dim);
DenseMatrix grad(grad_data, dim, dim);
const IntegrationRule &ir = fluxelem.GetNodes();
const int fnd = ir.GetNPoints();
flux.SetSize(fnd * tdim);
DenseMatrix loc_data_mat(u.GetData(), dof, dim);
for (int i = 0; i < fnd; i++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
el.CalcDShape(ip, dshape);
MultAtB(loc_data_mat, dshape, gh);
Trans.SetIntPoint(&ip);
Mult(gh, Trans.InverseJacobian(), grad);
M = mu->Eval(Trans, ip);
if (lambda)
{
L = lambda->Eval(Trans, ip);
}
else
{
L = q_lambda * M;
M = q_mu * M;
}
// stress = 2*M*e(u) + L*tr(e(u))*I, where
// e(u) = (1/2)*(grad(u) + grad(u)^T)
const double M2 = 2.0*M;
if (dim == 2)
{
L *= (grad(0,0) + grad(1,1));
// order of the stress entries: s_xx, s_yy, s_xy
flux(i+fnd*0) = M2*grad(0,0) + L;
flux(i+fnd*1) = M2*grad(1,1) + L;
flux(i+fnd*2) = M*(grad(0,1) + grad(1,0));
}
else if (dim == 3)
{
L *= (grad(0,0) + grad(1,1) + grad(2,2));
// order of the stress entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
flux(i+fnd*0) = M2*grad(0,0) + L;
flux(i+fnd*1) = M2*grad(1,1) + L;
flux(i+fnd*2) = M2*grad(2,2) + L;
flux(i+fnd*3) = M*(grad(0,1) + grad(1,0));
flux(i+fnd*4) = M*(grad(0,2) + grad(2,0));
flux(i+fnd*5) = M*(grad(1,2) + grad(2,1));
}
}
}
double ElasticityIntegrator::ComputeFluxEnergy(const FiniteElement &fluxelem,
ElementTransformation &Trans,
Vector &flux, Vector *d_energy)
{
const int dof = fluxelem.GetDof();
const int dim = fluxelem.GetDim();
const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
double L, M;
// The MFEM_ASSERT constraints in ElasticityIntegrator::ComputeElementFlux
// are assumed here too.
MFEM_ASSERT(d_energy == NULL, "anisotropic estimates are not supported");
MFEM_ASSERT(flux.Size() == dof*tdim, "invalid 'flux' vector");
#ifndef MFEM_THREAD_SAFE
shape.SetSize(dof);
#else
Vector shape(dof);
#endif
double pointstress_data[6];
Vector pointstress(pointstress_data, tdim);
// View of the 'flux' vector as a (dof x tdim) matrix
DenseMatrix flux_mat(flux.GetData(), dof, tdim);
// Use the same integration rule as in AssembleElementMatrix, replacing 'el'
// with 'fluxelem' when 'IntRule' is not set.
// Should we be using a different (more accurate) rule here?
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = 2 * Trans.OrderGrad(&fluxelem);
ir = &IntRules.Get(fluxelem.GetGeomType(), order);
}
double energy = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
fluxelem.CalcShape(ip, shape);
flux_mat.MultTranspose(shape, pointstress);
Trans.SetIntPoint(&ip);
double w = Trans.Weight() * ip.weight;
M = mu->Eval(Trans, ip);
if (lambda)
{
L = lambda->Eval(Trans, ip);
}
else
{
L = q_lambda * M;
M = q_mu * M;
}
// The strain energy density at a point is given by (1/2)*(s : e) where s
// and e are the stress and strain tensors, respectively. Since we only
// have the stress, we need to compute the strain from the stress:
// s = 2*mu*e + lambda*tr(e)*I
// Taking trace on both sides we find:
// tr(s) = 2*mu*tr(e) + lambda*tr(e)*dim = (2*mu + dim*lambda)*tr(e)
// which gives:
// tr(e) = tr(s)/(2*mu + dim*lambda)
// Then from the first identity above we can find the strain:
// e = (1/(2*mu))*(s - lambda*tr(e)*I)
double pt_e; // point strain energy density
const double *s = pointstress_data;
if (dim == 2)
{
// s entries: s_xx, s_yy, s_xy
const double tr_e = (s[0] + s[1])/(2*(M + L));
L *= tr_e;
pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + 2*s[2]*s[2]);
}
else // (dim == 3)
{
// s entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
const double tr_e = (s[0] + s[1] + s[2])/(2*M + 3*L);
L *= tr_e;
pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + s[2]*(s[2] - L) +
2*(s[3]*s[3] + s[4]*s[4] + s[5]*s[5]));
}
energy += w * pt_e;
}
return energy;
}
void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Trans,
@@ -3047,32 +3215,38 @@ void NormalInterpolator::AssembleElementMatrix2(
}
namespace internal
{
// Scalar shape functions scaled by scalar coefficient.
// Used in the implementation of class ScalarProductInterpolator below.
struct ShapeCoefficient : public VectorCoefficient
{
Coefficient &Q;
const FiniteElement &fe;
ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
: VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
using VectorCoefficient::Eval;
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
V.SetSize(vdim);
fe.CalcPhysShape(T, V);
V *= Q.Eval(T, ip);
}
};
}
void
ScalarProductInterpolator::AssembleElementMatrix2(const FiniteElement &dom_fe,
const FiniteElement &ran_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
// Scalar shape functions scaled by scalar coefficient
struct ShapeCoefficient : public VectorCoefficient
{
Coefficient &Q;
const FiniteElement &fe;
ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
: VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
using VectorCoefficient::Eval;
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
V.SetSize(vdim);
fe.CalcPhysShape(T, V);
V *= Q.Eval(T, ip);
}
};
ShapeCoefficient dom_shape_coeff(Q, dom_fe);
internal::ShapeCoefficient dom_shape_coeff(Q, dom_fe);
elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
@@ -3209,6 +3383,35 @@ VectorCrossProductInterpolator::AssembleElementMatrix2(
}
namespace internal
{
// Vector shape functions dot product with a vector coefficient.
// Used in the implementation of class VectorInnerProductInterpolator below.
struct VDotVShapeCoefficient : public VectorCoefficient
{
VectorCoefficient &VQ;
const FiniteElement &fe;
DenseMatrix vshape;
Vector vc;
VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
: VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
using VectorCoefficient::Eval;
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
V.SetSize(vdim);
VQ.Eval(vc, T, ip);
fe.CalcPhysVShape(T, vshape);
vshape.Mult(vc, V);
}
};
}
void
VectorInnerProductInterpolator::AssembleElementMatrix2(
const FiniteElement &dom_fe,
@@ -3216,30 +3419,7 @@ VectorInnerProductInterpolator::AssembleElementMatrix2(
ElementTransformation &Trans,
DenseMatrix &elmat)
{
// Vector shape functions dot product with a vector coefficient
struct VDotVShapeCoefficient : public VectorCoefficient
{
VectorCoefficient &VQ;
const FiniteElement &fe;
DenseMatrix vshape;
Vector vc;
VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
: VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
using VectorCoefficient::Eval;
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
V.SetSize(vdim);
VQ.Eval(vc, T, ip);
fe.CalcPhysVShape(T, vshape);
vshape.Mult(vc, V);
}
};
VDotVShapeCoefficient dom_shape_coeff(VQ, dom_fe);
internal::VDotVShapeCoefficient dom_shape_coeff(VQ, dom_fe);
elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
+86 -6
View File
@@ -69,12 +69,60 @@ public:
const Vector &elfun, DenseMatrix &elmat)
{ AssembleFaceMatrix(el1, el2, Tr, elmat); }
/** @brief Virtual method required for Zienkiewicz-Zhu type error estimators.
The purpose of the method is to compute a local "flux" finite element
function given a local finite element solution. The "flux" function has
to be computed in terms of its coefficients (represented by the Vector
@a flux) which multiply the basis functions defined by the FiniteElement
@a fluxelem. Typically, the "flux" function will have more than one
component and consequently @a flux should be store the coefficients of
all components: first all coefficient for component 0, then all
coefficients for component 1, etc. What the "flux" function represents
depends on the specific integrator. For example, in the case of
DiffusionIntegrator, the flux is the gradient of the solution multiplied
by the diffusion coefficient.
@param[in] el FiniteElement of the solution.
@param[in] Trans The ElementTransformation describing the physical
position of the mesh element.
@param[in] u Solution coefficients representing the expansion of the
solution function in the basis of @a el.
@param[in] fluxelem FiniteElement of the "flux".
@param[out] flux "Flux" coefficients representing the expansion of the
"flux" function in the basis of @a fluxelem. The size
of @a flux as a Vector has to be set by this method,
e.g. using Vector::SetSize().
@param[in] with_coef If zero (the default value is 1) the implementation
of the method may choose not to scale the "flux"
function by any coefficients describing the
integrator.
*/
virtual void ComputeElementFlux(const FiniteElement &el,
ElementTransformation &Trans,
Vector &u,
const FiniteElement &fluxelem,
Vector &flux, int with_coef = 1) { }
/** @brief Virtual method required for Zienkiewicz-Zhu type error estimators.
The purpose of this method is to compute a local number that measures the
energy of a given "flux" function (see ComputeElementFlux() for a
description of the "flux" function). Typically, the energy of a "flux"
function should be equal to a_local(u,u), if the "flux" is defined from
a solution u; here a_local(.,.) denotes the element-local bilinear
form represented by the integrator.
@param[in] fluxelem FiniteElement of the "flux".
@param[in] Trans The ElementTransformation describing the physical
position of the mesh element.
@param[in] flux "Flux" coefficients representing the expansion of the
"flux" function in the basis of @a fluxelem.
@param[out] d_energy If not NULL, the given Vector should be set to
represent directional energy split that can be used
for anisotropic error estimation.
@returns The computed energy.
*/
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
ElementTransformation &Trans,
Vector &flux, Vector *d_energy = NULL)
@@ -1706,6 +1754,7 @@ public:
class VectorMassIntegrator: public BilinearFormIntegrator
{
private:
int vdim;
Vector shape, te_shape, vec;
DenseMatrix partelmat;
DenseMatrix mcoeff;
@@ -1718,22 +1767,25 @@ private:
public:
/// Construct an integrator with coefficient 1.0
VectorMassIntegrator()
{ Q = NULL; VQ = NULL; MQ = NULL; Q_order = 0; }
: vdim(-1), Q(NULL), VQ(NULL), MQ(NULL), Q_order(0) { }
/** Construct an integrator with scalar coefficient q.
If possible, save memory by using a scalar integrator since
the resulting matrix is block diagonal with the same diagonal
block repeated. */
VectorMassIntegrator(Coefficient &q, int qo = 0)
: Q(&q) { VQ = NULL; MQ = NULL; Q_order = qo; }
: vdim(-1), Q(&q) { VQ = NULL; MQ = NULL; Q_order = qo; }
VectorMassIntegrator(Coefficient &q, const IntegrationRule *ir)
: BilinearFormIntegrator(ir), Q(&q)
: BilinearFormIntegrator(ir), vdim(-1), Q(&q)
{ VQ = NULL; MQ = NULL; Q_order = 0; }
/// Construct an integrator with diagonal coefficient q
VectorMassIntegrator(VectorCoefficient &q, int qo = 0)
: VQ(&q) { Q = NULL; MQ = NULL; Q_order = qo; }
: vdim(q.GetVDim()), VQ(&q) { Q = NULL; MQ = NULL; Q_order = qo; }
/// Construct an integrator with matrix coefficient q
VectorMassIntegrator(MatrixCoefficient &q, int qo = 0)
: MQ(&q) { Q = NULL; VQ = NULL; Q_order = qo; }
: vdim(q.GetVDim()), MQ(&q) { Q = NULL; VQ = NULL; Q_order = qo; }
int GetVDim() const { return vdim; }
void SetVDim(int vdim) { this->vdim = vdim; }
virtual void AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
@@ -2018,7 +2070,8 @@ private:
Coefficient *lambda, *mu;
#ifndef MFEM_THREAD_SAFE
DenseMatrix dshape, Jinv, gshape, pelmat;
Vector shape;
DenseMatrix dshape, gshape, pelmat;
Vector divshape;
#endif
@@ -2033,6 +2086,33 @@ public:
virtual void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
DenseMatrix &);
/** Compute the stress corresponding to the local displacement @a u and
interpolate it at the nodes of the given @a fluxelem. Only the symmetric
part of the stress is stored, so that the size of @a flux is equal to
the number of DOFs in @a fluxelem times dim*(dim+1)/2. In 2D, the order
of the stress components is: s_xx, s_yy, s_xy. In 3D, it is: s_xx, s_yy,
s_zz, s_xy, s_xz, s_yz. In other words, @a flux is the local vector for
a FE space with dim*(dim+1)/2 vector components, based on the finite
element @a fluxelem. */
virtual void ComputeElementFlux(const FiniteElement &el,
ElementTransformation &Trans,
Vector &u,
const FiniteElement &fluxelem,
Vector &flux, int with_coef = 1);
/** Compute the element energy (integral of the strain energy density)
corresponding to the stress represented by @a flux which is a vector of
coefficients multiplying the basis functions defined by @a fluxelem. In
other words, @a flux is the local vector for a FE space with
dim*(dim+1)/2 vector components, based on the finite element @a fluxelem.
The number of components, dim*(dim+1)/2 is such that it represents the
symmetric part of the (symmetric) stress tensor. The order of the
components is: s_xx, s_yy, s_xy in 2D, and s_xx, s_yy, s_zz, s_xy, s_xz,
s_yz in 3D. */
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
ElementTransformation &Trans,
Vector &flux, Vector *d_energy = NULL);
};
/** Integrator for the DG form:
+279 -2
View File
@@ -87,7 +87,6 @@ double DeltaCoefficient::EvalDelta(ElementTransformation &T,
return weight ? weight->Eval(T, ip, GetTime())*w : w;
}
void VectorCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir)
{
@@ -153,11 +152,17 @@ void VectorArrayCoefficient::Eval(Vector &V, ElementTransformation &T,
}
VectorGridFunctionCoefficient::VectorGridFunctionCoefficient (
GridFunction *gf) : VectorCoefficient (gf -> VectorDim())
GridFunction *gf)
: VectorCoefficient ((gf) ? gf -> VectorDim() : 0)
{
GridFunc = gf;
}
void VectorGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
{
GridFunc = gf; vdim = (gf) ? gf -> VectorDim() : 0;
}
void VectorGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
@@ -170,6 +175,64 @@ void VectorGridFunctionCoefficient::Eval(
GridFunc->GetVectorValues(T, ir, M);
}
GradientGridFunctionCoefficient::GradientGridFunctionCoefficient (
GridFunction *gf)
: VectorCoefficient((gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0)
{
GridFunc = gf;
}
void GradientGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
{
GridFunc = gf; vdim = (gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0;
}
void GradientGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
GridFunc->GetGradient(T, V);
}
void GradientGridFunctionCoefficient::Eval(
DenseMatrix &M, ElementTransformation &T, const IntegrationRule &ir)
{
GridFunc->GetGradients(T, ir, M);
}
CurlGridFunctionCoefficient::CurlGridFunctionCoefficient (
GridFunction *gf)
: VectorCoefficient ((gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0)
{
GridFunc = gf;
}
void CurlGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
{
GridFunc = gf; vdim = (gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0;
}
void CurlGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
GridFunc->GetCurl(T, V);
}
DivergenceGridFunctionCoefficient::DivergenceGridFunctionCoefficient (
GridFunction *gf) : Coefficient()
{
GridFunc = gf;
}
double DivergenceGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
return GridFunc->GetDivergence(T);
}
void VectorDeltaCoefficient::SetDirection(const Vector &_d)
{
dir = _d;
@@ -287,6 +350,220 @@ void MatrixRestrictedCoefficient::Eval(DenseMatrix &K, ElementTransformation &T,
}
}
InnerProductCoefficient::InnerProductCoefficient(VectorCoefficient &A,
VectorCoefficient &B)
: a(&A), b(&B)
{
MFEM_ASSERT(A.GetVDim() == B.GetVDim(),
"InnerProductCoefficient: "
"Arguments have incompatible dimensions.");
}
double InnerProductCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(va, T, ip);
b->Eval(vb, T, ip);
return va * vb;
}
VectorRotProductCoefficient::VectorRotProductCoefficient(VectorCoefficient &A,
VectorCoefficient &B)
: a(&A), b(&B), va(A.GetVDim()), vb(B.GetVDim())
{
MFEM_ASSERT(A.GetVDim() == 2 && B.GetVDim() == 2,
"VectorRotProductCoefficient: "
"Arguments must have dimension equal to two.");
}
double VectorRotProductCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(va, T, ip);
b->Eval(vb, T, ip);
return va[0] * vb[1] - va[1] * vb[0];
}
DeterminantCoefficient::DeterminantCoefficient(MatrixCoefficient &A)
: a(&A), ma(A.GetHeight(), A.GetWidth())
{
MFEM_ASSERT(A.GetHeight() == A.GetWidth(),
"DeterminantCoefficient: "
"Argument must be a square matrix.");
}
double DeterminantCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(ma, T, ip);
return ma.Det();
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &A,
VectorCoefficient &B,
double _alpha, double _beta)
: VectorCoefficient(A.GetVDim()), a(&A), b(&B), alpha(_alpha), beta(_beta),
va(A.GetVDim())
{
MFEM_ASSERT(A.GetVDim() == B.GetVDim(),
"VectorSumCoefficient: "
"Arguments must have the same dimension.");
}
void VectorSumCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
b->Eval(V, T, ip);
if ( beta != 1.0 ) { V *= beta; }
a->Eval(va, T, ip);
V.Add(alpha, va);
}
ScalarVectorProductCoefficient::ScalarVectorProductCoefficient(
Coefficient &A,
VectorCoefficient &B)
: VectorCoefficient(B.GetVDim()), a(&A), b(&B)
{}
void ScalarVectorProductCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
double sa = a->Eval(T, ip);
b->Eval(V, T, ip);
V *= sa;
}
VectorCrossProductCoefficient::VectorCrossProductCoefficient(
VectorCoefficient &A,
VectorCoefficient &B)
: VectorCoefficient(3), a(&A), b(&B), va(A.GetVDim()), vb(B.GetVDim())
{
MFEM_ASSERT(A.GetVDim() == 3 && B.GetVDim() == 3,
"VectorCrossProductCoefficient: "
"Arguments must have dimension equal to three.");
}
void VectorCrossProductCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(va, T, ip);
b->Eval(vb, T, ip);
V.SetSize(3);
V[0] = va[1] * vb[2] - va[2] * vb[1];
V[1] = va[2] * vb[0] - va[0] * vb[2];
V[2] = va[0] * vb[1] - va[1] * vb[0];
}
MatVecCoefficient::MatVecCoefficient(MatrixCoefficient &A,
VectorCoefficient &B)
: VectorCoefficient(A.GetHeight()), a(&A), b(&B),
ma(A.GetHeight(), A.GetWidth()), vb(B.GetVDim())
{
MFEM_ASSERT(A.GetWidth() == B.GetVDim(),
"MatVecCoefficient: Arguments have incompatible dimensions.");
}
void MatVecCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(ma, T, ip);
b->Eval(vb, T, ip);
ma.Mult(vb, V);
}
void IdentityMatrixCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip)
{
M.SetSize(dim);
M = 0.0;
for (int d=0; d<dim; d++) { M(d,d) = 1.0; }
}
MatrixSumCoefficient::MatrixSumCoefficient(MatrixCoefficient &A,
MatrixCoefficient &B,
double _alpha, double _beta)
: MatrixCoefficient(A.GetHeight(), A.GetWidth()),
a(&A), b(&B), alpha(_alpha), beta(_beta),
ma(A.GetHeight(), A.GetWidth())
{
MFEM_ASSERT(A.GetHeight() == B.GetHeight() && A.GetWidth() == B.GetWidth(),
"MatrixSumCoefficient: "
"Arguments must have the same dimensions.");
}
void MatrixSumCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip)
{
b->Eval(M, T, ip);
if ( beta != 1.0 ) { M *= beta; }
a->Eval(ma, T, ip);
M.Add(alpha, ma);
}
ScalarMatrixProductCoefficient::ScalarMatrixProductCoefficient(
Coefficient &A,
MatrixCoefficient &B)
: MatrixCoefficient(B.GetHeight(), B.GetWidth()), a(&A), b(&B)
{}
void ScalarMatrixProductCoefficient::Eval(DenseMatrix &M,
ElementTransformation &T,
const IntegrationPoint &ip)
{
double sa = a->Eval(T, ip);
b->Eval(M, T, ip);
M *= sa;
}
TransposeMatrixCoefficient::TransposeMatrixCoefficient(MatrixCoefficient &A)
: MatrixCoefficient(A.GetWidth(), A.GetHeight()), a(&A)
{}
void TransposeMatrixCoefficient::Eval(DenseMatrix &M,
ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(M, T, ip);
M.Transpose();
}
InverseMatrixCoefficient::InverseMatrixCoefficient(MatrixCoefficient &A)
: MatrixCoefficient(A.GetHeight(), A.GetWidth()), a(&A)
{
MFEM_ASSERT(A.GetHeight() == A.GetWidth(),
"InverseMatrixCoefficient: "
"Argument must be a square matrix.");
}
void InverseMatrixCoefficient::Eval(DenseMatrix &M,
ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(M, T, ip);
M.Invert();
}
OuterProductCoefficient::OuterProductCoefficient(VectorCoefficient &A,
VectorCoefficient &B)
: MatrixCoefficient(A.GetVDim(), B.GetVDim()), a(&A), b(&B),
va(A.GetVDim()), vb(B.GetVDim())
{}
void OuterProductCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(va, T, ip);
b->Eval(vb, T, ip);
M.SetSize(va.Size(), vb.Size());
for (int i=0; i<va.Size(); i++)
{
for (int j=0; j<vb.Size(); j++)
{
M(i, j) = va[i] * vb[j];
}
}
}
double LpNormLoop(double p, Coefficient &coeff, Mesh &mesh,
const IntegrationRule *irs[])
{
+368 -6
View File
@@ -39,9 +39,19 @@ public:
void SetTime(double t) { time = t; }
double GetTime() { return time; }
/** @brief Evaluate the coefficient in the element described by @a T at the
point @a ip. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/** @brief Evaluate the coefficient in the element described by @a T at the
point @a ip at time @a t. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
double Eval(ElementTransformation &T,
const IntegrationPoint &ip, double t)
{
@@ -157,6 +167,7 @@ private:
int Component;
public:
GridFunctionCoefficient() : GridF(NULL), Component(1) { }
/** Construct GridFunctionCoefficient from a given GridFunction, and
optionally specify a component to use if it is a vector GridFunction. */
GridFunctionCoefficient (GridFunction *gf, int comp = 1)
@@ -242,7 +253,7 @@ public:
Coefficient *Weight() { return weight; }
void GetDeltaCenter(Vector& center);
/// Return the Scale() multiplied by the weight Coefficient, if any.
double EvalDelta(ElementTransformation &T, const IntegrationPoint &ip);
virtual double EvalDelta(ElementTransformation &T, const IntegrationPoint &ip);
/** @brief A DeltaFunction cannot be evaluated. Calling this method will
cause an MFEM error, terminating the application. */
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
@@ -280,11 +291,26 @@ public:
/// Returns dimension of the vector.
int GetVDim() { return vdim; }
/** @brief Evaluate the vector coefficient in the element described by @a T
at the point @a ip, storing the result in @a V. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
// General implementation using the Eval method for one IntegrationPoint.
// Can be overloaded for more efficient implementation.
/** @brief Evaluate the vector coefficient in the element described by @a T
at all points of @a ir, storing the result in @a M. */
/** The dimensions of @a M are GetVDim() by ir.GetNPoints() and they must be
set by the implementation of this method.
The general implementation provided by the base class (using the Eval
method for one IntegrationPoint at a time) can be overloaded for more
efficient implementation.
@note The IntegrationPoint associated with @a T is not used, and this
method will generally modify this IntegrationPoint associated with @a T.
*/
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir);
@@ -374,9 +400,10 @@ protected:
GridFunction *GridFunc;
public:
VectorGridFunctionCoefficient() : VectorCoefficient(0), GridFunc(NULL) { }
VectorGridFunctionCoefficient(GridFunction *gf);
void SetGridFunction(GridFunction *gf) { GridFunc = gf; }
void SetGridFunction(GridFunction *gf);
GridFunction * GetGridFunction() const { return GridFunc; }
virtual void Eval(Vector &V, ElementTransformation &T,
@@ -388,6 +415,63 @@ public:
virtual ~VectorGridFunctionCoefficient() { }
};
/// Vector coefficient defined as the Gradient of a scalar GridFunction
class GradientGridFunctionCoefficient : public VectorCoefficient
{
protected:
GridFunction *GridFunc;
public:
GradientGridFunctionCoefficient(GridFunction *gf);
void SetGridFunction(GridFunction *gf);
GridFunction * GetGridFunction() const { return GridFunc; }
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationRule &ir);
virtual ~GradientGridFunctionCoefficient() { }
};
/// Vector coefficient defined as the Curl of a vector GridFunction
class CurlGridFunctionCoefficient : public VectorCoefficient
{
protected:
GridFunction *GridFunc;
public:
CurlGridFunctionCoefficient(GridFunction *gf);
void SetGridFunction(GridFunction *gf);
GridFunction * GetGridFunction() const { return GridFunc; }
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
virtual ~CurlGridFunctionCoefficient() { }
};
/// Scalar coefficient defined as the Divergence of a vector GridFunction
class DivergenceGridFunctionCoefficient : public Coefficient
{
protected:
GridFunction *GridFunc;
public:
DivergenceGridFunctionCoefficient(GridFunction *gf);
void SetGridFunction(GridFunction *gf) { GridFunc = gf; }
GridFunction * GetGridFunction() const { return GridFunc; }
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
virtual ~DivergenceGridFunctionCoefficient() { }
};
/// VectorDeltaCoefficient: DeltaCoefficient with a direction
class VectorDeltaCoefficient : public VectorCoefficient
{
@@ -420,8 +504,8 @@ public:
/** @brief Return the specified direction vector multiplied by the value
returned by DeltaCoefficient::EvalDelta() of the associated scalar
DeltaCoefficient. */
void EvalDelta(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
virtual void EvalDelta(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
using VectorCoefficient::Eval;
/** @brief A VectorDeltaFunction cannot be evaluated. Calling this method
will cause an MFEM error, terminating the application. */
@@ -470,6 +554,11 @@ public:
// For backward compatibility
int GetVDim() const { return width; }
/** @brief Evaluate the matrix coefficient in the element described by @a T
at the point @a ip, storing the result in @a K. */
/** @note When this method is called, the caller must make sure that the
IntegrationPoint associated with @a T is the same as @a ip. This can be
achieved by calling T.SetIntPoint(&ip). */
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
@@ -571,6 +660,279 @@ public:
const IntegrationPoint &ip);
};
/// Coefficients based on sums and products of other coefficients
/// Scalar coefficient defined as the sum of two scalar coefficients
class SumCoefficient : public Coefficient
{
private:
Coefficient * a;
Coefficient * b;
double alpha;
double beta;
public:
// Result is _alpha * A + _beta * B
SumCoefficient(Coefficient &A, Coefficient &B,
double _alpha = 1.0, double _beta = 1.0)
: a(&A), b(&B), alpha(_alpha), beta(_beta) { }
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return alpha * a->Eval(T, ip) + beta * b->Eval(T, ip); }
};
/// Scalar coefficient defined as the product of two scalar coefficients
class ProductCoefficient : public Coefficient
{
private:
Coefficient * a;
Coefficient * b;
public:
ProductCoefficient(Coefficient &A, Coefficient &B)
: a(&A), b(&B) { }
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return a->Eval(T, ip) * b->Eval(T, ip); }
};
/// Scalar coefficient defined as a scalar raised to a power
class PowerCoefficient : public Coefficient
{
private:
Coefficient * a;
double p;
public:
// Result is A^p
PowerCoefficient(Coefficient &A, double _p)
: a(&A), p(_p) { }
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return pow(a->Eval(T, ip), p); }
};
/// Scalar coefficient defined as the inner product of two vector coefficients
class InnerProductCoefficient : public Coefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
InnerProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Scalar coefficient defined as a cross product of two vectors in 2D
class VectorRotProductCoefficient : public Coefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
VectorRotProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Scalar coefficient defined as the determinant of a matrix coefficient
class DeterminantCoefficient : public Coefficient
{
private:
MatrixCoefficient * a;
mutable DenseMatrix ma;
public:
DeterminantCoefficient(MatrixCoefficient &A);
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Vector coefficient defined as the sum of two vector coefficients
class VectorSumCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
double alpha;
double beta;
mutable Vector va;
public:
// Result is _alpha * A + _beta * B
VectorSumCoefficient(VectorCoefficient &A, VectorCoefficient &B,
double _alpha = 1.0, double _beta = 1.0);
/// Evaluate the coefficient
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Vector coefficient defined as a product of a scalar and a vector
class ScalarVectorProductCoefficient : public VectorCoefficient
{
private:
Coefficient * a;
VectorCoefficient * b;
public:
ScalarVectorProductCoefficient(Coefficient &A, VectorCoefficient &B);
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Vector coefficient defined as a cross product of two vectors
class VectorCrossProductCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
VectorCrossProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Vector coefficient defined as a matrix vector product
class MatVecCoefficient : public VectorCoefficient
{
private:
MatrixCoefficient * a;
VectorCoefficient * b;
mutable DenseMatrix ma;
mutable Vector vb;
public:
MatVecCoefficient(MatrixCoefficient &A, VectorCoefficient &B);
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the identity of dimension d
class IdentityMatrixCoefficient : public MatrixCoefficient
{
private:
int dim;
public:
IdentityMatrixCoefficient(int d)
: MatrixCoefficient(d, d), dim(d) { }
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the sum of two matrix coefficients
class MatrixSumCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
MatrixCoefficient * b;
double alpha;
double beta;
mutable DenseMatrix ma;
public:
// Result is _alpha * A + _beta * B
MatrixSumCoefficient(MatrixCoefficient &A, MatrixCoefficient &B,
double _alpha = 1.0, double _beta = 1.0);
/// Evaluate the coefficient
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as a product of a scalar and a matrix
class ScalarMatrixProductCoefficient : public MatrixCoefficient
{
private:
Coefficient * a;
MatrixCoefficient * b;
public:
ScalarMatrixProductCoefficient(Coefficient &A, MatrixCoefficient &B);
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the transpose a matrix
class TransposeMatrixCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
public:
TransposeMatrixCoefficient(MatrixCoefficient &A);
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the inverse a matrix
class InverseMatrixCoefficient : public MatrixCoefficient
{
private:
MatrixCoefficient * a;
public:
InverseMatrixCoefficient(MatrixCoefficient &A);
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the outer product of two vectors
class OuterProductCoefficient : public MatrixCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
mutable Vector va;
mutable Vector vb;
public:
OuterProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/** Compute the Lp norm of a function f.
\f$ \| f \|_{Lp} = ( \int_\Omega | f |^p d\Omega)^{1/p} \f$ */
double ComputeLpNorm(double p, Coefficient &coeff, Mesh &mesh,
+4 -4
View File
@@ -699,8 +699,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
n_topo["type"] = "unstructured";
n_topo["coordset"] = coordset_name;
Element::Type ele_type = static_cast<Element::Type>(mesh->GetElement(
0)->GetType());
Element::Type ele_type = mesh->GetElementType(0);
std::string ele_shape = ElementTypeToShapeName(ele_type);
@@ -774,8 +773,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
n_bndry_topo["type"] = "unstructured";
n_bndry_topo["coordset"] = coordset_name;
Element::Type bndry_ele_type = static_cast<Element::Type>(mesh->GetBdrElement(
0)->GetType());
Element::Type bndry_ele_type = mesh->GetBdrElementType(0);
std::string bndry_ele_shape = ElementTypeToShapeName(bndry_ele_type);
@@ -1163,6 +1161,8 @@ ConduitDataCollection::ElementTypeToShapeName(Element::Type element_type)
case Element::QUADRILATERAL: return "quad";
case Element::TETRAHEDRON: return "tet";
case Element::HEXAHEDRON: return "hex";
case Element::WEDGE:
default: ;
}
return "unknown";
+3 -1
View File
@@ -367,7 +367,8 @@ int InverseElementTransformation::Transform(const Vector &pt,
}
void IsoparametricTransformation::SetIdentityTransformation(int GeomType)
void IsoparametricTransformation::SetIdentityTransformation(
Geometry::Type GeomType)
{
switch (GeomType)
{
@@ -377,6 +378,7 @@ void IsoparametricTransformation::SetIdentityTransformation(int GeomType)
case Geometry::SQUARE : FElem = &QuadrilateralFE; break;
case Geometry::TETRAHEDRON : FElem = &TetrahedronFE; break;
case Geometry::CUBE : FElem = &HexahedronFE; break;
case Geometry::PRISM : FElem = &WedgeFE; break;
default:
MFEM_ABORT("unknown Geometry::Type!");
}
+4 -3
View File
@@ -34,7 +34,8 @@ protected:
ADJUGATE_MASK = 4,
INVERSE_MASK = 8
};
int geom, space_dim;
Geometry::Type geom;
int space_dim;
// Evaluate the Jacobian of the transformation at the IntPoint and store it
// in dFdx.
@@ -82,7 +83,7 @@ public:
virtual int OrderGrad(const FiniteElement *fe) = 0;
/// Return the Geometry::Type of the reference element.
int GetGeometryType() const { return geom; }
Geometry::Type GetGeometryType() const { return geom; }
/// Return the dimension of the reference element.
int GetDimension() const { return Geometry::Dimension[geom]; }
@@ -312,7 +313,7 @@ public:
DenseMatrix &GetPointMat() { return PointMat; }
void FinalizeTransformation() { space_dim = PointMat.Height(); }
void SetIdentityTransformation(int GeomType);
void SetIdentityTransformation(Geometry::Type GeomType);
virtual void Transform(const IntegrationPoint &, Vector &);
virtual void Transform(const IntegrationRule &, DenseMatrix &);
+3 -2
View File
@@ -17,13 +17,14 @@ namespace mfem
void ZienkiewiczZhuEstimator::ComputeEstimates()
{
flux_space->Update(false);
// In parallel, 'flux' can be a GridFunction, as long as 'flux_space' is a
// ParFiniteElementSpace and 'solution' is a ParGridFunction.
GridFunction flux(flux_space);
if (!anisotropic) { aniso_flags.SetSize(0); }
const int with_subdomains = 1;
total_error = ZZErrorEstimator(*integ, *solution, flux, error_estimates,
anisotropic ? &aniso_flags : NULL,
with_subdomains);
flux_averaging);
current_sequence = solution->FESpace()->GetMesh()->GetSequence();
}
+11
View File
@@ -77,6 +77,7 @@ protected:
double total_error;
bool anisotropic;
Array<int> aniso_flags;
int flux_averaging; // see SetFluxAveraging()
BilinearFormIntegrator *integ; ///< Not owned.
GridFunction *solution; ///< Not owned.
@@ -109,6 +110,7 @@ public:
: current_sequence(-1),
total_error(),
anisotropic(false),
flux_averaging(0),
integ(&integ),
solution(&sol),
flux_space(flux_fes),
@@ -127,6 +129,7 @@ public:
: current_sequence(-1),
total_error(),
anisotropic(false),
flux_averaging(0),
integ(&integ),
solution(&sol),
flux_space(&flux_fes),
@@ -138,6 +141,14 @@ public:
ComputeFluxEnergy() method. */
void SetAnisotropic(bool aniso = true) { anisotropic = aniso; }
/** @brief Set the way the flux is averaged (smoothed) across elements.
When @a fa is zero (default), averaging is performed globally. When @a fa
is non-zero, the flux averaging is performed locally for each mesh
attribute, i.e. the flux is not averaged across interfaces between
different mesh attributes. */
void SetFluxAveraging(int fa) { flux_averaging = fa; }
/// Return the total error from the last error estimate.
double GetTotalError() const { return total_error; }
+641 -2
View File
@@ -22,7 +22,7 @@ namespace mfem
using namespace std;
FiniteElement::FiniteElement(int D, int G, int Do, int O, int F)
FiniteElement::FiniteElement(int D, Geometry::Type G, int Do, int O, int F)
: Nodes(Do)
{
Dim = D ; GeomType = G ; Dof = Do ; Order = O ; FuncSpace = F;
@@ -114,6 +114,12 @@ void FiniteElement::GetLocalInterpolation (ElementTransformation &Trans,
mfem_error ("GetLocalInterpolation (...) is not overloaded !");
}
void FiniteElement::GetLocalRestriction(ElementTransformation &,
DenseMatrix &) const
{
mfem_error("FiniteElement::GetLocalRestriction() is not overloaded !");
}
void FiniteElement::GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -292,6 +298,51 @@ void NodalFiniteElement::ProjectCurl_2D(
}
}
void InvertLinearTrans(ElementTransformation &trans,
const IntegrationPoint &pt, Vector &x)
{
// invert a linear transform with one Newton step
IntegrationPoint p0;
p0.Set3(0, 0, 0);
trans.Transform(p0, x);
double store[3];
Vector v(store, x.Size());
pt.Get(v, x.Size());
v -= x;
trans.InverseJacobian().Mult(v, x);
}
void NodalFiniteElement::GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{
IntegrationPoint ipt;
Vector pt(&ipt.x, Dim);
#ifdef MFEM_THREAD_SAFE
Vector c_shape(Dof);
#endif
Trans.SetIntPoint(&Nodes[0]);
for (int j = 0; j < Dof; j++)
{
InvertLinearTrans(Trans, Nodes[j], pt);
if (Geometries.CheckPoint(GeomType, ipt)) // do we need an epsilon here?
{
CalcShape(ipt, c_shape);
R.SetRow(j, c_shape);
}
else
{
// Set the whole row to avoid valgrind warnings in R.Threshold().
R.SetRow(j, infinity());
}
}
R.Threshold(1e-12);
}
void NodalFiniteElement::Project (
Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
{
@@ -466,6 +517,24 @@ void PositiveFiniteElement::Project(
}
}
void PositiveFiniteElement::Project(
VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
{
MFEM_ASSERT(dofs.Size() == vc.GetVDim()*Dof, "");
Vector x(vc.GetVDim());
for (int i = 0; i < Dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
Trans.SetIntPoint(&ip);
vc.Eval (x, Trans, ip);
for (int j = 0; j < x.Size(); j++)
{
dofs(Dof*j+i) = x(j);
}
}
}
void PositiveFiniteElement::Project(
const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
{
@@ -933,6 +1002,90 @@ void VectorFiniteElement::LocalInterpolation_ND(
}
}
void VectorFiniteElement::LocalRestriction_RT(
const double *nk, const Array<int> &d2n, ElementTransformation &Trans,
DenseMatrix &R) const
{
double pt_data[Geometry::MaxDim];
IntegrationPoint ip;
Vector pt(pt_data, Dim);
#ifdef MFEM_THREAD_SAFE
DenseMatrix vshape(Dof, Dim);
#endif
Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
const DenseMatrix &J = Trans.Jacobian();
const double weight = Trans.Weight();
for (int j = 0; j < Dof; j++)
{
InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
ip.Set(pt_data, Dim);
if (Geometries.CheckPoint(GeomType, ip)) // do we need an epsilon here?
{
CalcVShape(ip, vshape);
J.MultTranspose(nk+Dim*d2n[j], pt_data);
pt /= weight;
for (int k = 0; k < Dof; k++)
{
double R_jk = 0.0;
for (int d = 0; d < Dim; d++)
{
R_jk += vshape(k,d)*pt_data[d];
}
R(j,k) = R_jk;
}
}
else
{
// Set the whole row to avoid valgrind warnings in R.Threshold().
R.SetRow(j, infinity());
}
}
R.Threshold(1e-12);
}
void VectorFiniteElement::LocalRestriction_ND(
const double *tk, const Array<int> &d2t, ElementTransformation &Trans,
DenseMatrix &R) const
{
double pt_data[Geometry::MaxDim];
IntegrationPoint ip;
Vector pt(pt_data, Dim);
#ifdef MFEM_THREAD_SAFE
DenseMatrix vshape(Dof, Dim);
#endif
Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
const DenseMatrix &Jinv = Trans.InverseJacobian();
for (int j = 0; j < Dof; j++)
{
InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
ip.Set(pt_data, Dim);
if (Geometries.CheckPoint(GeomType, ip)) // do we need an epsilon here?
{
CalcVShape(ip, vshape);
Jinv.Mult(tk+Dim*d2t[j], pt_data);
for (int k = 0; k < Dof; k++)
{
double R_jk = 0.0;
for (int d = 0; d < Dim; d++)
{
R_jk += vshape(k,d)*pt_data[d];
}
R(j,k) = R_jk;
}
}
else
{
// Set the whole row to avoid valgrind warnings in R.Threshold().
R.SetRow(j, infinity());
}
}
R.Threshold(1e-12);
}
PointFiniteElement::PointFiniteElement()
: NodalFiniteElement(0, Geometry::POINT, 1, 0)
@@ -2550,6 +2703,7 @@ void TriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
dshape(7,2) = ox * y;
}
P0SegmentFiniteElement::P0SegmentFiniteElement(int Ord)
: NodalFiniteElement(1, Geometry::SEGMENT, 1, Ord) // defaul Ord = 0
{
@@ -6697,8 +6851,8 @@ Poly_1D::~Poly_1D()
}
}
Poly_1D poly1d;
Array2D<int> Poly_1D::binom;
Poly_1D poly1d;
TensorBasisElement::TensorBasisElement(const int dims, const int p,
@@ -8250,6 +8404,294 @@ void H1Pos_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
}
H1_WedgeElement::H1_WedgeElement(const int p,
const int btype)
: NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
p, FunctionSpace::Qk),
TriangleFE(p, btype),
SegmentFE(p, btype)
{
#ifndef MFEM_THREAD_SAFE
t_shape.SetSize(TriangleFE.GetDof());
s_shape.SetSize(SegmentFE.GetDof());
t_dshape.SetSize(TriangleFE.GetDof(), 2);
s_dshape.SetSize(SegmentFE.GetDof(), 1);
#endif
t_dof.SetSize(Dof);
s_dof.SetSize(Dof);
// Nodal DoFs
t_dof[0] = 0; s_dof[0] = 0;
t_dof[1] = 1; s_dof[1] = 0;
t_dof[2] = 2; s_dof[2] = 0;
t_dof[3] = 0; s_dof[3] = 1;
t_dof[4] = 1; s_dof[4] = 1;
t_dof[5] = 2; s_dof[5] = 1;
// Edge DoFs
int ne = p-1;
for (int i=1; i<p; i++)
{
t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
}
// Triangular Face DoFs
int k=0;
int nt = (p-1)*(p-2)/2;
for (int j=1; j<p; j++)
{
for (int i=1; i<p-j; i++)
{
int l = j - p + (((2 * p - 1) - i) * i) / 2;
t_dof[6 + 9 * ne + k] = 3 * p + l; s_dof[6 + 9 * ne + k] = 0;
t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
k++;
}
}
// Quadrilateral Face DoFs
k=0;
int nq = (p-1)*(p-1);
for (int j=1; j<p; j++)
{
for (int i=1; i<p; i++)
{
t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
k++;
}
}
// Interior DoFs
int m=0;
for (int k=1; k<p; k++)
{
int l=0;
for (int j=1; j<p; j++)
{
for (int i=1; i<j; i++)
{
t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
l++; m++;
}
}
}
// Define Nodes
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
for (int i=0; i<Dof; i++)
{
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
}
}
void H1_WedgeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
Vector s_shape(SegmentFE.GetDof());
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
SegmentFE.CalcShape(ipz, s_shape);
for (int i=0; i<Dof; i++)
{
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
}
}
void H1_WedgeElement::CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
Vector s_shape(SegmentFE.GetDof());
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
TriangleFE.CalcDShape(ip, t_dshape);
SegmentFE.CalcShape(ipz, s_shape);
SegmentFE.CalcDShape(ipz, s_dshape);
for (int i=0; i<Dof; i++)
{
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
}
}
H1Pos_WedgeElement::H1Pos_WedgeElement(const int p)
: PositiveFiniteElement(3, Geometry::PRISM,
((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
TriangleFE(p),
SegmentFE(p)
{
#ifndef MFEM_THREAD_SAFE
t_shape.SetSize(TriangleFE.GetDof());
s_shape.SetSize(SegmentFE.GetDof());
t_dshape.SetSize(TriangleFE.GetDof(), 2);
s_dshape.SetSize(SegmentFE.GetDof(), 1);
#endif
t_dof.SetSize(Dof);
s_dof.SetSize(Dof);
// Nodal DoFs
t_dof[0] = 0; s_dof[0] = 0;
t_dof[1] = 1; s_dof[1] = 0;
t_dof[2] = 2; s_dof[2] = 0;
t_dof[3] = 0; s_dof[3] = 1;
t_dof[4] = 1; s_dof[4] = 1;
t_dof[5] = 2; s_dof[5] = 1;
// Edge DoFs
int ne = p-1;
for (int i=1; i<p; i++)
{
t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
}
// Triangular Face DoFs
int k=0;
int nt = (p-1)*(p-2)/2;
for (int j=1; j<p; j++)
{
for (int i=1; i<j; i++)
{
t_dof[6 + 9 * ne + k] = 3 * p + k; s_dof[6 + 9 * ne + k] = 0;
t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
k++;
}
}
// Quadrilateral Face DoFs
k=0;
int nq = (p-1)*(p-1);
for (int j=1; j<p; j++)
{
for (int i=1; i<p; i++)
{
t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
k++;
}
}
// Interior DoFs
int m=0;
for (int k=1; k<p; k++)
{
int l=0;
for (int j=1; j<p; j++)
{
for (int i=1; i<j; i++)
{
t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
l++; m++;
}
}
}
// Define Nodes
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
for (int i=0; i<Dof; i++)
{
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
}
}
void H1Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
Vector s_shape(SegmentFE.GetDof());
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
SegmentFE.CalcShape(ipz, s_shape);
for (int i=0; i<Dof; i++)
{
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
}
}
void H1Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
Vector s_shape(SegmentFE.GetDof());
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
TriangleFE.CalcDShape(ip, t_dshape);
SegmentFE.CalcShape(ipz, s_shape);
SegmentFE.CalcDShape(ipz, s_dshape);
for (int i=0; i<Dof; i++)
{
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
}
}
L2_SegmentElement::L2_SegmentElement(const int p, const int btype)
: NodalTensorFiniteElement(1, p, VerifyOpen(btype), L2_DOF_MAP)
{
@@ -9153,6 +9595,182 @@ void L2Pos_TetrahedronElement::ProjectDelta(int vertex, Vector &dofs) const
}
L2_WedgeElement::L2_WedgeElement(const int p, const int btype)
: NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
p, FunctionSpace::Qk),
TriangleFE(p, btype),
SegmentFE(p, btype)
{
#ifndef MFEM_THREAD_SAFE
t_shape.SetSize(TriangleFE.GetDof());
s_shape.SetSize(SegmentFE.GetDof());
t_dshape.SetSize(TriangleFE.GetDof(), 2);
s_dshape.SetSize(SegmentFE.GetDof(), 1);
#endif
t_dof.SetSize(Dof);
s_dof.SetSize(Dof);
// Interior DoFs
int m=0;
for (int k=0; k<=p; k++)
{
int l=0;
for (int j=0; j<=p; j++)
{
for (int i=0; i<=j; i++)
{
t_dof[m] = l;
s_dof[m] = k;
l++; m++;
}
}
}
// Define Nodes
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
for (int i=0; i<Dof; i++)
{
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
}
}
void L2_WedgeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
Vector s_shape(SegmentFE.GetDof());
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
SegmentFE.CalcShape(ipz, s_shape);
for (int i=0; i<Dof; i++)
{
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
}
}
void L2_WedgeElement::CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
Vector s_shape(SegmentFE.GetDof());
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
TriangleFE.CalcDShape(ip, t_dshape);
SegmentFE.CalcShape(ipz, s_shape);
SegmentFE.CalcDShape(ipz, s_dshape);
for (int i=0; i<Dof; i++)
{
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
}
}
L2Pos_WedgeElement::L2Pos_WedgeElement(const int p)
: PositiveFiniteElement(3, Geometry::PRISM,
((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
TriangleFE(p),
SegmentFE(p)
{
#ifndef MFEM_THREAD_SAFE
t_shape.SetSize(TriangleFE.GetDof());
s_shape.SetSize(SegmentFE.GetDof());
t_dshape.SetSize(TriangleFE.GetDof(), 2);
s_dshape.SetSize(SegmentFE.GetDof(), 1);
#endif
t_dof.SetSize(Dof);
s_dof.SetSize(Dof);
// Interior DoFs
int m=0;
for (int k=0; k<=p; k++)
{
int l=0;
for (int j=0; j<=p; j++)
{
for (int i=0; i<=j; i++)
{
t_dof[m] = l;
s_dof[m] = k;
l++; m++;
}
}
}
// Define Nodes
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
for (int i=0; i<Dof; i++)
{
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
}
}
void L2Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
Vector s_shape(SegmentFE.GetDof());
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
SegmentFE.CalcShape(ipz, s_shape);
for (int i=0; i<Dof; i++)
{
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
}
}
void L2Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const
{
#ifdef MFEM_THREAD_SAFE
Vector t_shape(TriangleFE.GetDof());
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
Vector s_shape(SegmentFE.GetDof());
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
#endif
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
TriangleFE.CalcShape(ip, t_shape);
TriangleFE.CalcDShape(ip, t_dshape);
SegmentFE.CalcShape(ipz, s_shape);
SegmentFE.CalcDShape(ipz, s_dshape);
for (int i=0; i<Dof; i++)
{
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
}
}
const double RT_QuadrilateralElement::nk[8] =
{ 0., -1., 1., 0., 0., 1., -1., 0. };
@@ -11227,4 +11845,25 @@ void NURBS3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
}
}
// Global object definitions
// Object declared in mesh/triangle.hpp.
// Defined here to ensure it is constructed before 'Geometries'.
Linear2DFiniteElement TriangleFE;
// Object declared in mesh/tetrahedron.hpp.
// Defined here to ensure it is constructed before 'Geometries'.
Linear3DFiniteElement TetrahedronFE;
// Object declared in mesh/wedge.hpp.
// Defined here to ensure it is constructed after 'poly1d' and before
// 'Geometries'.
H1_WedgeElement WedgeFE(1);
// Object declared in geom.hpp.
// Construct 'Geometries' after 'TriangleFE', 'TetrahedronFE', and 'WedgeFE'.
Geometry Geometries;
}
+192 -14
View File
@@ -140,13 +140,13 @@ class KnotVector;
class FiniteElement
{
protected:
int Dim, ///< Dimension of reference space
GeomType, ///< Geometry::Type of the reference element
FuncSpace, RangeType, MapType,
int Dim; ///< Dimension of reference space
Geometry::Type GeomType; ///< Geometry::Type of the reference element
int FuncSpace, RangeType, MapType,
DerivType, DerivRangeType, DerivMapType;
mutable
int Dof, ///< Number of degrees of freedom
Order; ///< Order/degree of the shape functions
int Dof, ///< Number of degrees of freedom
Order; ///< Order/degree of the shape functions
mutable int Orders[Geometry::MaxDim]; ///< Anisotropic orders
IntegrationRule Nodes;
#ifndef MFEM_THREAD_SAFE
@@ -205,13 +205,14 @@ public:
@param O Order/degree of the FiniteElement
@param F FunctionSpace type of the FiniteElement
*/
FiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk);
FiniteElement(int D, Geometry::Type G, int Do, int O,
int F = FunctionSpace::Pk);
/// Returns the reference space dimension for the finite element
int GetDim() const { return Dim; }
/// Returns the Geometry::Type of the reference element
int GetGeomType() const { return GeomType; }
Geometry::Type GetGeomType() const { return GeomType; }
/// Returns the number of degrees of freedom in the finite element
int GetDof() const { return Dof; }
@@ -336,6 +337,24 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const;
/** @brief Return a local restriction matrix @a R (Dof x Dof) mapping fine
dofs to coarse dofs.
The fine element is the image of the base geometry under the given
transformation, @a Trans.
The assumption in this method is that a subset of the coarse dofs can be
expressed only in terms of the dofs of the given fine element.
Rows in @a R corresponding to coarse dofs that cannot be expressed in
terms of the fine dofs will be marked as invalid by setting the first
entry (column 0) in the row to infinity().
This method assumes that the dimensions of @a R are set before it is
called. */
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const;
/** @brief Return interpolation matrix, @a I, which maps dofs from a coarse
element, @a fe, to the fine dofs on @a this finite element. */
/** @a Trans represents the mapping from the reference element of @a this
@@ -446,7 +465,8 @@ protected:
}
public:
ScalarFiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk)
ScalarFiniteElement(int D, Geometry::Type G, int Do, int O,
int F = FunctionSpace::Pk)
#ifdef MFEM_THREAD_SAFE
: FiniteElement(D, G, Do, O, F)
{ DerivType = GRAD; DerivRangeType = VECTOR; DerivMapType = H_CURL; }
@@ -484,13 +504,17 @@ protected:
DenseMatrix &curl) const;
public:
NodalFiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk)
NodalFiniteElement(int D, Geometry::Type G, int Do, int O,
int F = FunctionSpace::Pk)
: ScalarFiniteElement(D, G, Do, O, F) { }
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ NodalLocalInterpolation(Trans, I, *this); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const;
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -522,7 +546,7 @@ public:
class PositiveFiniteElement : public ScalarFiniteElement
{
public:
PositiveFiniteElement(int D, int G, int Do, int O,
PositiveFiniteElement(int D, Geometry::Type G, int Do, int O,
int F = FunctionSpace::Pk) :
ScalarFiniteElement(D, G, Do, O, F)
{ }
@@ -543,6 +567,9 @@ public:
virtual void Project(Coefficient &coeff,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
};
@@ -627,6 +654,14 @@ protected:
ElementTransformation &Trans,
DenseMatrix &I) const;
void LocalRestriction_RT(const double *nk, const Array<int> &d2n,
ElementTransformation &Trans,
DenseMatrix &R) const;
void LocalRestriction_ND(const double *tk, const Array<int> &d2t,
ElementTransformation &Trans,
DenseMatrix &R) const;
static const VectorFiniteElement &CheckVectorFE(const FiniteElement &fe)
{
if (fe.GetRangeType() != VECTOR)
@@ -635,7 +670,7 @@ protected:
}
public:
VectorFiniteElement (int D, int G, int Do, int O, int M,
VectorFiniteElement (int D, Geometry::Type G, int Do, int O, int M,
int F = FunctionSpace::Pk) :
#ifdef MFEM_THREAD_SAFE
FiniteElement(D, G, Do, O, F)
@@ -1018,6 +1053,7 @@ public:
{ dofs = 0.0; dofs(vertex) = 1.0; }
};
/// Crouzeix-Raviart finite element on triangle
class CrouzeixRaviartFiniteElement : public NodalFiniteElement
{
@@ -1682,14 +1718,16 @@ public:
Array will be empty. */
const Array<int> &GetDofMap() const { return dof_map; }
static int GetTensorProductGeometry(int dim)
static Geometry::Type GetTensorProductGeometry(int dim)
{
switch (dim)
{
case 1: return Geometry::SEGMENT;
case 2: return Geometry::SQUARE;
case 3: return Geometry::CUBE;
default: MFEM_ABORT("invalid dimension: " << dim); return -1;
default:
MFEM_ABORT("invalid dimension: " << dim);
return Geometry::INVALID;
}
}
@@ -1919,6 +1957,71 @@ public:
};
class H1_WedgeElement : public NodalFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector t_shape, s_shape;
mutable DenseMatrix t_dshape, s_dshape;
#endif
Array<int> t_dof, s_dof;
H1_TriangleElement TriangleFE;
H1_SegmentElement SegmentFE;
public:
H1_WedgeElement(const int p,
const int btype = BasisType::GaussLobatto);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
/// Class for linear FE on wedge
class BiLinear3DFiniteElement : public H1_WedgeElement
{
public:
/// Construct a linear FE on wedge
BiLinear3DFiniteElement() : H1_WedgeElement(1) {}
};
/// Class for quadratic FE on wedge
class BiQuadratic3DFiniteElement : public H1_WedgeElement
{
public:
/// Construct a quadratic FE on wedge
BiQuadratic3DFiniteElement() : H1_WedgeElement(2) {}
};
/// Class for cubic FE on wedge
class BiCubic3DFiniteElement : public H1_WedgeElement
{
public:
/// Construct a cubic FE on wedge
BiCubic3DFiniteElement() : H1_WedgeElement(3) {}
};
class H1Pos_WedgeElement : public PositiveFiniteElement
{
protected:
#ifndef MFEM_THREAD_SAFE
mutable Vector t_shape, s_shape;
mutable DenseMatrix t_dshape, s_dshape;
#endif
Array<int> t_dof, s_dof;
H1Pos_TriangleElement TriangleFE;
H1Pos_SegmentElement SegmentFE;
public:
H1Pos_WedgeElement(const int p);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
class L2_SegmentElement : public NodalTensorFiniteElement
{
private:
@@ -2096,6 +2199,53 @@ public:
};
class L2_WedgeElement : public NodalFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector t_shape, s_shape;
mutable DenseMatrix t_dshape, s_dshape;
#endif
Array<int> t_dof, s_dof;
L2_TriangleElement TriangleFE;
L2_SegmentElement SegmentFE;
public:
L2_WedgeElement(const int p,
const int btype = BasisType::GaussLegendre);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
class P0WedgeFiniteElement : public L2_WedgeElement
{
public:
P0WedgeFiniteElement () : L2_WedgeElement(0) {}
};
class L2Pos_WedgeElement : public PositiveFiniteElement
{
protected:
#ifndef MFEM_THREAD_SAFE
mutable Vector t_shape, s_shape;
mutable DenseMatrix t_dshape, s_dshape;
#endif
Array<int> t_dof, s_dof;
L2Pos_TriangleElement TriangleFE;
L2Pos_SegmentElement SegmentFE;
public:
L2Pos_WedgeElement(const int p);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
class RT_QuadrilateralElement : public VectorFiniteElement
{
private:
@@ -2122,6 +2272,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2175,6 +2328,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2221,6 +2377,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2273,6 +2432,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2324,6 +2486,10 @@ public:
DenseMatrix &I) const
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2381,6 +2547,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2427,6 +2596,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2478,6 +2650,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2521,6 +2696,9 @@ public:
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
@@ -2552,7 +2730,7 @@ protected:
mutable Vector weights;
public:
NURBSFiniteElement(int D, int G, int Do, int O, int F)
NURBSFiniteElement(int D, Geometry::Type G, int Do, int O, int F)
: ScalarFiniteElement(D, G, Do, O, F)
{
ijk = NULL;
+161 -107
View File
@@ -22,12 +22,15 @@ namespace mfem
using namespace std;
int FiniteElementCollection::HasFaceDofs(int GeomType) const
int FiniteElementCollection::HasFaceDofs(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::TETRAHEDRON: return DofForGeometry (Geometry::TRIANGLE);
case Geometry::CUBE: return DofForGeometry (Geometry::SQUARE);
case Geometry::PRISM:
return max(DofForGeometry (Geometry::TRIANGLE),
DofForGeometry (Geometry::SQUARE));
default:
mfem_error ("FiniteElementCollection::HasFaceDofs:"
" unknown geometry type.");
@@ -314,7 +317,7 @@ template <Geometry::Type geom, Geometry::Type f_geom,
typename v_t, typename e_t, typename eo_t>
inline void FiniteElementCollection::
GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
int &nf, int &f, int &fg, int &fo, const int face_info)
int &nf, int &f, Geometry::Type &fg, int &fo, const int face_info)
{
typedef typename Geometry::Constants< geom> g_consts;
typedef typename Geometry::Constants<f_geom> f_consts;
@@ -358,7 +361,8 @@ GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
}
}
void FiniteElementCollection::SubDofOrder(int Geom, int SDim, int Info,
void FiniteElementCollection::SubDofOrder(Geometry::Type Geom, int SDim,
int Info,
Array<int> &dofs) const
{
// Info = 64 * SubIndex + SubOrientation
@@ -380,8 +384,9 @@ void FiniteElementCollection::SubDofOrder(int Geom, int SDim, int Info,
}
else
{
int v[4], e[4], eo[4], f[1], fg[1], fo[1];
int v[4], e[4], eo[4], f[1], fo[1];
int av = 0, nv = 0, ae = 0, ne = 0, nf = 0;
Geometry::Type fg[1];
switch (Geom)
{
@@ -528,7 +533,7 @@ not_supp:
}
const FiniteElement *
LinearFECollection::FiniteElementForGeometry(int GeomType) const
LinearFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -538,13 +543,14 @@ LinearFECollection::FiniteElementForGeometry(int GeomType) const
case Geometry::SQUARE: return &QuadrilateralFE;
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
default:
mfem_error ("LinearFECollection: unknown geometry type.");
}
return &SegmentFE; // Make some compilers happy
}
int LinearFECollection::DofForGeometry(int GeomType) const
int LinearFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -554,20 +560,22 @@ int LinearFECollection::DofForGeometry(int GeomType) const
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 0;
case Geometry::PRISM: return 0;
default:
mfem_error ("LinearFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
int * LinearFECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *LinearFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
return NULL;
}
const FiniteElement *
QuadraticFECollection::FiniteElementForGeometry(int GeomType) const
QuadraticFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -577,13 +585,14 @@ QuadraticFECollection::FiniteElementForGeometry(int GeomType) const
case Geometry::SQUARE: return &QuadrilateralFE;
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
default:
mfem_error ("QuadraticFECollection: unknown geometry type.");
}
return &SegmentFE; // Make some compilers happy
}
int QuadraticFECollection::DofForGeometry(int GeomType) const
int QuadraticFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -593,13 +602,15 @@ int QuadraticFECollection::DofForGeometry(int GeomType) const
case Geometry::SQUARE: return 1;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 1;
case Geometry::PRISM: return 0;
default:
mfem_error ("QuadraticFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
int * QuadraticFECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *QuadraticFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
static int indexes[] = { 0 };
@@ -608,7 +619,8 @@ int * QuadraticFECollection::DofOrderForOrientation(int GeomType, int Or) const
const FiniteElement *
QuadraticPosFECollection::FiniteElementForGeometry(int GeomType) const
QuadraticPosFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -620,7 +632,7 @@ QuadraticPosFECollection::FiniteElementForGeometry(int GeomType) const
return NULL; // Make some compilers happy
}
int QuadraticPosFECollection::DofForGeometry(int GeomType) const
int QuadraticPosFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -633,8 +645,8 @@ int QuadraticPosFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * QuadraticPosFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *QuadraticPosFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
static int indexes[] = { 0 };
@@ -643,7 +655,7 @@ const
const FiniteElement *
CubicFECollection::FiniteElementForGeometry(int GeomType) const
CubicFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -653,13 +665,14 @@ CubicFECollection::FiniteElementForGeometry(int GeomType) const
case Geometry::SQUARE: return &QuadrilateralFE;
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
default:
mfem_error ("CubicFECollection: unknown geometry type.");
}
return &SegmentFE; // Make some compilers happy
}
int CubicFECollection::DofForGeometry(int GeomType) const
int CubicFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -669,13 +682,15 @@ int CubicFECollection::DofForGeometry(int GeomType) const
case Geometry::SQUARE: return 4;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 8;
case Geometry::PRISM: return 2;
default:
mfem_error ("CubicFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
int * CubicFECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *CubicFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SEGMENT)
{
@@ -709,7 +724,8 @@ int * CubicFECollection::DofOrderForOrientation(int GeomType, int Or) const
const FiniteElement *
CrouzeixRaviartFECollection::FiniteElementForGeometry(int GeomType) const
CrouzeixRaviartFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -722,7 +738,7 @@ CrouzeixRaviartFECollection::FiniteElementForGeometry(int GeomType) const
return &SegmentFE; // Make some compilers happy
}
int CrouzeixRaviartFECollection::DofForGeometry(int GeomType) const
int CrouzeixRaviartFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -736,8 +752,8 @@ int CrouzeixRaviartFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * CrouzeixRaviartFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *CrouzeixRaviartFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
static int indexes[] = { 0 };
@@ -746,7 +762,7 @@ const
const FiniteElement *
RT0_2DFECollection::FiniteElementForGeometry(int GeomType) const
RT0_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -759,7 +775,7 @@ RT0_2DFECollection::FiniteElementForGeometry(int GeomType) const
return &SegmentFE; // Make some compilers happy
}
int RT0_2DFECollection::DofForGeometry(int GeomType) const
int RT0_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -773,8 +789,8 @@ int RT0_2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RT0_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int * RT0_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
@@ -788,7 +804,7 @@ const
const FiniteElement *
RT1_2DFECollection::FiniteElementForGeometry(int GeomType) const
RT1_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -801,7 +817,7 @@ RT1_2DFECollection::FiniteElementForGeometry(int GeomType) const
return &SegmentFE; // Make some compilers happy
}
int RT1_2DFECollection::DofForGeometry(int GeomType) const
int RT1_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -815,8 +831,8 @@ int RT1_2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RT1_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *RT1_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
static int ind_pos[] = { 0, 1 };
static int ind_neg[] = { -2, -1 };
@@ -829,7 +845,7 @@ const
}
const FiniteElement *
RT2_2DFECollection::FiniteElementForGeometry(int GeomType) const
RT2_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -842,7 +858,7 @@ RT2_2DFECollection::FiniteElementForGeometry(int GeomType) const
return &SegmentFE; // Make some compilers happy
}
int RT2_2DFECollection::DofForGeometry(int GeomType) const
int RT2_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -856,8 +872,8 @@ int RT2_2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RT2_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *RT2_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
static int ind_pos[] = { 0, 1, 2 };
static int ind_neg[] = { -3, -2, -1 };
@@ -871,7 +887,7 @@ const
const FiniteElement *
Const2DFECollection::FiniteElementForGeometry(int GeomType) const
Const2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -883,7 +899,7 @@ Const2DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int Const2DFECollection::DofForGeometry(int GeomType) const
int Const2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -897,15 +913,16 @@ int Const2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * Const2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *Const2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
return NULL;
}
const FiniteElement *
LinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
LinearDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -917,7 +934,7 @@ LinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int LinearDiscont2DFECollection::DofForGeometry(int GeomType) const
int LinearDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -931,15 +948,16 @@ int LinearDiscont2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * LinearDiscont2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int * LinearDiscont2DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
GaussLinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
GaussLinearDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -952,7 +970,8 @@ GaussLinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int GaussLinearDiscont2DFECollection::DofForGeometry(int GeomType) const
int GaussLinearDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
const
{
switch (GeomType)
{
@@ -967,15 +986,15 @@ int GaussLinearDiscont2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * GaussLinearDiscont2DFECollection::DofOrderForOrientation(
int GeomType, int Or) const
const int *GaussLinearDiscont2DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
P1OnQuadFECollection::FiniteElementForGeometry(int GeomType) const
P1OnQuadFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
if (GeomType != Geometry::SQUARE)
{
@@ -984,7 +1003,7 @@ P1OnQuadFECollection::FiniteElementForGeometry(int GeomType) const
return &QuadrilateralFE;
}
int P1OnQuadFECollection::DofForGeometry(int GeomType) const
int P1OnQuadFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -997,15 +1016,16 @@ int P1OnQuadFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * P1OnQuadFECollection::DofOrderForOrientation(
int GeomType, int Or) const
const int *P1OnQuadFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
QuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
QuadraticDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1017,7 +1037,8 @@ QuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int QuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
int QuadraticDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
const
{
switch (GeomType)
{
@@ -1031,15 +1052,16 @@ int QuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * QuadraticDiscont2DFECollection::DofOrderForOrientation(
int GeomType, int Or) const
const int *QuadraticDiscont2DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1050,7 +1072,8 @@ QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
return NULL; // Make some compilers happy
}
int QuadraticPosDiscont2DFECollection::DofForGeometry(int GeomType) const
int QuadraticPosDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
const
{
switch (GeomType)
{
@@ -1065,7 +1088,8 @@ int QuadraticPosDiscont2DFECollection::DofForGeometry(int GeomType) const
const FiniteElement *
GaussQuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType)
GaussQuadraticDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType)
const
{
switch (GeomType)
@@ -1079,7 +1103,8 @@ const
return &QuadrilateralFE; // Make some compilers happy
}
int GaussQuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
int GaussQuadraticDiscont2DFECollection::DofForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1094,15 +1119,16 @@ int GaussQuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * GaussQuadraticDiscont2DFECollection::DofOrderForOrientation(
int GeomType, int Or) const
const int *GaussQuadraticDiscont2DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
CubicDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
CubicDiscont2DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1114,7 +1140,7 @@ CubicDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int CubicDiscont2DFECollection::DofForGeometry(int GeomType) const
int CubicDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1128,15 +1154,16 @@ int CubicDiscont2DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * CubicDiscont2DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *CubicDiscont2DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
LinearNonConf3DFECollection::FiniteElementForGeometry(int GeomType) const
LinearNonConf3DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1150,7 +1177,7 @@ LinearNonConf3DFECollection::FiniteElementForGeometry(int GeomType) const
return &TriangleFE; // Make some compilers happy
}
int LinearNonConf3DFECollection::DofForGeometry(int GeomType) const
int LinearNonConf3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1166,8 +1193,8 @@ int LinearNonConf3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * LinearNonConf3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *LinearNonConf3DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
static int indexes[] = { 0 };
@@ -1176,43 +1203,46 @@ const
const FiniteElement *
Const3DFECollection::FiniteElementForGeometry(int GeomType) const
Const3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
default:
mfem_error ("Const3DFECollection: unknown geometry type.");
}
return &TetrahedronFE; // Make some compilers happy
}
int Const3DFECollection::DofForGeometry(int GeomType) const
int Const3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::POINT: return 0;
case Geometry::SEGMENT: return 0;
case Geometry::TRIANGLE: return 0;
case Geometry::TETRAHEDRON: return 1;
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 1;
case Geometry::CUBE: return 1;
case Geometry::PRISM: return 1;
default:
mfem_error ("Const3DFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
int * Const3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *Const3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
return NULL;
}
const FiniteElement *
LinearDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
LinearDiscont3DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1224,7 +1254,7 @@ LinearDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
return &TetrahedronFE; // Make some compilers happy
}
int LinearDiscont3DFECollection::DofForGeometry(int GeomType) const
int LinearDiscont3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1240,15 +1270,16 @@ int LinearDiscont3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * LinearDiscont3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *LinearDiscont3DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
QuadraticDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
QuadraticDiscont3DFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1260,7 +1291,8 @@ QuadraticDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
return &TetrahedronFE; // Make some compilers happy
}
int QuadraticDiscont3DFECollection::DofForGeometry(int GeomType) const
int QuadraticDiscont3DFECollection::DofForGeometry(Geometry::Type GeomType)
const
{
switch (GeomType)
{
@@ -1276,14 +1308,15 @@ int QuadraticDiscont3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * QuadraticDiscont3DFECollection::DofOrderForOrientation(
int GeomType, int Or) const
const int *QuadraticDiscont3DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
return NULL;
}
const FiniteElement *
RefinedLinearFECollection::FiniteElementForGeometry(int GeomType) const
RefinedLinearFECollection::FiniteElementForGeometry(
Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1299,7 +1332,7 @@ RefinedLinearFECollection::FiniteElementForGeometry(int GeomType) const
return &SegmentFE; // Make some compilers happy
}
int RefinedLinearFECollection::DofForGeometry(int GeomType) const
int RefinedLinearFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1315,8 +1348,8 @@ int RefinedLinearFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RefinedLinearFECollection::DofOrderForOrientation(int GeomType,
int Or) const
const int *RefinedLinearFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or) const
{
static int indexes[] = { 0 };
@@ -1325,7 +1358,7 @@ int * RefinedLinearFECollection::DofOrderForOrientation(int GeomType,
const FiniteElement *
ND1_3DFECollection::FiniteElementForGeometry(int GeomType) const
ND1_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1337,7 +1370,7 @@ ND1_3DFECollection::FiniteElementForGeometry(int GeomType) const
return &HexahedronFE; // Make some compilers happy
}
int ND1_3DFECollection::DofForGeometry(int GeomType) const
int ND1_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1353,8 +1386,8 @@ int ND1_3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * ND1_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *ND1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
@@ -1368,7 +1401,7 @@ const
const FiniteElement *
RT0_3DFECollection::FiniteElementForGeometry(int GeomType) const
RT0_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1382,7 +1415,7 @@ RT0_3DFECollection::FiniteElementForGeometry(int GeomType) const
return &HexahedronFE; // Make some compilers happy
}
int RT0_3DFECollection::DofForGeometry(int GeomType) const
int RT0_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1398,8 +1431,8 @@ int RT0_3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RT0_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *RT0_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
@@ -1416,7 +1449,7 @@ const
}
const FiniteElement *
RT1_3DFECollection::FiniteElementForGeometry(int GeomType) const
RT1_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1429,7 +1462,7 @@ RT1_3DFECollection::FiniteElementForGeometry(int GeomType) const
return &HexahedronFE; // Make some compilers happy
}
int RT1_3DFECollection::DofForGeometry(int GeomType) const
int RT1_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -1444,8 +1477,8 @@ int RT1_3DFECollection::DofForGeometry(int GeomType) const
return 0; // Make some compilers happy
}
int * RT1_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
const
const int *RT1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SQUARE)
{
@@ -1468,6 +1501,9 @@ const
H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
{
MFEM_VERIFY(p >= 1, "H1_FECollection requires order >= 1.");
MFEM_VERIFY(dim >= 0 && dim <= 3, "H1_FECollection requires 0 <= dim <= 3.");
const int pm1 = p - 1, pm2 = pm1 - 1, pm3 = pm2 - 1;
int pt_type = BasisType::GetQuadrature1D(btype);
@@ -1601,22 +1637,26 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
{
H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
H1_dof[Geometry::CUBE] = QuadDof*pm1;
H1_dof[Geometry::PRISM] = TriDof*pm1;
if (b_type == BasisType::Positive)
{
H1_Elements[Geometry::TETRAHEDRON] = new H1Pos_TetrahedronElement(p);
H1_Elements[Geometry::CUBE] = new H1Pos_HexahedronElement(p);
H1_Elements[Geometry::PRISM] = new H1Pos_WedgeElement(p);
}
else
{
H1_Elements[Geometry::TETRAHEDRON] =
new H1_TetrahedronElement(p, btype);
H1_Elements[Geometry::CUBE] = new H1_HexahedronElement(p, btype);
H1_Elements[Geometry::PRISM] = new H1_WedgeElement(p, btype);
}
}
}
}
int *H1_FECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *H1_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SEGMENT)
{
@@ -1652,7 +1692,7 @@ FiniteElementCollection *H1_FECollection::GetTraceCollection() const
return (dim < 0) ? NULL : new H1_Trace_FECollection(p, dim, b_type);
}
const int *H1_FECollection::GetDofMap(int GeomType) const
const int *H1_FECollection::GetDofMap(Geometry::Type GeomType) const
{
const int *dof_map = NULL;
const FiniteElement *fe = H1_Elements[GeomType];
@@ -1708,6 +1748,8 @@ H1_Trace_FECollection::H1_Trace_FECollection(const int p, const int dim,
L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
const int map_type)
{
MFEM_VERIFY(p >= 0, "L2_FECollection requires order >= 0.");
b_type = BasisType::Check(btype);
const char *prefix = NULL;
switch (map_type)
@@ -1820,22 +1862,26 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
{
L2_Elements[Geometry::TETRAHEDRON] = new L2Pos_TetrahedronElement(p);
L2_Elements[Geometry::CUBE] = new L2Pos_HexahedronElement(p);
L2_Elements[Geometry::PRISM] = new L2Pos_WedgeElement(p);
}
else
{
L2_Elements[Geometry::TETRAHEDRON] =
new L2_TetrahedronElement(p, btype);
L2_Elements[Geometry::CUBE] = new L2_HexahedronElement(p, btype);
L2_Elements[Geometry::PRISM] = new L2_WedgeElement(p, btype);
}
L2_Elements[Geometry::TETRAHEDRON]->SetMapType(map_type);
L2_Elements[Geometry::CUBE]->SetMapType(map_type);
L2_Elements[Geometry::PRISM]->SetMapType(map_type);
// All trace element use the default Gauss-Legendre nodal points
Tr_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p);
Tr_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p);
const int TetDof = L2_Elements[Geometry::TETRAHEDRON]->GetDof();
const int HexDof = L2_Elements[Geometry::CUBE]->GetDof();
const int MaxDof = std::max(TetDof, HexDof);
const int PriDof = L2_Elements[Geometry::PRISM]->GetDof();
const int MaxDof = std::max(TetDof, std::max(PriDof, HexDof));
OtherDofOrd = new int[MaxDof];
for (int j = 0; j < MaxDof; j++)
{
@@ -1850,7 +1896,8 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
}
}
int *L2_FECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *L2_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
switch (GeomType)
{
@@ -1882,6 +1929,8 @@ RT_FECollection::RT_FECollection(const int p, const int dim,
const int cb_type, const int ob_type)
: ob_type(ob_type)
{
MFEM_VERIFY(p >= 0, "RT_FECollection requires order >= 0.");
int cp_type = BasisType::GetQuadrature1D(cb_type);
int op_type = BasisType::GetQuadrature1D(ob_type);
@@ -2069,7 +2118,8 @@ void RT_FECollection::InitFaces(const int p, const int dim, const int map_type,
}
}
int *RT_FECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *RT_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SEGMENT)
{
@@ -2157,6 +2207,9 @@ DG_Interface_FECollection::DG_Interface_FECollection(const int p, const int dim,
ND_FECollection::ND_FECollection(const int p, const int dim,
const int cb_type, const int ob_type)
{
MFEM_VERIFY(p >= 1, "ND_FECollection requires order >= 1.");
MFEM_VERIFY(dim >= 1 && dim <= 3, "ND_FECollection requires 1 <= dim <= 3.");
const int pm1 = p - 1, pm2 = p - 2;
if (cb_type == BasisType::GaussLobatto &&
@@ -2310,7 +2363,8 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
}
}
int *ND_FECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *ND_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
if (GeomType == Geometry::SEGMENT)
{
@@ -2320,8 +2374,7 @@ int *ND_FECollection::DofOrderForOrientation(int GeomType, int Or) const
{
if (Or != 0 && Or != 5)
{
MFEM_ABORT("ND_FECollection::DofOrderForOrientation: "
"triangle face orientation " << Or << " is not supported! "
MFEM_ABORT("triangle face orientation " << Or << " is not supported! "
"Use Mesh::ReorientTetMesh to fix it.");
}
return TriDofOrd[Or%6];
@@ -2457,7 +2510,7 @@ NURBSFECollection::~NURBSFECollection()
}
const FiniteElement *
NURBSFECollection::FiniteElementForGeometry(int GeomType) const
NURBSFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
@@ -2470,13 +2523,14 @@ NURBSFECollection::FiniteElementForGeometry(int GeomType) const
return SegmentFE; // Make some compilers happy
}
int NURBSFECollection::DofForGeometry(int GeomType) const
int NURBSFECollection::DofForGeometry(Geometry::Type GeomType) const
{
mfem_error("NURBSFECollection::DofForGeometry");
return 0; // Make some compilers happy
}
int *NURBSFECollection::DofOrderForOrientation(int GeomType, int Or) const
const int *NURBSFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{
mfem_error("NURBSFECollection::DofOrderForOrientation");
return NULL;
+148 -104
View File
@@ -36,23 +36,26 @@ protected:
template <Geometry::Type geom, Geometry::Type f_geom,
typename v_t, typename e_t, typename eo_t>
static inline void GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
int &nf, int &f, int &fg, int &fo,
int &nf, int &f, Geometry::Type &fg, int &fo,
const int face_info);
public:
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const = 0;
FiniteElementForGeometry(Geometry::Type GeomType) const = 0;
virtual int DofForGeometry(int GeomType) const = 0;
virtual int DofForGeometry(Geometry::Type GeomType) const = 0;
virtual int * DofOrderForOrientation(int GeomType, int Or) const = 0;
/** @brief Returns an array, say p, that maps a local permuted index i to
a local base index: base_i = p[i]. */
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const = 0;
virtual const char * Name() const { return "Undefined"; }
int HasFaceDofs(int GeomType) const;
int HasFaceDofs(Geometry::Type GeomType) const;
virtual const FiniteElement *TraceFiniteElementForGeometry(
int GeomType) const
Geometry::Type GeomType) const
{
return FiniteElementForGeometry(GeomType);
}
@@ -72,7 +75,8 @@ public:
the sub-manifold (inside Geom) and its orientation are given by the
parameter Info = 64 * SubIndex + SubOrientation. Naturally, it is assumed
that 0 <= SDim <= Dim(Geom). */
void SubDofOrder(int Geom, int SDim, int Info, Array<int> &dofs) const;
void SubDofOrder(Geometry::Type Geom, int SDim, int Info,
Array<int> &dofs) const;
};
/// Arbitrary order H1-conforming (continuous) finite elements.
@@ -90,17 +94,19 @@ public:
explicit H1_FECollection(const int p, const int dim = 3,
const int btype = BasisType::GaussLobatto);
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const
{ return H1_Elements[GeomType]; }
virtual int DofForGeometry(int GeomType) const
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return H1_dof[GeomType]; }
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char *Name() const { return h1_name; }
FiniteElementCollection *GetTraceCollection() const;
int GetBasisType() const { return b_type; }
/// Get the Cartesian to local H1 dof map
const int *GetDofMap(int GeomType) const;
const int *GetDofMap(Geometry::Type GeomType) const;
virtual ~H1_FECollection();
};
@@ -141,9 +147,10 @@ public:
const int btype = BasisType::GaussLegendre,
const int map_type = FiniteElement::VALUE);
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const
{ return L2_Elements[GeomType]; }
virtual int DofForGeometry(int GeomType) const
virtual int DofForGeometry(Geometry::Type GeomType) const
{
if (L2_Elements[GeomType])
{
@@ -151,11 +158,12 @@ public:
}
return 0;
}
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char *Name() const { return d_name; }
virtual const FiniteElement *TraceFiniteElementForGeometry(
int GeomType) const
Geometry::Type GeomType) const
{
return Tr_Elements[GeomType];
}
@@ -193,11 +201,13 @@ public:
const int cb_type = BasisType::GaussLobatto,
const int ob_type = BasisType::GaussLegendre);
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type GeomType) const
{ return RT_Elements[GeomType]; }
virtual int DofForGeometry(int GeomType) const
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return RT_dof[GeomType]; }
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char *Name() const { return rt_name; }
FiniteElementCollection *GetTraceCollection() const;
@@ -240,11 +250,13 @@ public:
const int cb_type = BasisType::GaussLobatto,
const int ob_type = BasisType::GaussLegendre);
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
virtual const FiniteElement *FiniteElementForGeometry(Geometry::Type GeomType)
const
{ return ND_Elements[GeomType]; }
virtual int DofForGeometry(int GeomType) const
virtual int DofForGeometry(Geometry::Type GeomType) const
{ return ND_dof[GeomType]; }
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char *Name() const { return nd_name; }
FiniteElementCollection *GetTraceCollection() const;
@@ -301,11 +313,12 @@ public:
void SetOrder(int Order) const;
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char *Name() const { return name; }
@@ -325,15 +338,17 @@ private:
const BiLinear2DFiniteElement QuadrilateralFE;
const Linear3DFiniteElement TetrahedronFE;
const TriLinear3DFiniteElement ParallelepipedFE;
const H1_WedgeElement WedgeFE;
public:
LinearFECollection() { }
LinearFECollection() : WedgeFE(1) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "Linear"; }
};
@@ -348,16 +363,18 @@ private:
const BiQuad2DFiniteElement QuadrilateralFE;
const Quadratic3DFiniteElement TetrahedronFE;
const LagrangeHexFiniteElement ParallelepipedFE;
const H1_WedgeElement WedgeFE;
public:
QuadraticFECollection() : ParallelepipedFE(2) { }
QuadraticFECollection() : ParallelepipedFE(2), WedgeFE(2) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "Quadratic"; }
};
@@ -373,11 +390,12 @@ public:
QuadraticPosFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "QuadraticPos"; }
};
@@ -392,16 +410,19 @@ private:
const BiCubic2DFiniteElement QuadrilateralFE;
const Cubic3DFiniteElement TetrahedronFE;
const LagrangeHexFiniteElement ParallelepipedFE;
const H1_WedgeElement WedgeFE;
public:
CubicFECollection() : ParallelepipedFE(3) { }
CubicFECollection()
: ParallelepipedFE(3), WedgeFE(3, BasisType::ClosedUniform) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "Cubic"; }
};
@@ -417,11 +438,12 @@ public:
CrouzeixRaviartFECollection() : SegmentFE(1) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "CrouzeixRaviart"; }
};
@@ -439,11 +461,12 @@ public:
LinearNonConf3DFECollection () { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "LinearNonConf3D"; }
};
@@ -461,11 +484,12 @@ public:
RT0_2DFECollection() : SegmentFE(0) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT0_2D"; }
};
@@ -482,11 +506,12 @@ public:
RT1_2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT1_2D"; }
};
@@ -503,11 +528,12 @@ public:
RT2_2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT2_2D"; }
};
@@ -523,11 +549,12 @@ public:
Const2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "Const2D"; }
};
@@ -544,11 +571,12 @@ public:
LinearDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "LinearDiscont2D"; }
};
@@ -565,11 +593,12 @@ public:
GaussLinearDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "GaussLinearDiscont2D"; }
};
@@ -582,9 +611,10 @@ private:
public:
P1OnQuadFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "P1OnQuad"; }
};
@@ -600,11 +630,12 @@ public:
QuadraticDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "QuadraticDiscont2D"; }
};
@@ -618,9 +649,10 @@ private:
public:
QuadraticPosDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{ return NULL; }
virtual const char * Name() const { return "QuadraticPosDiscont2D"; }
};
@@ -637,11 +669,12 @@ public:
GaussQuadraticDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "GaussQuadraticDiscont2D"; }
};
@@ -658,11 +691,12 @@ public:
CubicDiscont2DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "CubicDiscont2D"; }
};
@@ -674,16 +708,18 @@ class Const3DFECollection : public FiniteElementCollection
private:
const P0TetFiniteElement TetrahedronFE;
const P0HexFiniteElement ParallelepipedFE;
const L2_WedgeElement WedgeFE;
public:
Const3DFECollection () { }
Const3DFECollection() : WedgeFE(0) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "Const3D"; }
};
@@ -700,11 +736,12 @@ public:
LinearDiscont3DFECollection () { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "LinearDiscont3D"; }
};
@@ -721,11 +758,12 @@ public:
QuadraticDiscont3DFECollection () : ParallelepipedFE(2) { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "QuadraticDiscont3D"; }
};
@@ -745,11 +783,12 @@ public:
RefinedLinearFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RefinedLinear"; }
};
@@ -766,11 +805,12 @@ public:
ND1_3DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "ND1_3D"; }
};
@@ -788,11 +828,12 @@ public:
RT0_3DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT0_3D"; }
};
@@ -809,11 +850,12 @@ public:
RT1_3DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(int GeomType) const;
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(int GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT1_3D"; }
};
@@ -823,17 +865,19 @@ class Local_FECollection : public FiniteElementCollection
{
private:
char d_name[32];
int GeomType;
Geometry::Type GeomType;
FiniteElement *Local_Element;
public:
Local_FECollection(const char *fe_name);
virtual const FiniteElement *FiniteElementForGeometry(int _GeomType) const
virtual const FiniteElement *FiniteElementForGeometry(
Geometry::Type _GeomType) const
{ return (GeomType == _GeomType) ? Local_Element : NULL; }
virtual int DofForGeometry(int _GeomType) const
virtual int DofForGeometry(Geometry::Type _GeomType) const
{ return (GeomType == _GeomType) ? Local_Element->GetDof() : 0; }
virtual int *DofOrderForOrientation(int GeomType, int Or) const
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const
{ return NULL; }
virtual const char *Name() const { return d_name; }
+151 -112
View File
@@ -93,13 +93,13 @@ FiniteElementSpace::FiniteElementSpace(const FiniteElementSpace &orig,
int FiniteElementSpace::GetOrder(int i) const
{
int GeomType = mesh->GetElementBaseGeometry(i);
Geometry::Type GeomType = mesh->GetElementBaseGeometry(i);
return fec->FiniteElementForGeometry(GeomType)->GetOrder();
}
int FiniteElementSpace::GetFaceOrder(int i) const
{
int GeomType = mesh->GetFaceBaseGeometry(i);
Geometry::Type GeomType = mesh->GetFaceBaseGeometry(i);
return fec->FiniteElementForGeometry(GeomType)->GetOrder();
}
@@ -497,23 +497,27 @@ FiniteElementSpace::H2L_GlobalRestrictionMatrix (FiniteElementSpace *lfes)
R = new SparseMatrix (lfes -> GetNDofs(), ndofs);
if (!lfes->GetNE())
{
R->Finalize();
return R;
}
const FiniteElement *h_fe = this -> GetFE (0);
const FiniteElement *l_fe = lfes -> GetFE (0);
Geometry::Type cached_geom = Geometry::INVALID;
const FiniteElement *h_fe = NULL;
const FiniteElement *l_fe = NULL;
IsoparametricTransformation T;
T.SetIdentityTransformation(h_fe->GetGeomType());
h_fe->Project(*l_fe, T, loc_restr);
for (int i = 0; i < mesh -> GetNE(); i++)
{
this -> GetElementDofs (i, h_dofs);
lfes -> GetElementDofs (i, l_dofs);
// Assuming 'loc_restr' depends only on the Geometry::Type.
const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
if (geom != cached_geom)
{
h_fe = this -> GetFE (i);
l_fe = lfes -> GetFE (i);
T.SetIdentityTransformation(h_fe->GetGeomType());
h_fe->Project(*l_fe, T, loc_restr);
cached_geom = geom;
}
R -> SetSubMatrix (l_dofs, h_dofs, loc_restr, 1);
}
@@ -599,7 +603,7 @@ void FiniteElementSpace::BuildConformingInterpolation() const
if (entity > 1) { T.SetFE(&QuadrilateralFE); }
else { T.SetFE(&SegmentFE); }
int geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
Geometry::Type geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
const FiniteElement* fe = fec->FiniteElementForGeometry(geom);
if (!fe) { continue; }
@@ -780,17 +784,25 @@ int FiniteElementSpace::GetNConformingDofs() const
SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
const int coarse_ndofs, const Table &coarse_elem_dof,
const DenseTensor &localP) const
const DenseTensor localP[]) const
{
MFEM_VERIFY(mesh->GetLastOperation() == Mesh::REFINE, "");
Array<int> dofs, coarse_dofs, coarse_vdofs;
Vector row;
const int coarse_ldof = localP.SizeJ();
const int fine_ldof = localP.SizeI();
SparseMatrix *P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim,
coarse_ldof);
Mesh::GeometryList elem_geoms(*mesh);
SparseMatrix *P;
if (elem_geoms.Size() == 1)
{
const int coarse_ldof = localP[elem_geoms[0]].SizeJ();
P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim, coarse_ldof);
}
else
{
P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim);
}
Array<int> mark(P->Height());
mark = 0;
@@ -800,7 +812,9 @@ SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
for (int k = 0; k < mesh->GetNE(); k++)
{
const Embedding &emb = rtrans.embeddings[k];
const DenseMatrix &lP = localP(emb.matrix);
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
const DenseMatrix &lP = localP[geom](emb.matrix);
const int fine_ldof = localP[geom].SizeI();
elem_dof->GetRow(k, dofs);
coarse_elem_dof.GetRow(emb.parent, coarse_dofs);
@@ -826,17 +840,19 @@ SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
}
MFEM_ASSERT(mark.Sum() == P->Height(), "Not all rows of P set.");
if (elem_geoms.Size() != 1) { P->Finalize(); }
return P;
}
void FiniteElementSpace::GetLocalRefinementMatrices(DenseTensor &localP) const
void FiniteElementSpace::GetLocalRefinementMatrices(
Geometry::Type geom, DenseTensor &localP) const
{
int geom = mesh->GetElementBaseGeometry(); // assuming the same geom
const FiniteElement *fe = fec->FiniteElementForGeometry(geom);
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
const DenseTensor &pmats = rtrans.GetPointMatrices(geom);
int nmat = rtrans.point_matrices.SizeK();
int nmat = pmats.SizeK();
int ldof = fe->GetDof(); // assuming the same FE everywhere
IsoparametricTransformation isotr;
@@ -846,7 +862,7 @@ void FiniteElementSpace::GetLocalRefinementMatrices(DenseTensor &localP) const
localP.SetSize(ldof, ldof, nmat);
for (int i = 0; i < nmat; i++)
{
isotr.GetPointMat() = rtrans.point_matrices(i);
isotr.GetPointMat() = pmats(i);
isotr.FinalizeTransformation();
fe->GetLocalInterpolation(isotr, localP(i));
}
@@ -857,8 +873,13 @@ SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
{
MFEM_VERIFY(ndofs >= old_ndofs, "Previous space is not coarser.");
DenseTensor localP;
GetLocalRefinementMatrices(localP);
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
}
return RefinementMatrix_main(old_ndofs, *old_elem_dof, localP);
}
@@ -874,7 +895,12 @@ FiniteElementSpace::RefinementOperator::RefinementOperator
width = old_ndofs * fespace->GetVDim();
height = fespace->GetVSize();
fespace->GetLocalRefinementMatrices(localP);
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
for (int i = 0; i < elem_geoms.Size(); i++)
{
fespace->GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
}
}
FiniteElementSpace::RefinementOperator::RefinementOperator(
@@ -882,7 +908,14 @@ FiniteElementSpace::RefinementOperator::RefinementOperator(
: Operator(fespace->GetVSize(), coarse_fes->GetVSize()),
fespace(fespace), old_elem_dof(NULL)
{
fespace->GetLocalRefinementMatrices(*coarse_fes, localP);
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
for (int i = 0; i < elem_geoms.Size(); i++)
{
fespace->GetLocalRefinementMatrices(*coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
}
// Make a copy of the coarse elem_dof Table.
old_elem_dof = new Table(coarse_fes->GetElementToDofTable());
}
@@ -909,7 +942,8 @@ void FiniteElementSpace::RefinementOperator
for (int k = 0; k < mesh->GetNE(); k++)
{
const Embedding &emb = rtrans.embeddings[k];
const DenseMatrix &lP = localP(emb.matrix);
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
const DenseMatrix &lP = localP[geom](emb.matrix);
fespace->GetElementDofs(k, dofs);
old_elem_dof->GetRow(emb.parent, old_dofs);
@@ -941,70 +975,29 @@ void FiniteElementSpace::RefinementOperator
}
}
void InvertLinearTrans(IsoparametricTransformation &trans,
const DenseMatrix &invdfdx,
const IntegrationPoint &pt, Vector &x)
void FiniteElementSpace::GetLocalDerefinementMatrices(Geometry::Type geom,
DenseTensor &localR) const
{
// invert a linear transform with one Newton step
IntegrationPoint p0;
p0.Set3(0, 0, 0);
trans.Transform(p0, x);
double store[3];
Vector v(store, x.Size());
pt.Get(v, x.Size());
v -= x;
invdfdx.Mult(v, x);
}
void FiniteElementSpace::GetLocalDerefinementMatrices(DenseTensor &localR) const
{
int geom = mesh->GetElementBaseGeometry(); // assuming the same geom
const FiniteElement *fe = fec->FiniteElementForGeometry(geom);
const IntegrationRule &nodes = fe->GetNodes();
const CoarseFineTransformations &dtrans =
mesh->ncmesh->GetDerefinementTransforms();
const DenseTensor &pmats = dtrans.GetPointMatrices(geom);
int nmat = dtrans.point_matrices.SizeK();
int ldof = fe->GetDof();
int dim = mesh->Dimension();
const int nmat = pmats.SizeK();
const int ldof = fe->GetDof();
LinearFECollection linfec;
IsoparametricTransformation isotr;
isotr.SetFE(linfec.FiniteElementForGeometry(geom));
DenseMatrix invdfdx(dim);
IntegrationPoint ipt;
Vector pt(&ipt.x, dim), shape(ldof);
isotr.SetIdentityTransformation(geom);
// calculate local restriction matrices for all refinement types
localR.SetSize(ldof, ldof, nmat);
for (int i = 0; i < nmat; i++)
{
DenseMatrix &lR = localR(i);
lR = infinity(); // marks invalid rows
isotr.GetPointMat() = dtrans.point_matrices(i);
isotr.GetPointMat() = pmats(i);
isotr.FinalizeTransformation();
isotr.SetIntPoint(&nodes[0]);
CalcInverse(isotr.Jacobian(), invdfdx);
for (int j = 0; j < nodes.Size(); j++)
{
InvertLinearTrans(isotr, invdfdx, nodes[j], pt);
if (Geometries.CheckPoint(geom, ipt)) // do we need an epsilon here?
{
IntegrationPoint ip;
ip.Set(pt, dim);
MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(fe),
"only nodal FEs are implemented");
fe->CalcShape(ip, shape); // TODO: H(curl), etc.?
lR.SetRow(j, shape);
}
}
lR.Threshold(1e-12);
fe->GetLocalRestriction(isotr, localR(i));
}
}
@@ -1018,21 +1011,38 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
Array<int> dofs, old_dofs, old_vdofs;
Vector row;
DenseTensor localR;
GetLocalDerefinementMatrices(localR);
Mesh::GeometryList elem_geoms(*mesh);
SparseMatrix *R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim,
localR.SizeI());
DenseTensor localR[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalDerefinementMatrices(elem_geoms[i], localR[elem_geoms[i]]);
}
SparseMatrix *R;
if (elem_geoms.Size() == 1)
{
R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim,
localR[elem_geoms[0]].SizeI());
}
else
{
R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim);
}
Array<int> mark(R->Height());
mark = 0;
const CoarseFineTransformations &dtrans =
mesh->ncmesh->GetDerefinementTransforms();
MFEM_ASSERT(dtrans.embeddings.Size() == old_elem_dof->Size(), "");
int num_marked = 0;
for (int k = 0; k < dtrans.embeddings.Size(); k++)
{
const Embedding &emb = dtrans.embeddings[k];
DenseMatrix &lR = localR(emb.matrix);
const Geometry::Type geom = mesh->GetElementBaseGeometry(emb.parent);
DenseMatrix &lR = localR[geom](emb.matrix);
elem_dof->GetRow(emb.parent, dofs);
old_elem_dof->GetRow(k, old_dofs);
@@ -1054,36 +1064,41 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
lR.GetRow(i, row);
R->SetRow(r, old_vdofs, row);
mark[m] = 1;
num_marked++;
}
}
}
}
MFEM_ASSERT(mark.Sum() == R->Height(), "Not all rows of R set.");
MFEM_VERIFY(num_marked == R->Height(),
"internal error: not all rows of R were set.");
if (elem_geoms.Size() != 1) { R->Finalize(); }
return R;
}
void FiniteElementSpace::GetLocalRefinementMatrices(
const FiniteElementSpace &coarse_fes, DenseTensor &localP) const
const FiniteElementSpace &coarse_fes, Geometry::Type geom,
DenseTensor &localP) const
{
// Assumptions: see the declaration of the method.
int fine_geom = mesh->GetElementBaseGeometry(0);
const FiniteElement *fine_fe = fec->FiniteElementForGeometry(fine_geom);
const FiniteElement *coarse_fe = coarse_fes.GetFE(0);
const FiniteElement *fine_fe = fec->FiniteElementForGeometry(geom);
const FiniteElement *coarse_fe =
coarse_fes.fec->FiniteElementForGeometry(geom);
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
const DenseTensor &pmats = rtrans.GetPointMatrices(geom);
int nmat = rtrans.point_matrices.SizeK();
int nmat = pmats.SizeK();
IsoparametricTransformation isotr;
isotr.SetIdentityTransformation(fine_geom);
isotr.SetIdentityTransformation(geom);
// Calculate the local interpolation matrices for all refinement types
localP.SetSize(fine_fe->GetDof(), coarse_fe->GetDof(), nmat);
for (int i = 0; i < nmat; i++)
{
isotr.GetPointMat() = rtrans.point_matrices(i);
isotr.GetPointMat() = pmats(i);
isotr.FinalizeTransformation();
fine_fe->GetTransferMatrix(*coarse_fe, isotr, localP(i));
}
@@ -1191,22 +1206,25 @@ void FiniteElementSpace::Construct()
cP_is_set = false;
// Th is initialized/destroyed before this method is called.
if (mesh->Dimension() == 3 && mesh->GetNE())
if (mesh->GetNFaces() > 0)
{
// Here we assume that all faces in the mesh have the same base
// geometry -- the base geometry of the 0-th face element.
// The class Mesh assumes the same inside GetFaceBaseGeometry(...).
// Thus we do not need to generate all the faces in the mesh
// if we do not need them.
int fdof = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
if (fdof > 0)
bool have_face_dofs = false;
for (int g = Geometry::DimStart[2]; g < Geometry::DimStart[3]; g++)
{
if (mesh->HasGeometry(Geometry::Type(g)) &&
fec->DofForGeometry(Geometry::Type(g)) > 0)
{
have_face_dofs = true;
break;
}
}
if (have_face_dofs)
{
fdofs = new int[mesh->GetNFaces()+1];
fdofs[0] = 0;
for (int i = 0; i < mesh->GetNFaces(); i++)
{
nfdofs += fdof;
// nfdofs += fec->DofForGeometry(mesh->GetFaceBaseGeometry(i));
nfdofs += fec->DofForGeometry(mesh->GetFaceBaseGeometry(i));
fdofs[i+1] = nfdofs;
}
}
@@ -1218,7 +1236,7 @@ void FiniteElementSpace::Construct()
bdofs[0] = 0;
for (int i = 0; i < mesh->GetNE(); i++)
{
int geom = mesh->GetElementBaseGeometry(i);
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
nbdofs += fec->DofForGeometry(geom);
bdofs[i+1] = nbdofs;
}
@@ -1239,8 +1257,8 @@ void FiniteElementSpace::GetElementDofs (int i, Array<int> &dofs) const
else
{
Array<int> V, E, Eo, F, Fo;
int k, j, nv, ne, nf, nb, nfd, nd;
int *ind, dim;
int k, j, nv, ne, nf, nb, nfd, nd, dim;
const int *ind;
dim = mesh->Dimension();
nv = fec->DofForGeometry(Geometry::POINT);
@@ -1354,8 +1372,8 @@ void FiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
else
{
Array<int> V, E, Eo;
int k, j, nv, ne, nf, nd, iF, oF;
int *ind, dim;
int k, j, nv, ne, nf, nd, iF, oF, dim;
const int *ind;
dim = mesh->Dimension();
nv = fec->DofForGeometry(Geometry::POINT);
@@ -1411,8 +1429,8 @@ void FiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
// if (dim == 3)
{
ne = nv + ne * E.Size();
ind = (fec->DofOrderForOrientation(
mesh->GetBdrElementBaseGeometry(i), oF));
ind = fec->DofOrderForOrientation(
mesh->GetBdrElementBaseGeometry(i), oF);
for (j = 0; j < nf; j++)
{
if (ind[j] < 0)
@@ -1623,7 +1641,7 @@ const FiniteElement *FiniteElementSpace::GetEdgeElement(int i) const
}
const FiniteElement *FiniteElementSpace::GetTraceElement(
int i, int geom_type) const
int i, Geometry::Type geom_type) const
{
return fec->TraceFiniteElementForGeometry(geom_type);
}
@@ -1663,8 +1681,14 @@ void FiniteElementSpace::GetTransferOperator(
if (T.Type() == Operator::MFEM_SPARSEMAT)
{
DenseTensor localP;
GetLocalRefinementMatrices(coarse_fes, localP);
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalRefinementMatrices(coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
}
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
coarse_fes.GetElementToDofTable(),
localP));
@@ -1812,8 +1836,9 @@ void FiniteElementSpace::Save(std::ostream &out) const
const double eps = 5e-14;
nurbs_unit_weights = (NURBSext->GetWeights().Min() >= 1.0-eps &&
NURBSext->GetWeights().Max() <= 1.0+eps);
if (NURBSext->GetOrder() == NURBSFECollection::VariableOrder ||
(NURBSext != mesh->NURBSext && !nurbs_unit_weights))
if ((NURBSext->GetOrder() == NURBSFECollection::VariableOrder) ||
(NURBSext != mesh->NURBSext && !nurbs_unit_weights) ||
(NURBSext->GetMaster().Size() != 0 ))
{
fes_format = 100; // v1.0 format
}
@@ -1843,6 +1868,13 @@ void FiniteElementSpace::Save(std::ostream &out) const
// 1 = do not write the size, just the entries:
NURBSext->GetOrders().Save(out, 1);
}
// If periodic BCs are given, write connectivity
if (NURBSext->GetMaster().Size() != 0 )
{
out <<"NURBS_periodic\n";
NURBSext->GetMaster().Save(out);
NURBSext->GetSlave().Save(out);
}
// If the weights are not unit, write them to the output:
if (!nurbs_unit_weights)
{
@@ -1920,6 +1952,13 @@ FiniteElementCollection *FiniteElementSpace::Load(Mesh *m, std::istream &input)
NURBSext = new NURBSExtension(m->NURBSext, orders);
}
}
else if (buff == "NURBS_periodic")
{
Array<int> master, slave;
master.Load(input);
slave.Load(input);
NURBSext->ConnectBoundaries(master,slave);
}
else if (buff == "NURBS_weights")
{
MFEM_VERIFY(NURBSext, "NURBS_weights: NURBS_orders have to be "
+15 -9
View File
@@ -136,7 +136,7 @@ protected:
class RefinementOperator : public Operator
{
const FiniteElementSpace* fespace;
DenseTensor localP;
DenseTensor localP[Geometry::NumGeom];
Table* old_elem_dof; // Owned.
public:
@@ -152,15 +152,18 @@ protected:
// This method makes the same assumptions as the method:
// void GetLocalRefinementMatrices(
// const FiniteElementSpace &coarse_fes, DenseTensor &localP) const
// const FiniteElementSpace &coarse_fes, Geometry::Type geom,
// DenseTensor &localP) const
// which is defined below. It also assumes that the coarse fes and this have
// the same vector dimension, vdim.
SparseMatrix *RefinementMatrix_main(const int coarse_ndofs,
const Table &coarse_elem_dof,
const DenseTensor &localP) const;
const DenseTensor localP[]) const;
void GetLocalRefinementMatrices(DenseTensor &localP) const;
void GetLocalDerefinementMatrices(DenseTensor &localR) const;
void GetLocalRefinementMatrices(Geometry::Type geom,
DenseTensor &localP) const;
void GetLocalDerefinementMatrices(Geometry::Type geom,
DenseTensor &localR) const;
/** Calculate explicit GridFunction interpolation matrix (after mesh
refinement). NOTE: consider using the RefinementOperator class instead
@@ -173,10 +176,10 @@ protected:
// This method assumes that this->mesh is a refinement of coarse_fes->mesh
// and that the CoarseFineTransformations of this->mesh are set accordingly.
// Another assumption is that the FEs of this use the same MapType as the FEs
// of coarse_fes. Finally, it assumes that this->mesh and coarse_fes->mesh
// are NOT mixed meshes, and that the spaces this and coarse_fes are NOT
// variable-order spaces.
// of coarse_fes. Finally, it assumes that the spaces this and coarse_fes are
// NOT variable-order spaces.
void GetLocalRefinementMatrices(const FiniteElementSpace &coarse_fes,
Geometry::Type geom,
DenseTensor &localP) const;
/// Help function for constructors + Load().
@@ -266,8 +269,11 @@ public:
const FiniteElementCollection *FEColl() const { return fec; }
/// Number of all scalar vertex dofs
int GetNVDofs() const { return nvdofs; }
/// Number of all scalar edge-interior dofs
int GetNEDofs() const { return nedofs; }
/// Number of all scalar face-interior dofs
int GetNFDofs() const { return nfdofs; }
/// Returns number of vertices in the mesh.
@@ -398,7 +404,7 @@ public:
const FiniteElement *GetEdgeElement(int i) const;
/// Return the trace element from element 'i' to the given 'geom_type'
const FiniteElement *GetTraceElement(int i, int geom_type) const;
const FiniteElement *GetTraceElement(int i, Geometry::Type geom_type) const;
/** Mark degrees of freedom associated with boundary elements with
the specified boundary attributes (marked in 'bdr_attr_is_ess').
+216 -23
View File
@@ -10,15 +10,16 @@
// Software Foundation) version 2.1 dated February 1999.
#include "fem.hpp"
#include "../mesh/wedge.hpp"
namespace mfem
{
const char *Geometry::Name[NumGeom] =
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube" };
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism" };
const double Geometry::Volume[NumGeom] =
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0 };
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5 };
Geometry::Geometry()
{
@@ -112,6 +113,32 @@ Geometry::Geometry()
GeomVert[5]->IntPoint(7).y = 1.0;
GeomVert[5]->IntPoint(7).z = 1.0;
// Vertices for Geometry::PRISM
GeomVert[6] = new IntegrationRule(6);
GeomVert[6]->IntPoint(0).x = 0.0;
GeomVert[6]->IntPoint(0).y = 0.0;
GeomVert[6]->IntPoint(0).z = 0.0;
GeomVert[6]->IntPoint(1).x = 1.0;
GeomVert[6]->IntPoint(1).y = 0.0;
GeomVert[6]->IntPoint(1).z = 0.0;
GeomVert[6]->IntPoint(2).x = 0.0;
GeomVert[6]->IntPoint(2).y = 1.0;
GeomVert[6]->IntPoint(2).z = 0.0;
GeomVert[6]->IntPoint(3).x = 0.0;
GeomVert[6]->IntPoint(3).y = 0.0;
GeomVert[6]->IntPoint(3).z = 1.0;
GeomVert[6]->IntPoint(4).x = 1.0;
GeomVert[6]->IntPoint(4).y = 0.0;
GeomVert[6]->IntPoint(4).z = 1.0;
GeomVert[6]->IntPoint(5).x = 0.0;
GeomVert[6]->IntPoint(5).y = 1.0;
GeomVert[6]->IntPoint(5).z = 1.0;
GeomCenter[POINT].x = 0.0;
GeomCenter[POINT].y = 0.0;
GeomCenter[POINT].z = 0.0;
@@ -136,12 +163,17 @@ Geometry::Geometry()
GeomCenter[CUBE].y = 0.5;
GeomCenter[CUBE].z = 0.5;
GeomCenter[PRISM].x = 1.0 / 3.0;
GeomCenter[PRISM].y = 1.0 / 3.0;
GeomCenter[PRISM].z = 0.5;
GeomToPerfGeomJac[POINT] = NULL;
GeomToPerfGeomJac[SEGMENT] = new DenseMatrix(1);
GeomToPerfGeomJac[TRIANGLE] = new DenseMatrix(2);
GeomToPerfGeomJac[SQUARE] = new DenseMatrix(2);
GeomToPerfGeomJac[TETRAHEDRON] = new DenseMatrix(3);
GeomToPerfGeomJac[CUBE] = new DenseMatrix(3);
GeomToPerfGeomJac[PRISM] = new DenseMatrix(3);
PerfGeomToGeomJac[POINT] = NULL;
PerfGeomToGeomJac[SEGMENT] = NULL;
@@ -149,12 +181,12 @@ Geometry::Geometry()
PerfGeomToGeomJac[SQUARE] = NULL;
PerfGeomToGeomJac[TETRAHEDRON] = new DenseMatrix(3);
PerfGeomToGeomJac[CUBE] = NULL;
PerfGeomToGeomJac[PRISM] = new DenseMatrix(3);
GeomToPerfGeomJac[SEGMENT]->Diag(1.0, 1);
{
Linear2DFiniteElement TriFE;
IsoparametricTransformation tri_T;
tri_T.SetFE(&TriFE);
tri_T.SetFE(&TriangleFE);
GetPerfPointMat (TRIANGLE, tri_T.GetPointMat());
tri_T.FinalizeTransformation();
tri_T.SetIntPoint(&GeomCenter[TRIANGLE]);
@@ -163,9 +195,8 @@ Geometry::Geometry()
}
GeomToPerfGeomJac[SQUARE]->Diag(1.0, 2);
{
Linear3DFiniteElement TetFE;
IsoparametricTransformation tet_T;
tet_T.SetFE(&TetFE);
tet_T.SetFE(&TetrahedronFE);
GetPerfPointMat (TETRAHEDRON, tet_T.GetPointMat());
tet_T.FinalizeTransformation();
tet_T.SetIntPoint(&GeomCenter[TETRAHEDRON]);
@@ -173,6 +204,15 @@ Geometry::Geometry()
CalcInverse(tet_T.Jacobian(), *PerfGeomToGeomJac[TETRAHEDRON]);
}
GeomToPerfGeomJac[CUBE]->Diag(1.0, 3);
{
IsoparametricTransformation pri_T;
pri_T.SetFE(&WedgeFE);
GetPerfPointMat (PRISM, pri_T.GetPointMat());
pri_T.FinalizeTransformation();
pri_T.SetIntPoint(&GeomCenter[PRISM]);
*GeomToPerfGeomJac[PRISM] = pri_T.Jacobian();
CalcInverse(pri_T.Jacobian(), *PerfGeomToGeomJac[PRISM]);
}
}
Geometry::~Geometry()
@@ -195,6 +235,7 @@ const IntegrationRule * Geometry::GetVertices(int GeomType)
case Geometry::SQUARE: return GeomVert[3];
case Geometry::TETRAHEDRON: return GeomVert[4];
case Geometry::CUBE: return GeomVert[5];
case Geometry::PRISM: return GeomVert[6];
default:
mfem_error ("Geometry::GetVertices(...)");
}
@@ -262,6 +303,16 @@ void Geometry::GetRandomPoint(int GeomType, IntegrationPoint &ip)
ip.y = double(rand()) / RAND_MAX;
ip.z = double(rand()) / RAND_MAX;
break;
case Geometry::PRISM:
ip.x = double(rand()) / RAND_MAX;
ip.y = double(rand()) / RAND_MAX;
ip.z = double(rand()) / RAND_MAX;
if (ip.x + ip.y > 1.0)
{
ip.x = 1.0 - ip.x;
ip.y = 1.0 - ip.y;
}
break;
default:
MFEM_ABORT("Unknown type of reference element!");
}
@@ -319,6 +370,10 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip)
if (ip.x < 0.0 || ip.x > 1.0 || ip.y < 0.0 || ip.y > 1.0 ||
ip.z < 0.0 || ip.z > 1.0) { return false; }
break;
case Geometry::PRISM:
if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.y > 1.0 ||
ip.z < 0.0 || ip.z > 1.0) { return false; }
break;
default:
MFEM_ABORT("Unknown type of reference element!");
}
@@ -379,6 +434,16 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip, double eps)
return false;
}
break;
case Geometry::PRISM:
if ( internal::FuzzyLT(ip.x, 0.0, eps)
|| internal::FuzzyLT(ip.y, 0.0, eps)
|| internal::FuzzyGT(ip.x+ip.y, 1.0, eps)
|| internal::FuzzyLT(ip.z, 0.0, eps)
|| internal::FuzzyGT(ip.z, 1.0, eps) )
{
return false;
}
break;
default:
MFEM_ABORT("Unknown type of reference element!");
}
@@ -461,14 +526,14 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
}
case Geometry::TRIANGLE:
{
double lend[3] = { end.x, end.y, 1-end.x-end.y };
double lbeg[3] = { beg.x, beg.y, 1-beg.x-beg.y };
double lend[3] = { end.x, end.y, 1.0-end.x-end.y };
double lbeg[3] = { beg.x, beg.y, 1.0-beg.x-beg.y };
return internal::IntersectSegment<3,2>(lbeg, lend, end);
}
case Geometry::SQUARE:
{
double lend[4] = { end.x, end.y, 1-end.x, 1.0-end.y };
double lbeg[4] = { beg.x, beg.y, 1-beg.x, 1.0-beg.y };
double lend[4] = { end.x, end.y, 1.0-end.x, 1.0-end.y };
double lbeg[4] = { beg.x, beg.y, 1.0-beg.x, 1.0-beg.y };
return internal::IntersectSegment<4,2>(lbeg, lend, end);
}
case Geometry::TETRAHEDRON:
@@ -487,6 +552,12 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
};
return internal::IntersectSegment<6,3>(lbeg, lend, end);
}
case Geometry::PRISM:
{
double lend[5] = { end.x, end.y, end.z, 1.0-end.x-end.y, 1.0-end.z };
double lbeg[5] = { beg.x, beg.y, beg.z, 1.0-beg.x-beg.y, 1.0-beg.z };
return internal::IntersectSegment<5,3>(lbeg, lend, end);
}
default:
MFEM_ABORT("Unknown type of reference element!");
}
@@ -574,6 +645,16 @@ bool Geometry::ProjectPoint(int GeomType, IntegrationPoint &ip)
return in_x && in_y && in_z;
}
case PRISM:
{
bool in_tri, in_z;
in_tri = internal::ProjectTriangle(ip.x, ip.y);
if (ip.z < 0.0) { in_z = false; ip.z = 0.0; }
else if (ip.z > 1.0) { in_z = false; ip.z = 1.0; }
else { in_z = true; }
return in_tri && in_z;
}
default:
MFEM_ABORT("Reference element type is not supported!");
}
@@ -636,6 +717,18 @@ void Geometry::GetPerfPointMat(int GeomType, DenseMatrix &pm)
}
break;
case Geometry::PRISM:
{
pm.SetSize (3, 6);
pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676; pm(2,2) = 0.0;
pm(0,3) = 0.0; pm(1,3) = 0.0; pm(2,3) = 1.0;
pm(0,4) = 1.0; pm(1,4) = 0.0; pm(2,4) = 1.0;
pm(0,5) = 0.5; pm(1,5) = 0.86602540378443864676; pm(2,5) = 1.0;
}
break;
default:
mfem_error ("Geometry::GetPerfPointMat (...)");
}
@@ -654,11 +747,13 @@ void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
}
}
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6 };
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3 };
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8 };
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12 };
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6 };
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5 };
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3 };
const int Geometry::DimStart[MaxDim+2] =
{ POINT, SEGMENT, TRIANGLE, TETRAHEDRON, NUM_GEOMETRIES };
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6 };
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9 };
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5 };
const int Geometry::
Constants<Geometry::POINT>::Orient[1][1] = {{0}};
@@ -723,7 +818,11 @@ const int Geometry::
Constants<Geometry::TETRAHEDRON>::VertToVert::I[4] = {0, 3, 5, 6};
const int Geometry::
Constants<Geometry::TETRAHEDRON>::VertToVert::J[6][2] =
{{1, 0}, {2, 1}, {3, 2}, {2, 3}, {3, 4}, {3, 5}};
{
{1, 0}, {2, 1}, {3, 2}, // 0,1:0 0,2:1 0,3:2
{2, 3}, {3, 4}, // 1,2:3 1,3:4
{3, 5} // 2,3:5
};
const int Geometry::
Constants<Geometry::CUBE>::Edges[12][2] =
@@ -757,7 +856,29 @@ Constants<Geometry::CUBE>::VertToVert::J[12][2] =
{7,-7} // 6,7:-7
};
Geometry Geometries;
const int Geometry::
Constants<Geometry::PRISM>::Edges[9][2] =
{{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5}, {5, 3}, {0, 3}, {1, 4}, {2, 5}};
const int Geometry::
Constants<Geometry::PRISM>::FaceTypes[5] =
{
Geometry::TRIANGLE, Geometry::TRIANGLE,
Geometry::SQUARE, Geometry::SQUARE, Geometry::SQUARE
};
const int Geometry::
Constants<Geometry::PRISM>::FaceVert[5][4] =
{{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, {1, 2, 5, 4}, {2, 0, 3, 5}};
const int Geometry::
Constants<Geometry::PRISM>::VertToVert::I[6] = {0, 3, 5, 6, 8, 9};
const int Geometry::
Constants<Geometry::PRISM>::VertToVert::J[9][2] =
{
{1, 0}, {2, -3}, {3, 6}, // 0,1:0 0,2:-3 0,3:6
{2, 1}, {4, 7}, // 1,2:1 1,4:7
{5, 8}, // 2,5:8
{4, 3}, {5, -6}, // 3,4:3 3,5:-6
{5, 4} // 4,5:4
};
GeometryRefiner::GeometryRefiner()
@@ -774,7 +895,8 @@ GeometryRefiner::~GeometryRefiner()
}
}
RefinedGeometry *GeometryRefiner::FindInRGeom(int Geom, int Times, int ETimes,
RefinedGeometry *GeometryRefiner::FindInRGeom(Geometry::Type Geom,
int Times, int ETimes,
int Type)
{
Array<RefinedGeometry *> &RGA = RGeom[Geom];
@@ -789,7 +911,7 @@ RefinedGeometry *GeometryRefiner::FindInRGeom(int Geom, int Times, int ETimes,
return NULL;
}
IntegrationRule *GeometryRefiner::FindInIntPts(int Geom, int NPts)
IntegrationRule *GeometryRefiner::FindInIntPts(Geometry::Type Geom, int NPts)
{
Array<IntegrationRule *> &IPA = IntPts[Geom];
for (int i = 0; i < IPA.Size(); i++)
@@ -800,9 +922,10 @@ IntegrationRule *GeometryRefiner::FindInIntPts(int Geom, int NPts)
return NULL;
}
RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
RefinedGeometry * GeometryRefiner::Refine(Geometry::Type Geom,
int Times, int ETimes)
{
int i, j, k, l;
int i, j, k, l, m;
Times = std::max(Times, 1);
ETimes = std::max(ETimes, 1);
@@ -1024,7 +1147,7 @@ RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
// enumerate and define the vertices
Array<int> vi((n+1)*(n+1)*(n+1));
vi = -1;
int m = 0;
m = 0;
for (k = 0; k <= n; k++)
for (j = 0; j <= k; j++)
for (i = 0; i <= j; i++)
@@ -1115,13 +1238,83 @@ RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
return RG;
}
case Geometry::PRISM:
{
const int n = Times;
RG = new RefinedGeometry ((n+1)*(n+1)*(n+2)/2, 6*n*n*n, 0);
RG->Times = Times;
RG->ETimes = ETimes;
RG->Type = type;
// enumerate and define the vertices
m = 0;
for (l = k = 0; k <= n; k++)
for (j = 0; j <= n; j++)
for (i = 0; i <= n-j; i++, l++)
{
IntegrationPoint &ip = RG->RefPts.IntPoint(l);
if (type == 0)
{
ip.x = double(i) / n;
ip.y = double(j) / n;
ip.z = double(k) / n;
}
else
{
ip.x = cp[i]/(cp[i] + cp[j] + cp[n-i-j]);
ip.y = cp[j]/(cp[i] + cp[j] + cp[n-i-j]);
ip.z = cp[k];
}
m++;
}
if (m != (n+1)*(n+1)*(n+2)/2)
{
mfem_error("GeometryRefiner::Refine() for PRISM #1");
}
// elements
Array<int> &G = RG->RefGeoms;
m = 0;
for (m = k = 0; k < n; k++)
for (l = j = 0; j < n; j++, l++)
for (i = 0; i < n-j; i++, l++)
{
G[m++] = l + (k+0) * (n+1) * (n+2) / 2;
G[m++] = l + 1 + (k+0) * (n+1) * (n+2) / 2;
G[m++] = l - j + (2 + (k+0) * (n+2)) * (n+1) / 2;
G[m++] = l + (k+1) * (n+1) * (n+2) / 2;
G[m++] = l + 1 + (k+1) * (n+1) * (Times+2) / 2;
G[m++] = l - j + (2 + (k+1) * (n+2)) * (n+1) / 2;
if (i+j+1 < n)
{
G[m++] = l + 1 + (k+0) * (n+1) * (n+2)/2;
G[m++] = l - j + (2 + (k+0) * (n+1)) * (n+2) / 2;
G[m++] = l - j + (2 + (k+0) * (n+2)) * (n+1) / 2;
G[m++] = l + 1 + (k+1) * (n+1) * (n+2) / 2;
G[m++] = l - j + (2 + (k+1) * (n+1)) * (n+2) / 2;
G[m++] = l - j + (2 + (k+1) * (n+2)) * (n+1) / 2;
}
}
if (m != 6*n*n*n)
{
mfem_error("GeometryRefiner::Refine() for PRISM #2");
}
for (i = 0; i < m; i++)
if (G[i] < 0)
{
mfem_error("GeometryRefiner::Refine() for PRISM #3");
}
RGeom[Geometry::PRISM].Append(RG);
return RG;
}
default:
return NULL;
}
}
const IntegrationRule *GeometryRefiner::RefineInterior(int Geom, int Times)
const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
int Times)
{
IntegrationRule *ir = NULL;
+40 -11
View File
@@ -25,18 +25,26 @@ namespace mfem
Geometry::TRIANGLE - triangle with vertices (0,0), (1,0), (0,1)
Geometry::SQUARE - the unit square (0,1)x(0,1)
Geometry::TETRAHEDRON - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1)
Geometry::CUBE - the unit cube */
Geometry::CUBE - the unit cube
Geometry::PRISM - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,0,1),(0,1,1)
*/
class Geometry
{
public:
enum Type { POINT, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE };
enum Type
{
INVALID = -1,
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM,
NUM_GEOMETRIES
};
static const int NumGeom = 6;
static const int NumGeom = NUM_GEOMETRIES;
static const int MaxDim = 3;
static const int NumBdrArray[NumGeom];
static const char *Name[NumGeom];
static const double Volume[NumGeom];
static const int Dimension[NumGeom];
static const int DimStart[MaxDim+2]; // including MaxDim+1
static const int NumVerts[NumGeom];
static const int NumEdges[NumGeom];
static const int NumFaces[NumGeom];
@@ -126,7 +134,7 @@ template <> struct Geometry::Constants<Geometry::TRIANGLE>
static const int NumVert = 3;
static const int NumEdges = 3;
static const int Edges[NumEdges][2];
// Lower-triangular part of the local vertex-to-vertex graph.
// Upper-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
@@ -152,7 +160,7 @@ template <> struct Geometry::Constants<Geometry::SQUARE>
static const int NumVert = 4;
static const int NumEdges = 4;
static const int Edges[NumEdges][2];
// Lower-triangular part of the local vertex-to-vertex graph.
// Upper-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
@@ -176,7 +184,7 @@ template <> struct Geometry::Constants<Geometry::TETRAHEDRON>
static const int FaceTypes[NumFaces];
static const int MaxFaceVert = 3;
static const int FaceVert[NumFaces][MaxFaceVert];
// Lower-triangular part of the local vertex-to-vertex graph.
// Upper-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
@@ -194,7 +202,7 @@ template <> struct Geometry::Constants<Geometry::CUBE>
static const int FaceTypes[NumFaces];
static const int MaxFaceVert = 4;
static const int FaceVert[NumFaces][MaxFaceVert];
// Lower-triangular part of the local vertex-to-vertex graph.
// Upper-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
@@ -202,8 +210,28 @@ template <> struct Geometry::Constants<Geometry::CUBE>
};
};
template <> struct Geometry::Constants<Geometry::PRISM>
{
static const int Dimension = 3;
static const int NumVert = 6;
static const int NumEdges = 9;
static const int Edges[NumEdges][2];
static const int NumFaces = 5;
static const int FaceTypes[NumFaces];
static const int MaxFaceVert = 4;
static const int FaceVert[NumFaces][MaxFaceVert];
// Upper-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
static const int J[NumEdges][2]; // {end,edge_idx}
};
};
// Defined in fe.cpp to ensure construction after 'mfem::WedgeFE'.
extern Geometry Geometries;
class RefinedGeometry
{
public:
@@ -224,8 +252,9 @@ private:
Array<RefinedGeometry *> RGeom[Geometry::NumGeom];
Array<IntegrationRule *> IntPts[Geometry::NumGeom];
RefinedGeometry *FindInRGeom(int Geom, int Times, int ETimes, int Type);
IntegrationRule *FindInIntPts(int Geom, int NPts);
RefinedGeometry *FindInRGeom(Geometry::Type Geom, int Times, int ETimes,
int Type);
IntegrationRule *FindInIntPts(Geometry::Type Geom, int NPts);
public:
GeometryRefiner();
@@ -235,10 +264,10 @@ public:
/// Get the Quadrature1D type of points used for subdivision.
int GetType() const { return type; }
RefinedGeometry *Refine(int Geom, int Times, int ETimes = 1);
RefinedGeometry *Refine(Geometry::Type Geom, int Times, int ETimes = 1);
/// @note This method always uses Quadrature1D::OpenUniform points.
const IntegrationRule *RefineInterior(int Geom, int Times);
const IntegrationRule *RefineInterior(Geometry::Type Geom, int Times);
~GeometryRefiner();
};
+419 -157
View File
@@ -294,7 +294,7 @@ int GridFunction::VectorDim() const
if (!fes->GetNE())
{
const FiniteElementCollection *fec = fes->FEColl();
static const int geoms[3] =
static const Geometry::Type geoms[3] =
{ Geometry::SEGMENT, Geometry::TRIANGLE, Geometry::TETRAHEDRON };
fe = fec->FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
}
@@ -915,9 +915,7 @@ double GridFunction::GetDivergence(ElementTransformation &tr) const
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &J = tr.Jacobian();
DenseMatrix Jinv(J.Width(), J.Height());
CalcInverse(J, Jinv);
const DenseMatrix &Jinv = tr.InverseJacobian();
div_v = 0.0;
for (int i = 0; i < Jinv.Width(); i++)
{
@@ -950,9 +948,7 @@ void GridFunction::GetCurl(ElementTransformation &tr, Vector &curl) const
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &J = tr.Jacobian();
DenseMatrix Jinv(J.Width(), J.Height());
CalcInverse(J, Jinv);
const DenseMatrix &Jinv = tr.InverseJacobian();
DenseMatrix grad(grad_hat.Height(), Jinv.Width()); // vdim x FElem->Dim
Mult(grad_hat, Jinv, grad);
MFEM_ASSERT(grad.Height() == grad.Width(), "");
@@ -999,7 +995,7 @@ void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) const
const FiniteElement *fe = fes->GetFE(elNo);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
int dim = fe->GetDim(), dof = fe->GetDof();
DenseMatrix dshape(dof, dim), Jinv(dim);
DenseMatrix dshape(dof, dim);
Vector lval, gh(dim);
Array<int> dofs;
@@ -1008,21 +1004,20 @@ void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) const
GetSubVector(dofs, lval);
fe->CalcDShape(tr.GetIntPoint(), dshape);
dshape.MultTranspose(lval, gh);
CalcInverse(tr.Jacobian(), Jinv);
Jinv.MultTranspose(gh, grad);
tr.InverseJacobian().MultTranspose(gh, grad);
}
void GridFunction::GetGradients(const int elem, const IntegrationRule &ir,
void GridFunction::GetGradients(ElementTransformation &tr,
const IntegrationRule &ir,
DenseMatrix &grad) const
{
const FiniteElement *fe = fes->GetFE(elem);
int elNo = tr.ElementNo;
const FiniteElement *fe = fes->GetFE(elNo);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
ElementTransformation *Tr = fes->GetElementTransformation(elem);
DenseMatrix dshape(fe->GetDof(), fe->GetDim());
DenseMatrix Jinv(fe->GetDim());
Vector lval, gh(fe->GetDim()), gcol;
Array<int> dofs;
fes->GetElementDofs(elem, dofs);
fes->GetElementDofs(elNo, dofs);
GetSubVector(dofs, lval);
grad.SetSize(fe->GetDim(), ir.GetNPoints());
for (int i = 0; i < ir.GetNPoints(); i++)
@@ -1030,9 +1025,9 @@ void GridFunction::GetGradients(const int elem, const IntegrationRule &ir,
const IntegrationPoint &ip = ir.IntPoint(i);
fe->CalcDShape(ip, dshape);
dshape.MultTranspose(lval, gh);
Tr->SetIntPoint(&ip);
tr.SetIntPoint(&ip);
grad.GetColumnReference(i, gcol);
CalcInverse(Tr->Jacobian(), Jinv);
const DenseMatrix &Jinv = tr.InverseJacobian();
Jinv.MultTranspose(gh, gcol);
}
}
@@ -1044,9 +1039,7 @@ void GridFunction::GetVectorGradient(
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &J = tr.Jacobian();
DenseMatrix Jinv(J.Width(), J.Height());
CalcInverse(J, Jinv);
const DenseMatrix &Jinv = tr.InverseJacobian();
grad.SetSize(grad_hat.Height(), Jinv.Width());
Mult(grad_hat, Jinv, grad);
}
@@ -1083,26 +1076,37 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
void GridFunction::ProjectGridFunction(const GridFunction &src)
{
// Assuming that the projection matrix is the same for all elements
Mesh *mesh = fes->GetMesh();
bool sameP = false;
DenseMatrix P;
if (!fes->GetNE())
{
return;
}
if (!mesh->GetNE()) { return; }
Geometry::Type geom, cached_geom = Geometry::INVALID;
if (mesh->GetNumGeometries(mesh->Dimension()) == 1)
{
// Assuming that the projection matrix is the same for all elements
sameP = true;
fes->GetFE(0)->Project(*src.fes->GetFE(0),
*mesh->GetElementTransformation(0), P);
}
const int vdim = fes->GetVDim();
MFEM_VERIFY(vdim == src.fes->GetVDim(), "incompatible vector dimensions!");
fes->GetFE(0)->Project(*src.fes->GetFE(0),
*mesh->GetElementTransformation(0), P);
int vdim = fes->GetVDim();
if (vdim != src.fes->GetVDim())
mfem_error("GridFunction::ProjectGridFunction() :"
" incompatible vector dimensions!");
Array<int> src_vdofs, dest_vdofs;
Vector src_lvec, dest_lvec(vdim*P.Height());
for (int i = 0; i < mesh->GetNE(); i++)
{
// Assuming the projection matrix P depends only on the element geometry
if ( !sameP && (geom = mesh->GetElementBaseGeometry(i)) != cached_geom )
{
fes->GetFE(i)->Project(*src.fes->GetFE(i),
*mesh->GetElementTransformation(i), P);
dest_lvec.SetSize(vdim*P.Height());
cached_geom = geom;
}
src.fes->GetElementVDofs(i, src_vdofs);
src.GetSubVector(src_vdofs, src_lvec);
for (int vd = 0; vd < vdim; vd++)
@@ -1288,6 +1292,194 @@ void GridFunction::AccumulateAndCountZones(VectorCoefficient &vcoeff,
}
}
void GridFunction::AccumulateAndCountBdrValues(
Coefficient *coeff[], VectorCoefficient *vcoeff, Array<int> &attr,
Array<int> &values_counter)
{
int i, j, fdof, d, ind, vdim;
double val;
const FiniteElement *fe;
ElementTransformation *transf;
Array<int> vdofs;
Vector vc;
values_counter.SetSize(Size());
values_counter = 0;
vdim = fes->GetVDim();
for (i = 0; i < fes->GetNBE(); i++)
{
if (attr[fes->GetBdrAttribute(i) - 1] == 0) { continue; }
fe = fes->GetBE(i);
fdof = fe->GetDof();
transf = fes->GetBdrElementTransformation(i);
const IntegrationRule &ir = fe->GetNodes();
fes->GetBdrElementVDofs(i, vdofs);
for (j = 0; j < fdof; j++)
{
const IntegrationPoint &ip = ir.IntPoint(j);
transf->SetIntPoint(&ip);
if (vcoeff) { vcoeff->Eval(vc, *transf, ip); }
for (d = 0; d < vdim; d++)
{
if (!vcoeff && !coeff[d]) { continue; }
val = vcoeff ? vc(d) : coeff[d]->Eval(*transf, ip);
if ( (ind = vdofs[fdof*d+j]) < 0 )
{
val = -val, ind = -1-ind;
}
if (++values_counter[ind] == 1)
{
(*this)(ind) = val;
}
else
{
(*this)(ind) += val;
}
}
}
}
// In the case of partially conforming space, i.e. (fes->cP != NULL), we need
// to set the values of all dofs on which the dofs set above depend.
// Dependency is defined from the matrix A = cP.cR: dof i depends on dof j
// iff A_ij != 0. It is sufficient to resolve just the first level of
// dependency, since A is a projection matrix: A^n = A due to cR.cP = I.
// Cases like these arise in 3D when boundary edges are constrained by
// (depend on) internal faces/elements. We use the virtual method
// GetBoundaryClosure from NCMesh to resolve the dependencies.
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
{
Vector vals;
Mesh *mesh = fes->GetMesh();
NCMesh *ncmesh = mesh->ncmesh;
Array<int> bdr_edges, bdr_vertices;
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges);
for (i = 0; i < bdr_edges.Size(); i++)
{
int edge = bdr_edges[i];
fes->GetEdgeVDofs(edge, vdofs);
if (vdofs.Size() == 0) { continue; }
transf = mesh->GetEdgeTransformation(edge);
transf->Attribute = -1; // FIXME: set the boundary attribute
fe = fes->GetEdgeElement(edge);
if (!vcoeff)
{
vals.SetSize(fe->GetDof());
for (d = 0; d < vdim; d++)
{
if (!coeff[d]) { continue; }
fe->Project(*coeff[d], *transf, vals);
for (int k = 0; k < vals.Size(); k++)
{
ind = vdofs[d*vals.Size()+k];
if (++values_counter[ind] == 1)
{
(*this)(ind) = vals(k);
}
else
{
(*this)(ind) += vals(k);
}
}
}
}
else // vcoeff != NULL
{
vals.SetSize(vdim*fe->GetDof());
fe->Project(*vcoeff, *transf, vals);
for (int k = 0; k < vals.Size(); k++)
{
ind = vdofs[k];
if (++values_counter[ind] == 1)
{
(*this)(ind) = vals(k);
}
else
{
(*this)(ind) += vals(k);
}
}
}
}
}
}
static void accumulate_dofs(const Array<int> &dofs, const Vector &vals,
Vector &gf, Array<int> &values_counter)
{
for (int i = 0; i < dofs.Size(); i++)
{
int k = dofs[i];
double val = vals(i);
if (k < 0) { k = -1 - k; val = -val; }
if (++values_counter[k] == 1)
{
gf(k) = val;
}
else
{
gf(k) += val;
}
}
}
void GridFunction::AccumulateAndCountBdrTangentValues(
VectorCoefficient &vcoeff, Array<int> &bdr_attr,
Array<int> &values_counter)
{
const FiniteElement *fe;
ElementTransformation *T;
Array<int> dofs;
Vector lvec;
values_counter.SetSize(Size());
values_counter = 0;
for (int i = 0; i < fes->GetNBE(); i++)
{
if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
{
continue;
}
fe = fes->GetBE(i);
T = fes->GetBdrElementTransformation(i);
fes->GetBdrElementDofs(i, dofs);
lvec.SetSize(fe->GetDof());
fe->Project(vcoeff, *T, lvec);
accumulate_dofs(dofs, lvec, *this, values_counter);
}
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
{
Mesh *mesh = fes->GetMesh();
NCMesh *ncmesh = mesh->ncmesh;
Array<int> bdr_edges, bdr_vertices;
ncmesh->GetBoundaryClosure(bdr_attr, bdr_vertices, bdr_edges);
for (int i = 0; i < bdr_edges.Size(); i++)
{
int edge = bdr_edges[i];
fes->GetEdgeDofs(edge, dofs);
if (dofs.Size() == 0) { continue; }
T = mesh->GetEdgeTransformation(edge);
T->Attribute = -1; // FIXME: set the boundary attribute
fe = fes->GetEdgeElement(edge);
lvec.SetSize(fe->GetDof());
fe->Project(vcoeff, *T, lvec);
accumulate_dofs(dofs, lvec, *this, values_counter);
}
}
}
void GridFunction::ComputeMeans(AvgType type, Array<int> &zones_per_vdof)
{
switch (type)
@@ -1295,14 +1487,16 @@ void GridFunction::ComputeMeans(AvgType type, Array<int> &zones_per_vdof)
case ARITHMETIC:
for (int i = 0; i < size; i++)
{
(*this)(i) /= zones_per_vdof[i];
const int nz = zones_per_vdof[i];
if (nz) { (*this)(i) /= nz; }
}
break;
case HARMONIC:
for (int i = 0; i < size; i++)
{
(*this)(i) = zones_per_vdof[i]/(*this)(i);
const int nz = zones_per_vdof[i];
if (nz) { (*this)(i) = nz/(*this)(i); }
}
break;
@@ -1562,85 +1756,37 @@ void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff,
ComputeMeans(type, zones_per_vdof);
}
void GridFunction::ProjectBdrCoefficient(
Coefficient *coeff[], Array<int> &attr)
void GridFunction::ProjectBdrCoefficient(VectorCoefficient &vcoeff,
Array<int> &attr)
{
int i, j, fdof, d, ind, vdim;
double val;
const FiniteElement *fe;
ElementTransformation *transf;
Array<int> vdofs;
vdim = fes->GetVDim();
for (i = 0; i < fes->GetNBE(); i++)
Array<int> values_counter;
AccumulateAndCountBdrValues(NULL, &vcoeff, attr, values_counter);
ComputeMeans(ARITHMETIC, values_counter);
#ifdef MFEM_DEBUG
Array<int> ess_vdofs_marker;
fes->GetEssentialVDofs(attr, ess_vdofs_marker);
for (int i = 0; i < values_counter.Size(); i++)
{
if (attr[fes->GetBdrAttribute(i) - 1])
{
fe = fes->GetBE(i);
fdof = fe->GetDof();
transf = fes->GetBdrElementTransformation(i);
const IntegrationRule &ir = fe->GetNodes();
fes->GetBdrElementVDofs(i, vdofs);
for (j = 0; j < fdof; j++)
{
const IntegrationPoint &ip = ir.IntPoint(j);
transf->SetIntPoint(&ip);
for (d = 0; d < vdim; d++)
{
if (!coeff[d]) { continue; }
val = coeff[d]->Eval(*transf, ip);
if ( (ind = vdofs[fdof*d+j]) < 0 )
{
val = -val, ind = -1-ind;
}
(*this)(ind) = val;
}
}
}
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
"internal error");
}
#endif
}
// In the case of partially conforming space, i.e. (fes->cP != NULL), we need
// to set the values of all dofs on which the dofs set above depend.
// Dependency is defined from the matrix A = cP.cR: dof i depends on dof j
// iff A_ij != 0. It is sufficient to resolve just the first level of
// dependency since A is a projection matrix: A^n = A due to cR.cP = I.
// Cases like this arise in 3D when boundary edges are constrained by (depend
// on) internal faces/elements.
// We use the virtual method GetBoundaryClosure from NCMesh to resolve the
// dependencies.
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
void GridFunction::ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr)
{
Array<int> values_counter;
AccumulateAndCountBdrValues(coeff, NULL, attr, values_counter);
ComputeMeans(ARITHMETIC, values_counter);
#ifdef MFEM_DEBUG
Array<int> ess_vdofs_marker;
fes->GetEssentialVDofs(attr, ess_vdofs_marker);
for (int i = 0; i < values_counter.Size(); i++)
{
Vector vals;
Mesh *mesh = fes->GetMesh();
NCMesh *ncmesh = mesh->ncmesh;
Array<int> bdr_edges, bdr_vertices;
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges);
for (i = 0; i < bdr_edges.Size(); i++)
{
int edge = bdr_edges[i];
fes->GetEdgeVDofs(edge, vdofs);
if (vdofs.Size() == 0) { continue; }
transf = mesh->GetEdgeTransformation(edge);
transf->Attribute = -1; // FIXME: set the boundary attribute
fe = fes->GetEdgeElement(edge);
vals.SetSize(fe->GetDof());
for (d = 0; d < vdim; d++)
{
if (!coeff[d]) { continue; }
fe->Project(*coeff[d], *transf, vals);
for (int k = 0; k < vals.Size(); k++)
{
(*this)(vdofs[d*vals.Size()+k]) = vals(k);
}
}
}
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
"internal error");
}
#endif
}
void GridFunction::ProjectBdrCoefficientNormal(
@@ -1717,46 +1863,18 @@ void GridFunction::ProjectBdrCoefficientNormal(
void GridFunction::ProjectBdrCoefficientTangent(
VectorCoefficient &vcoeff, Array<int> &bdr_attr)
{
const FiniteElement *fe;
ElementTransformation *T;
Array<int> dofs;
Vector lvec;
for (int i = 0; i < fes->GetNBE(); i++)
Array<int> values_counter;
AccumulateAndCountBdrTangentValues(vcoeff, bdr_attr, values_counter);
ComputeMeans(ARITHMETIC, values_counter);
#ifdef MFEM_DEBUG
Array<int> ess_vdofs_marker;
fes->GetEssentialVDofs(bdr_attr, ess_vdofs_marker);
for (int i = 0; i < values_counter.Size(); i++)
{
if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
{
continue;
}
fe = fes->GetBE(i);
T = fes->GetBdrElementTransformation(i);
fes->GetBdrElementDofs(i, dofs);
lvec.SetSize(fe->GetDof());
fe->Project(vcoeff, *T, lvec);
SetSubVector(dofs, lvec);
}
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
{
Mesh *mesh = fes->GetMesh();
NCMesh *ncmesh = mesh->ncmesh;
Array<int> bdr_edges, bdr_vertices;
ncmesh->GetBoundaryClosure(bdr_attr, bdr_vertices, bdr_edges);
for (int i = 0; i < bdr_edges.Size(); i++)
{
int edge = bdr_edges[i];
fes->GetEdgeDofs(edge, dofs);
if (dofs.Size() == 0) { continue; }
T = mesh->GetEdgeTransformation(edge);
T->Attribute = -1; // FIXME: set the boundary attribute
fe = fes->GetEdgeElement(edge);
lvec.SetSize(fe->GetDof());
fe->Project(vcoeff, *T, lvec);
SetSubVector(dofs, lvec);
}
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
"internal error");
}
#endif
}
double GridFunction::ComputeL2Error(
@@ -2237,6 +2355,69 @@ double GridFunction::ComputeLpError(const double p, Coefficient &exsol,
return error;
}
void GridFunction::ComputeElementLpErrors(const double p, Coefficient &exsol,
GridFunction &error,
Coefficient *weight,
const IntegrationRule *irs[]) const
{
error = 0.0;
const FiniteElement *fe;
ElementTransformation *T;
Vector vals;
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
int intorder = 2*fe->GetOrder() + 1; // <----------
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
GetValues(i, *ir, vals);
T = fes->GetElementTransformation(i);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
T->SetIntPoint(&ip);
double err = fabs(vals(j) - exsol.Eval(*T, ip));
if (p < infinity())
{
err = pow(err, p);
if (weight)
{
err *= weight->Eval(*T, ip);
}
error[i] += ip.weight * T->Weight() * err;
}
else
{
if (weight)
{
err *= weight->Eval(*T, ip);
}
error[i] = std::max(error[i], err);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error[i] < 0.)
{
error[i] = -pow(-error[i], 1./p);
}
else
{
error[i] = pow(error[i], 1./p);
}
}
}
}
double GridFunction::ComputeLpError(const double p, VectorCoefficient &exsol,
Coefficient *weight,
VectorCoefficient *v_weight,
@@ -2328,6 +2509,96 @@ double GridFunction::ComputeLpError(const double p, VectorCoefficient &exsol,
return error;
}
void GridFunction::ComputeElementLpErrors(const double p,
VectorCoefficient &exsol,
GridFunction &error,
Coefficient *weight,
VectorCoefficient *v_weight,
const IntegrationRule *irs[]) const
{
error = 0.0;
const FiniteElement *fe;
ElementTransformation *T;
DenseMatrix vals, exact_vals;
Vector loc_errs;
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
int intorder = 2*fe->GetOrder() + 1; // <----------
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
T = fes->GetElementTransformation(i);
GetVectorValues(*T, *ir, vals);
exsol.Eval(exact_vals, *T, *ir);
vals -= exact_vals;
loc_errs.SetSize(vals.Width());
if (!v_weight)
{
// compute the lengths of the errors at the integration points
// thus the vector norm is rotationally invariant
vals.Norm2(loc_errs);
}
else
{
v_weight->Eval(exact_vals, *T, *ir);
// column-wise dot product of the vector error (in vals) and the
// vector weight (in exact_vals)
for (int j = 0; j < vals.Width(); j++)
{
double err = 0.0;
for (int d = 0; d < vals.Height(); d++)
{
err += vals(d,j)*exact_vals(d,j);
}
loc_errs(j) = fabs(err);
}
}
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
T->SetIntPoint(&ip);
double err = loc_errs(j);
if (p < infinity())
{
err = pow(err, p);
if (weight)
{
err *= weight->Eval(*T, ip);
}
error[i] += ip.weight * T->Weight() * err;
}
else
{
if (weight)
{
err *= weight->Eval(*T, ip);
}
error[i] = std::max(error[i], err);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error[i] < 0.)
{
error[i] = -pow(-error[i], 1./p);
}
else
{
error[i] = pow(error[i], 1./p);
}
}
}
}
GridFunction & GridFunction::operator=(double value)
{
Vector::operator=(value);
@@ -2341,11 +2612,6 @@ GridFunction & GridFunction::operator=(const Vector &v)
return *this;
}
GridFunction & GridFunction::operator=(const GridFunction &v)
{
return this->operator=((const Vector &)v);
}
void GridFunction::Save(std::ostream &out) const
{
fes->Save(out);
@@ -2489,11 +2755,11 @@ void GridFunction::SaveSTL(std::ostream &out, int TimesToRefine)
bbox[2][0] = bbox[2][1] = 0.0;
for (i = 0; i < mesh->GetNE(); i++)
{
n = fes->GetFE(i)->GetGeomType();
RefG = GlobGeometryRefiner.Refine(n, TimesToRefine);
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
RefG = GlobGeometryRefiner.Refine(geom, TimesToRefine);
GetValues(i, RefG->RefPts, values, pointmat);
Array<int> &RG = RefG->RefGeoms;
n = Geometries.NumBdr(n);
n = Geometries.NumBdr(geom);
for (k = 0; k < RG.Size()/n; k++)
{
for (j = 0; j < n; j++)
@@ -2645,11 +2911,7 @@ double ZZErrorEstimator(BilinearFormIntegrator &blfi,
int nsd = 1;
if (with_subdomains)
{
for (int i = 0; i < nfe; i++)
{
int attr = ufes->GetAttribute(i);
if (attr > nsd) { nsd = attr; }
}
nsd = ufes->GetMesh()->attributes.Max();
}
double total_error = 0.0;
+118 -21
View File
@@ -27,10 +27,13 @@ namespace mfem
class GridFunction : public Vector
{
protected:
/// FE space on which grid function lives.
/// FE space on which the grid function lives. Owned if #fec is not NULL.
FiniteElementSpace *fes;
/// Used when the grid function is read from a file
/** @brief Used when the grid function is read from a file. It can also be
set explicitly, see MakeOwner().
If not NULL, this pointer is owned by the GridFunction. */
FiniteElementCollection *fec;
long sequence; // see FiniteElementSpace::sequence, Mesh::sequence
@@ -67,7 +70,7 @@ public:
GridFunction() { fes = NULL; fec = NULL; sequence = 0; }
/// Copy constructor.
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
GridFunction(const GridFunction &orig)
: Vector(orig), fes(orig.fes), fec(NULL), sequence(orig.sequence) { }
@@ -92,6 +95,15 @@ public:
GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces);
/// Copy assignment. Only the data of the base class Vector is copied.
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
have the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
GridFunction &operator=(const GridFunction &rhs)
{ return operator=((const Vector &)rhs); }
/// Make the GridFunction the owner of 'fec' and 'fes'
void MakeOwner(FiniteElementCollection *_fec) { fec = _fec; }
@@ -173,9 +185,13 @@ public:
void GetGradient(ElementTransformation &tr, Vector &grad) const;
void GetGradients(const int elem, const IntegrationRule &ir,
void GetGradients(ElementTransformation &tr, const IntegrationRule &ir,
DenseMatrix &grad) const;
void GetGradients(const int elem, const IntegrationRule &ir,
DenseMatrix &grad) const
{ GetGradients(*fes->GetElementTransformation(elem), ir, grad); }
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const;
/** Compute \f$ (\int_{\Omega} (*this) \psi_i)/(\int_{\Omega} \psi_i) \f$,
@@ -235,18 +251,40 @@ protected:
void AccumulateAndCountZones(VectorCoefficient &vcoeff, AvgType type,
Array<int> &zones_per_vdof);
void AccumulateAndCountBdrValues(Coefficient *coeff[],
VectorCoefficient *vcoeff, Array<int> &attr,
Array<int> &values_counter);
void AccumulateAndCountBdrTangentValues(VectorCoefficient &vcoeff,
Array<int> &bdr_attr,
Array<int> &values_counter);
// Complete the computation of averages; called e.g. after
// AccumulateAndCountZones().
void ComputeMeans(AvgType type, Array<int> &zones_per_vdof);
public:
/** @brief Project a Coefficient on the GridFunction, modifying only DOFs on
the boundary associated with the boundary attributes marked in the
@a attr array. */
void ProjectBdrCoefficient(Coefficient &coeff, Array<int> &attr)
{
Coefficient *coeff_p = &coeff;
ProjectBdrCoefficient(&coeff_p, attr);
}
void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
/** @brief Project a VectorCoefficient on the GridFunction, modifying only
DOFs on the boundary associated with the boundary attributes marked in
the @a attr array. */
virtual void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
Array<int> &attr);
/** @brief Project a set of Coefficient%s on the components of the
GridFunction, modifying only DOFs on the boundary associated with the
boundary attributed marked in the @a attr array. */
/** If a Coefficient pointer in the array @a coeff is NULL, that component
will not be touched. */
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
/** Project the normal component of the given VectorCoefficient on
the boundary. Only boundary attributes that are marked in
@@ -254,11 +292,11 @@ public:
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff,
Array<int> &bdr_attr);
/** Project the tangential components of the given VectorCoefficient on
the boundary. Only boundary attributes that are marked in
'bdr_attr' are projected. Assumes ND-type VectorFE GridFunction. */
void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
Array<int> &bdr_attr);
/** @brief Project the tangential components of the given VectorCoefficient
on the boundary. Only boundary attributes that are marked in @a bdr_attr
are projected. Assumes ND-type VectorFE GridFunction. */
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
Array<int> &bdr_attr);
virtual double ComputeL2Error(Coefficient &exsol,
const IntegrationRule *irs[] = NULL) const
@@ -306,6 +344,33 @@ public:
Coefficient *weight = NULL,
const IntegrationRule *irs[] = NULL) const;
/** Compute the Lp error in each element of the mesh and store the results in
the GridFunction @a error. The result should be an L2 GridFunction of
order zero using map type VALUE. */
virtual void ComputeElementLpErrors(const double p, Coefficient &exsol,
GridFunction &error,
Coefficient *weight = NULL,
const IntegrationRule *irs[] = NULL
) const;
virtual void ComputeElementL1Errors(Coefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(1.0, exsol, error, NULL, irs); }
virtual void ComputeElementL2Errors(Coefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(2.0, exsol, error, NULL, irs); }
virtual void ComputeElementMaxErrors(Coefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, irs); }
/** When given a vector weight, compute the pointwise (scalar) error as the
dot product of the vector error with the vector weight. Otherwise, the
scalar error is the l_2 norm of the vector error. */
@@ -314,6 +379,34 @@ public:
VectorCoefficient *v_weight = NULL,
const IntegrationRule *irs[] = NULL) const;
/** Compute the Lp error in each element of the mesh and store the results in
the GridFunction @ error. The result should be an L2 GridFunction of
order zero using map type VALUE. */
virtual void ComputeElementLpErrors(const double p, VectorCoefficient &exsol,
GridFunction &error,
Coefficient *weight = NULL,
VectorCoefficient *v_weight = NULL,
const IntegrationRule *irs[] = NULL
) const;
virtual void ComputeElementL1Errors(VectorCoefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(1.0, exsol, error, NULL, NULL, irs); }
virtual void ComputeElementL2Errors(VectorCoefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(2.0, exsol, error, NULL, NULL, irs); }
virtual void ComputeElementMaxErrors(VectorCoefficient &exsol,
GridFunction &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, NULL, irs); }
virtual void ComputeFlux(BilinearFormIntegrator &blfi,
GridFunction &flux,
int wcoef = 1, int subdomain = -1);
@@ -322,15 +415,10 @@ public:
GridFunction &operator=(double value);
/// Copy the data from @a v.
/** The size of @a v must be equal to the size of the FiniteElementSpace
@a fes. */
/** The size of @a v must be equal to the size of the associated
FiniteElementSpace #fes. */
GridFunction &operator=(const Vector &v);
/// Copy the data from @a v.
/** The GridFunctions @a v and @a *this must have FiniteElementSpaces with
the same size. */
GridFunction &operator=(const GridFunction &v);
/// Transform by the Space UpdateMatrix (e.g., on Mesh change).
virtual void Update();
@@ -411,6 +499,12 @@ public:
QuadratureFunction()
: qspace(NULL), vdim(0), own_qspace(false) { }
/** @brief Copy constructor. The QuadratureSpace ownership flag, #own_qspace,
in the new object is set to false. */
QuadratureFunction(const QuadratureFunction &orig)
: Vector(orig),
qspace(orig.qspace), vdim(orig.vdim), own_qspace(false) { }
/// Create a QuadratureFunction based on the given QuadratureSpace.
/** The QuadratureFunction does not assume ownership of the QuadratureSpace.
@note The Vector data is not initialized. */
@@ -476,13 +570,16 @@ public:
QuadratureFunction &operator=(double value);
/// Copy the data from @a v.
/** The size of @a v must be equal to the size of the QuadratureSpace
@a qspace. */
/** The size of @a v must be equal to the size of the associated
QuadratureSpace #qspace. */
QuadratureFunction &operator=(const Vector &v);
/// Copy the data from @a v.
/// Copy assignment. Only the data of the base class Vector is copied.
/** The QuadratureFunctions @a v and @a *this must have QuadratureSpaces with
the same size. */
the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
QuadratureFunction &operator=(const QuadratureFunction &v);
/// Get the IntegrationRule associated with mesh element @a idx.
+35
View File
@@ -854,6 +854,9 @@ IntegrationRules::IntegrationRules(int Ref, int _type):
TetrahedronIntRules.SetSize(32);
TetrahedronIntRules = NULL;
PrismIntRules.SetSize(32);
PrismIntRules = NULL;
CubeIntRules.SetSize(32);
CubeIntRules = NULL;
}
@@ -870,6 +873,7 @@ const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
case Geometry::SQUARE: ir_array = &SquareIntRules; break;
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
case Geometry::CUBE: ir_array = &CubeIntRules; break;
case Geometry::PRISM: ir_array = &PrismIntRules; break;
default:
mfem_error("IntegrationRules::Get(...) : Unknown geometry type!");
ir_array = NULL;
@@ -915,6 +919,7 @@ void IntegrationRules::Set(int GeomType, int Order, IntegrationRule &IntRule)
case Geometry::SQUARE: ir_array = &SquareIntRules; break;
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
case Geometry::CUBE: ir_array = &CubeIntRules; break;
case Geometry::PRISM: ir_array = &PrismIntRules; break;
default:
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
ir_array = NULL;
@@ -957,6 +962,7 @@ IntegrationRules::~IntegrationRules()
DeleteIntRuleArray(SquareIntRules);
DeleteIntRuleArray(TetrahedronIntRules);
DeleteIntRuleArray(CubeIntRules);
DeleteIntRuleArray(PrismIntRules);
}
@@ -977,6 +983,8 @@ IntegrationRule *IntegrationRules::GenerateIntegrationRule(int GeomType,
return TetrahedronIntegrationRule(Order);
case Geometry::CUBE:
return CubeIntegrationRule(Order);
case Geometry::PRISM:
return PrismIntegrationRule(Order);
default:
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
return NULL;
@@ -1584,6 +1592,33 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
}
}
// Integration rules for reference prism
IntegrationRule *IntegrationRules::PrismIntegrationRule(int Order)
{
IntegrationRule * irt = GenerateIntegrationRule(Geometry::TRIANGLE, Order);
IntegrationRule * irs = GenerateIntegrationRule(Geometry::SEGMENT, Order);
int nt = irt->GetNPoints();
int ns = irs->GetNPoints();
AllocIntRule(PrismIntRules, Order);
PrismIntRules[Order] = new IntegrationRule(nt * ns);
for (int ks=0; ks<ns; ks++)
{
const IntegrationPoint & ips = irs->IntPoint(ks);
for (int kt=0; kt<nt; kt++)
{
int kp = ks * nt + kt;
const IntegrationPoint & ipt = irt->IntPoint(kt);
IntegrationPoint & ipp = PrismIntRules[Order]->IntPoint(kp);
ipp.x = ipt.x;
ipp.y = ipt.y;
ipp.z = ips.x;
ipp.weight = ipt.weight * ips.weight;
}
}
return PrismIntRules[Order];
}
// Integration rules for reference cube
IntegrationRule *IntegrationRules::CubeIntegrationRule(int Order)
{
+2
View File
@@ -306,6 +306,7 @@ private:
Array<IntegrationRule *> TriangleIntRules;
Array<IntegrationRule *> SquareIntRules;
Array<IntegrationRule *> TetrahedronIntRules;
Array<IntegrationRule *> PrismIntRules;
Array<IntegrationRule *> CubeIntRules;
void AllocIntRule(Array<IntegrationRule *> &ir_array, int Order)
@@ -330,6 +331,7 @@ private:
IntegrationRule *TriangleIntegrationRule(int Order);
IntegrationRule *SquareIntegrationRule(int Order);
IntegrationRule *TetrahedronIntegrationRule(int Order);
IntegrationRule *PrismIntegrationRule(int Order);
IntegrationRule *CubeIntegrationRule(int Order);
void DeleteIntRuleArray(Array<IntegrationRule *> &ir_array);
+77 -8
View File
@@ -16,6 +16,23 @@
namespace mfem
{
LinearForm::LinearForm(FiniteElementSpace *f, LinearForm *lf)
: Vector(f->GetVSize())
{
fes = f;
extern_lfs = 1;
// Copy the pointers to the integrators
dlfi = lf->dlfi;
dlfi_delta = lf->dlfi_delta;
blfi = lf->blfi;
flfi = lf->flfi;
flfi_marker = lf->flfi_marker;
}
void LinearForm::AddDomainIntegrator(LinearFormIntegrator *lfi)
{
DeltaLFIntegrator *maybe_delta =
@@ -33,6 +50,14 @@ void LinearForm::AddDomainIntegrator(LinearFormIntegrator *lfi)
void LinearForm::AddBoundaryIntegrator (LinearFormIntegrator * lfi)
{
blfi.Append (lfi);
blfi_marker.Append(NULL); // NULL -> all attributes are active
}
void LinearForm::AddBoundaryIntegrator (LinearFormIntegrator * lfi,
Array<int> &bdr_attr_marker)
{
blfi.Append (lfi);
blfi_marker.Append(&bdr_attr_marker);
}
void LinearForm::AddBdrFaceIntegrator (LinearFormIntegrator * lfi)
@@ -59,6 +84,7 @@ void LinearForm::Assemble()
Vector::operator=(0.0);
if (dlfi.Size())
{
for (i = 0; i < fes -> GetNE(); i++)
{
fes -> GetElementVDofs (i, vdofs);
@@ -69,12 +95,38 @@ void LinearForm::Assemble()
AddElementVector (vdofs, elemvect);
}
}
}
AssembleDelta();
if (blfi.Size())
{
Mesh *mesh = fes->GetMesh();
// Which boundary attributes need to be processed?
Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
mesh->bdr_attributes.Max() : 0);
bdr_attr_marker = 0;
for (int k = 0; k < blfi.Size(); k++)
{
if (blfi_marker[k] == NULL)
{
bdr_attr_marker = 1;
break;
}
Array<int> &bdr_marker = *blfi_marker[k];
MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
"invalid boundary marker for boundary integrator #"
<< k << ", counting from zero");
for (int i = 0; i < bdr_attr_marker.Size(); i++)
{
bdr_attr_marker[i] |= bdr_marker[i];
}
}
for (i = 0; i < fes -> GetNBE(); i++)
{
const int bdr_attr = mesh->GetBdrAttribute(i);
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
fes -> GetBdrElementVDofs (i, vdofs);
eltrans = fes -> GetBdrElementTransformation (i);
for (int k=0; k < blfi.Size(); k++)
@@ -83,7 +135,7 @@ void LinearForm::Assemble()
AddElementVector (vdofs, elemvect);
}
}
}
if (flfi.Size())
{
FaceElementTransformations *tr;
@@ -180,13 +232,30 @@ void LinearForm::AssembleDelta()
}
}
LinearForm::~LinearForm()
LinearForm & LinearForm::operator=(double value)
{
int k;
for (k=0; k < dlfi_delta.Size(); k++) { delete dlfi_delta[k]; }
for (k=0; k < dlfi.Size(); k++) { delete dlfi[k]; }
for (k=0; k < blfi.Size(); k++) { delete blfi[k]; }
for (k=0; k < flfi.Size(); k++) { delete flfi[k]; }
Vector::operator=(value);
return *this;
}
LinearForm & LinearForm::operator=(const Vector &v)
{
MFEM_ASSERT(fes && v.Size() == fes->GetVSize(), "");
Vector::operator=(v);
return *this;
}
LinearForm::~LinearForm()
{
if (!extern_lfs)
{
int k;
for (k=0; k < dlfi_delta.Size(); k++) { delete dlfi_delta[k]; }
for (k=0; k < dlfi.Size(); k++) { delete dlfi[k]; }
for (k=0; k < blfi.Size(); k++) { delete blfi[k]; }
for (k=0; k < flfi.Size(); k++) { delete flfi[k]; }
}
}
}
+98 -17
View File
@@ -22,9 +22,13 @@ namespace mfem
/// Class for linear form - Vector with associated FE space and LFIntegrators.
class LinearForm : public Vector
{
private:
/// FE space on which LF lives.
FiniteElementSpace * fes;
protected:
/// FE space on which the LinearForm lives. Not owned.
FiniteElementSpace *fes;
/** @brief Indicates the LinerFormIntegrator%s stored in #dlfi, #dlfi_delta,
#blfi, and #flfi are owned by another LinearForm. */
int extern_lfs;
/// Set of Domain Integrators to be applied.
Array<LinearFormIntegrator*> dlfi;
@@ -34,10 +38,11 @@ private:
/// Set of Boundary Integrators to be applied.
Array<LinearFormIntegrator*> blfi;
Array<Array<int>*> blfi_marker; ///< Entries are not owned.
/// Set of Boundary Face Integrators to be applied.
Array<LinearFormIntegrator*> flfi;
Array<Array<int>*> flfi_marker;
Array<Array<int>*> flfi_marker; ///< Entries are not owned.
/// The element ids where the centers of the delta functions lie
Array<int> dlfi_delta_elem_id;
@@ -51,47 +56,115 @@ private:
/// Force (re)computation of delta locations.
void ResetDeltaLocations() { dlfi_delta_elem_id.SetSize(0); }
public:
/// Creates linear form associated with FE space *f.
LinearForm (FiniteElementSpace * f) : Vector (f -> GetVSize())
{ fes = f; }
private:
/// Copy construction is not supported; body is undefined.
LinearForm(const LinearForm &);
LinearForm() { fes = NULL; }
public:
/// Creates linear form associated with FE space @a *f.
/** The pointer @a f is not owned by the newly constructed object. */
LinearForm(FiniteElementSpace *f) : Vector(f->GetVSize())
{ fes = f; extern_lfs = 0; }
/** @brief Create a LinearForm on the FiniteElementSpace @a f, using the
same integrators as the LinearForm @a lf.
The pointer @a f is not owned by the newly constructed object.
The integrators in @a lf are copied as pointers and they are not owned by
the newly constructed LinearForm. */
LinearForm(FiniteElementSpace *f, LinearForm *lf);
/// Create an empty LinearForm without an associated FiniteElementSpace.
/** The associated FiniteElementSpace can be set later using one of the
methods: Update(FiniteElementSpace *) or
Update(FiniteElementSpace *, Vector &, int). */
LinearForm() { fes = NULL; extern_lfs = 0; }
/// Copy assignment. Only the data of the base class Vector is copied.
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
have the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
LinearForm &operator=(const LinearForm &rhs)
{ return operator=((const Vector &)rhs); }
/// (DEPRECATED) Return the FE space associated with the LinearForm.
/** @deprecated Use FESpace() instead. */
FiniteElementSpace * GetFES() { return fes; }
FiniteElementSpace *GetFES() { return fes; }
/// Read+write access to the associated FiniteElementSpace.
FiniteElementSpace *FESpace() { return fes; }
/// Read-only access to the associated FiniteElementSpace.
const FiniteElementSpace *FESpace() const { return fes; }
/// Adds new Domain Integrator.
void AddDomainIntegrator (LinearFormIntegrator * lfi);
/// Adds new Domain Integrator. Assumes ownership of @a lfi.
void AddDomainIntegrator(LinearFormIntegrator *lfi);
/// Adds new Boundary Integrator.
void AddBoundaryIntegrator (LinearFormIntegrator * lfi);
/// Adds new Boundary Integrator. Assumes ownership of @a lfi.
void AddBoundaryIntegrator(LinearFormIntegrator *lfi);
/// Adds new Boundary Face Integrator.
void AddBdrFaceIntegrator (LinearFormIntegrator * lfi);
/** @brief Add new Boundary Integrator, restricted to the given boundary
attributes.
Assumes ownership of @a lfi. The array @a bdr_attr_marker is stored
internally as a pointer to the given Array<int> object. */
void AddBoundaryIntegrator(LinearFormIntegrator *lfi,
Array<int> &bdr_attr_marker);
/// Adds new Boundary Face Integrator. Assumes ownership of @a lfi.
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi);
/** @brief Add new Boundary Face Integrator, restricted to the given boundary
attributes. */
attributes.
Assumes ownership of @a lfi. The array @a bdr_attr_marker is stored
internally as a pointer to the given Array<int> object. */
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi,
Array<int> &bdr_attr_marker);
/** @brief Access all integrators added with AddDomainIntegrator() which are
not DeltaLFIntegrator%s or they are DeltaLFIntegrator%s with non-delta
coefficients. */
Array<LinearFormIntegrator*> *GetDLFI() { return &dlfi; }
/** @brief Access all integrators added with AddDomainIntegrator() which are
DeltaLFIntegrator%s with delta coefficients. */
Array<DeltaLFIntegrator*> *GetDLFI_Delta() { return &dlfi_delta; }
/// Access all integrators added with AddBoundaryIntegrator().
Array<LinearFormIntegrator*> *GetBLFI() { return &blfi; }
/// Access all integrators added with AddBdrFaceIntegrator().
Array<LinearFormIntegrator*> *GetFLFI() { return &flfi; }
/** @brief Access all boundary markers added with AddBdrFaceIntegrator().
If no marker was specified when the integrator was added, the
corresponding pointer (to Array<int>) will be NULL. */
Array<Array<int>*> *GetFLFI_Marker() { return &flfi_marker; }
/// Assembles the linear form i.e. sums over all domain/bdr integrators.
void Assemble();
/// Assembles delta functions of the linear form
void AssembleDelta();
/// Update the object according to the associated FE space #fes.
/** This method should be called when the asscociated FE space #fes has been
updated, e.g. after its associated Mesh object has been refined.
@note This method does not perform assembly. */
void Update() { SetSize(fes->GetVSize()); ResetDeltaLocations(); }
/// Associate a new FE space, @a *f, with this object and Update() it. */
void Update(FiniteElementSpace *f)
{ fes = f; SetSize(f->GetVSize()); ResetDeltaLocations(); }
/** @brief Associate a new FE space, @a *f, with this object and use the data
of @a v, offset by @a v_offset, to initialize this object's Vector::data.
@note This method does not perform assembly. */
void Update(FiniteElementSpace *f, Vector &v, int v_offset);
/// Return the action of the LinearForm as a linear mapping.
@@ -101,6 +174,14 @@ public:
and GridFunction. */
double operator()(const GridFunction &gf) const { return (*this)*gf; }
/// Redefine '=' for LinearForm = constant.
LinearForm &operator=(double value);
/// Copy the data from @a v.
/** The size of @a v must be equal to the size of the associated
FiniteElementSpace #fes. */
LinearForm &operator=(const Vector &v);
/// Destroys linear form.
~LinearForm();
};
+67 -3
View File
@@ -28,8 +28,10 @@ namespace mfem
class ParBilinearForm : public BilinearForm
{
protected:
ParFiniteElementSpace *pfes;
mutable ParGridFunction X, Y; // used in TrueAddMult
ParFiniteElementSpace *pfes; ///< Points to the same object as #fes
/// Auxiliary objects used in TrueAddMult().
mutable ParGridFunction X, Y;
OperatorHandle p_mat, p_mat_e;
@@ -40,12 +42,28 @@ protected:
void AssembleSharedFaces(int skip_zeros = 1);
private:
/// Copy construction is not supported; body is undefined.
ParBilinearForm(const ParBilinearForm &);
/// Copy assignment is not supported; body is undefined.
ParBilinearForm &operator=(const ParBilinearForm &);
public:
/// Creates parallel bilinear form associated with the FE space @a *pf.
/** The pointer @a pf is not owned by the newly constructed object. */
ParBilinearForm(ParFiniteElementSpace *pf)
: BilinearForm(pf), pfes(pf),
p_mat(Operator::Hypre_ParCSR), p_mat_e(Operator::Hypre_ParCSR)
{ keep_nbr_block = false; }
/** @brief Create a ParBilinearForm on the ParFiniteElementSpace @a *pf,
using the same integrators as the ParBilinearForm @a *bf.
The pointer @a pf is not owned by the newly constructed object.
The integrators in @a bf are copied as pointers and they are not owned by
the newly constructed ParBilinearForm. */
ParBilinearForm(ParFiniteElementSpace *pf, ParBilinearForm *bf)
: BilinearForm(pf, bf), pfes(pf),
p_mat(Operator::Hypre_ParCSR), p_mat_e(Operator::Hypre_ParCSR)
@@ -219,11 +237,25 @@ public:
class ParMixedBilinearForm : public MixedBilinearForm
{
protected:
/// Points to the same object as #trial_fes
ParFiniteElementSpace *trial_pfes;
/// Points to the same object as #test_fes
ParFiniteElementSpace *test_pfes;
mutable ParGridFunction X, Y; // used in TrueAddMult
/// Auxiliary objects used in TrueAddMult().
mutable ParGridFunction X, Y;
private:
/// Copy construction is not supported; body is undefined.
ParMixedBilinearForm(const ParMixedBilinearForm &);
/// Copy assignment is not supported; body is undefined.
ParMixedBilinearForm &operator=(const ParMixedBilinearForm &);
public:
/** @brief Construct a ParMixedBilinearForm on the given FiniteElementSpace%s
@a trial_fes and @a test_fes. */
/** The pointers @a trial_fes and @a test_fes are not owned by the newly
constructed object. */
ParMixedBilinearForm(ParFiniteElementSpace *trial_fes,
ParFiniteElementSpace *test_fes)
: MixedBilinearForm(trial_fes, test_fes)
@@ -232,6 +264,24 @@ public:
test_pfes = test_fes;
}
/** @brief Create a ParMixedBilinearForm on the given FiniteElementSpace%s
@a trial_fes and @a test_fes, using the same integrators as the
ParMixedBilinearForm @a mbf.
The pointers @a trial_fes and @a test_fes are not owned by the newly
constructed object.
The integrators in @a mbf are copied as pointers and they are not owned
by the newly constructed ParMixedBilinearForm. */
ParMixedBilinearForm(ParFiniteElementSpace *trial_fes,
ParFiniteElementSpace *test_fes,
ParMixedBilinearForm * mbf)
: MixedBilinearForm(trial_fes, test_fes, mbf)
{
trial_pfes = trial_fes;
test_pfes = test_fes;
}
/// Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
HypreParMatrix *ParallelAssemble();
@@ -251,10 +301,24 @@ public:
class ParDiscreteLinearOperator : public DiscreteLinearOperator
{
protected:
/// Points to the same object as #trial_fes
ParFiniteElementSpace *domain_fes;
/// Points to the same object as #test_fes
ParFiniteElementSpace *range_fes;
private:
/// Copy construction is not supported; body is undefined.
ParDiscreteLinearOperator(const ParDiscreteLinearOperator &);
/// Copy assignment is not supported; body is undefined.
ParDiscreteLinearOperator &operator=(const ParDiscreteLinearOperator &);
public:
/** @brief Construct a ParDiscreteLinearOperator on the given
FiniteElementSpace%s @a dfes (domain FE space) and @a rfes (range FE
space). */
/** The pointers @a dfes and @a rfes are not owned by the newly constructed
object. */
ParDiscreteLinearOperator(ParFiniteElementSpace *dfes,
ParFiniteElementSpace *rfes)
: DiscreteLinearOperator(dfes, rfes) { domain_fes=dfes; range_fes=rfes; }
+217 -55
View File
@@ -140,6 +140,13 @@ void ParFiniteElementSpace::Construct()
}
else // Nonconforming()
{
// Initialize 'gcomm' for the cut (aka "partially conforming") space.
// In the process, the array 'ldof_ltdof' is also initialized (for the cut
// space) and used; however, it will be overwritten below with the real
// true dofs. Also, 'ldof_sign' and 'ldof_group' are constructed for the
// cut space.
ConstructTrueDofs();
// calculate number of ghost DOFs
ngvdofs = pncmesh->GetNGhostVertices()
* fec->DofForGeometry(Geometry::POINT);
@@ -153,7 +160,7 @@ void ParFiniteElementSpace::Construct()
if (pmesh->Dimension() > 2)
{
ngfdofs = pncmesh->GetNGhostFaces()
* fec->DofForGeometry(mesh->GetBdrElementBaseGeometry());
* fec->DofForGeometry(pncmesh->GetGhostFaceGeometry(0));
}
// total number of ghost DOFs. Ghost DOFs start at index 'ndofs', i.e.,
@@ -171,12 +178,51 @@ void ParFiniteElementSpace::Construct()
}
}
void ParFiniteElementSpace::PrintPartitionStats()
{
long ltdofs = ltdof_size;
long min_ltdofs, max_ltdofs, sum_ltdofs;
MPI_Reduce(&ltdofs, &min_ltdofs, 1, MPI_LONG, MPI_MIN, 0, MyComm);
MPI_Reduce(&ltdofs, &max_ltdofs, 1, MPI_LONG, MPI_MAX, 0, MyComm);
MPI_Reduce(&ltdofs, &sum_ltdofs, 1, MPI_LONG, MPI_SUM, 0, MyComm);
if (MyRank == 0)
{
double avg = double(sum_ltdofs) / NRanks;
mfem::out << "True DOF partitioning: min " << min_ltdofs
<< ", avg " << std::fixed << std::setprecision(1) << avg
<< ", max " << max_ltdofs
<< ", (max-avg)/avg " << 100.0*(max_ltdofs - avg)/avg
<< "%" << std::endl;
}
if (NRanks <= 32)
{
if (MyRank == 0)
{
mfem::out << "True DOFs by rank: " << ltdofs;
for (int i = 1; i < NRanks; i++)
{
MPI_Status status;
MPI_Recv(&ltdofs, 1, MPI_LONG, i, 123, MyComm, &status);
mfem::out << " " << ltdofs;
}
mfem::out << "\n";
}
else
{
MPI_Send(&ltdofs, 1, MPI_LONG, 0, 123, MyComm);
}
}
}
void ParFiniteElementSpace::GetGroupComm(
GroupCommunicator &gc, int ldof_type, Array<int> *ldof_sign)
{
int gr;
int ng = pmesh->GetNGroups();
int nvd, ned, nfd;
int nvd, ned, ntd = 0, nqd = 0;
Array<int> dofs;
int group_ldof_counter;
@@ -184,8 +230,18 @@ void ParFiniteElementSpace::GetGroupComm(
nvd = fec->DofForGeometry(Geometry::POINT);
ned = fec->DofForGeometry(Geometry::SEGMENT);
// Assuming all faces are the same type:
nfd = (fdofs) ? (fdofs[1]-fdofs[0]) : (0);
if (fdofs)
{
if (mesh->HasGeometry(Geometry::TRIANGLE))
{
ntd = fec->DofForGeometry(Geometry::TRIANGLE);
}
if (mesh->HasGeometry(Geometry::SQUARE))
{
nqd = fec->DofForGeometry(Geometry::SQUARE);
}
}
if (ldof_sign)
{
@@ -199,7 +255,8 @@ void ParFiniteElementSpace::GetGroupComm(
{
group_ldof_counter += nvd * pmesh->GroupNVertices(gr);
group_ldof_counter += ned * pmesh->GroupNEdges(gr);
group_ldof_counter += nfd * pmesh->GroupNFaces(gr);
group_ldof_counter += ntd * pmesh->GroupNTriangles(gr);
group_ldof_counter += nqd * pmesh->GroupNQuadrilaterals(gr);
}
if (ldof_type)
{
@@ -213,12 +270,13 @@ void ParFiniteElementSpace::GetGroupComm(
group_ldof.GetI()[0] = group_ldof.GetI()[1] = 0;
for (gr = 1; gr < ng; gr++)
{
int j, k, l, m, o, nv, ne, nf;
int j, k, l, m, o, nv, ne, nt, nq;
const int *ind;
nv = pmesh->GroupNVertices(gr);
ne = pmesh->GroupNEdges(gr);
nf = pmesh->GroupNFaces(gr);
nt = pmesh->GroupNTriangles(gr);
nq = pmesh->GroupNQuadrilaterals(gr);
// vertices
if (nvd > 0)
@@ -284,18 +342,55 @@ void ParFiniteElementSpace::GetGroupComm(
}
}
// faces
if (nfd > 0)
// triangles
if (ntd > 0)
{
for (j = 0; j < nf; j++)
for (j = 0; j < nt; j++)
{
pmesh->GroupFace(gr, j, k, o);
pmesh->GroupTriangle(gr, j, k, o);
dofs.SetSize(nfd);
dofs.SetSize(ntd);
m = nvdofs+nedofs+fdofs[k];
ind = fec->DofOrderForOrientation(
mesh->GetFaceBaseGeometry(k), o);
for (l = 0; l < nfd; l++)
ind = fec->DofOrderForOrientation(Geometry::TRIANGLE, o);
for (l = 0; l < ntd; l++)
{
if (ind[l] < 0)
{
dofs[l] = m + (-1-ind[l]);
if (ldof_sign)
{
(*ldof_sign)[dofs[l]] = -1;
}
}
else
{
dofs[l] = m + ind[l];
}
}
if (ldof_type)
{
DofsToVDofs(dofs);
}
for (l = 0; l < dofs.Size(); l++)
{
group_ldof.GetJ()[group_ldof_counter++] = dofs[l];
}
}
}
// quadrilaterals
if (nqd > 0)
{
for (j = 0; j < nq; j++)
{
pmesh->GroupQuadrilateral(gr, j, k, o);
dofs.SetSize(nqd);
m = nvdofs+nedofs+fdofs[k];
ind = fec->DofOrderForOrientation(Geometry::SQUARE, o);
for (l = 0; l < nqd; l++)
{
if (ind[l] < 0)
{
@@ -418,12 +513,13 @@ void ParFiniteElementSpace::GetSharedEdgeDofs(
}
}
void ParFiniteElementSpace::GetSharedFaceDofs(
void ParFiniteElementSpace::GetSharedTriangleDofs(
int group, int fi, Array<int> &dofs) const
{
int l_face, ori;
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNFaces(group), "invalid face index");
pmesh->GroupFace(group, fi, l_face, ori);
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNTriangles(group),
"invalid triangular face index");
pmesh->GroupTriangle(group, fi, l_face, ori);
if (ori == 0)
{
GetFaceDofs(l_face, dofs);
@@ -431,7 +527,31 @@ void ParFiniteElementSpace::GetSharedFaceDofs(
else
{
Array<int> rdofs;
fec->SubDofOrder(pmesh->GetFaceBaseGeometry(l_face), 2, ori, dofs);
fec->SubDofOrder(Geometry::TRIANGLE, 2, ori, dofs);
GetFaceDofs(l_face, rdofs);
for (int i = 0; i < dofs.Size(); i++)
{
const int di = dofs[i];
dofs[i] = (di >= 0) ? rdofs[di] : -1-rdofs[-1-di];
}
}
}
void ParFiniteElementSpace::GetSharedQuadrilateralDofs(
int group, int fi, Array<int> &dofs) const
{
int l_face, ori;
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNQuadrilaterals(group),
"invalid quadrilateral face index");
pmesh->GroupQuadrilateral(group, fi, l_face, ori);
if (ori == 0)
{
GetFaceDofs(l_face, dofs);
}
else
{
Array<int> rdofs;
fec->SubDofOrder(Geometry::SQUARE, 2, ori, dofs);
GetFaceDofs(l_face, rdofs);
for (int i = 0; i < dofs.Size(); i++)
{
@@ -556,30 +676,26 @@ HypreParMatrix *ParFiniteElementSpace::GetPartialConformingInterpolation()
void ParFiniteElementSpace::DivideByGroupSize(double *vec)
{
if (Nonconforming())
{
MFEM_ABORT("Not implemented for NC mesh.");
}
GroupTopology &gt = GetGroupTopo();
for (int i = 0; i < ldof_group.Size(); i++)
{
if (gt.IAmMaster(ldof_group[i])) // we are the master
{
vec[ldof_ltdof[i]] /= gt.GetGroupSize(ldof_group[i]);
if (ldof_ltdof[i] >= 0) // see note below
{
vec[ldof_ltdof[i]] /= gt.GetGroupSize(ldof_group[i]);
}
// NOTE: in NC meshes, ldof_ltdof generated for the gtopo
// groups by ConstructTrueDofs gets overwritten by
// BuildParallelConformingInterpolation. Some DOFs that are
// seen as true by the conforming code are actually slaves and
// end up with a -1 in ldof_ltdof.
}
}
}
GroupCommunicator *ParFiniteElementSpace::ScalarGroupComm()
{
if (Nonconforming())
{
// MFEM_WARNING("Not implemented for NC mesh.");
return NULL;
}
GroupCommunicator *gc = new GroupCommunicator(GetGroupTopo());
if (NURBSext)
{
@@ -594,15 +710,10 @@ GroupCommunicator *ParFiniteElementSpace::ScalarGroupComm()
void ParFiniteElementSpace::Synchronize(Array<int> &ldof_marker) const
{
if (Nonconforming())
{
MFEM_ABORT("Not implemented for NC mesh.");
}
// For non-conforming mesh, synchronization is performed on the cut (aka
// "partially conforming") space.
if (ldof_marker.Size() != GetVSize())
{
mfem_error("ParFiniteElementSpace::Synchronize");
}
MFEM_VERIFY(ldof_marker.Size() == GetVSize(), "invalid in/out array");
// implement allreduce(|) as reduce(|) + broadcast
gcomm->Reduce<int>(ldof_marker, GroupCommunicator::BitOR);
@@ -991,7 +1102,7 @@ void ParFiniteElementSpace::GetFaceNbrFaceVDofs(int i, Array<int> &vdofs) const
const int nd = face_nbr_element_dof.RowSize(el2);
const int *vol_vdofs = face_nbr_element_dof.GetRow(el2);
const Element *face_nbr_el = pmesh->face_nbr_elements[el2];
const int geom = face_nbr_el->GetGeometryType();
Geometry::Type geom = face_nbr_el->GetGeometryType();
const int face_dim = Geometry::Dimension[geom]-1;
fec->SubDofOrder(geom, face_dim, inf2, vdofs);
@@ -1023,8 +1134,8 @@ const FiniteElement *ParFiniteElementSpace::GetFaceNbrFaceFE(int i) const
{
// Works in tandem with GetFaceNbrFaceVDofs() defined above.
MFEM_ASSERT(Nonconforming() && !NURBSext, "");
const int geom = (pmesh->Dimension() == 2) ?
Geometry::SEGMENT : Geometry::SQUARE;
Geometry::Type geom = (pmesh->Dimension() == 2) ?
Geometry::SEGMENT : Geometry::SQUARE;
return fec->FiniteElementForGeometry(geom);
}
@@ -1175,7 +1286,9 @@ void ParFiniteElementSpace::GetGhostEdgeDofs(const MeshId &edge_id,
void ParFiniteElementSpace::GetGhostFaceDofs(const MeshId &face_id,
Array<int> &dofs) const
{
MFEM_ASSERT(mesh->GetFaceBaseGeometry(0) == Geometry::SQUARE, "");
const int ghost_face_index = face_id.index - pncmesh->GetNFaces();
MFEM_ASSERT(pncmesh->GetGhostFaceGeometry(ghost_face_index)
== Geometry::SQUARE, "");
int nv = fec->DofForGeometry(Geometry::POINT);
int ne = fec->DofForGeometry(Geometry::SEGMENT);
@@ -1209,8 +1322,8 @@ void ParFiniteElementSpace::GetGhostFaceDofs(const MeshId &face_id,
}
}
int first = ndofs + ngvdofs + ngedofs +
(face_id.index - pncmesh->GetNFaces())*nf;
// Assuming all ghost faces have the same number of dofs:
int first = ndofs + ngvdofs + ngedofs + ghost_face_index*nf;
for (int j = 0; j < nf; j++)
{
dofs[offset++] = first + j;
@@ -1252,7 +1365,8 @@ void ParFiniteElementSpace::GetBareDofs(int entity, int index,
break;
default:
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
ned = fec->DofForGeometry(Geometry::SQUARE);
ghost = pncmesh->GetNFaces();
first = (index < ghost)
? nvdofs + nedofs + index*ned // regular face
@@ -1292,8 +1406,9 @@ int ParFiniteElementSpace::PackDof(int entity, int index, int edof) const
: ndofs + ngvdofs + (index - ghost)*ned + edof; // ghost edge
default:
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
ghost = pncmesh->GetNFaces();
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
ned = fec->DofForGeometry(Geometry::SQUARE);
return (index < ghost)
? nvdofs + nedofs + index*ned + edof // regular face
@@ -1326,7 +1441,8 @@ void ParFiniteElementSpace::UnpackDof(int dof,
dof -= nedofs;
if (dof < nfdofs) // regular face
{
int nf = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
int nf = fec->DofForGeometry(Geometry::SQUARE);
entity = 2, index = dof / nf, edof = dof % nf;
return;
}
@@ -1351,7 +1467,7 @@ void ParFiniteElementSpace::UnpackDof(int dof,
dof -= ngedofs;
if (dof < ngfdofs) // ghost face
{
int nf = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
int nf = fec->DofForGeometry(pncmesh->GetGhostFaceGeometry(0));
entity = 2, index = pncmesh->GetNFaces() + dof / nf, edof = dof % nf;
return;
}
@@ -1578,7 +1694,7 @@ void NeighborRowMessage::Decode(int rank)
rows.clear();
rows.reserve(nrows);
int fgeom = pncmesh->GetFaceGeometry();
Geometry::Type fgeom = pncmesh->GetFaceGeometry();
// read rows
for (int ent = 0, gi = 0; ent < 3; ent++)
@@ -1640,6 +1756,9 @@ ParFiniteElementSpace::ScheduleSendRow(const PMatrixRow &row, int dof,
msg.AddRow(ent, idx, edof, group_id, row);
msg.SetNCMesh(pncmesh);
msg.SetFEC(fec);
#ifdef MFEM_PMATRIX_STATS
n_rows_sent++;
#endif
}
}
}
@@ -1662,7 +1781,9 @@ void ParFiniteElementSpace::ForwardRow(const PMatrixRow &row, int dof,
msg.AddRow(ent, idx, edof, invalid, row);
msg.SetNCMesh(pncmesh);
msg.SetFEC(fec);
#ifdef MFEM_PMATRIX_STATS
n_rows_fwd++;
#endif
#ifdef MFEM_DEBUG_PMATRIX
mfem::out << "Rank " << pncmesh->GetMyRank() << " forwarding to "
<< rank << ": ent " << ent << ", index" << idx
@@ -1744,6 +1865,11 @@ int ParFiniteElementSpace
{
bool dg = (nvdofs == 0 && nedofs == 0 && nfdofs == 0);
#ifdef MFEM_PMATRIX_STATS
n_msgs_sent = n_msgs_recv = 0;
n_rows_sent = n_rows_recv = n_rows_fwd = 0;
#endif
// *** STEP 1: build master-slave dependency lists ***
int total_dofs = ndofs + ngdofs;
@@ -1763,7 +1889,8 @@ int ParFiniteElementSpace
if (entity > 1) { T.SetFE(&QuadrilateralFE); }
else { T.SetFE(&SegmentFE); }
int geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
Geometry::Type geom = (entity > 1) ?
Geometry::SQUARE : Geometry::SEGMENT;
const FiniteElement* fe = fec->FiniteElementForGeometry(geom);
if (!fe) { continue; }
@@ -1921,6 +2048,9 @@ int ParFiniteElementSpace
// send identity rows
NeighborRowMessage::IsendAll(send_msg.back(), MyComm);
#ifdef MFEM_PMATRIX_STATS
n_msgs_sent += send_msg.back().size();
#endif
if (R) { (*R)->Finalize(); }
@@ -1948,6 +2078,10 @@ int ParFiniteElementSpace
while (NeighborRowMessage::IProbe(rank, size, MyComm))
{
recv_msg.Recv(rank, size, MyComm);
#ifdef MFEM_PMATRIX_STATS
n_msgs_recv++;
n_rows_recv += recv_msg.GetRows().size();
#endif
const NeighborRowMessage::RowInfo::List &rows = recv_msg.GetRows();
for (unsigned i = 0; i < rows.size(); i++)
@@ -2022,6 +2156,9 @@ int ParFiniteElementSpace
// send current batch of messages
NeighborRowMessage::IsendAll(send_msg.back(), MyComm);
#ifdef MFEM_PMATRIX_STATS
n_msgs_sent += send_msg.back().size();
#endif
}
if (P)
@@ -2045,6 +2182,31 @@ int ParFiniteElementSpace
NeighborRowMessage::WaitAllSent(*it);
}
#ifdef MFEM_PMATRIX_STATS
int n_rounds = send_msg.size();
int glob_rounds, glob_msgs_sent, glob_msgs_recv;
int glob_rows_sent, glob_rows_recv, glob_rows_fwd;
MPI_Reduce(&n_rounds, &glob_rounds, 1, MPI_INT, MPI_SUM, 0, MyComm);
MPI_Reduce(&n_msgs_sent, &glob_msgs_sent, 1, MPI_INT, MPI_SUM, 0, MyComm);
MPI_Reduce(&n_msgs_recv, &glob_msgs_recv, 1, MPI_INT, MPI_SUM, 0, MyComm);
MPI_Reduce(&n_rows_sent, &glob_rows_sent, 1, MPI_INT, MPI_SUM, 0, MyComm);
MPI_Reduce(&n_rows_recv, &glob_rows_recv, 1, MPI_INT, MPI_SUM, 0, MyComm);
MPI_Reduce(&n_rows_fwd, &glob_rows_fwd, 1, MPI_INT, MPI_SUM, 0, MyComm);
if (MyRank == 0)
{
mfem::out << "P matrix stats (avg per rank): "
<< double(glob_rounds)/NRanks << " rounds, "
<< double(glob_msgs_sent)/NRanks << " msgs sent, "
<< double(glob_msgs_recv)/NRanks << " msgs recv, "
<< double(glob_rows_sent)/NRanks << " rows sent, "
<< double(glob_rows_recv)/NRanks << " rows recv, "
<< double(glob_rows_fwd)/NRanks << " rows forwarded."
<< std::endl;
}
#endif
return num_true_dofs*vdim;
}
@@ -2305,7 +2467,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
Vector row;
ParNCMesh* pncmesh = pmesh->pncmesh;
int geom = pncmesh->GetElementGeometry();
Geometry::Type geom = pncmesh->GetElementGeometry();
int ldof = fec->FiniteElementForGeometry(geom)->GetDof();
const CoarseFineTransformations &dtrans = pncmesh->GetDerefinementTransforms();
@@ -2355,7 +2517,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
}
DenseTensor localR;
GetLocalDerefinementMatrices(localR);
GetLocalDerefinementMatrices(geom, localR);
// create the diagonal part of the derefinement matrix
SparseMatrix *diag = new SparseMatrix(ndofs*vdim, old_ndofs*vdim);
+16 -5
View File
@@ -119,6 +119,11 @@ private:
int PackDof(int entity, int index, int edof) const;
void UnpackDof(int dof, int &entity, int &index, int &edof) const;
#ifdef MFEM_PMATRIX_STATS
mutable int n_msgs_sent, n_msgs_recv;
mutable int n_rows_sent, n_rows_recv, n_rows_fwd;
#endif
void ScheduleSendRow(const struct PMatrixRow &row, int dof, GroupId group_id,
std::map<int, class NeighborRowMessage> &send_msg) const;
@@ -182,7 +187,7 @@ public:
/** @brief Copy constructor: deep copy all data from @a orig except the
ParMesh, the FiniteElementCollection, and some derived data. */
/** If the @a pmesh or @a fec poiters are NULL (default), then the new
/** If the @a pmesh or @a fec pointers are NULL (default), then the new
ParFiniteElementSpace will reuse the respective pointers from @a orig. If
any of these pointers is not NULL, the given pointer will be used instead
of the one used by @a orig.
@@ -205,7 +210,7 @@ public:
ParFiniteElementSpace(const FiniteElementSpace &orig, ParMesh &pmesh,
const FiniteElementCollection *fec = NULL);
/** @brief Construct the *local* ParFiniteElementSpace corresponing to the
/** @brief Construct the *local* ParFiniteElementSpace corresponding to the
global FE space, @a global_fes. */
/** The parameter @a pm is the *local* ParMesh obtained by decomposing the
global Mesh used by @a global_fes. The array @a partitioning represents
@@ -260,7 +265,8 @@ public:
virtual void GetFaceDofs(int i, Array<int> &dofs) const;
void GetSharedEdgeDofs(int group, int ei, Array<int> &dofs) const;
void GetSharedFaceDofs(int group, int fi, Array<int> &dofs) const;
void GetSharedTriangleDofs(int group, int fi, Array<int> &dofs) const;
void GetSharedQuadrilateralDofs(int group, int fi, Array<int> &dofs) const;
/// The true dof-to-dof interpolation matrix
HypreParMatrix *Dof_TrueDof_Matrix() const
@@ -285,11 +291,14 @@ public:
/// Return a const reference to the internal GroupCommunicator (on VDofs)
const GroupCommunicator &GroupComm() const { return *gcomm; }
/// Return a new GroupCommunicator on Dofs
/// Return a new GroupCommunicator on scalar dofs, i.e. for VDim = 1.
/** @note The returned pointer must be deleted by the caller. */
GroupCommunicator *ScalarGroupComm();
/** Given an integer array on the local degrees of freedom, perform
/** @brief Given an integer array on the local degrees of freedom, perform
a bitwise OR between the shared dofs. */
/** For non-conforming mesh, synchronization is performed on the cut (aka
"partially conforming") space. */
void Synchronize(Array<int> &ldof_marker) const;
/// Determine the boundary degrees of freedom
@@ -356,6 +365,8 @@ public:
virtual ~ParFiniteElementSpace() { Destroy(); }
void PrintPartitionStats();
// Obsolete, kept for backward compatibility
int TrueVSize() const { return ltdof_size; }
};
+108 -23
View File
@@ -147,12 +147,14 @@ HypreParVector *ParGridFunction::GetTrueDofs() const
void ParGridFunction::ParallelAverage(Vector &tv) const
{
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
pfes->DivideByGroupSize(tv);
}
void ParGridFunction::ParallelAverage(HypreParVector &tv) const
{
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
pfes->DivideByGroupSize(tv);
}
@@ -395,6 +397,94 @@ void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &vcoeff,
ComputeMeans(type, zones_per_vdof);
}
void ParGridFunction::ProjectBdrCoefficient(
Coefficient *coeff[], VectorCoefficient *vcoeff, Array<int> &attr)
{
Array<int> values_counter;
AccumulateAndCountBdrValues(coeff, vcoeff, attr, values_counter);
if (pfes->Conforming())
{
Vector values(Size());
for (int i = 0; i < values.Size(); i++)
{
values(i) = values_counter[i] ? (*this)(i) : 0.0;
}
// Count the values globally.
GroupCommunicator &gcomm = pfes->GroupComm();
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
// Accumulate the values globally.
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
// Only the values in the master are guaranteed to be correct!
for (int i = 0; i < values.Size(); i++)
{
if (values_counter[i])
{
(*this)(i) = values(i)/values_counter[i];
}
}
}
else
{
// FIXME: same as the conforming case after 'cut-mesh-groups-dev-*' is
// merged?
ComputeMeans(ARITHMETIC, values_counter);
}
#ifdef MFEM_DEBUG
Array<int> ess_vdofs_marker;
pfes->GetEssentialVDofs(attr, ess_vdofs_marker);
for (int i = 0; i < values_counter.Size(); i++)
{
MFEM_ASSERT(pfes->GetLocalTDofNumber(i) == -1 ||
bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
"internal error");
}
#endif
}
void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
Array<int> &bdr_attr)
{
Array<int> values_counter;
AccumulateAndCountBdrTangentValues(vcoeff, bdr_attr, values_counter);
if (pfes->Conforming())
{
Vector values(Size());
for (int i = 0; i < values.Size(); i++)
{
values(i) = values_counter[i] ? (*this)(i) : 0.0;
}
// Count the values globally.
GroupCommunicator &gcomm = pfes->GroupComm();
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
// Accumulate the values globally.
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
// Only the values in the master are guaranteed to be correct!
for (int i = 0; i < values.Size(); i++)
{
if (values_counter[i])
{
(*this)(i) = values(i)/values_counter[i];
}
}
}
else
{
// FIXME: same as the conforming case after 'cut-mesh-groups-dev-*' is
// merged?
ComputeMeans(ARITHMETIC, values_counter);
}
#ifdef MFEM_DEBUG
Array<int> ess_vdofs_marker;
pfes->GetEssentialVDofs(bdr_attr, ess_vdofs_marker);
for (int i = 0; i < values_counter.Size(); i++)
{
MFEM_ASSERT(pfes->GetLocalTDofNumber(i) == -1 ||
bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
"internal error");
}
#endif
}
void ParGridFunction::Save(std::ostream &out) const
{
for (int i = 0; i < size; i++)
@@ -589,22 +679,12 @@ void ParGridFunction::ComputeFlux(
Array<int> count(flux.Size());
SumFluxAndCount(blfi, flux, count, wcoef, subdomain);
if (ffes->Conforming()) // FIXME: nonconforming
{
// Accumulate flux and counts in parallel
// Accumulate flux and counts in parallel
ffes->GroupComm().Reduce<double>(flux, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<double>(flux);
ffes->GroupComm().Reduce<double>(flux, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<double>(flux);
ffes->GroupComm().Reduce<int>(count, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<int>(count);
}
else
{
MFEM_ABORT("Averaging on processor boundaries not implemented for "
"NC meshes yet.\n"
"Use L2ZZErrorEstimator() instead of ZZErrorEstimator().");
}
ffes->GroupComm().Reduce<int>(count, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<int>(count);
// complete averaging
for (int i = 0; i < count.Size(); i++)
@@ -658,15 +738,20 @@ double L2ZZErrorEstimator(BilinearFormIntegrator &flux_integrator,
ParLinearForm *b = new ParLinearForm(&smooth_flux_fes);
VectorGridFunctionCoefficient f(&flux);
if (smooth_flux_fes.GetFE(0)->GetRangeType() == FiniteElement::SCALAR)
if (xfes->GetNE())
{
a->AddDomainIntegrator(new VectorMassIntegrator);
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
}
else
{
a->AddDomainIntegrator(new VectorFEMassIntegrator);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
if (smooth_flux_fes.GetFE(0)->GetRangeType() == FiniteElement::SCALAR)
{
VectorMassIntegrator *vmass = new VectorMassIntegrator;
vmass->SetVDim(smooth_flux_fes.GetVDim());
a->AddDomainIntegrator(vmass);
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
}
else
{
a->AddDomainIntegrator(new VectorFEMassIntegrator);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
}
}
b->Assemble();
+35 -2
View File
@@ -32,13 +32,22 @@ double GlobalLpNorm(const double p, double loc_norm, MPI_Comm comm);
class ParGridFunction : public GridFunction
{
protected:
ParFiniteElementSpace *pfes;
ParFiniteElementSpace *pfes; ///< Points to the same object as #fes
/** @brief Vector used to store data from face-neighbor processors,
initialized by ExchangeFaceNbrData(). */
Vector face_nbr_data;
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff,
Array<int> &attr);
public:
ParGridFunction() { pfes = NULL; }
/// Copy constructor. The internal vector #face_nbr_data is not copied.
ParGridFunction(const ParGridFunction &orig)
: GridFunction(orig), pfes(orig.pfes) { }
ParGridFunction(ParFiniteElementSpace *pf) : GridFunction(pf), pfes(pf) { }
/// Construct a ParGridFunction using previously allocated array @a data.
@@ -74,6 +83,15 @@ public:
constructed. The new ParGridFunction assumes ownership of both. */
ParGridFunction(ParMesh *pmesh, std::istream &input);
/// Copy assignment. Only the data of the base class Vector is copied.
/** It is assumed that this object and @a rhs use ParFiniteElementSpace%s
that have the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
ParGridFunction &operator=(const ParGridFunction &rhs)
{ return operator=((const Vector &)rhs); }
/// Assign constant values to the ParGridFunction data.
ParGridFunction &operator=(double value)
{ GridFunction::operator=(value); return *this; }
@@ -138,7 +156,7 @@ public:
/// Set the GridFunction from the given true-dof vector.
virtual void SetFromTrueDofs(const Vector &tv) { Distribute(tv); }
/// Short semantic for Distribute
/// Short semantic for Distribute()
ParGridFunction &operator=(const HypreParVector &tv)
{ Distribute(&tv); return (*this); }
@@ -197,6 +215,21 @@ public:
virtual void ProjectDiscCoefficient(VectorCoefficient &vcoeff, AvgType type);
using GridFunction::ProjectBdrCoefficient;
// Only the values in the master are guaranteed to be correct!
virtual void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
Array<int> &attr)
{ ProjectBdrCoefficient(NULL, &vcoeff, attr); }
// Only the values in the master are guaranteed to be correct!
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr)
{ ProjectBdrCoefficient(coeff, NULL, attr); }
// Only the values in the master are guaranteed to be correct!
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
Array<int> &bdr_attr);
virtual double ComputeL1Error(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL) const
{

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