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
Veselin Dobrev c9dd7fc319 Merge pull request #581 from mfem/intpoint-checks
Add dimension checks in the Get and Set methods of IntegrationPoint
2018-08-28 17:08:55 -07: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
Tzanio Kolev 893b127aed Merge pull request #567 from mfem/remove_walk
Removed Walk() from SparseMatrix [remove_walk]
2018-08-22 09:59:38 -04: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
Veselin Dobrev 550f8b1844 Add dimension checks in the Get and Set methods of IntegrationPoint. 2018-08-16 19:36:55 -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
Tzanio Kolev 761a9269c2 Merge pull request #540 from mfem/conforming-tet-refinement-fix
Fix for Tetrahedral Mesh Refinement [conforming-tet-refinement-fix]
2018-08-11 13:55:17 -04: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
kalchev1 62b33689a5 Removed Walk() from SparseMatrix(). 2018-08-02 13:20:38 -07:00
Cameron Smith 6d8f70ba57 support pumi built with zoltan/parmetis/simmodsuite 2018-08-01 21:03:20 +00:00
Veselin Dobrev bfdf9efe31 Update CHANGELOG - mention the improved tetrahedral mesh refinement. 2018-07-30 20:18:27 -07:00
Veselin Dobrev 523cc56fe3 In example 13p, support higher order Nedelec spaces on tet meshes. 2018-07-30 17:50:51 -07:00
Veselin Dobrev cad5015b15 Fix a bug in the parallel refinement of tetrahedral meshes. 2018-07-30 10:33:23 -07:00
Tzanio Kolev eea8eb2185 Merge pull request #528 from mfem/cubit2d-dev
2D Cubit mesh support [cubit2d-dev]
2018-07-30 13:26:51 -04:00
Tzanio Kolev 8847515e10 Merge pull request #538 from mfem/sidredc-groups-dev
Pass bp_index group instead of global group to SidreDataCollection with external DS [sidredc-groups-dev]
2018-07-30 12:46:03 -04:00
Tzanio Kolev 77e891594c Merge pull request #552 from mfem/densemat-gen-eigs-dev
Adding generalized eigenvalue solver to DenseMatrix class [densemat-gen-eigs-dev]
2018-07-30 09:28:22 -04:00
Tzanio Kolev 9e463e651f Merge pull request #553 from mfem/kronecker-prod-dev
Adding various methods mixing sparse and dense matrices [kronecker-prod-dev]
2018-07-30 09:27:50 -04:00
Tzanio Kolev 550013e3ca Merge pull request #556 from mfem/elem-center-dev
Adding Mesh::GetElementCenter method [elem-center-dev]
2018-07-30 09:26:32 -04:00
Tzanio Kolev ca3153c960 Merge pull request #551 from mfem/stable3d-print-dev
Adding a STable3D::Print method for debugging purposes [stable3d-print-dev]
2018-07-30 09:25:58 -04:00
Veselin Dobrev 22a2ff788b Fix a potential issue in the parallel refinement of tetrahedral meshes.
In ParMesh::LocalRefinement, in 3D, make sure the asynchronous MPI sends
are complete before overwriting or destroying the send buffers.
2018-07-29 22:56:15 -07:00
Veselin Dobrev cd66c1dd39 Full support for local refinement of parallel tetrahedral meshes.
In ParMesh::LocalRefinement:
* Removed the restriction on the complexity of the shared face
  splittings.
* Replaced the function-wide variables 'i' and 'j' with locally defined
  versions.
2018-07-29 22:13:04 -07:00
Veselin Dobrev eaa31ad517 Improve the local refinement of parallel tet meshes
The shared face refinements can now be more general - the binary
refinement tree is encoded as an int. If the full refinement tree
cannot be encoded as an int, an error will be generated.
2018-07-29 15:04:11 -07: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 59600de4e2 Restoring Example 1 (test version was accidently commited). 2018-07-27 16:37:44 -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
Tzanio 4ff1f83372 Mentioned 2D Cubit support in CHANGELOG 2018-07-27 15:29:31 -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 ed24bda6ba Fixing an accidental recursion loop... 2018-07-26 08:44: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
Veselin Dobrev df73fff427 In the CUBIT mesh reader, allow loading of meshes without side-sets. 2018-07-25 14:43:04 -07:00
Stowell, Mark L 40e07a61c3 Adding Mesh::GetElementCenter method 2018-07-25 14:24:56 -07:00
Stowell, Mark L e068bd6883 Adding new files to CMake files 2018-07-25 13:35:35 -07:00
Veselin Dobrev abd5c313d9 Remove unused code 2018-07-25 10:34:22 -07:00
Stowell, Mark L 4dd0799db8 Updating CHANGELOG with news of ex20 and ex20p 2018-07-25 09:36:31 -07:00
Veselin Dobrev d949c58e7d Some code cleanup and minor tweaks. 2018-07-24 21:47:32 -07:00
Veselin Dobrev 11131bf004 Merge branch 'master' into conforming-tet-refinement-fix 2018-07-24 20:59:20 -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
Thomas Stitt 76b79f5b0f fix doc param name 2018-07-24 14:43:19 -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
Tzanio 955b1a8e78 Minor 2018-07-24 04:37:00 -07:00
Tzanio e684c8d7bf Extra new line 2018-07-24 04:31:13 -07:00
Stowell, Mark L 0290cdf39f Adding various methods mixing sparse and dense matrices 2018-07-23 21:33:11 -07:00
Stowell, Mark L e785777248 Adding generalized eigenvalue solver to DenseMatrix class 2018-07-23 20:46:05 -07:00
Stowell, Mark L 577399cb45 Adding a STable3D::Print method for debugging purposes 2018-07-23 20:24:19 -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
Tzanio Kolev 58f8873b73 Merge pull request #541 from mfem/FixVectorRestrictedCoefficient
Fixed DenseMatrix::SetSize call argument [FixVectorRestrictedCoefficient]
2018-07-23 14:56:10 -04:00
Tzanio Kolev 5feae230e2 Merge pull request #522 from mfem/pmatrix-groups-fix
Better processor groups in P matrix construction [pmatrix-groups-fix]
2018-07-23 14:55:45 -04: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
Veselin Dobrev be1d6582fc Merge branch 'master' into FixVectorRestrictedCoefficient 2018-07-18 14:46:41 -07:00
Veselin Dobrev ee38e0bc9f Merge pull request #542 from mfem/revert-480-cut-mesh-groups-dev
Revert "Group communicator on (parallel) cut meshes [cut-mesh-groups-dev]"
2018-07-18 22:41:16 +01:00
Veselin Dobrev 39fd944dba Revert "Group communicator on (parallel) cut meshes [cut-mesh-groups-dev]" 2018-07-18 14:26:30 -07:00
Syun'ichi Shiraiwa 1ace21502c Fixed DenseMatrix::SetSize call argument 2018-07-18 11:10:26 -04:00
aschaf 7482db6bc0 Fixed parallel version of AMR for tet meshes.
As for serial, added overloads of ParMesh::GetFaceSplittings and ParMesh::RefineGroups with HashTable<Hashed2>.
2018-07-18 15:56:15 +02:00
aschaf 3552fc6223 Fix for (serial) AMR of tetrahedral meshes
Added two new functions to Mesh:
   > Bisection(int, HashTable<Hashed2> &)
   > BdrBisection(int, HashTable<Hashed2> &)
which are adapted to the new data structure.
Added also an overload to Element::NeedRefinement with HashTable<Hashed2> and implemented it for Tetrahedron and Triangle.
Rewrote the tetrahedron case in  LocalRefinement by changing the DSTable v_to_v to an HashMap<Hashed2> object.
2018-07-18 13:41:04 +02:00
Robert Anderson f950613551 Merge pull request #480 from mfem/cut-mesh-groups-dev
Group communicator on (parallel) cut meshes [cut-mesh-groups-dev]
2018-07-13 20:32:33 -07:00
Robert W. Anderson 1dcbb71b8a Merge branch 'cut-mesh-groups-dev' of github.com:mfem/mfem into cut-mesh-groups-dev 2018-07-13 20:19:05 -07:00
Robert W. Anderson 282f35f6e0 use scalar group comm, works in nonconforming case 2018-07-13 20:17:59 -07:00
Robert W. Anderson acafb9f51a construct true dofs in nonconforming case since we now have comm groups 2018-07-13 20:17:29 -07:00
Thomas Stitt 91e027f3da When using an external sidredatacollection pass in the blueprint_index
group instead of the global group. The global group is used only
to create the blueprint index group and the global group may be shared
between multiple users; it is easier to manage if the sdc only creates
groups and views under unshared groups.
2018-07-13 17:27:58 -07:00
Tzanio Kolev 14ffb48a7f Merge pull request #521 from mfem/h1_hessian-dev
CalcHessian for H1_TriangleElement and H1_TetrahedronElement [h1_hessian-dev]
2018-07-12 07:59:47 +01:00
Tzanio Kolev adf023e004 Merge pull request #501 from mfem/visit-lod-dev
Adding a desired LOD field to the visit output [visit-lod-dev]
2018-07-12 07:59:30 +01:00
Jun Kudo 1a3e725327 Style mesh/mesh_readers.cpp 2018-07-05 09:18:44 -07:00
Jakub Cerveny 05381c7054 Simplified flagging of shared entities (removed extra 'if's). 2018-07-05 09:28:45 +02:00
Veselin Dobrev c0b2b60849 Some tweaks in VisItDataCollection.
This should fix a segfault uncovered by the internal unit tests,
which probably was due to 'mesh' being NULL leading to segfault
when accessing 'mesh->NURBSext'.
2018-07-03 16:34:05 -07:00
aschaf ff25ff7fc7 Changed the formula for the second derivative of the Chebyshev polynomials 2018-07-03 11:14:13 +02:00
Jun Kudo dbabb7b0f6 Add 2D cubit mesh reader functionality 2018-07-02 13:23:40 -07:00
Tzanio Kolev e67555245b Merge pull request #519 from mfem/quad-hex-refine-fix
Fix quad/hex refinement by adding DeleteLazyTables() [quad-hex-refine-fix]
2018-07-02 16:29:03 +02:00
Tzanio Kolev e5629820e1 Merge pull request #506 from mfem/stefanozampini/fix-example
Fixes to PETSc examples [stefanozampini/fix-example]
2018-07-02 16:28:27 +02:00
Jakub Cerveny ebe26c548c One more fix of dof_owner/group init, now it runs OK on vulcan 64K cores. 2018-06-29 14:08:36 +02:00
Jakub Cerveny d8c6edeb4a Fixed initialization of dof_group/owner. 2018-06-29 11:07:35 +02:00
Tzanio 8ebd1614a3 better formating 2018-06-28 23:01:59 -07:00
Tzanio dd905c22a1 make style 2018-06-28 22:57:10 -07:00
Jakub Cerveny be0751c4d2 Merge branch 'master' into pmatrix-groups-fix 2018-06-28 16:12:08 +02:00
Jakub Cerveny 3dc412dcc0 Reverting debug stuff in ex1p.cpp. 2018-06-28 16:07:41 +02:00
Jakub Cerveny 8a82a839bb Cleaned up init of dof_group[], dof_owner[]. 2018-06-28 16:06:06 +02:00
Jakub Cerveny 22af5c49f3 Fixed two more errors, new groups are now working. 2018-06-28 15:35:03 +02:00
Tamas Horvath 0e0a2b1611 Fix quad/hex refinement by adding DeleteLazyTables() 2018-06-27 10:41:44 -04:00
Stefano Zampini 5ebce1f5e0 Merge branch 'stefanozampini/fix-example' of github.com:mfem/mfem into stefanozampini/fix-example 2018-06-26 13:37:43 +03:00
Stefano Zampini a88beec11e update PETSc options file to prevent examples from failing 2018-06-26 13:35:50 +03:00
Jakub Cerveny f46f27daac Fixed initialization of dof_group (some shared entites were skipped). 2018-06-22 14:56:32 +02:00
Veselin Dobrev 0824833e35 Update the PETSc example tests in the CMake build system. 2018-06-16 18:56:01 -07:00
aschaf f03324b804 H1_TriangleElement & H1_TetrahedronElement: added CalcHessian
I implmented CalcHessian for H1_TriangleElement and H1_TetrahedronElement. The 2nd derivatives in the Hessian are orderd "u_xx, u_xy, u_yy" and "u_xx, u_xy, u_xz, u_yy, u_yz, u_zz", respectively.

Poly_1D was expanded by a third CalcBasis function which takes an additional argument for the 2nd derivative. As only CalcChebyshev is not commented out, I just implemented the 2nd derivatives for the Chebyshev Polynomials, also with an additional argument for the 2nd derivative.
2018-06-16 12:34:36 +02:00
Jakub Cerveny 4884209327 Debugging new P matrix groups. 2018-06-15 20:38:24 +02: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
Tzanio Kolev fd809e44b5 Merge pull request #514 from mfem/doxygen-fix
Fixing a few links on the main Doxygen page [doxygen-fix]
2018-06-12 07:00:49 +02:00
Tzanio 5d466d9583 Fixing a few links on the main Doxygen page 2018-06-11 17:52:36 -07:00
Tzanio Kolev 4eb307758e Merge pull request #510 from mfem/pumi-skip-tests
Skip the PUMI tests if the PUMI data directory is not available [pumi-skip-tests]
2018-06-11 15:57:57 +02:00
Tzanio Kolev 996842cb94 Merge pull request #511 from mfem/par-mesh-read-fix
Add optional 'refine' parameter to the ParMesh constructor ... [par-mesh-read-fix]
2018-06-11 15:57:08 +02:00
Veselin Dobrev 4d3b1fab9a Add optional 'refine' parameter to the ParMesh constructor that
reads from an input stream.
2018-06-04 18:08:51 -07:00
Veselin Dobrev e50bf78531 Skip the PUMI tests if the PUMI data directory is not available. 2018-06-03 00:28:15 -07:00
Cameron Smith 14143faa88 create config.mk, install config.mk and test.mk 2018-06-01 13:52:31 -05:00
Jakub Cerveny 8a87fbffde Finished better calculation of groups and shared lists, debugging. 2018-06-01 17:12:25 +02:00
Jakub Cerveny fa3ded8e1a WIP better calculation of groups and shared lists 2018-05-31 18:22:20 +02:00
Stefano Zampini d73d29508b Add nonoverlapping assembly to ex6p tests 2018-05-31 11:49:30 +03:00
Stefano Zampini b8fb486ba5 Added hybridization example (improve code coverage) 2018-05-31 11:12:53 +03:00
Stefano Zampini eb651cd3fc Change composed object name to match that used inside the PETSc library 2018-05-31 11:10:20 +03:00
Stefano Zampini 3d62128f3a PETSc examples: test local boundary specification 2018-05-31 10:54:00 +03:00
Stefano Zampini b79d47eb93 Synch PETSc rc files with PETSc 3.9 2018-05-31 10:53:38 +03:00
Stefano Zampini 30f623bdad PETSc example ex5p : added command line option to cover more library code 2018-05-31 10:52:18 +03:00
Veselin Dobrev a7e2df44c6 Merge pull request #504 from mfem/bump-to-v3.4.1
Update version to 3.4.1 -- new development version [bump-to-v3.4.1]
2018-05-30 16:10:20 -07:00
Jakub Cerveny 4a4ed4c0c3 WIP better calculation of shared groups and lists in ParNCMesh. 2018-05-30 17:36:07 +02:00
Veselin Dobrev 7b2e60490d Update version to 3.4.1 -- new development version.
In doc/CodeDocumentation.conf.in, add examples/pumi to the list of
directories searched for source files.
2018-05-29 19:14:08 -07:00
Veselin Dobrev 0715efbaf9 Merge pull request #487 from mfem/docs-dev
Improved documentation [docs-dev]
2018-05-29 16:39:33 -07:00
Tzanio 0cdd280bb4 Small change in meshing README 2018-05-29 16:36:13 -07:00
Veselin Dobrev ce12d07d38 In CONTRIBUTING.md, add the directory examples/pumi in the code overview
diagram.
2018-05-29 15:51:00 -07:00
Tzanio 37757faaae Merge branch 'master' into docs-dev 2018-05-29 06:20:43 -07:00
Tzanio Kolev ca14e8054a Merge pull request #503 from mfem/slave-faces-fix
Shared slave faces fix
2018-05-29 06:19:16 -07:00
Tzanio Kolev a0dec4d0fb Merge pull request #499 from najlkin/pr3
Improved QuadratureFunction and QuadratureSpace...
2018-05-29 06:19:03 -07:00
Tzanio Kolev 787efc1f52 Merge pull request #489 from najlkin/pr2
Added const qualifier to the solutions in the essential bc elimination methods
2018-05-29 06:18:46 -07:00
Tzanio Kolev 4a3c6794a0 Merge pull request #237 from mfem/pumi-dev
Parallel Unstructured Mesh Infrastructure (PUMI) integration [pumi-dev]
2018-05-29 06:18:09 -07:00
Jakub Cerveny c77e3318e9 After testing, turned on the temporary suboptimal version of ParNCMesh::AddMasterSlaveConnections. 2018-05-28 15:41:12 +02:00
Tzanio 59afdb57fc Updated examples/README.html 2018-05-25 17:32:11 -07:00
Tzanio b1112870d1 mfem-3.4 will be released on May 29th, 2018. 2018-05-25 16:32:50 -07:00
Tzanio 954c5b7f04 All green 2018-05-25 16:24:34 -07:00
Tzanio 7f515c1031 Typo 2018-05-25 16:08:13 -07:00
Tzanio e48992b6e3 Adding README in examples/pumi (similar to sundials, petsc) 2018-05-25 16:00:47 -07:00
Tzanio 055efbad50 Minor 2018-05-25 15:56:13 -07:00
Tzanio 81e8551911 Uniform copyright 2018-05-25 15:50:18 -07:00
Tzanio 55fc5f2536 Updated CHANGELOG 2018-05-25 15:43:40 -07:00
Tzanio 2886d5b08f Mention GLVis in INSTALL 2018-05-25 15:41:28 -07: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 b6b5e5f53e Updated html files with 3.4 documentation from mfem/web/mfem-3.4 branch 2018-05-24 19:25:21 -07:00
Tzanio 3e4784271a Edited CONTRIBUTING.md file 2018-05-24 18:46:58 -07:00
Tzanio fb1d5b98dd Edited INSTALL file 2018-05-24 18:43:21 -07:00
Tzanio 55b058e498 Updated/fixed PUMI's Example 2 and 6p. 2018-05-24 18:32:10 -07:00
Tzanio 601f1cfbfa Styling of PUMI's Example 1/1p 2018-05-24 17:34:48 -07:00
Tzanio 1acffab78f Editorial changes in CHANGELOG and pumi.cpp. 2018-05-24 16:50:25 -07:00
Veselin Dobrev 6f2aebc7bb Update examples/pumi/makefile and 'make style'. 2018-05-24 11:25:57 -07:00
KazemKamran 66fbfd2a41 some cleaning in pumi.cpp
some cleaning in pumi.cpp
2018-05-24 14:05:40 -04:00
KazemKamran da6de9371a Adding doxygen of pumi examples 2018-05-24 12:09:58 -04:00
KazemKamran a7efad3e4a Unifying example headers, rename ex2p.cpp to ex2.cpp 2018-05-24 12:09:58 -04:00
KazemKamran 0afab1d564 Add a blurb for PUMI examples 2018-05-24 12:09:58 -04:00
Jan Nikl 401a66040c make style on the commit 48dd20d2e8 2018-05-24 15:52:04 +02:00
Tzanio Kolev 93525246b0 Merge pull request #500 from najlkin/pr4
Fixed assignment of an IntegrationRule in the constructor of NonlinearFormIntegrator
2018-05-24 06:45:11 -07:00
Ido Akkerman d0661f2302 Adding a desired LOD field to the visit output 2018-05-24 14:25:03 +02:00
Veselin Dobrev acacabd432 A few small improvements. 2018-05-23 17:37:37 -07:00
Tzanio 91615ed76b Small edits in pumi.cpp 2018-05-23 11:55:28 -07:00
Jan Nikl bd790b1996 Fixed assignment of an IntegrationRule in the constructor of NonlinearFormIntegrator. 2018-05-23 15:52:41 +02:00
Jan Nikl d501e8c9f3 Fixed the order of elements in the matrix obtained from GetElementValues of QuadratureFunction. 2018-05-23 15:40:46 +02:00
Veselin Dobrev a818788468 In mesh/pumi.cpp: more tweaks and fixed leaks. 2018-05-22 19:42:29 -07:00
Veselin Dobrev 15e3c5f821 Some tweaks in mesh/pumi.cpp; also, fixed a couple of memory leaks. 2018-05-22 14:08:17 -07:00
Veselin Dobrev 50f8519818 Fix a warning 2018-05-21 22:15:03 -07:00
Veselin Dobrev 79f2e1bd05 In mesh/pumi.cpp, restore calls that used to initialize unused
variables and still need to be called discarding the returned
value. Also, make some small formatting and coding tweaks.

All PUMI examples require MPI.

Update .gitignore.
2018-05-21 21:30:39 -07:00
Veselin Dobrev 3d052b07a6 In the makefile build system, define MFEM_USE_SIMMETRIX. 2018-05-21 18:57:57 -07:00
Veselin Dobrev 75f47a3deb Fix a few issues in the CMake build system.
Set suitable number of processors for running the PUMI parallel
examples.
2018-05-21 17:39:11 -07:00
Tzanio f91d406ce3 Silence compiler warnings in pumi.cpp 2018-05-21 17:26:09 -07:00
Veselin Dobrev d9e12f8c7e Fix examples/pumi/ex6p. 2018-05-21 15:17:49 -07:00
Tzanio f212f83a13 Merge branch 'pumi-dev' of github.com:mfem/mfem into pumi-dev 2018-05-21 15:01:14 -07:00
Tzanio 56ebcb4016 A few changes & fixes 2018-05-21 15:01:11 -07:00
Veselin Dobrev 7e89151592 Add forgotten makefile in the previous commit. 2018-05-21 15:00:11 -07:00
Veselin Dobrev 878338b1a5 Add support for building with make.
Apply astyle formatting to the PUMI examples.
2018-05-21 14:51:16 -07:00
Jan Nikl bba14e664e Added constant qualifiers to the QuadratureFunction and QuadratureSpace where applicable and added new const versions of the GetElementValues methods. 2018-05-21 22:32:48 +02:00
Jan Nikl 67da6e2d30 Added assignment operators to QuadratureFunction. 2018-05-21 22:30:33 +02:00
Tzanio 99e3fccd32 Merge branch 'master' into pumi-dev 2018-05-21 13:19:21 -07:00
Tzanio b0987500a4 make style 2018-05-21 13:18:44 -07:00
Tzanio d363dd71d4 Merge branch 'master' into docs-dev 2018-05-21 13:10:47 -07:00
Tzanio Kolev b90140c46f Merge pull request #497 from mfem/simplex-refine-fix
Fix an issue in the local refinement of simplex meshes [simplex-refine-fix]
2018-05-21 13:10:01 -07:00
Tzanio Kolev 386e342e68 Merge pull request #494 from mfem/task/2018_05_conduit_extra_boundary_topo_guard
Conduit blueprint to MFEM mesh: guard against missing boundary info
2018-05-21 13:09:25 -07:00
Tzanio Kolev 78a1b093fe Merge pull request #493 from mfem/sidre-dev
Bugfix for handling of SidreDataCollection boundary mesh blueprint index [sidre-dev]
2018-05-21 13:08:58 -07:00
Veselin Dobrev 8d1a5dfa31 Fix an issue in the local refinement of simplex meshes where the
lazy-generated Tables 'el_to_el', 'face_edge', and 'edge_vertex'
were not reset after refinement.
2018-05-18 16:19:50 -07:00
Tzanio Kolev 31ac08e6f2 Merge pull request #486 from mfem/vectorcurlcurl-fix
Bugfix for VectorCurlCurlIntegrator assemble [vectorcurlcurl-fix]
2018-05-18 14:41:59 -07:00
Jakub Cerveny 1e76ed107a After merging pmatrix-dev, at least one thing got broken: ParMesh::Print for AMR meshes.
Since in pmatrix-dev, slave faces are no longer considered shared (their P rows are not
needed by the processor owning the master face), they are also not printed when visualizing
the parallel solution. I suspect this also might have broken NC face neighbors. This branch
contains a temporary solution, a downgrade of ParNCMesh::AddMasterSlaveRanks, so that it
works the old way: slave faces are grouped with the masters. This fixes visualization and
maybe other things, but may negatively impact performance of (or even break) the P matrix
construction. I need to look more into this to find a permanent solution.
2018-05-18 22:50:19 +02:00
Cyrus Harrison e09f9d8128 guard against missing boundary info 2018-05-16 12:19:33 -07:00
Kenneth Weiss ec4fcba705 Bugfix for handling of SidreDataCollection boundary mesh blueprint index
The blueprint index was only being genererated for the boundary mesh when
rank 0 had boundary elements. We need to generate the boundary mesh
group and associated blueprint index if any of the domains have boundary
elements.
2018-05-15 20:15:26 -07:00
Veselin Dobrev e4eb8aa6df Fixed a link in CONTRIBUTING.md 2018-05-09 22:55:50 -07:00
Tzanio 1f4ead94a3 Testing docs layouts 2018-05-09 13:59:26 -07:00
Tzanio 179fc91a55 Testing docs layouts 2018-05-09 13:49:27 -07:00
Tzanio 4037e17135 Rearanged README 2018-05-09 13:38:14 -07:00
Tzanio 67e8010987 Fixed Spack URL 2018-05-09 13:35:45 -07:00
Jan Nikl 48dd20d2e8 Added const qualifier to the solution vectors in the essential bc elimination methods. 2018-05-09 10:00:12 +02:00
Tzanio 33427e3bcd Added Code Overview in CONTRIBUTING. Updated README 2018-05-07 19:08:07 -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
Tzanio e090a781a2 Merge branch 'master' into vectorcurlcurl-fix 2018-05-07 17:33:00 -07:00
Tzanio b62a60837a Bugfix for https://github.com/mfem/mfem/issues/467#issuecomment-380136269 2018-05-07 17:16:37 -07:00
Jakub Cerveny 2767704cc6 ParFESpace: added DOF partitioning stats. 2018-05-04 18:40:29 +02:00
KazemKamran c94be388e1 Resolve name conflict in adding MeshAdapt example 2018-05-04 10:00:29 -04:00
KazemKamran 37ddcfe14d Merge branch 'pumi-dev-ma' into pumi-dev 2018-05-04 09:46:17 -04:00
KazemKamran 37686b0321 Add the PUMI-MFEM MeshAdapt interface implementation and an example 2018-05-03 17:44:16 -04:00
Jakub Cerveny 0958ac8644 P matrix construction: added collection of comm statistics. 2018-05-03 17:06:58 +02:00
Tzanio 293687453e Merge branch 'master' into pumi-dev 2018-05-01 11:17:34 -07:00
Tzanio 67401330d9 make style 2018-04-23 10:45:27 -07:00
Robert W. Anderson dce6ebf20d merge master 2018-03-21 15:43:32 -07:00
Jakub Červený 253e1dc320 Added missing assert in Vector::AddElementVector (based on similar function). 2018-03-16 16:49:05 +01:00
Cameron Smith 15b684fe21 pumi: forgot to remove config header 2018-03-14 09:12:03 -04:00
Tzanio 1bd99fd5dc Various small changes 2018-03-13 18:45:03 -07:00
KazemKamran 165dea0c66 Revert the previous commit and delete pumi addition in INSTALL, CMAKE only 2018-03-13 19:27:59 -04:00
KazemKamran 473240f1c2 Revert "Revert changes in INSTALL"
This reverts commit bb0cae0619.
2018-03-13 19:23:57 -04:00
KazemKamran bb0cae0619 Revert changes in INSTALL 2018-03-13 18:07:05 -04:00
Cameron Smith 6d1a1a19fe Revert "Update miniapps/common/CMakeLists.txt from master"
This reverts commit de5c1c376b.  It breaks the
compile.
2018-03-13 17:34:17 -04:00
Cameron Smith 6601d3757b pumi: move simmetrix define to config.hpp.in 2018-03-13 17:32:21 -04:00
KazemKamran 5252b05a79 Update miniapps/common/CMakeLists.txt from master 2018-03-13 17:15:12 -04:00
KazemKamran de5c1c376b Update miniapps/common/CMakeLists.txt from master 2018-03-13 17:10:40 -04:00
Tzanio 12c109f9e9 Update CHANGELOG 2018-03-13 13:38:51 -07:00
Tzanio 1007624ddb Update INSTALL 2018-03-13 13:32:15 -07:00
Tzanio d65e45277b make style 2018-03-13 13:19:00 -07:00
KazemKamran 4824b02b48 removing README.mfem-pumi-install, use the Spack installation 2018-03-13 16:09:59 -04:00
KazemKamran ddecdf017f change file name pumi_mesh.* to pumi.* 2018-03-12 15:07:41 -04:00
KazemKamran 25e5327b6a Make changes required after review 2018-03-12 12:04:32 -04:00
KazemKamran c4fe5bcde1 Merge branch 'pumi-dev' of github.com:mfem/mfem into pumi-dev
Making the changes required after review
2018-03-12 11:54:08 -04:00
KazemKamran dbf8797f2c Removing data/pumi 2018-03-12 11:52:34 -04:00
KazemKamran 7763533785 Make changes required after review 2018-03-12 11:49:03 -04:00
Tzanio d5874e20e5 Merge branch 'master' into pumi-dev 2018-03-12 06:17:58 -07:00
KazemKamran 56dd3dd069 resolving conflicts 2018-03-08 12:13:35 -05:00
Jakub Cerveny 761854a143 DebugDump helpers in DenseTensor and BilinearForm 2018-03-08 16:38:38 +01:00
Tzanio 4e3f26c602 Fixed merge conflict 2018-03-07 11:28:28 -08:00
Tzanio caeae60c12 Merge branch 'master' into pumi-dev
Conflicts:
	config/cmake/config.hpp.in
	config/defaults.cmake
	config/defaults.mk
	makefile
2018-03-07 11:22:44 -08: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
Robert W. Anderson 134f97c0d8 comment out the setting of master and slave faces in face_info 2018-01-23 19:36:52 -08:00
Robert W. Anderson 5caeea07a0 return faces_tbl from InitFromNCMesh for use in group construction in 3D 2018-01-23 19:36:08 -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
Tzanio e5c7383441 Small fixes. Should pass CI testing now... 2018-01-04 18:19:23 -08:00
Tzanio 41e6d31236 Merge branch 'master' into pumi-dev 2018-01-04 17:33:40 -08:00
Cameron Smith a22eeeab5a improve build instructions
add metis
use a toolchain on vulcan to avoid strange errors
2017-12-11 10:21:40 -08:00
Cameron Smith e60e51db39 pumi examples: remove simutil_[start|stop] 2017-12-11 10:21:40 -08:00
Cameron Smith e17ee11dc1 use mpi for serial tests
needed on ray
2017-12-11 10:21:40 -08:00
Robert W. Anderson 4f00b2d6bb Merge branch 'master' into cut-mesh-groups-dev 2017-12-05 15:34:51 -08:00
Robert W. Anderson eba6d4805b working for simple 2D cases 2017-12-05 15:32:22 -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
Tzanio 482378c7ec Merge branch 'master' into pumi-dev 2017-11-10 16:58:20 -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
KazemKamran d2cf23afde using theirs 2017-10-18 10:09:35 -04:00
KazemKamran 2b541c5e12 Merge branch 'pumi-dev' of github.com:mfem/mfem into pumi-dev
Conflicts:
	examples/pumi_atr_ex2.cpp
2017-10-17 13:15:35 -04: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
KazemKamran 9e294fc98c Add dmg model for pumi example 2017-10-12 15:05:35 -04:00
Tzanio aaa7fc536c Merge branch 'master' into pumi-dev 2017-09-22 07:35:37 -07:00
Tzanio 1d3cbc5871 Merge branch 'master' into pumi-dev 2017-09-06 19:32:15 -07:00
Tzanio 60ed92ab5a Merge branch 'master' into pumi-dev 2017-09-06 19:08:44 -07:00
Tzanio 5560d92fab make style 2017-08-29 18:18:51 -07:00
Tzanio 36650e8833 Merge branch 'master' into pumi-dev 2017-08-29 18:18:26 -07:00
KazemKamran 5dd5511fdd Add dmg model for pumi example 2017-08-08 12:43:46 -04:00
KazemKamran 7ff222b79d dmg model for attribute example 2017-08-08 12:09:59 -04:00
KazemKamran 72e42566a9 Fix a leak bug 2017-08-04 11:43:29 -04:00
KazemKamran 66e1b3641c Boundary condition classification example 2017-08-03 15:54:07 -04:00
KazemKamran c790490f91 Boundary condition classification example 2017-08-03 15:49:21 -04:00
Cameron Smith 4f34a3b696 Merge branch 'master' into pumi-dev 2017-07-20 16:12:13 -04:00
Cameron Smith 9dfe4dc6f4 cmake config header 2017-07-20 15:34:44 -04:00
Cameron Smith 7474b3deb9 restore pumi cmake option 2017-07-20 15:34:44 -04:00
Cameron Smith 325479260c gnu-make support for building without pumi 2017-07-20 15:34:40 -04:00
Cameron Smith 6ca81275dc undo some early build system changes 2017-07-20 10:48:12 -04:00
Cameron Smith 00baeb86c3 don't infect all compilation with MFEM_USE_SIMMETRIX
define a header with the preprocessor variable defined
2017-07-13 16:49:42 -04:00
Cameron Smith 54d850bbe1 use the discrete model
pumi tests pass without simmetrix
ctest -R 'pumi|Generate'
2017-07-13 13:49:00 -04:00
Cameron Smith c375afe382 missing discrete models 2017-07-13 13:41:46 -04:00
Cameron Smith 3102f164d6 gmi_sim is optional
pumi examples fail with Test project /lore/cwsmith/develop/mfem/mfem
2017-07-13 11:56:30 -04:00
Cameron Smith 04acee1f28 README: enable pumi 2017-07-12 15:31:23 -04:00
KazemKamran 71d87aa1f2 Changes to compile MFEM wo PUMI 2017-07-11 17:44:55 -04:00
KazemKamran bcfe52d498 separate pumi examples 2017-07-11 17:41:37 -04:00
Cameron Smith a8d474f3f6 instructions for installing with pumi support 2017-07-07 14:09:32 -04:00
Cameron Smith 6143572d6a miniapps/common: use pumi 2017-06-29 17:02:38 -04:00
Cameron Smith f0a41dd3d6 support serial tests with 'p' in the name 2017-06-29 16:50:16 -04:00
KazemKamran 02b65854c2 Clean unifor refinement (wo size field) 2017-06-26 14:21:10 -04:00
KazemKamran ffea082dc9 Adding PUMI examples and data 2017-06-20 18:15:11 -04:00
KazemKamran 9d79904c50 minor necessary change 2017-06-20 14:58:50 -04:00
KazemKamran eb2017b5b5 Add pumi supports for parallel and serial mesh loading 2017-06-19 11:13:29 -04: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
341 changed files with 47232 additions and 18516 deletions
+26
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]
@@ -112,6 +121,15 @@ examples/petsc/deformed.*
examples/petsc/velocity.*
examples/petsc/elastic_energy.*
examples/pumi/ex1
examples/pumi/ex[126]p
examples/pumi/refined.mesh
examples/pumi/sol.gf
examples/pumi/mesh.*
examples/pumi/sol.*
examples/pumi/displaced.mesh
miniapps/electromagnetics/volta
miniapps/electromagnetics/tesla
miniapps/electromagnetics/maxwell
@@ -124,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*
@@ -156,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
+123 -3
View File
@@ -8,11 +8,126 @@
http://mfem.org
Version 3.3.3 (development)
Version 3.4.1 (development)
===========================
More efficient non-conforming adaptive mesh refinement
------------------------------------------------------
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 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
=====================================
More general and efficient mesh adaptivity
------------------------------------------
- Added support for PUMI, the Parallel Unstructured Mesh Infrastructure from
https://scorec.rpi.edu/pumi. PUMI is an unstructured, distributed mesh data
management system that is capable of handling general non-manifold models and
effectively supports automated adaptive analysis. PUMI enables for the first
time support for parallel unstructured modifications of MFEM meshes.
- Significantly reduced MPI communication in the construction of the parallel
prolongation matrix in ParFiniteElementSpace, for much improved parallel
scaling of non-conforming AMR on hundreds of thousands of MPI tasks. The
@@ -81,6 +196,11 @@ New and updated examples and miniapps
NURBS meshes in the miniapps/nurbs directory. Currently the directory contains
variable order NURBS versions of examples 1, 1p and 11p.
- Added PUMI versions of examples ex1, ex1p, ex2 and ex6p in a new examples/pumi
directory. The new examples demonstrate the PUMI APIs for parallel and serial
mesh loading (ex1 and ex1p), applying BCs using classification (ex2), and
performing parallel mesh adaptation (ex6p).
- Added two new miniapps related to DataCollection I/O in miniapps/tools:
load-dc.cpp can be used to visualize fields saved via DataCollection classes;
convert-dc.cpp demonstrates how to convert between MFEM's different concrete
+33 -8
View File
@@ -45,7 +45,7 @@ project(mfem NONE)
# Current version of MFEM, see also `makefile`.
# mfem_VERSION = (string)
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
set(${PROJECT_NAME}_VERSION 3.3.3)
set(${PROJECT_NAME}_VERSION 3.4.1)
# Prohibit in-source build
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
@@ -139,7 +139,7 @@ if (MFEM_USE_MPI)
set(PETSC_INCLUDE_DIRS ${PETSC_INCLUDES})
endif()
else()
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK)
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK PUMI)
foreach(PKG IN LISTS PKGS_NEED_MPI)
if (MFEM_USE_${PKG})
message(STATUS "Disabling package ${PKG} - requires MPI")
@@ -246,6 +246,22 @@ if (MFEM_USE_SIDRE)
find_package(Axom REQUIRED Sidre SLIC axom_utils)
endif()
# PUMI
if (MFEM_USE_PUMI)
# If PUMI_DIR was specified, only link to that directory,
# i.e. don't link to another installation in /usr/lib by mistake
find_package(SCOREC 2.1.0 REQUIRED OPTIONAL_COMPONENTS gmi_sim
CONFIG PATHS ${PUMI_DIR} NO_DEFAULT_PATH)
if (SCOREC_FOUND)
# Define a header file with the MFEM_USE_SIMMETRIX preprocessor variable
set(MFEM_USE_SIMMETRIX ${SCOREC_gmi_sim_FOUND})
set(PUMI_FOUND ${SCOREC_FOUND})
get_target_property(PUMI_INCLUDE_DIRS
SCOREC::apf INTERFACE_INCLUDE_DIRECTORIES)
set(PUMI_LIBRARIES SCOREC::core)
endif()
endif()
# MFEM_TIMER_TYPE
if (NOT DEFINED MFEM_TIMER_TYPE)
if (APPLE)
@@ -270,8 +286,8 @@ endif()
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
# be before SuiteSparse.
set(MFEM_TPLS MPI_CXX OPENMP BLAS LAPACK METIS HYPRE SuiteSparse SUNDIALS PETSC
MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT GECKO GNUTLS NETCDF MPFR POSIXCLOCKS
MFEMBacktrace ZLIB)
MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT GECKO GNUTLS NETCDF MPFR PUMI
POSIXCLOCKS MFEMBacktrace ZLIB)
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
set(TPL_LIBRARIES "")
set(TPL_INCLUDE_DIRS "")
@@ -296,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
#-------------------------------------------------------------------------------
@@ -372,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.
@@ -391,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
@@ -527,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()
+114 -6
View File
@@ -1,3 +1,15 @@
<p align="center">
<a href="http://mfem.org/"><img alt="mfem" src="http://mfem.org/img/logo-300.png"></a>
</p>
<p align="center">
<a href="https://github.com/mfem/mfem/blob/master/COPYRIGHT"><img alt="License" src="https://img.shields.io/badge/License-LGPL--2.1-brightgreen.svg"></a>
<a href="https://travis-ci.org/mfem/mfem"><img alt="Build Status" src="https://travis-ci.org/mfem/mfem.svg?branch=master"></a>
<a href="https://ci.appveyor.com/project/mfem/mfem"><img alt="Build Status" src="https://ci.appveyor.com/api/projects/status/19non9sqm6msi2wy?svg=true"></a>
<a href="http://mfem.github.io/doxygen/html/index.html"><img alt="Doxygen" src="https://img.shields.io/badge/code-documented-brightgreen.svg"></a>
</p>
# How to Contribute
The MFEM team welcomes contributions at all levels: bugfixes; code
@@ -16,6 +28,7 @@ See the [Quick Summary](#quick-summary) section for the main highlights of our
GitHub workflow. For more details, consult the following sections and refer
back to them before issuing pull requests:
- [Code Overview](#code-overview)
- [GitHub Workflow](#github-workflow)
- [MFEM Organization](#mfem-organization)
- [New Feature Development](#new-feature-development)
@@ -53,6 +66,102 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
- Don't hesitate to [contact us](#contact-information) if you have any questions.
### Code Overview
- The MFEM library uses object-orient design principles which reflect, in code,
the independent mathematical concepts of meshing, linear algebra and finite
element spaces and operators.
- The MFEM source code has the following structure:
```
.
├── config
│ └── cmake
│ └── modules
├── data
├── doc
│ └── web
│ └── examples
├── examples
│ ├── petsc
│ ├── pumi
│ └── sundials
├── fem
├── general
├── linalg
├── mesh
├── miniapps
│ ├── common
│ ├── electromagnetics
│ ├── meshing
│ ├── nurbs
│ ├── performance
│ └── tools
└── tests
├── unit
│ ├── ...
└── ...
```
- The main directories are `fem/`, `mesh/` and `linalg/` containing the C++
classes implementing the finite element, mesh and linear algebra concepts
respectively.
- The main mesh classes are:
+ [`Mesh`](http://mfem.github.io/doxygen/html/classmfem_1_1Mesh.html)
+ [`NCMesh`](http://mfem.github.io/doxygen/html/classmfem_1_1NCMesh.html)
+ [`Element`](http://mfem.github.io/doxygen/html/classmfem_1_1Element.html)
+ [`ElementTransformation`](http://mfem.github.io/doxygen/html/classmfem_1_1ElementTransformation.html)
- The main finite element classes are:
+ [`FiniteElement`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElement.html)
+ [`FiniteElementCollection`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElement.html)
+ [`FiniteElementSpace`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElementSpace.html)
+ [`GridFunction`](http://mfem.github.io/doxygen/html/classmfem_1_1GridFunction.html)
+ [`BilinearFormIntegrator`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearFormIntegrator.html) and [`LinearFormIntegrator`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearFormIntegrator.html)
+ [`LinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearFormIntegrator.html), [`BilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html) and [`MixedBilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1MixedBilinearForm.html)
- The main linear algebra classes and sources are
+ [`Operator`](http://mfem.github.io/doxygen/html/classmfem_1_1Operator.html) and [`BilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html)
+ [`Vector`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html) and [`LinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearForm.html)
+ [`DenseMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1DenseMatrix.html) and [`SparseMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1SparseMatrix.html)
+ Sparse [smoothers](http://mfem.github.io/doxygen/html/sparsesmoothers_8hpp.html) and linear [solvers](http://mfem.github.io/doxygen/html/solvers_8hpp.html)
- Parallel MPI objects in MFEM inherit their serial counterparts, so a parallel
mesh for example is just a serial mesh on each task plus the information on
shared geometric entities between different tasks. The parallel source files
have a `p` prefix, e.g. `pmesh.cpp` vs. the serial `mesh.cpp`.
- The main parallel classes are
+ [`ParMesh`](http://mfem.github.io/doxygen/html/solvers_8hpp.html)
+ [`ParNCMesh`](http://mfem.github.io/doxygen/html/classmfem_1_1ParMesh.html)
+ [`ParFiniteElementSpace`](http://mfem.github.io/doxygen/html/classmfem_1_1ParFiniteElementSpace.html)
+ [`ParGridFunction`](http://mfem.github.io/doxygen/html/classmfem_1_1ParGridFunction.html)
+ [`ParBilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1ParBilinearForm.html) and [`ParLinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1ParLinearForm.html)
+ [`HypreParMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreParMatrix.html) and [`HypreParVector`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreParVector.html)
+ [`HypreSolver`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreSolver.html) and other [hypre classes](http://mfem.github.io/doxygen/html/hypre_8hpp.html)
- The `general/` directory contains C++ classes that serve as utilities for
communication, error handling, arrays, (Boolean) tables, timing, etc.
- The `config/` directory contains build-related files, both for the plain
Makefile and the CMake build options.
- The `doc/` directory contains configuration for the Doxygen code documentation
that can either be build locally, or browsed online at
http://mfem.github.io/doxygen/html/index.html.
- The `data/` directory contains a collection of small mesh files, that are used
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.
## GitHub Workflow
The GitHub organization, https://github.com/mfem, is the main developer hub for
@@ -122,7 +231,7 @@ will allow us to reach you directly with project announcements.
# Work on "feature-dev", add local commits
# ...
# One time only) push the branch to github and setup your local
# (One time only) push the branch to github and setup your local
# branch to track the github branch (for "git pull"):
git push -u origin feature-dev
@@ -215,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.
@@ -257,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.
@@ -332,7 +441,7 @@ MFEM uses a `master`/`next`-branch workflow as described below:
- [ ] `CHANGELOG`
- [ ] `makefile`
- [ ] `CMakeLists.txt`
- [ ] `doc/CodeDocumentation.conf`
- [ ] `doc/CodeDocumentation.conf.in`
- [ ] (LLNL only) Make sure all `README.html` files in the source repo are up to date.
- [ ] Tag the repository:
@@ -371,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
+16
View File
@@ -32,6 +32,9 @@ following package managers:
- OpenHPC, http://openhpc.community
- Homebrew/Science, https://github.com/Homebrew/homebrew-science
We also recommend downloading and building the MFEM-based GLVis visualization
tool which can be used to visualize the meshes and solution in MFEM's examples
and miniapps. See http://glvis.org and http://mfem.org/building.
Quick start with GNU make
=========================
@@ -352,6 +355,13 @@ MFEM_USE_GZSTREAM = YES/NO
before attempting to use it with MFEM.
When enabled, this option uses the ZLIB_* library options, see below.
MFEM_USE_PUMI = YES/NO
Enable the usage of PUMI (https://scorec.rpi.edu/pumi/) in MFEM. The Parallel
Unstructured Mesh Infrastructure (PUMI) is an unstructured, distributed mesh
data management system that is capable of handling general non-manifold
models and effectively supports automated adaptive analysis. PUMI enables
support for parallel unstructured mesh modifications in MFEM.
MFEM_BUILD_TAG = (any value)
An optional tag to characterize the build. Exported to config/config.mk.
Can be used to identify the MFEM build from other makefiles.
@@ -461,6 +471,10 @@ The specific libraries and their options are:
https://support.hdfgroup.org/HDF5 (HDF5)
Options: CONDUIT_OPT, CONDUIT_LIB.
- PUMI, used when MFEM_USE_PUMI = YES.
URL: https://scorec.rpi.edu/pumi
Options: PUMI_OPT, PUMI_LIB.
- MPFR (optional), used when MFEM_USE_MPFR = YES.
URL: http://mpfr.org, it depends on the GMP library: https://gmplib.org
Options: MPFR_OPT, MPFR_LIB.
@@ -593,6 +607,7 @@ MFEM_USE_GNUTLS
MFEM_USE_NETCDF
MFEM_USE_MPFR
MFEM_USE_GZSTREAM
MFEM_USE_PUMI
The following options are CMake specific:
@@ -638,6 +653,7 @@ The CMake build system adds auto-detection for the following packages/libraries:
- MPFR
- LIBUNWIND
- POSIXCLOCKS
- PUMI
The following built-in CMake packages are also used:
+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!
+10 -6
View File
@@ -12,11 +12,15 @@ to enable the research and development of scalable finite element discretization
and solver algorithms through general finite element abstractions, accurate and
flexible visualization, and tight integration with the hypre library.
For building instructions, see the file INSTALL, or type "make help". Copyright
information and licensing restrictions can be found in the file COPYRIGHT.
* For building instructions, see the file INSTALL, or type "make help".
The best starting point for new users interested in MFEM's features is the
interactive documentation in examples/README.html.
* Copyright and licensing information can be found in the file COPYRIGHT.
* The best starting point for new users interested in MFEM's features is the
interactive documentation in examples/README.html.
* Developers interested in contributing to the library, should read the
instructions and documentation in the CONTRIBUTING.md file.
Conceptually, MFEM can be viewed as a finite element toolbox that provides the
building blocks for developing finite element algorithms in a manner similar to
@@ -56,8 +60,8 @@ time integrators, etc.
For examples of using MFEM, see the examples/ and miniapps/ directories, as well
as the OpenGL visualization tool GLVis which is available at http://glvis.org.
This project is released under the LGPL v2.1 license. See LICENSE file for full
details.
This project is released under the LGPL v2.1 license with static linking
exception. See files COPYRIGHT and LICENSE file for full details.
LLNL Release Number: LLNL-CODE-443211
DOI: 10.11578/dc.20171025.1248
-215
View File
@@ -1,215 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_ARRAY_HPP
#define MFEM_BACKENDS_BASE_ARRAY_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "layout.hpp"
#include "utils.hpp"
namespace mfem
{
/// Extension to the template class Array<T>
class PArray : public RefCounted
{
protected:
/// Layout with shared ownership (smart pointer)
DLayout layout;
/**
@name Virtual interface
*/
///@{
virtual void *DoGetData() const = 0;
/** @brief Create and return a new array (in @a *clone) of the same dynamic
type as this array using the same layout and ItemSize().
Set @a *clone to NULL if allocation fails.
If @a copy_data is true, the contents of this array is copied to the new
array; otherwise, the new array remains uninitialized.
If @a buffer is not NULL, return the array data of the newly created
object (in @a *buffer) , if it is stored as a contiguous array on the
host; otherwise, set @a *buffer to NULL. */
virtual PArray *DoClone(bool copy_data, void **buffer,
std::size_t item_size) const = 0;
/// Resize the array, reallocating its data if necessary.
/** If @a buffer is not NULL, return the array data (in @a *buffer), if it
is stored as a contiguous array on the host; otherwise, set @a *buffer to
NULL. Returns 0 on success and non-zero otherwise, e.g. if memory
allocation fails.
If the @a new_layout is not supported, a non-zero error code will be
returned.
The @a new_layout has to be valid, i.e. new_layout != NULL and
new_layout->HasEngine() == true.
@note If reallocation is performed, the previous content of the array is
NOT copied to the new location. */
virtual int DoResize(PLayout &new_layout, void **buffer,
std::size_t item_size) = 0;
/** @brief Get access to the contents of the array in host memory, as a
contiguous array. */
/** If the array data is stored as a contiguous array in host memory, return
a pointer to it. Otherwise, copy the data to @a buffer (if @a buffer is
not NULL) and return @a buffer.
@note If not NULL, @a buffer is assumed to be of size greater than or
equal to Size(). */
virtual void *DoPullData(void *buffer, std::size_t item_size) = 0;
/** @brief Set all entries of the array to the (single) value pointed to by
@a value_ptr. */
virtual void DoFill(const void *value_ptr, std::size_t item_size) = 0;
/** @brief Set all Size() entries of the array from the given contiguous
array, @a src_buffer, on the host. */
virtual void DoPushData(const void *src_buffer, std::size_t item_size) = 0;
/// Copy the data from @a src to @a *this.
/** Both arrays must have the same dynamic type, layout, and item_size. */
virtual void DoAssign(const PArray &src, std::size_t item_size) = 0;
///@}
// End: Virtual interface
public:
/** @brief The @a layout parameter will be reference counted and therefore it
should be dynamically allocated. */
/** The @a layout must be valid in the sense that layout != NULL and
layout->HasEngine() == true. */
PArray(PLayout &p_layout)
: layout(&p_layout)
{
MFEM_ASSERT(layout && layout->HasEngine(), "invalid layout");
}
virtual ~PArray() { }
/// Get the current size of the array.
std::size_t Size() const { return layout->Size(); }
/// Get the current layout of the array.
PLayout &GetLayout() const { return *layout; }
/// TODO
template <typename derived_t>
derived_t &As() { return dynamic_cast<derived_t&>(*this); }
/// TODO
template <typename derived_t>
const derived_t &As() const { return dynamic_cast<const derived_t&>(*this); }
// TODO: Error handling ... handle errors at the Engine level, at the class
// level, or at the method level?
// TODO: Asynchronous execution interface ...
/**
@name Public virtual interface
*/
///@{
template <typename T=void>
T* GetData() const { return (T*) DoGetData(); }
/** @brief Create and return a new array (in @a *clone) of the same dynamic
type as this array using the same layout and ItemSize().
Set @a *clone to NULL if allocation fails.
If @a copy_data is true, the contents of this array is copied to the new
array; otherwise, the new array remains uninitialized.
If @a buffer is not NULL, return the array data of the newly created
object (in @a *buffer) , if it is stored as a contiguous array on the
host; otherwise, set @a *buffer to NULL. */
template <typename T>
DArray Clone(bool copy_data, T **buffer) const
{ return DArray(DoClone(copy_data, (void**)buffer, sizeof(T))); }
/// Resize the array, reallocating its data if necessary.
/** If @a buffer is not NULL, return the array data (in @a *buffer), if it
is stored as a contiguous array on the host; otherwise, set @a *buffer to
NULL. Returns 0 on success and non-zero otherwise, e.g. if memory
allocation fails.
If the @a new_layout is not supported, a non-zero error code will be
returned.
The @a new_layout has to be valid, i.e. new_layout != NULL and
new_layout->HasEngine() == true.
@note If reallocation is performed, the previous content of the array is
NOT copied to the new location. */
template <typename T>
int Resize(PLayout &new_layout, T **buffer)
{ return DoResize(new_layout, (void**)buffer, sizeof(T)); }
/// Shortcut for Resize(*layout, buffer).
/** This method is useful for updating the array after its layout is changed
externally. */
template <typename T>
int Update(T **buffer)
{ return DoResize(*layout, (void**)buffer, sizeof(T)); }
/// Shortcut for layout->Resize(new_size) followed by Update()
template <typename T>
int Resize(std::size_t new_size, T **buffer)
{ layout->Resize(new_size); return Update(buffer); }
/** @brief Get access to the contents of the array in host memory, as a
contiguous array. */
/** If the array data is stored as a contiguous array in host memory, return
a pointer to it. Otherwise, copy the data to @a buffer (if @a buffer is
not NULL) and return @a buffer.
@note If not NULL, @a buffer is assumed to be of size greater than or
equal to Size(). */
template <typename T>
T *PullData(T *buffer)
{ return Size() ? (T*)DoPullData((void*)buffer, sizeof(T)) : NULL; }
/** @brief Set all entries of the array to the (single) value pointed to by
@a value_ptr. */
template <typename T>
void Fill(const T &value) { if (Size()) { DoFill(&value, sizeof(T)); } }
/** @brief Set all Size() entries of the array from the given contiguous
array, @a src_buffer, on the host. */
template <typename T>
void PushData(const T *src_buffer)
{ if (Size()) { DoPushData(src_buffer, sizeof(T)); } }
/// Copy the data from @a src to @a *this.
/** Both arrays must have the same dynamic type, layout, and entry type. */
template <typename T>
void Assign(const PArray &src) { if (Size()) { DoAssign(src, sizeof(T)); } }
///@}
// End: Virtual interface
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_ARRAY_HPP
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_BACKEND_HPP
#define MFEM_BACKENDS_BASE_BACKEND_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "memory_resource.hpp"
#include "engine.hpp"
#include "array.hpp"
#include "vector.hpp"
#include "fespace.hpp"
#include "bilinearform.hpp"
#include <string>
#ifdef MFEM_USE_MPI
#include <mpi.h>
#endif
namespace mfem
{
/// TODO
class Backend
{
public:
/// TODO
virtual ~Backend() { }
/// TODO
virtual bool Supports(const std::string &engine_spec) const = 0;
/// TODO
virtual Engine *Create(const std::string &engine_spec) = 0;
#ifdef MFEM_USE_MPI
/// TODO
virtual Engine *Create(MPI_Comm comm, const std::string &engine_spec) = 0;
#endif
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_BACKEND_HPP
-72
View File
@@ -1,72 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_BILINEARFORM_HPP
#define MFEM_BACKENDS_BASE_BILINEARFORM_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "engine.hpp"
namespace mfem
{
class Vector;
class OperatorHandle;
class BilinearForm;
/// TODO: doxygen
class PBilinearForm : public RefCounted
{
protected:
/// Engine with shared ownership
SharedPtr<const Engine> engine;
/// Not owned.
BilinearForm *bform;
public:
/// TODO: doxygen
PBilinearForm(const Engine &e, BilinearForm &bf)
: engine(&e), bform(&bf) { }
/// Virtual destructor
virtual ~PBilinearForm() { }
/// Get the associated Engine
const Engine &GetEngine() const { return *engine; }
/// Assemble the PBilinearForm.
/** This method is called from the method BilinearForm::Assemble() of the
associated BilinearForm #bform.
@returns True, if the host assembly should be skipped. */
virtual bool Assemble() = 0;
/// TODO: doxygen
virtual void FormSystemMatrix(const Array<int> &ess_tdof_list,
OperatorHandle &A) = 0;
/// TODO: doxygen
virtual void FormLinearSystem(const Array<int> &ess_tdof_list,
Vector &x, Vector &b,
OperatorHandle &A, Vector &X, Vector &B,
int copy_interior) = 0;
/// TODO: doxygen
virtual void RecoverFEMSolution(const Vector &X, const Vector &b,
Vector &x) = 0;
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_BILINEARFORM_HPP
-29
View File
@@ -1,29 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "engine.hpp"
#include "fespace.hpp"
#include "bilinearform.hpp"
namespace mfem
{
DFiniteElementSpace Engine::MakeFESpace(FiniteElementSpace &fes) const
{
return DFiniteElementSpace(new PFiniteElementSpace(*this, fes));
}
} // namespace mfem
#endif // MFEM_USE_BACKENDS
-210
View File
@@ -1,210 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_ENGINE_HPP
#define MFEM_BACKENDS_BASE_ENGINE_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "../../general/scalars.hpp"
#include "memory_resource.hpp"
#include "smart_pointers.hpp"
#include "utils.hpp"
#ifdef MFEM_USE_MPI
#include <mpi.h>
#endif
namespace mfem
{
// Forward declarations.
class Backend;
template <typename T> class Array;
class Vector;
class Operator;
class FiniteElementSpace;
class LinearForm;
class BilinearForm;
class MixedBilinearForm;
class NonlinearForm;
/// In parallel, each MPI rank will usually create a single engine.
class Engine : public RefCounted
{
protected:
Backend *backend; ///< Backend that created the engine. Not owned.
#ifdef MFEM_USE_MPI
MPI_Comm comm; ///< Associated MPI communicator (may be MPI_COMM_NULL).
#endif
/// Number of memory resources used by the Engine.
int num_mem_res;
/// Number of workers used by the Engine.
int num_workers;
/// Memory resources used by the engine - array of pointers.
/** Both the array and the entries are owned. */
MemoryResource **memory_resources;
/// Relative computational speed of the workers. Owned.
double *workers_weights;
/// For each worker, which memory resource it uses.
int *workers_mem_res;
public:
/// TODO: doxygen
Engine(Backend *b, int n_mem, int n_workers)
: backend(b),
#ifdef MFEM_USE_MPI
comm(MPI_COMM_NULL),
#endif
num_mem_res(n_mem),
num_workers(n_workers),
memory_resources(new MemoryResource*[num_mem_res]()),
workers_weights(new double[num_workers]()),
workers_mem_res(new int[num_workers]())
{ /* Note: all arrays are value-initialized with zeros. */ }
/// TODO: doxygen
virtual ~Engine()
{
delete [] workers_mem_res;
delete [] workers_weights;
for (int i = 0; i < num_mem_res; i++)
{
delete memory_resources[i];
}
delete [] memory_resources;
}
/**
@name Machine resources interface
*/
///@{
#ifdef MFEM_USE_MPI
/// Get the associated MPI_Comm
MPI_Comm GetComm() const { return comm; }
#endif
/// TODO
int GetNumMemRes() const { return num_mem_res; }
/// TODO
MemoryResource &GetMemRes(int idx) const { return *memory_resources[idx]; }
/// TODO
int GetNumWorkers() const { return num_workers; }
/// TODO
const double *GetWorkersWeights() const { return workers_weights; }
/// TODO
const int *GetWorkersMemRes() const { return workers_mem_res; }
///@}
// End: Machine resources interface
/// TODO
template <typename derived_t>
derived_t &As() { *util::As<derived_t>(this); }
/// TODO
template <typename derived_t>
const derived_t &As() const { *util::As<const derived_t>(this); }
// TODO: Error handling ... handle errors at the Engine level, at the class
// level, or at the method level?
/**
@name Virtual interface: finite element data structures and algorithms
*/
///@{
// TODO: Asynchronous execution in this class ...
/// Allocate and return a new layout for the given @a size.
/** The layout decomposition is determined automatically by the Engine using
a deterministic algorithm: calls to this method with the same @a size
will produce the same result, as long as the Engine remains unmodified
between the calls.
The returned object is allocated with operator new and must be
deallocated by the caller.
TODO: Returns NULL if memory allocation fails?
*/
virtual DLayout MakeLayout(std::size_t size) const = 0;
/// Allocate and return a new layout for the given worker decomposition.
/** The returned object is allocated with operator new and must be
deallocated by the caller.
TODO: Returns NULL if memory allocation fails?
The @a offsets should satisfy: offsets.Size() == number of workers + 1,
offsets[0] == 0, and offsets[i] <= offsets[i+1], for i: 0 <= i < number
of workers. */
virtual DLayout MakeLayout(const Array<std::size_t> &offsets) const = 0;
// Note: There may be other ways to construct layouts in the future, e.g.
// block-vector layouts, or multi-vector layouts.
/// TODO
virtual DArray MakeArray(PLayout &layout, std::size_t item_size) const = 0;
/// Allocate and return a new vector using the given @a layout.
/** The returned object is a smart pointer that will automatically deallocate
the vector.
TODO: Produce an error if memory allocation fails?
Only layouts returned by this Engine are guaranteed to be supported.
Using a type that is not supported will produce an error. */
virtual DVector MakeVector(PLayout &layout,
int type_id = ScalarId<double>::value) const = 0;
/// TODO: doxygen
virtual DFiniteElementSpace MakeFESpace(FiniteElementSpace &fes) const;
/// TODO: doxygen
virtual DBilinearForm MakeBilinearForm(BilinearForm &bf) const = 0;
// Question: How do we construct coefficients?
/// FIXME - What will the actual parameters be?
virtual void AssembleLinearForm(LinearForm &l_form) const = 0;
/// FIXME - What will the actual parameters be?
virtual Operator *MakeOperator(const MixedBilinearForm &mbl_form) const = 0;
/// FIXME - What will the actual parameters be?
virtual Operator *MakeOperator(const NonlinearForm &nl_form) const = 0;
///@}
// End: Virtual interface
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_ENGINE_HPP
-61
View File
@@ -1,61 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_FE_SPACE_HPP
#define MFEM_BACKENDS_BASE_FE_SPACE_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "engine.hpp"
#include "utils.hpp"
namespace mfem
{
class FiniteElementSpace;
/// TODO: doxygen
class PFiniteElementSpace : public RefCounted
{
protected:
/// Engine with shared ownership
SharedPtr<const Engine> engine;
/// Not owned.
FiniteElementSpace *fes;
public:
/// TODO: doxygen
PFiniteElementSpace(const Engine &e, FiniteElementSpace &fespace)
: engine(&e), fes(&fespace) { }
/// Virtual destructor
virtual ~PFiniteElementSpace() { }
/// Get the associated engine
const Engine &GetEngine() const { return *engine; }
mfem::FiniteElementSpace* GetFESpace() const { return fes; }
/// TODO
template <typename derived_t>
derived_t &As() { return *util::As<derived_t>(this); }
/// TODO
template <typename derived_t>
const derived_t &As() const { return *util::As<const derived_t>(this); }
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_FE_SPACE_HPP
-104
View File
@@ -1,104 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_LAYOUT_HPP
#define MFEM_BACKENDS_BASE_LAYOUT_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "smart_pointers.hpp"
#include "engine.hpp"
namespace mfem
{
/// Polymorphic layout (array/vector layout descriptor)
class PLayout : public RefCounted
{
protected:
/// Engine with shared ownership
SharedPtr<const Engine> engine;
std::size_t size;
template <typename DObject>
struct Maker
{
template <typename entry_t>
static DObject MakeNew(PLayout &layout);
};
public:
explicit PLayout(std::size_t s = 0) : engine(NULL), size(s) { }
explicit PLayout(const Engine &e, std::size_t s = 0)
: engine(&e), size(s) { }
virtual ~PLayout() { }
/**
@name Virtual interface
*/
///@{
/// Resize the layout
virtual void Resize(std::size_t new_size) { size = new_size; }
/// Resize the layout based on the given worker offsets
virtual void Resize(const Array<std::size_t> &offsets)
{ MFEM_ABORT("method not supported"); }
///@}
// End: Virtual interface
/// Layouts without engine cannot create DArray, DVector, etc.
bool HasEngine() const { return engine != NULL; }
/// TODO: doxygen
const Engine &GetEngine() const { return *engine; }
/// TODO: doxygen
std::size_t Size() const { return size; }
/// TODO
template <typename derived_t>
derived_t &As() { return *util::As<derived_t>(this); }
/// TODO
template <typename derived_t>
const derived_t &As() const { return *util::As<const derived_t>(this); }
/// TODO: doxygen
template <typename DObject, typename entry_t>
DObject Make()
{
MFEM_ASSERT(HasEngine(), "this method requires an Engine");
return Maker<DObject>::template MakeNew<entry_t>(*this);
}
};
template <> struct PLayout::Maker<DArray>
{
template <typename entry_t> static DArray MakeNew(PLayout &layout)
{ return layout.GetEngine().MakeArray(layout, sizeof(entry_t)); }
};
template <> struct PLayout::Maker<DVector>
{
template <typename entry_t> static DVector MakeNew(PLayout &layout)
{ return layout.GetEngine().MakeVector(layout, ScalarId<entry_t>::value); }
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_LAYOUT_HPP
-59
View File
@@ -1,59 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "memory_resource.hpp"
#include "../../general/error.hpp"
#include <cstdlib>
#include <cstring>
#include <cerrno>
namespace mfem
{
void *NewDeleteMemoryResource::DoAllocate(std::size_t bytes,
std::size_t alignment)
{
void *p = ::operator new[](bytes);
MFEM_VERIFY(!alignment || (std::size_t)(p) % alignment == 0,
"invalid alignment");
return p;
}
void NewDeleteMemoryResource::DoDeallocate(void *p, std::size_t bytes,
std::size_t alignment)
{
::operator delete[](p);
}
void *AlignedMemoryResource::DoAllocate(std::size_t bytes,
std::size_t alignment)
{
void *p;
if (!alignment) { alignment = sizeof(long double); }
MFEM_VERIFY(posix_memalign(&p, alignment, bytes) == 0,
"error in posix_memalign(): " << strerror(errno));
return p;
}
void AlignedMemoryResource::DoDeallocate(void *p, std::size_t bytes,
std::size_t alignment)
{
free(p);
}
} // namespace mfem
#endif // MFEM_USE_BACKENDS
-70
View File
@@ -1,70 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_MEMORY_RESOURCE_HPP
#define MFEM_BACKENDS_BASE_MEMORY_RESOURCE_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include <cstddef>
namespace mfem
{
/// Polymorphic memory resource. Similar to C++17's std::pmr::memory_resource.
class MemoryResource
{
protected:
virtual void *DoAllocate(std::size_t bytes, std::size_t alignment) = 0;
virtual void DoDeallocate(void* p, std::size_t bytes,
std::size_t alignment) = 0;
public:
// Implicitly defined default & copy constructors
/// Virtual destructor.
virtual ~MemoryResource() { }
/// If alignment == 0, use default alignment.
void *Allocate(std::size_t bytes, std::size_t alignment = 0)
{ return DoAllocate(bytes, alignment); }
/// If alignment == 0, use default alignment.
void Deallocate(void *p, std::size_t bytes, std::size_t alignment = 0)
{ DoDeallocate(p, bytes, alignment); }
};
/** @brief Dynamic host memory resource using operator new[](std::size_t) for
allocation and operator delete[](void*) for deallocation. */
class NewDeleteMemoryResource : public MemoryResource
{
protected:
virtual void *DoAllocate(std::size_t bytes, std::size_t alignment);
virtual void DoDeallocate(void *p, std::size_t bytes, std::size_t alignment);
};
/** @brief Dynamic host memory resource using posix_memalign() for aligned
allocation and free() for deallocation. */
class AlignedMemoryResource : public MemoryResource
{
protected:
virtual void *DoAllocate(std::size_t bytes, std::size_t alignment);
virtual void DoDeallocate(void *p, std::size_t bytes, std::size_t alignment);
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_MEMORY_RESOURCE_HPP
-233
View File
@@ -1,233 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_SMART_POINTERS_HPP
#define MFEM_BACKENDS_BASE_SMART_POINTERS_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "utils.hpp"
#include "../../general/error.hpp"
#include <cstddef>
// #define MFEM_TRACE_SHARED_PTR
#ifdef MFEM_TRACE_SHARED_PTR
#include "../../general/globals.hpp"
#endif
namespace mfem
{
/// Base class for classes with simple reference counting.
/** Reference counting is performed by the class SharedPtr. */
class RefCounted
{
private:
mutable unsigned ref_count;
/// Only class SharedPtr can access ref_count.
template <typename T> friend class SharedPtr;
public:
RefCounted() : ref_count(0) { }
/** @brief Prevent SharedPtr objects from deleting this object by
incrementing the reference counter by one. */
void DontDelete() const { ++ref_count; }
};
/** @brief Smart pointer class that manages objects of type T derived from class
RefCounted. */
/** This class is generally meant to work with dynamically allocated object,
specifically objects allocated with operator new(). It will invoke operator
delete() to destroy the managed object when its reference counter reaches
zero. This behavior can be overriden by calling RefCounted::DontDelete() to
ensure that an object will not be deleted by a SharedPtr that holds a
pointer to it.
@note This class is NOT thread-safe and does not support circular ownership.
*/
template <typename T>
class SharedPtr
{
public:
typedef T stored_type;
private:
T *ptr;
void Init(T *new_ptr)
{
ptr = new_ptr;
if (ptr) { ++ptr->RefCounted::ref_count; }
#ifdef MFEM_TRACE_SHARED_PTR
#elif 0
mfem::out << " [" << _MFEM_FUNC_NAME << "]: ptr = " << ptr;
if (ptr)
{
mfem::out << ", new ref_count = " << ptr->RefCounted::ref_count;
}
mfem::out << '\n';
#endif
}
void Destroy()
{
MFEM_ASSERT(!ptr || ptr->RefCounted::ref_count >= 1, "invalid use");
if (ptr && --ptr->RefCounted::ref_count == 0) { delete ptr; }
#ifdef MFEM_TRACE_SHARED_PTR
#elif 0
mfem::out << " [" << _MFEM_FUNC_NAME << "]: ptr = " << ptr;
if (ptr)
{
mfem::out << ", new ref_count = " << ptr->RefCounted::ref_count;
}
mfem::out << '\n';
#endif
}
public:
SharedPtr() : ptr(NULL)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]: ptr = " << ptr << '\n';
#endif
}
SharedPtr(const SharedPtr &other)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Init(other.ptr);
}
template <typename U>
SharedPtr(const SharedPtr<U> &other)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Init(other.Get());
}
explicit SharedPtr(T *p)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Init(p);
}
~SharedPtr()
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Destroy();
}
SharedPtr &operator=(const SharedPtr &other)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Reset(other.ptr); return *this;
}
template <typename U>
SharedPtr &operator=(const SharedPtr<U> &other)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Reset(other.Get()); return *this;
}
T &operator*() const { return *ptr; }
T *operator->() const { return ptr; }
operator bool() const { return ptr; }
bool operator!() const { return !ptr; }
template <typename U>
bool operator==(const SharedPtr<U> &other) const
{ return ptr == other.Ptr(); }
template <typename U>
bool operator!=(const SharedPtr<U> &other) const
{ return ptr != other.Ptr(); }
template <typename U>
bool operator==(const U &p) const { return ptr == (void*) p; }
template <typename U>
bool operator!=(const U &p) const { return ptr != (void*) p; }
T *Get() const { return ptr; }
/// TODO
template <typename derived_t>
derived_t *As() const { return util::As<derived_t>(ptr); }
unsigned UseCount() const { return ptr ? ptr->RefCounted::ref_count : 0; }
void Reset()
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
Destroy();
ptr = NULL;
}
/// The type U* needs to be implicitly convertible to T*
template <typename U>
void Reset(U *new_ptr)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
if (ptr != new_ptr) { Destroy(); Init(new_ptr); }
}
void Swap(SharedPtr &other)
{
#ifdef MFEM_TRACE_SHARED_PTR
mfem::out << '[' << _MFEM_FUNC_NAME << "]\n";
#endif
std::swap(ptr, other.ptr);
}
};
template <class T>
inline void Swap(SharedPtr<T> &a, SharedPtr<T> &b) { a.Swap(b); }
class PLayout;
typedef SharedPtr<PLayout> DLayout;
class PArray;
typedef SharedPtr<PArray> DArray;
class PVector;
typedef SharedPtr<PVector> DVector;
class PFiniteElementSpace;
typedef SharedPtr<PFiniteElementSpace> DFiniteElementSpace;
class PBilinearForm;
typedef SharedPtr<PBilinearForm> DBilinearForm;
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_SMART_POINTERS_HPP
-52
View File
@@ -1,52 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_UTILS_HPP
#define MFEM_BACKENDS_BASE_UTILS_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "../../general/error.hpp"
namespace mfem
{
namespace util
{
//
// Inline methods
//
/// TODO: doxygen
template <typename derived_t, typename base_t>
inline derived_t *As(base_t *base_obj)
{
MFEM_ASSERT(dynamic_cast<derived_t*>(base_obj) != NULL,
"invalid object type");
return static_cast<derived_t*>(base_obj);
}
/// TODO: doxygen
template <typename derived_t, typename base_t>
inline derived_t *Is(base_t *base_obj)
{
return dynamic_cast<derived_t*>(base_obj);
}
} // namespace mfem::util
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_UTILS_HPP
-153
View File
@@ -1,153 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_BASE_VECTOR_HPP
#define MFEM_BACKENDS_BASE_VECTOR_HPP
#include "../../config/config.hpp"
#ifdef MFEM_USE_BACKENDS
#include "../../general/scalars.hpp"
#include "array.hpp"
namespace mfem
{
/// Polymorphic vector - array of scalars.
class PVector : virtual public PArray
{
protected:
/**
@name Virtual interface
*/
///@{
/** @brief Create and return a new vector of the same dynamic type as this
vector using the same layout with entries specified by @a buffer_type_id
which should be a constant defined by the `value` field in a
specialization of the template class mfem::ScalarId.
Returns NULL if allocation fails.
If @a copy_data is true, the contents of this vector is copied to the new
vector; otherwise, the new vector remains uninitialized.
If @a buffer is not NULL, return the vector data of the newly created
object (in @a *buffer), if it is stored as a contiguous array on the
host; otherwise, set @a *buffer to NULL. */
virtual PVector *DoVectorClone(bool copy_data, void **buffer,
int buffer_type_id) const = 0;
/** @brief Compute and return the dot product of @a *this and @a x. In the
case of an MPI-parallel vector, the result must be the MPI-global dot
product. */
/** Both vectors must have the same dynamic type and layout. */
virtual void DoDotProduct(const PVector &x, void *result,
int result_type_id) const = 0;
// TODO: add reduction operations: min, max, sum
/// Perform the operation @a *this = @a a @a x + @a b @a y.
/** Rules:
- the dynamic type of both @a x and @a y is the same as that of @a *this
- if @a a == 0, neither @a x nor its data are accessed
- if @a b == 0, neither @a y nor its data are accessed
- @a x's data is never the same as @a y's data, unless @a a == 0, or
@a b == 0
- @a x's data or @a y's data may be the same as the data of @a *this
- all accessed vectors, @a x, @a y, and @a *this have the same layout. */
virtual void DoAxpby(const void *a, const PVector &x,
const void *b, const PVector &y,
int ab_type_id) = 0;
///@}
// End: Virtual interface
public:
/** @brief Create a PVector. */
/** The @a layout must be valid in the sense that layout != NULL and
layout->HasEngine() == true. */
PVector(PLayout &p_layout)
: PArray(p_layout) { }
template <typename derived_t>
derived_t &As() { return *util::As<derived_t>(this); }
template <typename derived_t>
const derived_t &As() const { return *util::As<const derived_t>(this); }
// TODO: Error handling ... handle errors at the Engine level, at the class
// level, or at the method level?
// TODO: Asynchronous execution interface ...
// TODO: Multi-vector interface ...
/**
@name Public virtual interface
*/
///@{
/** @brief Create and return a new vector of the same dynamic type as this
vector using the same layout with entries of type @a scalar_t.
If @a copy_data is true, the contents of this vector is copied to the new
vector; otherwise, the new vector remains uninitialized.
If @a buffer is not NULL, return the vector data of the newly created
object (in @a *buffer) , if it is stored as a contiguous array on the
host; otherwise, set @a *buffer to NULL. */
template <typename scalar_t>
DVector Clone(bool copy_data, scalar_t **buffer) const
{
return DVector(DoVectorClone(copy_data, (void**)buffer,
ScalarId<scalar_t>::value));
}
/** @brief Compute and return the dot product of @a *this and @a x. In the
case of an MPI-parallel vector, the result must be the MPI-global dot
product. */
/** Both vectors must have the same dynamic type and layout. */
template <typename scalar_t>
scalar_t DotProduct(const PVector &x) const
{
scalar_t result;
DoDotProduct(x, &result, ScalarId<scalar_t>::value);
return result;
}
// TODO: add reduction operations: min, max, sum
/// Perform the operation @a *this = @a a @a x + @a b @a y.
/** Rules:
- the dynamic type of both @a x and @a y is the same as that of @a *this
- if @a a == 0, neither @a x nor its data are accessed
- if @a b == 0, neither @a y nor its data are accessed
- @a x's data is never the same as @a y's data, unless @a a == 0, or
@a b == 0
- @a x's data or @a y's data may be the same as the data of @a *this
- all accessed vectors, @a x, @a y, and @a *this have the same layout. */
template <typename scalar_t>
void Axpby(const scalar_t &a, const PVector &x,
const scalar_t &b, const PVector &y)
{ if (Size()) { DoAxpby(&a, x, &b, y, ScalarId<scalar_t>::value); } }
///@}
// End: Virtual interface
};
} // namespace mfem
#endif // MFEM_USE_BACKENDS
#endif // MFEM_BACKENDS_BASE_VECTOR_HPP
-66
View File
@@ -1,66 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
/*
---[ Defines Known At Compile-Time ]------------
ELEMENT_BATCH : How many elements are in each
. computation batch
NUM_DOFS_1D : Dofs in the 1D segments
NUM_DOFS_2D : Dofs in the 2D faces
NUM_DOFS_3D : Dofs in the 3D domain
NUM_QUAD_1D : Dofs in the 1D segments
NUM_QUAD_2D : Dofs in the 2D faces
NUM_QUAD_3D : Dofs in the 3D domain
NUM_MAX_1D : max(NUM_QUAD_1D, NUM_DOFS_1D)
NUM_QUAD_DOFS_1D: NUM_QUAD_1D * NUM_DOFS_1D
COEFF_ARGS : Code that passes required arguments to the kernel
COEFF : Code that computes the coefficient
================================================
[MISSING]
- Add support to auto-pick @dim and use @idxOrder on stack arrays
| double a[2][2];
| a[0][1]; <-- regular index
| a(0,1); <-- uses @idxOrder a[0][1] or a[1][0]
- Add support for @idxOrder to change indexing order after allocation
| double a[2][2] @idxOrder(0,1);
| a(0,1) -> a[1][0]
| @set(a, idxOrder(1,0));
| a(0,1) -> a[0][1]
- Add support to iterate over loop depending on mode
| for(i; @inner) {
| for(0 < j < N) {} <-- ++j or j += block?
| }
*/
#include "mfem-occa://defines.okl"
#if USING_TENSOR_OPS
# ifdef OCCA_USING_GPU
# if USING_LOW_ORDER
# include "mfem-occa://diffusion/tensor/gpuHighOrder.okl"
# else
# include "mfem-occa://diffusion/tensor/gpuHighOrder.okl"
# endif
# else
# include "mfem-occa://diffusion/tensor/cpu.okl"
# endif
#else
# ifdef OCCA_USING_GPU
# if USING_LOW_ORDER
# include "mfem-occa://diffusion/simplex/gpuHighOrder.okl"
# else
# include "mfem-occa://diffusion/simplex/gpuHighOrder.okl"
# endif
# else
# include "mfem-occa://diffusion/simplex/cpu.okl"
# endif
#endif
-123
View File
@@ -1,123 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "array.hpp"
namespace mfem
{
namespace occa
{
PArray *Array::DoClone(bool copy_data, void **buffer,
std::size_t item_size) const
{
Array *new_array = new Array(OccaLayout(), item_size);
if (copy_data)
{
new_array->slice.copyFrom(slice);
}
if (buffer)
{
*buffer = new_array->GetBuffer();
}
return new_array;
}
int Array::DoResize(PLayout &new_layout, void **buffer,
std::size_t item_size)
{
MFEM_ASSERT(dynamic_cast<Layout *>(&new_layout) != NULL,
"new_layout is not an OCCA Layout");
Layout *lt = static_cast<Layout *>(&new_layout);
layout.Reset(lt); // Reset() checks if the pointer is the same
int err = ResizeData(lt, item_size);
if (!err && buffer)
{
*buffer = GetBuffer();
}
return err;
}
void *Array::DoPullData(void *buffer, std::size_t item_size)
{
// called only when Size() != 0
if (!slice.getDevice().hasSeparateMemorySpace())
{
return slice.ptr();
}
if (buffer)
{
slice.copyTo(buffer);
}
return buffer;
}
void Array::DoFill(const void *value_ptr, std::size_t item_size)
{
// called only when Size() != 0
switch (item_size)
{
case sizeof(int8_t):
OccaFill((const int8_t *)value_ptr);
break;
case sizeof(int16_t):
OccaFill((const int16_t *)value_ptr);
break;
case sizeof(int32_t):
OccaFill((const int32_t *)value_ptr);
break;
// case sizeof(int64_t):
// OccaFill((const int64_t *)value_ptr);
// break;
case sizeof(double):
OccaFill((const double *)value_ptr);
break;
// case sizeof(::occa::double2):
// OccaFill((const ::occa::double2 *)value_ptr);
// break;
default:
MFEM_ABORT("item_size = " << item_size << " is not supported");
}
}
void Array::DoPushData(const void *src_buffer, std::size_t item_size)
{
// called only when Size() != 0
if (slice.getDevice().hasSeparateMemorySpace() || slice.ptr() != src_buffer)
{
slice.copyFrom(src_buffer);
}
}
void Array::DoAssign(const PArray &src, std::size_t item_size)
{
// called only when Size() != 0
// Note: static_cast can not be used here since PArray is a virtual base
// class.
const Array *source = dynamic_cast<const Array *>(&src);
MFEM_ASSERT(source != NULL, "invalid source Array type");
MFEM_ASSERT(Size() == source->Size(), "");
slice.copyFrom(source->slice);
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-133
View File
@@ -1,133 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_ARRAY_HPP
#define MFEM_BACKENDS_OCCA_ARRAY_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include <occa.hpp>
#include "layout.hpp"
#include "../base/array.hpp"
namespace mfem
{
namespace occa
{
class Array : public virtual PArray
{
protected:
//
// Inherited fields
//
// DLayout layout;
// Always true: Size()*item_size == slice.size() <= data.size()
mutable ::occa::memory data, slice;
//
// Virtual interface
//
virtual void *DoGetData() const { return GetBuffer(); }
virtual PArray *DoClone(bool copy_data, void **buffer,
std::size_t item_size) const;
virtual int DoResize(PLayout &new_layout, void **buffer,
std::size_t item_size);
virtual void *DoPullData(void *buffer, std::size_t item_size);
virtual void DoFill(const void *value_ptr, std::size_t item_size);
virtual void DoPushData(const void *src_buffer, std::size_t item_size);
virtual void DoAssign(const PArray &src, std::size_t item_size);
//
// Auxiliary methods
//
inline void *GetBuffer() const;
inline int ResizeData(const Layout *lt, std::size_t item_size);
template <typename T>
inline void OccaFill(const T *val_ptr)
{ ::occa::linalg::operator_eq<T>(slice, *val_ptr); }
public:
Array(Layout &lt, std::size_t item_size)
: PArray(lt),
data(lt.Alloc(lt.Size()*item_size)),
slice(data)
{ }
virtual ~Array() { }
inline void MakeRef(Array &master);
Layout &OccaLayout() const
{ return *static_cast<Layout *>(layout.Get()); }
::occa::memory &OccaMem() { return slice; }
const ::occa::memory &OccaMem() const { return slice; }
};
//
// Inline methods
//
inline void *Array::GetBuffer() const
{
if (!slice.getDevice().hasSeparateMemorySpace())
{
return slice.ptr();
}
return NULL;
}
inline int Array::ResizeData(const Layout *lt, std::size_t item_size)
{
const std::size_t new_bytes = lt->Size()*item_size;
if (data.size() < new_bytes ||
data.getDHandle() != lt->OccaEngine().GetDevice().getDHandle())
{
data = lt->Alloc(new_bytes);
slice = data;
// If memory allocation fails - an exception is thrown.
}
else if (slice.size() != new_bytes)
{
slice = data.slice(0, new_bytes);
}
return 0;
}
inline void Array::MakeRef(Array &master)
{
layout = master.layout;
data = master.data;
slice = master.slice;
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_ARRAY_HPP
-47
View File
@@ -1,47 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "backend.hpp"
#include "engine.hpp"
namespace mfem
{
namespace occa
{
bool Backend::Supports(const std::string &engine_spec) const
{
// TODO: check if 'engine_spec' is valid OCCA string.
return true;
}
mfem::Engine *Create(const std::string &engine_spec)
{
return new Engine(engine_spec);
}
#ifdef MFEM_USE_MPI
mfem::Engine *Create(MPI_Comm comm, const std::string &engine_spec)
{
return new Engine(comm, engine_spec);
}
#endif
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-49
View File
@@ -1,49 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_BACKEND_HPP
#define MFEM_BACKENDS_OCCA_BACKEND_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
// Only the Backend and Engine classes should be exposed through "backend.hpp"
#include "../base/backend.hpp"
#include "engine.hpp"
#include <occa.hpp>
namespace mfem
{
namespace occa
{
class Backend : public mfem::Backend
{
public:
virtual ~Backend();
virtual bool Supports(const std::string &engine_spec) const;
virtual mfem::Engine *Create(const std::string &engine_spec);
#ifdef MFEM_USE_MPI
virtual mfem::Engine *Create(MPI_Comm comm, const std::string &engine_spec);
#endif
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_BACKEND_HPP
-514
View File
@@ -1,514 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "backend.hpp"
#include "bilininteg.hpp"
#include "../../fem/bilinearform.hpp"
namespace mfem
{
namespace occa
{
OccaBilinearForm::OccaBilinearForm(FiniteElementSpace *ofespace_) :
Operator(ofespace_->OccaVLayout()),
localX((ofespace_->OccaEVLayout().DontDelete(), ofespace_->OccaEVLayout())),
localY((ofespace_->OccaEVLayout().DontDelete(), ofespace_->OccaEVLayout()))
{
Init(ofespace_->OccaEngine(), ofespace_, ofespace_);
}
OccaBilinearForm::OccaBilinearForm(FiniteElementSpace *otrialFESpace_,
FiniteElementSpace *otestFESpace_) :
Operator(otrialFESpace_->OccaVLayout(),
otestFESpace_->OccaVLayout()),
localX((otrialFESpace_->OccaEVLayout().DontDelete(), otrialFESpace_->OccaEVLayout())),
localY((otestFESpace_->OccaEVLayout().DontDelete(), otestFESpace_->OccaEVLayout()))
{
Init(otrialFESpace_->OccaEngine(), otrialFESpace_, otestFESpace_);
}
void OccaBilinearForm::Init(const Engine &e,
FiniteElementSpace *otrialFESpace_,
FiniteElementSpace *otestFESpace_)
{
engine.Reset(&e);
otrialFESpace = otrialFESpace_;
trialFESpace = otrialFESpace_->GetFESpace();
otestFESpace = otestFESpace_;
testFESpace = otestFESpace_->GetFESpace();
mesh = trialFESpace->GetMesh();
const int elements = GetNE();
const int trialVDim = trialFESpace->GetVDim();
const int trialLocalDofs = otrialFESpace->GetLocalDofs();
const int testLocalDofs = otestFESpace->GetLocalDofs();
// First-touch policy when running with OpenMP
if (GetDevice().mode() == "OpenMP")
{
const std::string &okl_path = OccaEngine().GetOklPath();
const std::string &okl_defines = OccaEngine().GetOklDefines();
::occa::kernel initLocalKernel =
GetDevice().buildKernel(okl_path + "utils.okl",
"InitLocalVector",
okl_defines);
const std::size_t sd = sizeof(double);
const uint64_t trialEntries = sd * (elements * trialLocalDofs);
const uint64_t testEntries = sd * (elements * testLocalDofs);
for (int v = 0; v < trialVDim; ++v)
{
const uint64_t trialOffset = v * trialEntries;
const uint64_t testOffset = v * testEntries;
initLocalKernel(elements, trialLocalDofs,
localX.OccaMem().slice(trialOffset, trialEntries));
initLocalKernel(elements, testLocalDofs,
localY.OccaMem().slice(testOffset, testEntries));
}
}
}
int OccaBilinearForm::BaseGeom() const
{
return mesh->GetElementBaseGeometry();
}
int OccaBilinearForm::GetDim() const
{
return mesh->Dimension();
}
int64_t OccaBilinearForm::GetNE() const
{
return mesh->GetNE();
}
Mesh& OccaBilinearForm::GetMesh() const
{
return *mesh;
}
FiniteElementSpace& OccaBilinearForm::GetTrialOccaFESpace() const
{
return *otrialFESpace;
}
FiniteElementSpace& OccaBilinearForm::GetTestOccaFESpace() const
{
return *otestFESpace;
}
mfem::FiniteElementSpace& OccaBilinearForm::GetTrialFESpace() const
{
return *trialFESpace;
}
mfem::FiniteElementSpace& OccaBilinearForm::GetTestFESpace() const
{
return *testFESpace;
}
int64_t OccaBilinearForm::GetTrialNDofs() const
{
return trialFESpace->GetNDofs();
}
int64_t OccaBilinearForm::GetTestNDofs() const
{
return testFESpace->GetNDofs();
}
int64_t OccaBilinearForm::GetTrialVDim() const
{
return trialFESpace->GetVDim();
}
int64_t OccaBilinearForm::GetTestVDim() const
{
return testFESpace->GetVDim();
}
const FiniteElement& OccaBilinearForm::GetTrialFE(const int i) const
{
return *(trialFESpace->GetFE(i));
}
const FiniteElement& OccaBilinearForm::GetTestFE(const int i) const
{
return *(testFESpace->GetFE(i));
}
// Adds new Domain Integrator.
void OccaBilinearForm::AddDomainIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props)
{
AddIntegrator(integrator, props, DomainIntegrator);
}
// Adds new Boundary Integrator.
void OccaBilinearForm::AddBoundaryIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props)
{
AddIntegrator(integrator, props, BoundaryIntegrator);
}
// Adds new interior Face Integrator.
void OccaBilinearForm::AddInteriorFaceIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props)
{
AddIntegrator(integrator, props, InteriorFaceIntegrator);
}
// Adds new boundary Face Integrator.
void OccaBilinearForm::AddBoundaryFaceIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props)
{
AddIntegrator(integrator, props, BoundaryFaceIntegrator);
}
// Adds Integrator based on OccaIntegratorType
void OccaBilinearForm::AddIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props,
const OccaIntegratorType itype)
{
if (integrator == NULL)
{
std::stringstream error_ss;
error_ss << "OccaBilinearForm::";
switch (itype)
{
case DomainIntegrator : error_ss << "AddDomainIntegrator"; break;
case BoundaryIntegrator : error_ss << "AddBoundaryIntegrator"; break;
case InteriorFaceIntegrator: error_ss << "AddInteriorFaceIntegrator"; break;
case BoundaryFaceIntegrator: error_ss << "AddBoundaryFaceIntegrator"; break;
}
error_ss << " (...):\n"
<< " Integrator is NULL";
const std::string error = error_ss.str();
mfem_error(error.c_str());
}
integrator->SetupIntegrator(*this, baseKernelProps + props, itype);
integrators.push_back(integrator);
}
const mfem::Operator* OccaBilinearForm::GetTrialProlongation() const
{
return otrialFESpace->GetProlongationOperator();
}
const mfem::Operator* OccaBilinearForm::GetTestProlongation() const
{
return otestFESpace->GetProlongationOperator();
}
const mfem::Operator* OccaBilinearForm::GetTrialRestriction() const
{
return otrialFESpace->GetRestrictionOperator();
}
const mfem::Operator* OccaBilinearForm::GetTestRestriction() const
{
return otestFESpace->GetRestrictionOperator();
}
void OccaBilinearForm::Assemble()
{
// [MISSING] Find geometric information that is needed by intergrators
// to share between integrators.
const int integratorCount = (int) integrators.size();
for (int i = 0; i < integratorCount; ++i)
{
integrators[i]->Assemble();
}
}
void OccaBilinearForm::FormLinearSystem(const mfem::Array<int> &constraintList,
mfem::Vector &x, mfem::Vector &b,
mfem::Operator *&Aout,
mfem::Vector &X, mfem::Vector &B,
int copy_interior)
{
FormOperator(constraintList, Aout);
InitRHS(constraintList, x, b, Aout, X, B, copy_interior);
}
void OccaBilinearForm::FormOperator(const mfem::Array<int> &constraintList,
mfem::Operator *&Aout)
{
const mfem::Operator *trialP = GetTrialProlongation();
const mfem::Operator *testP = GetTestProlongation();
mfem::Operator *rap = this;
if (trialP)
{
rap = new RAPOperator(*testP, *this, *trialP);
}
Aout = new OccaConstrainedOperator(rap, constraintList,
rap != this);
}
void OccaBilinearForm::InitRHS(const mfem::Array<int> &constraintList,
mfem::Vector &x, mfem::Vector &b,
mfem::Operator *A,
mfem::Vector &X, mfem::Vector &B,
int copy_interior)
{
const std::string okl_defines = OccaEngine().GetOklDefines();
// FIXME: move these kernels to the Backend?
static ::occa::kernelBuilder get_subvector_builder =
::occa::linalg::customLinearMethod(
"vector_get_subvector",
"const int dof_i = v2[i];"
"v0[i] = dof_i >= 0 ? v1[dof_i] : -v1[-dof_i - 1];",
"defines: {"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" VTYPE2: 'int',"
" TILESIZE: 128,"
"}" + okl_defines);
static ::occa::kernelBuilder set_subvector_builder =
::occa::linalg::customLinearMethod(
"vector_set_subvector",
"const int dof_i = v2[i];"
"if (dof_i >= 0) { v0[dof_i] = v1[i]; }"
"else { v0[-dof_i - 1] = -v1[i]; }",
"defines: {"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" VTYPE2: 'int',"
" TILESIZE: 128,"
"}" + okl_defines);
const mfem::Operator *P = GetTrialProlongation();
const mfem::Operator *R = GetTrialRestriction();
if (P)
{
// Variational restriction with P
B.Resize(P->InLayout());
P->MultTranspose(b, B);
X.Resize(R->OutLayout());
R->Mult(x, X);
}
else
{
// rap, X and B point to the same data as this, x and b
X.MakeRef(x);
B.MakeRef(b);
}
if (!copy_interior && constraintList.Size() > 0)
{
::occa::kernel get_subvector_kernel =
get_subvector_builder.build(GetDevice());
::occa::kernel set_subvector_kernel =
set_subvector_builder.build(GetDevice());
const Array &constrList = constraintList.Get_PArray()->As<Array>();
Vector subvec(constrList.OccaLayout());
get_subvector_kernel(constraintList.Size(),
subvec.OccaMem(),
X.Get_PVector()->As<Vector>().OccaMem(),
constrList.OccaMem());
X.Fill(0.0);
set_subvector_kernel(constraintList.Size(),
X.Get_PVector()->As<Vector>().OccaMem(),
subvec.OccaMem(),
constrList.OccaMem());
}
OccaConstrainedOperator *cA = dynamic_cast<OccaConstrainedOperator*>(A);
if (cA)
{
cA->EliminateRHS(X.Get_PVector()->As<Vector>(),
B.Get_PVector()->As<Vector>());
}
else
{
mfem_error("OccaBilinearForm::InitRHS expects an OccaConstrainedOperator");
}
}
// Matrix vector multiplication.
void OccaBilinearForm::Mult_(const Vector &x, Vector &y) const
{
otrialFESpace->GlobalToLocal(x, localX);
localY.Fill<double>(0.0);
const int integratorCount = (int) integrators.size();
for (int i = 0; i < integratorCount; ++i)
{
integrators[i]->MultAdd(localX, localY);
}
otestFESpace->LocalToGlobal(localY, y);
}
// Matrix transpose vector multiplication.
void OccaBilinearForm::MultTranspose_(const Vector &x, Vector &y) const
{
otestFESpace->GlobalToLocal(x, localX);
localY.Fill<double>(0.0);
const int integratorCount = (int) integrators.size();
for (int i = 0; i < integratorCount; ++i)
{
integrators[i]->MultTransposeAdd(localX, localY);
}
otrialFESpace->LocalToGlobal(localY, y);
}
void OccaBilinearForm::OccaRecoverFEMSolution(const mfem::Vector &X,
const mfem::Vector &b,
mfem::Vector &x)
{
const mfem::Operator *P = this->GetTrialProlongation();
if (P)
{
// Apply conforming prolongation
x.Resize(P->OutLayout());
P->Mult(X, x);
}
// Otherwise X and x point to the same data
}
// Frees memory bilinear form.
OccaBilinearForm::~OccaBilinearForm()
{
// Make sure all integrators free their data
IntegratorVector::iterator it = integrators.begin();
while (it != integrators.end())
{
delete *it;
++it;
}
}
void BilinearForm::InitOccaBilinearForm()
{
// Init 'obform' using 'bform'
MFEM_ASSERT(bform != NULL, "");
MFEM_ASSERT(obform == NULL, "");
FiniteElementSpace &ofes =
bform->FESpace()->Get_PFESpace()->As<FiniteElementSpace>();
obform = new OccaBilinearForm(&ofes);
// Transfer domain integrators
mfem::Array<mfem::BilinearFormIntegrator*> &dbfi = *bform->GetDBFI();
for (int i = 0; i < dbfi.Size(); i++)
{
std::string integ_name(dbfi[i]->Name());
Coefficient *scal_coeff = dbfi[i]->GetScalarCoefficient();
ConstantCoefficient *const_coeff =
dynamic_cast<ConstantCoefficient*>(scal_coeff);
// TODO: other types of coefficients ...
double val = const_coeff ? const_coeff->constant : 1.0;
OccaCoefficient ocoeff(obform->OccaEngine(), val);
OccaIntegrator *ointeg = NULL;
if (integ_name == "(undefined)")
{
MFEM_ABORT("BilinearFormIntegrator does not define Name()");
}
else if (integ_name == "diffusion")
{
ointeg = new OccaDiffusionIntegrator(ocoeff);
}
else
{
MFEM_ABORT("BilinearFormIntegrator [Name() = " << integ_name
<< "] is not supported");
}
const mfem::IntegrationRule *ir = dbfi[i]->GetIntRule();
if (ir) { ointeg->SetIntegrationRule(*ir); }
obform->AddDomainIntegrator(ointeg);
}
// TODO: other types of integrators ...
}
bool BilinearForm::Assemble()
{
if (obform == NULL) { InitOccaBilinearForm(); }
obform->Assemble();
return true; // --> host assembly is not needed
}
void BilinearForm::FormSystemMatrix(const mfem::Array<int> &ess_tdof_list,
mfem::OperatorHandle &A)
{
if (A.Type() == mfem::Operator::ANY_TYPE)
{
mfem::Operator *Aout = NULL;
obform->FormOperator(ess_tdof_list, Aout);
A.Reset(Aout);
}
else
{
MFEM_ABORT("Operator::Type is not supported, type = " << A.Type());
}
}
void BilinearForm::FormLinearSystem(const mfem::Array<int> &ess_tdof_list,
mfem::Vector &x, mfem::Vector &b,
mfem::OperatorHandle &A,
mfem::Vector &X, mfem::Vector &B,
int copy_interior)
{
FormSystemMatrix(ess_tdof_list, A);
obform->InitRHS(ess_tdof_list, x, b, A.Ptr(), X, B, copy_interior);
}
void BilinearForm::RecoverFEMSolution(const mfem::Vector &X,
const mfem::Vector &b,
mfem::Vector &x)
{
obform->OccaRecoverFEMSolution(X, b, x);
}
BilinearForm::~BilinearForm()
{
delete obform;
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-213
View File
@@ -1,213 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_BILINEAR_FORM_HPP
#define MFEM_BACKENDS_OCCA_BILINEAR_FORM_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "fespace.hpp"
namespace mfem
{
namespace occa
{
enum OccaIntegratorType
{
DomainIntegrator = 0,
BoundaryIntegrator = 1,
InteriorFaceIntegrator = 2,
BoundaryFaceIntegrator = 3
};
class OccaIntegrator;
/** Class for bilinear form - "Matrix" with associated FE space and
BLFIntegrators. */
class OccaBilinearForm : public Operator
{
friend class OccaIntegrator;
protected:
typedef std::vector<OccaIntegrator*> IntegratorVector;
SharedPtr<const Engine> engine;
// State information
mutable mfem::Mesh *mesh;
mutable FiniteElementSpace *otrialFESpace;
mutable mfem::FiniteElementSpace *trialFESpace;
mutable FiniteElementSpace *otestFESpace;
mutable mfem::FiniteElementSpace *testFESpace;
IntegratorVector integrators;
// Device data
::occa::properties baseKernelProps;
// The input and output vectors are mapped to local nodes for efficient
// operations. In other words, they are E-vectors.
// The size is: (number of elements) * (nodes in element) * (vector dim)
mutable Vector localX, localY;
public:
OccaBilinearForm(FiniteElementSpace *ofespace_);
OccaBilinearForm(FiniteElementSpace *otrialFESpace_,
FiniteElementSpace *otestFESpace_);
void Init(const Engine &e,
FiniteElementSpace *otrialFESpace_,
FiniteElementSpace *otestFESpace_);
const Engine &OccaEngine() const { return *engine; }
::occa::device GetDevice(int idx = 0) const
{ return engine->GetDevice(idx); }
// Useful mesh Information
int BaseGeom() const;
int GetDim() const;
int64_t GetNE() const;
mfem::Mesh& GetMesh() const;
FiniteElementSpace& GetTrialOccaFESpace() const;
FiniteElementSpace& GetTestOccaFESpace() const;
mfem::FiniteElementSpace& GetTrialFESpace() const;
mfem::FiniteElementSpace& GetTestFESpace() const;
// Useful FE information
int64_t GetTrialNDofs() const;
int64_t GetTestNDofs() const;
int64_t GetTrialVDim() const;
int64_t GetTestVDim() const;
const mfem::FiniteElement& GetTrialFE(const int i) const;
const mfem::FiniteElement& GetTestFE(const int i) const;
// Adds new Domain Integrator.
void AddDomainIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props =
::occa::properties());
// Adds new Boundary Integrator.
void AddBoundaryIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props =
::occa::properties());
// Adds new interior Face Integrator.
void AddInteriorFaceIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props =
::occa::properties());
// Adds new boundary Face Integrator.
void AddBoundaryFaceIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props =
::occa::properties());
// Adds Integrator based on OccaIntegratorType
void AddIntegrator(OccaIntegrator *integrator,
const ::occa::properties &props,
const OccaIntegratorType itype);
virtual const mfem::Operator *GetTrialProlongation() const;
virtual const mfem::Operator *GetTestProlongation() const;
virtual const mfem::Operator *GetTrialRestriction() const;
virtual const mfem::Operator *GetTestRestriction() const;
// Assembles the form i.e. sums over all domain/bdr integrators.
virtual void Assemble();
void FormLinearSystem(const mfem::Array<int> &constraintList,
mfem::Vector &x, mfem::Vector &b,
mfem::Operator *&Aout,
mfem::Vector &X, mfem::Vector &B,
int copy_interior = 0);
void FormOperator(const mfem::Array<int> &constraintList,
mfem::Operator *&Aout);
void InitRHS(const mfem::Array<int> &constraintList,
mfem::Vector &x, mfem::Vector &b,
mfem::Operator *Aout,
mfem::Vector &X, mfem::Vector &B,
int copy_interior = 0);
// overrides
virtual void Mult_(const Vector &x, Vector &y) const;
virtual void MultTranspose_(const Vector &x, Vector &y) const;
void OccaRecoverFEMSolution(const mfem::Vector &X, const mfem::Vector &b,
mfem::Vector &x);
// Destroys bilinear form.
~OccaBilinearForm();
};
/// TODO: doxygen
class BilinearForm : public mfem::PBilinearForm
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// mfem::BilinearForm *bform;
OccaBilinearForm *obform;
// Called from Assemble() if obform is NULL to initialize obform.
void InitOccaBilinearForm();
public:
/// TODO: doxygen
BilinearForm(const Engine &e, mfem::BilinearForm &bf)
: mfem::PBilinearForm(e, bf), obform(NULL) { }
/// Virtual destructor
virtual ~BilinearForm();
/// Assemble the PBilinearForm.
/** This method is called from the method mfem::BilinearForm::Assemble() of
the associated mfem::BilinearForm, #bform.
@returns True, if the host assembly should NOT be performed. */
virtual bool Assemble();
virtual void FormSystemMatrix(const mfem::Array<int> &ess_tdof_list,
mfem::OperatorHandle &A);
virtual void FormLinearSystem(const mfem::Array<int> &ess_tdof_list,
mfem::Vector &x, mfem::Vector &b,
mfem::OperatorHandle &A,
mfem::Vector &X, mfem::Vector &B,
int copy_interior);
virtual void RecoverFEMSolution(const mfem::Vector &X, const mfem::Vector &b,
mfem::Vector &x);
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_BILINEAR_FORM_HPP
-956
View File
@@ -1,956 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "bilininteg.hpp"
#include "../../fem/fem.hpp"
namespace mfem
{
namespace occa
{
std::map<std::string, OccaDofQuadMaps> OccaDofQuadMaps::AllDofQuadMaps;
OccaGeometry OccaGeometry::Get(::occa::device device,
FiniteElementSpace &ofespace,
const mfem::IntegrationRule &ir,
const int flags)
{
OccaGeometry geom;
mfem::Mesh &mesh = *(ofespace.GetMesh());
if (!mesh.GetNodes())
{
mesh.SetCurvature(1, false, -1, mfem::Ordering::byVDIM);
}
mfem::GridFunction &nodes = *(mesh.GetNodes());
const mfem::FiniteElementSpace &fespace = *(nodes.FESpace());
const mfem::FiniteElement &fe = *(fespace.GetFE(0));
const int dims = fe.GetDim();
const int elements = fespace.GetNE();
const int numDofs = fe.GetDof();
const int numQuad = ir.GetNPoints();
MFEM_ASSERT(dims == mesh.SpaceDimension(), "");
geom.meshNodes.allocate(device,
dims, numDofs, elements);
const mfem::Table &e2dTable = fespace.GetElementToDofTable();
const int *elementMap = e2dTable.GetJ();
nodes.Pull();
for (int e = 0; e < elements; ++e)
{
for (int dof = 0; dof < numDofs; ++dof)
{
const int gid = elementMap[dof + numDofs*e];
for (int dim = 0; dim < dims; ++dim)
{
geom.meshNodes(dim, dof, e) = nodes[fespace.DofToVDof(gid,dim)];
}
}
}
geom.meshNodes.keepInDevice();
if (flags & Jacobian)
{
geom.J.allocate(device,
dims, dims, numQuad, elements);
}
else
{
geom.J.allocate(device, 1);
}
if (flags & JacobianInv)
{
geom.invJ.allocate(device,
dims, dims, numQuad, elements);
}
else
{
geom.invJ.allocate(device, 1);
}
if (flags & JacobianDet)
{
geom.detJ.allocate(device,
numQuad, elements);
}
else
{
geom.detJ.allocate(device, 1);
}
geom.J.stopManaging();
geom.invJ.stopManaging();
geom.detJ.stopManaging();
OccaDofQuadMaps &maps = OccaDofQuadMaps::GetSimplexMaps(device, fe, ir);
::occa::properties props;
props["defines/NUM_DOFS"] = numDofs;
props["defines/NUM_QUAD"] = numQuad;
props["defines/STORE_JACOBIAN"] = (flags & Jacobian);
props["defines/STORE_JACOBIAN_INV"] = (flags & JacobianInv);
props["defines/STORE_JACOBIAN_DET"] = (flags & JacobianDet);
const std::string &okl_path = ofespace.OccaEngine().GetOklPath();
const std::string &okl_defines = ofespace.OccaEngine().GetOklDefines();
::occa::kernel init = device.buildKernel(okl_path + "geometry.okl",
stringWithDim("InitGeometryInfo",
fe.GetDim()),
props + okl_defines);
init(elements,
maps.dofToQuadD,
geom.meshNodes,
geom.J, geom.invJ, geom.detJ);
return geom;
}
OccaDofQuadMaps::OccaDofQuadMaps() :
hash() {}
OccaDofQuadMaps::OccaDofQuadMaps(const OccaDofQuadMaps &maps)
{
*this = maps;
}
OccaDofQuadMaps& OccaDofQuadMaps::operator = (const OccaDofQuadMaps &maps)
{
hash = maps.hash;
dofToQuad = maps.dofToQuad;
dofToQuadD = maps.dofToQuadD;
quadToDof = maps.quadToDof;
quadToDofD = maps.quadToDofD;
quadWeights = maps.quadWeights;
return *this;
}
OccaDofQuadMaps& OccaDofQuadMaps::Get(::occa::device device,
const FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return Get(device,
*fespace.GetFE(0),
*fespace.GetFE(0),
ir,
transpose);
}
OccaDofQuadMaps& OccaDofQuadMaps::Get(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return Get(device, fe, fe, ir, transpose);
}
OccaDofQuadMaps& OccaDofQuadMaps::Get(::occa::device device,
const FiniteElementSpace &trialFESpace,
const FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return Get(device,
*trialFESpace.GetFE(0),
*testFESpace.GetFE(0),
ir,
transpose);
}
OccaDofQuadMaps& OccaDofQuadMaps::Get(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return (dynamic_cast<const mfem::TensorBasisElement*>(&trialFE)
? GetTensorMaps(device, trialFE, testFE, ir, transpose)
: GetSimplexMaps(device, trialFE, testFE, ir, transpose));
}
OccaDofQuadMaps& OccaDofQuadMaps::GetTensorMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return GetTensorMaps(device,
fe, fe,
ir, transpose);
}
OccaDofQuadMaps& OccaDofQuadMaps::GetTensorMaps(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose)
{
const mfem::TensorBasisElement &trialTFE =
dynamic_cast<const mfem::TensorBasisElement&>(trialFE);
const mfem::TensorBasisElement &testTFE =
dynamic_cast<const mfem::TensorBasisElement&>(testFE);
std::stringstream ss;
ss << ::occa::hash(device)
<< "Tensor"
<< "O1:" << trialFE.GetOrder()
<< "O2:" << testFE.GetOrder()
<< "BT1:" << trialTFE.GetBasisType()
<< "BT2:" << testTFE.GetBasisType()
<< "Q:" << ir.GetNPoints();
std::string hash = ss.str();
// If we've already made the dof-quad maps, reuse them
OccaDofQuadMaps &maps = AllDofQuadMaps[hash];
if (!maps.hash.size())
{
// Create the dof-quad maps
maps.hash = hash;
OccaDofQuadMaps trialMaps = GetD2QTensorMaps(device, trialFE, ir);
OccaDofQuadMaps testMaps = GetD2QTensorMaps(device, testFE , ir, true);
maps.dofToQuad = trialMaps.dofToQuad;
maps.dofToQuadD = trialMaps.dofToQuadD;
maps.quadToDof = testMaps.dofToQuad;
maps.quadToDofD = testMaps.dofToQuadD;
maps.quadWeights = testMaps.quadWeights;
}
return maps;
}
OccaDofQuadMaps OccaDofQuadMaps::GetD2QTensorMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose)
{
const mfem::TensorBasisElement &tfe =
dynamic_cast<const mfem::TensorBasisElement&>(fe);
const mfem::Poly_1D::Basis &basis = tfe.GetBasis1D();
const int order = fe.GetOrder();
// [MISSING] Get 1D dofs
const int dofs = order + 1;
const int dims = fe.GetDim();
// Create the dof -> quadrature point map
const mfem::IntegrationRule &ir1D =
mfem::IntRules.Get(mfem::Geometry::SEGMENT, ir.GetOrder());
const int quadPoints = ir1D.GetNPoints();
const int quadPoints2D = quadPoints*quadPoints;
const int quadPoints3D = quadPoints2D*quadPoints;
const int quadPointsND = ((dims == 1) ? quadPoints :
((dims == 2) ? quadPoints2D : quadPoints3D));
OccaDofQuadMaps maps;
// Initialize the dof -> quad mapping
maps.dofToQuad.allocate(device,
quadPoints, dofs);
maps.dofToQuadD.allocate(device,
quadPoints, dofs);
double *quadWeights1DData = NULL;
if (transpose)
{
maps.dofToQuad.reindex(1,0);
maps.dofToQuadD.reindex(1,0);
// Initialize quad weights only for transpose
maps.quadWeights.allocate(device,
quadPointsND);
quadWeights1DData = new double[quadPoints];
}
mfem::Vector d2q(dofs);
mfem::Vector d2qD(dofs);
for (int q = 0; q < quadPoints; ++q)
{
const mfem::IntegrationPoint &ip = ir1D.IntPoint(q);
basis.Eval(ip.x, d2q, d2qD);
if (transpose)
{
quadWeights1DData[q] = ip.weight;
}
for (int d = 0; d < dofs; ++d)
{
maps.dofToQuad(q, d) = d2q[d];
maps.dofToQuadD(q, d) = d2qD[d];
}
}
maps.dofToQuad.keepInDevice();
maps.dofToQuadD.keepInDevice();
if (transpose)
{
for (int q = 0; q < quadPointsND; ++q)
{
const int qx = q % quadPoints;
const int qz = q / quadPoints2D;
const int qy = (q - qz*quadPoints2D) / quadPoints;
double w = quadWeights1DData[qx];
if (dims > 1)
{
w *= quadWeights1DData[qy];
}
if (dims > 2)
{
w *= quadWeights1DData[qz];
}
maps.quadWeights[q] = w;
}
maps.quadWeights.keepInDevice();
delete [] quadWeights1DData;
}
return maps;
}
OccaDofQuadMaps& OccaDofQuadMaps::GetSimplexMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose)
{
return GetSimplexMaps(device,
fe, fe,
ir, transpose);
}
OccaDofQuadMaps& OccaDofQuadMaps::GetSimplexMaps(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose)
{
std::stringstream ss;
ss << ::occa::hash(device)
<< "Simplex"
<< "O1:" << trialFE.GetOrder()
<< "O2:" << testFE.GetOrder()
<< "Q:" << ir.GetNPoints();
std::string hash = ss.str();
// If we've already made the dof-quad maps, reuse them
OccaDofQuadMaps &maps = AllDofQuadMaps[hash];
if (!maps.hash.size())
{
// Create the dof-quad maps
maps.hash = hash;
OccaDofQuadMaps trialMaps = GetD2QSimplexMaps(device, trialFE, ir);
OccaDofQuadMaps testMaps = GetD2QSimplexMaps(device, testFE , ir, true);
maps.dofToQuad = trialMaps.dofToQuad;
maps.dofToQuadD = trialMaps.dofToQuadD;
maps.quadToDof = testMaps.dofToQuad;
maps.quadToDofD = testMaps.dofToQuadD;
maps.quadWeights = testMaps.quadWeights;
}
return maps;
}
OccaDofQuadMaps OccaDofQuadMaps::GetD2QSimplexMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose)
{
const int dims = fe.GetDim();
const int numDofs = fe.GetDof();
const int numQuad = ir.GetNPoints();
OccaDofQuadMaps maps;
// Initialize the dof -> quad mapping
maps.dofToQuad.allocate(device,
numQuad, numDofs);
maps.dofToQuadD.allocate(device,
dims, numQuad, numDofs);
if (transpose)
{
maps.dofToQuad.reindex(1,0);
maps.dofToQuadD.reindex(1,0);
// Initialize quad weights only for transpose
maps.quadWeights.allocate(device,
numQuad);
}
mfem::Vector d2q(numDofs);
mfem::DenseMatrix d2qD(numDofs, dims);
for (int q = 0; q < numQuad; ++q)
{
const mfem::IntegrationPoint &ip = ir.IntPoint(q);
if (transpose)
{
maps.quadWeights[q] = ip.weight;
}
fe.CalcShape(ip, d2q);
fe.CalcDShape(ip, d2qD);
for (int d = 0; d < numDofs; ++d)
{
const double w = d2q[d];
maps.dofToQuad(q, d) = w;
for (int dim = 0; dim < dims; ++dim)
{
const double wD = d2qD(d, dim);
maps.dofToQuadD(dim, q, d) = wD;
}
}
}
maps.dofToQuad.keepInDevice();
maps.dofToQuadD.keepInDevice();
if (transpose)
{
maps.quadWeights.keepInDevice();
}
return maps;
}
//---[ Integrator Defines ]-----------
std::string stringWithDim(const std::string &s, const int dim)
{
std::string ret = s;
ret += ('0' + (char) dim);
ret += 'D';
return ret;
}
int closestWarpBatchTo(const int value)
{
return ((value + 31) / 32) * 32;
}
int closestMultipleWarpBatch(const int multiple, const int maxSize)
{
if (multiple > maxSize)
{
return maxSize;
}
int batch = (32 / multiple);
int minDiff = 32 - (multiple * batch);
for (int i = 64; i <= maxSize; i += 32)
{
const int newDiff = i - (multiple * (i / multiple));
if (newDiff < minDiff)
{
batch = (i / multiple);
minDiff = newDiff;
}
}
return batch;
}
void SetProperties(FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
SetProperties(fespace, fespace, ir, props);
}
void SetProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
props["defines/TRIAL_VDIM"] = trialFESpace.GetVDim();
props["defines/TEST_VDIM"] = testFESpace.GetVDim();
props["defines/NUM_DIM"] = trialFESpace.GetDim();
if (trialFESpace.hasTensorBasis())
{
SetTensorProperties(trialFESpace, testFESpace, ir, props);
}
else
{
SetSimplexProperties(trialFESpace, testFESpace, ir, props);
}
}
void SetTensorProperties(FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
SetTensorProperties(fespace, fespace, ir, props);
}
void SetTensorProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
const mfem::FiniteElement &trialFE = *(trialFESpace.GetFE(0));
const mfem::FiniteElement &testFE = *(testFESpace.GetFE(0));
const mfem::IntegrationRule &ir1D =
mfem::IntRules.Get(mfem::Geometry::SEGMENT, ir.GetOrder());
const int trialDofs = trialFE.GetDof();
const int testDofs = testFE.GetDof();
const int numQuad = ir.GetNPoints();
const int trialDofs1D = trialFE.GetOrder() + 1;
const int testDofs1D = testFE.GetOrder() + 1;
const int quad1D = ir1D.GetNPoints();
int trialDofsND = trialDofs1D;
int testDofsND = testDofs1D;
int quadND = quad1D;
const bool trialByVDIM = (trialFESpace.GetOrdering() == mfem::Ordering::byVDIM);
const bool testByVDIM = (testFESpace.GetOrdering() == mfem::Ordering::byVDIM);
props["defines/ORDERING_BY_NODES"] = 0;
props["defines/ORDERING_BY_VDIM"] = 1;
props["defines/VDIM_ORDERING"] = (int) trialByVDIM;
props["defines/TRIAL_ORDERING"] = (int) trialByVDIM;
props["defines/TEST_ORDERING"] = (int) testByVDIM;
props["defines/USING_TENSOR_OPS"] = 1;
props["defines/NUM_DOFS"] = trialDofs;
props["defines/NUM_QUAD"] = numQuad;
props["defines/TRIAL_DOFS"] = trialDofs;
props["defines/TEST_DOFS"] = testDofs;
for (int d = 1; d <= 3; ++d)
{
if (d > 1)
{
trialDofsND *= trialDofs1D;
testDofsND *= testDofs1D;
quadND *= quad1D;
}
props["defines"][stringWithDim("NUM_DOFS_", d)] = trialDofsND;
props["defines"][stringWithDim("NUM_QUAD_", d)] = quadND;
props["defines"][stringWithDim("TRIAL_DOFS_", d)] = trialDofsND;
props["defines"][stringWithDim("TEST_DOFS_" , d)] = testDofsND;
}
// 1D Defines
const int m1InnerBatch = 32 * ((quad1D + 31) / 32);
props["defines/A1_ELEMENT_BATCH"] = closestMultipleWarpBatch(quad1D, 512);
props["defines/M1_OUTER_ELEMENT_BATCH"] = closestMultipleWarpBatch(m1InnerBatch,
512);
props["defines/M1_INNER_ELEMENT_BATCH"] = m1InnerBatch;
// 2D Defines
props["defines/A2_ELEMENT_BATCH"] = 1;
props["defines/A2_QUAD_BATCH"] = 1;
props["defines/M2_ELEMENT_BATCH"] = 32;
// 3D Defines
const int a3QuadBatch = closestMultipleWarpBatch(quadND, 512);
props["defines/A3_ELEMENT_BATCH"] = closestMultipleWarpBatch(a3QuadBatch, 512);
props["defines/A3_QUAD_BATCH"] = a3QuadBatch;
}
void SetSimplexProperties(FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
SetSimplexProperties(fespace, fespace, ir, props);
}
void SetSimplexProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
::occa::properties &props)
{
const mfem::FiniteElement &trialFE = *(trialFESpace.GetFE(0));
const mfem::FiniteElement &testFE = *(testFESpace.GetFE(0));
const int trialDofs = trialFE.GetDof();
const int testDofs = testFE.GetDof();
const int numQuad = ir.GetNPoints();
const int maxDQ = std::max(std::max(trialDofs, testDofs), numQuad);
const bool trialByVDIM = (trialFESpace.GetOrdering() == mfem::Ordering::byVDIM);
const bool testByVDIM = (testFESpace.GetOrdering() == mfem::Ordering::byVDIM);
props["defines/ORDERING_BY_NODES"] = 0;
props["defines/ORDERING_BY_VDIM"] = 1;
props["defines/VDIM_ORDERING"] = (int) trialByVDIM;
props["defines/TRIAL_ORDERING"] = (int) trialByVDIM;
props["defines/TEST_ORDERING"] = (int) testByVDIM;
props["defines/USING_TENSOR_OPS"] = 0;
props["defines/NUM_DOFS"] = trialDofs;
props["defines/NUM_QUAD"] = numQuad;
props["defines/TRIAL_DOFS"] = trialDofs;
props["defines/TEST_DOFS"] = testDofs;
// 2D Defines
const int quadBatch = closestWarpBatchTo(numQuad);
props["defines/A2_ELEMENT_BATCH"] = closestMultipleWarpBatch(quadBatch, 2048);
props["defines/A2_QUAD_BATCH"] = quadBatch;
props["defines/M2_INNER_BATCH"] = closestWarpBatchTo(maxDQ);
// 3D Defines
props["defines/A3_ELEMENT_BATCH"] = closestMultipleWarpBatch(quadBatch, 2048);
props["defines/A3_QUAD_BATCH"] = quadBatch;
props["defines/M3_INNER_BATCH"] = closestWarpBatchTo(maxDQ);
}
//---[ Base Integrator ]--------------
OccaIntegrator::OccaIntegrator(const Engine &e)
: engine(&e),
bform(),
mesh(),
otrialFESpace(),
otestFESpace(),
trialFESpace(),
testFESpace(),
itype(DomainIntegrator),
ir(NULL),
hasTensorBasis(false) { }
OccaIntegrator::~OccaIntegrator() {}
void OccaIntegrator::SetupMaps()
{
maps = OccaDofQuadMaps::Get(GetDevice(),
*otrialFESpace,
*otestFESpace,
*ir);
mapsTranspose = OccaDofQuadMaps::Get(GetDevice(),
*otestFESpace,
*otrialFESpace,
*ir);
}
FiniteElementSpace& OccaIntegrator::GetTrialOccaFESpace() const
{
return *otrialFESpace;
}
FiniteElementSpace& OccaIntegrator::GetTestOccaFESpace() const
{
return *otestFESpace;
}
mfem::FiniteElementSpace& OccaIntegrator::GetTrialFESpace() const
{
return *trialFESpace;
}
mfem::FiniteElementSpace& OccaIntegrator::GetTestFESpace() const
{
return *testFESpace;
}
void OccaIntegrator::SetIntegrationRule(const mfem::IntegrationRule &ir_)
{
ir = &ir_;
}
const mfem::IntegrationRule& OccaIntegrator::GetIntegrationRule() const
{
return *ir;
}
OccaDofQuadMaps& OccaIntegrator::GetDofQuadMaps()
{
return maps;
}
void OccaIntegrator::SetupIntegrator(OccaBilinearForm &bform_,
const ::occa::properties &props_,
const OccaIntegratorType itype_)
{
MFEM_ASSERT(engine == &bform_.OccaEngine(), "");
bform = &bform_;
mesh = &(bform_.GetMesh());
otrialFESpace = &(bform_.GetTrialOccaFESpace());
otestFESpace = &(bform_.GetTestOccaFESpace());
trialFESpace = &(bform_.GetTrialFESpace());
testFESpace = &(bform_.GetTestFESpace());
hasTensorBasis = otrialFESpace->hasTensorBasis();
props = props_;
itype = itype_;
if (ir == NULL)
{
SetupIntegrationRule();
}
SetupMaps();
SetProperties(*otrialFESpace,
*otestFESpace,
*ir,
props);
Setup();
}
OccaGeometry OccaIntegrator::GetGeometry(const int flags)
{
return OccaGeometry::Get(GetDevice(), *otrialFESpace, *ir, flags);
}
::occa::kernel OccaIntegrator::GetAssembleKernel(const ::occa::properties
&props)
{
const mfem::FiniteElement &fe = *(trialFESpace->GetFE(0));
return GetKernel(stringWithDim("Assemble", fe.GetDim()),
props);
}
::occa::kernel OccaIntegrator::GetMultAddKernel(const ::occa::properties &props)
{
const mfem::FiniteElement &fe = *(trialFESpace->GetFE(0));
return GetKernel(stringWithDim("MultAdd", fe.GetDim()),
props);
}
::occa::kernel OccaIntegrator::GetKernel(const std::string &kernelName,
const ::occa::properties &props)
{
const std::string filename = GetName() + ".okl";
const std::string &okl_path = OccaEngine().GetOklPath();
const std::string &okl_defines = OccaEngine().GetOklDefines();
return GetDevice().buildKernel(okl_path + filename,
kernelName,
props + okl_defines);
}
//====================================
//---[ Diffusion Integrator ]---------
OccaDiffusionIntegrator::OccaDiffusionIntegrator(const OccaCoefficient &coeff_)
:
OccaIntegrator(coeff_.OccaEngine()),
coeff(coeff_),
assembledOperator(*(new Layout(coeff_.OccaEngine(), 0)))
{
coeff.SetName("COEFF");
}
OccaDiffusionIntegrator::~OccaDiffusionIntegrator() {}
std::string OccaDiffusionIntegrator::GetName()
{
return "DiffusionIntegrator";
}
void OccaDiffusionIntegrator::SetupIntegrationRule()
{
const FiniteElement &trialFE = *(trialFESpace->GetFE(0));
const FiniteElement &testFE = *(testFESpace->GetFE(0));
ir = &mfem::DiffusionIntegrator::GetRule(trialFE, testFE);
}
void OccaDiffusionIntegrator::Setup()
{
::occa::properties kernelProps = props;
coeff.Setup(*this, kernelProps);
// Setup assemble and mult kernels
assembleKernel = GetAssembleKernel(kernelProps);
multKernel = GetMultAddKernel(kernelProps);
}
void OccaDiffusionIntegrator::Assemble()
{
const mfem::FiniteElement &fe = *(trialFESpace->GetFE(0));
const int dims = fe.GetDim();
const int symmDims = (dims * (dims + 1)) / 2; // 1x1: 1, 2x2: 3, 3x3: 6
const int elements = trialFESpace->GetNE();
const int quadraturePoints = ir->GetNPoints();
OccaGeometry geom = GetGeometry(OccaGeometry::Jacobian);
assembledOperator.Resize<double>(symmDims * quadraturePoints * elements,
NULL);
assembleKernel((int) mesh->GetNE(),
maps.quadWeights,
geom.J,
coeff,
assembledOperator.OccaMem());
}
void OccaDiffusionIntegrator::MultAdd(Vector &x, Vector &y)
{
// Note: x and y are E-vectors
multKernel((int) mesh->GetNE(),
maps.dofToQuad,
maps.dofToQuadD,
maps.quadToDof,
maps.quadToDofD,
assembledOperator.OccaMem(),
x.OccaMem(), y.OccaMem());
}
//====================================
//---[ Mass Integrator ]--------------
OccaMassIntegrator::OccaMassIntegrator(const OccaCoefficient &coeff_) :
OccaIntegrator(coeff_.OccaEngine()),
coeff(coeff_),
assembledOperator(*(new Layout(coeff_.OccaEngine(), 0)))
{
coeff.SetName("COEFF");
}
OccaMassIntegrator::~OccaMassIntegrator() {}
std::string OccaMassIntegrator::GetName()
{
return "MassIntegrator";
}
void OccaMassIntegrator::SetupIntegrationRule()
{
const mfem::FiniteElement &trialFE = *(trialFESpace->GetFE(0));
const mfem::FiniteElement &testFE = *(testFESpace->GetFE(0));
mfem::ElementTransformation &T = *trialFESpace->GetElementTransformation(0);
ir = &mfem::MassIntegrator::GetRule(trialFE, testFE, T);
}
void OccaMassIntegrator::Setup()
{
::occa::properties kernelProps = props;
coeff.Setup(*this, kernelProps);
// Setup assemble and mult kernels
assembleKernel = GetAssembleKernel(kernelProps);
multKernel = GetMultAddKernel(kernelProps);
}
void OccaMassIntegrator::Assemble()
{
if (assembledOperator.Size())
{
return;
}
const int elements = trialFESpace->GetNE();
const int quadraturePoints = ir->GetNPoints();
OccaGeometry geom = GetGeometry(OccaGeometry::Jacobian);
assembledOperator.Resize<double>(quadraturePoints * elements, NULL);
assembleKernel((int) mesh->GetNE(),
maps.quadWeights,
geom.J,
coeff,
assembledOperator.OccaMem());
}
void OccaMassIntegrator::SetOperator(Vector &v)
{
assembledOperator = v;
}
void OccaMassIntegrator::MultAdd(Vector &x, Vector &y)
{
multKernel((int) mesh->GetNE(),
maps.dofToQuad,
maps.dofToQuadD,
maps.quadToDof,
maps.quadToDofD,
assembledOperator.OccaMem(),
x.OccaMem(), y.OccaMem());
}
//====================================
//---[ Vector Mass Integrator ]--------------
OccaVectorMassIntegrator::OccaVectorMassIntegrator(const OccaCoefficient &
coeff_)
:
OccaIntegrator(coeff_.OccaEngine()),
coeff(coeff_),
assembledOperator(*(new Layout(coeff_.OccaEngine(), 0)))
{
coeff.SetName("COEFF");
}
OccaVectorMassIntegrator::~OccaVectorMassIntegrator() {}
std::string OccaVectorMassIntegrator::GetName()
{
return "VectorMassIntegrator";
}
void OccaVectorMassIntegrator::SetupIntegrationRule()
{
const mfem::FiniteElement &trialFE = *(trialFESpace->GetFE(0));
const mfem::FiniteElement &testFE = *(testFESpace->GetFE(0));
mfem::ElementTransformation &T = *trialFESpace->GetElementTransformation(0);
ir = &mfem::MassIntegrator::GetRule(trialFE, testFE, T);
}
void OccaVectorMassIntegrator::Setup()
{
::occa::properties kernelProps = props;
coeff.Setup(*this, kernelProps);
// Setup assemble and mult kernels
assembleKernel = GetAssembleKernel(kernelProps);
multKernel = GetMultAddKernel(kernelProps);
}
void OccaVectorMassIntegrator::Assemble()
{
const int elements = trialFESpace->GetNE();
const int quadraturePoints = ir->GetNPoints();
OccaGeometry geom = GetGeometry(OccaGeometry::Jacobian);
assembledOperator.Resize<double>(quadraturePoints * elements, NULL);
assembleKernel((int) mesh->GetNE(),
maps.quadWeights,
geom.J,
coeff,
assembledOperator.OccaMem());
}
void OccaVectorMassIntegrator::MultAdd(Vector &x, Vector &y)
{
multKernel((int) mesh->GetNE(),
maps.dofToQuad,
maps.dofToQuadD,
maps.quadToDof,
maps.quadToDofD,
assembledOperator.OccaMem(),
x.OccaMem(), y.OccaMem());
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-323
View File
@@ -1,323 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_BILIN_INTEG_HPP
#define MFEM_BACKENDS_OCCA_BILIN_INTEG_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "fespace.hpp"
#include "bilinearform.hpp"
#include "coefficient.hpp"
namespace mfem
{
namespace occa
{
class OccaGeometry
{
public:
::occa::array<double> meshNodes;
::occa::array<double> J, invJ, detJ;
// byVDIM -> [x y z x y z x y z]
// byNodes -> [x x x y y y z z z]
static const int Jacobian = (1 << 0);
static const int JacobianInv = (1 << 1);
static const int JacobianDet = (1 << 2);
static OccaGeometry Get(::occa::device device,
FiniteElementSpace &ofespace,
const IntegrationRule &ir,
const int flags = (Jacobian |
JacobianInv |
JacobianDet));
};
class OccaDofQuadMaps
{
private:
// Reuse dof-quad maps
static std::map<std::string, OccaDofQuadMaps> AllDofQuadMaps;
std::string hash;
public:
// Local stiffness matrices (B and B^T operators)
::occa::array<double, ::occa::dynamic> dofToQuad, dofToQuadD; // B
::occa::array<double, ::occa::dynamic> quadToDof, quadToDofD; // B^T
::occa::array<double> quadWeights;
OccaDofQuadMaps();
OccaDofQuadMaps(const OccaDofQuadMaps &maps);
OccaDofQuadMaps& operator = (const OccaDofQuadMaps &maps);
// [[x y] [x y] [x y]]
// [[x y z] [x y z] [x y z]]
// mfem::GridFunction* mfem::Mesh::GetNodes() { return Nodes; }
// mfem::FiniteElementSpace *Nodes->FESpace()
// 25
// 1D [x x x x x x]
// 2D [x y x y x y]
// GetVdim()
// 3D ordering == byVDIM -> [x y z x y z x y z x y z x y z x y z]
// ordering == byNODES -> [x x x x x x y y y y y y z z z z z z]
static OccaDofQuadMaps& Get(::occa::device device,
const FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& Get(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& Get(::occa::device device,
const FiniteElementSpace &trialFESpace,
const FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& Get(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& GetTensorMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& GetTensorMaps(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps GetD2QTensorMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& GetSimplexMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps& GetSimplexMaps(::occa::device device,
const mfem::FiniteElement &trialFE,
const mfem::FiniteElement &testFE,
const mfem::IntegrationRule &ir,
const bool transpose = false);
static OccaDofQuadMaps GetD2QSimplexMaps(::occa::device device,
const mfem::FiniteElement &fe,
const mfem::IntegrationRule &ir,
const bool transpose = false);
};
//---[ Define Methods ]---------------
std::string stringWithDim(const std::string &s, const int dim);
int closestWarpBatch(const int multiple, const int maxSize);
void SetProperties(FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
::occa::properties &props);
void SetProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const mfem::IntegrationRule &ir,
::occa::properties &props);
void SetTensorProperties(FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir,
::occa::properties &props);
void SetTensorProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const IntegrationRule &ir,
::occa::properties &props);
void SetSimplexProperties(FiniteElementSpace &fespace,
const IntegrationRule &ir,
::occa::properties &props);
void SetSimplexProperties(FiniteElementSpace &trialFESpace,
FiniteElementSpace &testFESpace,
const IntegrationRule &ir,
::occa::properties &props);
//---[ Base Integrator ]--------------
class OccaIntegrator
{
protected:
SharedPtr<const Engine> engine;
OccaBilinearForm *bform;
mfem::Mesh *mesh;
FiniteElementSpace *otrialFESpace;
FiniteElementSpace *otestFESpace;
mfem::FiniteElementSpace *trialFESpace;
mfem::FiniteElementSpace *testFESpace;
::occa::properties props;
OccaIntegratorType itype;
const IntegrationRule *ir;
bool hasTensorBasis;
OccaDofQuadMaps maps;
OccaDofQuadMaps mapsTranspose;
public:
OccaIntegrator(const Engine &e);
virtual ~OccaIntegrator();
const Engine &OccaEngine() const { return *engine; }
::occa::device GetDevice(int idx = 0) const
{ return engine->GetDevice(idx); }
virtual std::string GetName() = 0;
FiniteElementSpace& GetTrialOccaFESpace() const;
FiniteElementSpace& GetTestOccaFESpace() const;
mfem::FiniteElementSpace& GetTrialFESpace() const;
mfem::FiniteElementSpace& GetTestFESpace() const;
void SetIntegrationRule(const mfem::IntegrationRule &ir_);
const mfem::IntegrationRule& GetIntegrationRule() const;
OccaDofQuadMaps& GetDofQuadMaps();
void SetupMaps();
virtual void SetupIntegrationRule() = 0;
virtual void SetupIntegrator(OccaBilinearForm &bform_,
const ::occa::properties &props_,
const OccaIntegratorType itype_);
virtual void Setup() = 0;
virtual void Assemble() = 0;
/// This method works on E-vectors!
virtual void MultAdd(Vector &x, Vector &y) = 0;
virtual void MultTransposeAdd(Vector &x, Vector &y)
{
mfem_error("OccaIntegrator::MultTransposeAdd() is not overloaded!");
}
OccaGeometry GetGeometry(const int flags = (OccaGeometry::Jacobian |
OccaGeometry::JacobianInv |
OccaGeometry::JacobianDet));
::occa::kernel GetAssembleKernel(const ::occa::properties &props);
::occa::kernel GetMultAddKernel(const ::occa::properties &props);
::occa::kernel GetKernel(const std::string &kernelName,
const ::occa::properties &props);
};
//====================================
//---[ Diffusion Integrator ]---------
class OccaDiffusionIntegrator : public OccaIntegrator
{
private:
OccaCoefficient coeff;
::occa::kernel assembleKernel, multKernel;
Vector assembledOperator;
public:
OccaDiffusionIntegrator(const OccaCoefficient &coeff_);
virtual ~OccaDiffusionIntegrator();
virtual std::string GetName();
virtual void SetupIntegrationRule();
virtual void Setup();
virtual void Assemble();
virtual void MultAdd(Vector &x, Vector &y);
};
//====================================
//---[ Mass Integrator ]--------------
class OccaMassIntegrator : public OccaIntegrator
{
private:
OccaCoefficient coeff;
::occa::kernel assembleKernel, multKernel;
Vector assembledOperator;
public:
OccaMassIntegrator(const OccaCoefficient &coeff_);
virtual ~OccaMassIntegrator();
virtual std::string GetName();
virtual void SetupIntegrationRule();
virtual void Setup();
virtual void Assemble();
void SetOperator(Vector &v);
virtual void MultAdd(Vector &x, Vector &y);
};
//====================================
//---[ Vector Mass Integrator ]--------------
class OccaVectorMassIntegrator : public OccaIntegrator
{
private:
OccaCoefficient coeff;
::occa::kernel assembleKernel, multKernel;
Vector assembledOperator;
public:
OccaVectorMassIntegrator(const OccaCoefficient &coeff_);
virtual ~OccaVectorMassIntegrator();
virtual std::string GetName();
virtual void SetupIntegrationRule();
virtual void Setup();
virtual void Assemble();
virtual void MultAdd(Vector &x, Vector &y);
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_BILIN_INTEG_HPP
-344
View File
@@ -1,344 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "coefficient.hpp"
#include "bilininteg.hpp"
namespace mfem
{
namespace occa
{
//---[ Parameter ]------------
OccaParameter::~OccaParameter() {}
void OccaParameter::Setup(OccaIntegrator &integ,
::occa::properties &props) {}
::occa::kernelArg OccaParameter::KernelArgs()
{
return ::occa::kernelArg();
}
//====================================
//---[ Include Parameter ]------------
OccaIncludeParameter::OccaIncludeParameter(const std::string &filename_) :
filename(filename_) {}
OccaParameter* OccaIncludeParameter::Clone()
{
return new OccaIncludeParameter(filename);
}
void OccaIncludeParameter::Setup(OccaIntegrator &integ,
::occa::properties &props)
{
props["headers"].asArray() += "#include " + filename;
}
//====================================
//---[ Source Parameter ]------------
OccaSourceParameter::OccaSourceParameter(const std::string &source_) :
source(source_) {}
OccaParameter* OccaSourceParameter::Clone()
{
return new OccaSourceParameter(source);
}
void OccaSourceParameter::Setup(OccaIntegrator &integ,
::occa::properties &props)
{
props["headers"].asArray() += source;
}
//====================================
//---[ Vector Parameter ]-------
OccaVectorParameter::OccaVectorParameter(const std::string &name_,
Vector &v_,
const bool useRestrict_) :
name(name_),
v(v_),
useRestrict(useRestrict_),
attr("") {}
OccaVectorParameter::OccaVectorParameter(const std::string &name_,
Vector &v_,
const std::string &attr_,
const bool useRestrict_) :
name(name_),
v(v_),
useRestrict(useRestrict_),
attr(attr_) {}
OccaParameter* OccaVectorParameter::Clone()
{
return new OccaVectorParameter(name, v, attr, useRestrict);
}
void OccaVectorParameter::Setup(OccaIntegrator &integ,
::occa::properties &props)
{
std::string &args = (props["defines/COEFF_ARGS"]
.asString()
.string());
args += "const double *";
if (useRestrict)
{
args += " restrict ";
}
args += name;
if (attr.size())
{
args += ' ';
args += attr;
}
args += ",\n";
}
::occa::kernelArg OccaVectorParameter::KernelArgs()
{
return ::occa::kernelArg(v.OccaMem());
}
//====================================
//---[ GridFunction Parameter ]-------
OccaGridFunctionParameter::OccaGridFunctionParameter(const std::string &name_,
OccaGridFunction &gf_,
const bool useRestrict_)
: name(name_),
gf(gf_),
gfQuad(*(new Layout(gf_.OccaLayout().OccaEngine(), 0))),
useRestrict(useRestrict_) {}
OccaParameter* OccaGridFunctionParameter::Clone()
{
OccaGridFunctionParameter *param =
new OccaGridFunctionParameter(name, gf, useRestrict);
param->gfQuad.MakeRef(gfQuad);
return param;
}
void OccaGridFunctionParameter::Setup(OccaIntegrator &integ,
::occa::properties &props)
{
std::string &args = (props["defines/COEFF_ARGS"]
.asString()
.string());
args += "const double *";
if (useRestrict)
{
args += " restrict ";
}
args += name;
args += " @dim(NUM_QUAD, numElements),\n";
gf.ToQuad(integ.GetIntegrationRule(), gfQuad);
}
::occa::kernelArg OccaGridFunctionParameter::KernelArgs()
{
return gfQuad.OccaMem();
}
//====================================
//---[ Coefficient ]------------------
OccaCoefficient::OccaCoefficient(const Engine &e, const double value) :
engine(&e),
integ(NULL),
name("COEFF")
{
coeffValue = value;
}
OccaCoefficient::OccaCoefficient(const Engine &e, const std::string &source) :
engine(&e),
integ(NULL),
name("COEFF")
{
coeffValue = source;
}
OccaCoefficient::OccaCoefficient(const Engine &e, const char *source) :
engine(&e),
integ(NULL),
name("COEFF")
{
coeffValue = source;
}
OccaCoefficient::OccaCoefficient(const OccaCoefficient &coeff) :
engine(coeff.engine),
integ(NULL),
name(coeff.name),
coeffValue(coeff.coeffValue)
{
const int paramCount = (int) coeff.params.size();
for (int i = 0; i < paramCount; ++i)
{
params.push_back(coeff.params[i]->Clone());
}
}
OccaCoefficient::~OccaCoefficient()
{
const int paramCount = (int) params.size();
for (int i = 0; i < paramCount; ++i)
{
delete params[i];
}
}
OccaCoefficient& OccaCoefficient::SetName(const std::string &name_)
{
name = name_;
return *this;
}
void OccaCoefficient::Setup(OccaIntegrator &integ_,
::occa::properties &props_)
{
integ = &integ_;
const int paramCount = (int) params.size();
props_["defines"][name + "_ARGS"] = "";
for (int i = 0; i < paramCount; ++i)
{
params[i]->Setup(integ_, props_);
}
props_["defines"][name] = coeffValue;
props = props_;
}
OccaCoefficient& OccaCoefficient::Add(OccaParameter *param)
{
params.push_back(param);
return *this;
}
OccaCoefficient& OccaCoefficient::IncludeHeader(const std::string &filename)
{
return Add(new OccaIncludeParameter(filename));
}
OccaCoefficient& OccaCoefficient::IncludeSource(const std::string &source)
{
return Add(new OccaSourceParameter(source));
}
OccaCoefficient& OccaCoefficient::AddVector(const std::string &name_,
Vector &v,
const bool useRestrict)
{
return Add(new OccaVectorParameter(name_, v, useRestrict));
}
OccaCoefficient& OccaCoefficient::AddVector(const std::string &name_,
Vector &v,
const std::string &attr,
const bool useRestrict)
{
return Add(new OccaVectorParameter(name_, v, attr, useRestrict));
}
OccaCoefficient& OccaCoefficient::AddGridFunction(const std::string &name_,
OccaGridFunction &gf,
const bool useRestrict)
{
return Add(new OccaGridFunctionParameter(name_, gf, useRestrict));
}
bool OccaCoefficient::IsConstant()
{
return coeffValue.isNumber();
}
double OccaCoefficient::GetConstantValue()
{
if (!IsConstant())
{
mfem_error("OccaCoefficient is not constant");
}
return coeffValue.number();
}
Vector OccaCoefficient::Eval()
{
if (integ == NULL)
{
mfem_error("OccaCoefficient requires a Setup() call before Eval()");
}
mfem::FiniteElementSpace &fespace = integ->GetTrialFESpace();
const mfem::IntegrationRule &ir = integ->GetIntegrationRule();
const int elements = fespace.GetNE();
const int numQuad = ir.GetNPoints();
Vector quadCoeff(*(new Layout(OccaEngine(), numQuad * elements)));
Eval(quadCoeff);
return quadCoeff;
}
void OccaCoefficient::Eval(Vector &quadCoeff)
{
const std::string &okl_path = OccaEngine().GetOklPath();
const std::string &okl_defines = OccaEngine().GetOklDefines();
static ::occa::kernelBuilder builder =
::occa::kernelBuilder::fromFile(okl_path + "coefficient.okl",
"CoefficientEval", okl_defines);
if (integ == NULL)
{
mfem_error("OccaCoefficient requires a Setup() call before Eval()");
}
const int elements = integ->GetTrialFESpace().GetNE();
::occa::properties kernelProps = props;
if (name != "COEFF")
{
kernelProps["defines/COEFF"] = name;
kernelProps["defines/COEFF_ARGS"] = name + "_ARGS";
}
kernelProps += okl_defines;
::occa::kernel evalKernel = builder.build(GetDevice(), kernelProps);
evalKernel(elements, *this, quadCoeff.OccaMem());
}
OccaCoefficient::operator ::occa::kernelArg ()
{
::occa::kernelArg kArg;
const int paramCount = (int) params.size();
for (int i = 0; i < paramCount; ++i)
{
kArg.add(params[i]->KernelArgs());
}
return kArg;
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-284
View File
@@ -1,284 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_COEFFICIENT_HPP
#define MFEM_BACKENDS_OCCA_COEFFICIENT_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "vector.hpp"
#include "gridfunc.hpp"
namespace mfem
{
namespace occa
{
class OccaIntegrator;
class OccaParameter
{
public:
virtual ~OccaParameter();
virtual OccaParameter* Clone() = 0;
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props);
virtual ::occa::kernelArg KernelArgs();
};
//---[ Include Parameter ]------------
class OccaIncludeParameter : public OccaParameter
{
private:
std::string filename;
public:
OccaIncludeParameter(const std::string &filename_);
virtual OccaParameter* Clone();
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props);
};
//====================================
//---[ Source Parameter ]------------
class OccaSourceParameter : public OccaParameter
{
private:
std::string source;
public:
OccaSourceParameter(const std::string &filename_);
virtual OccaParameter* Clone();
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props);
};
//====================================
//---[ Define Parameter ]------------
template <class TM>
class OccaDefineParameter : public OccaParameter
{
private:
const std::string name;
TM value;
public:
OccaDefineParameter(const std::string &name_,
const TM &value_) :
name(name_),
value(value_) {}
virtual OccaParameter* Clone()
{
return new OccaDefineParameter(name, value);
}
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props)
{
props["defines"][name] = value;
}
};
//====================================
//---[ Variable Parameter ]-----------
template <class TM>
class OccaVariableParameter : public OccaParameter
{
private:
const std::string name;
const TM &value;
public:
OccaVariableParameter(const std::string &name_,
const TM &value_) :
name(name_),
value(value_) {}
virtual OccaParameter* Clone()
{
return new OccaVariableParameter(name, value);
}
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props)
{
std::string &args = (props["defines/COEFF_ARGS"]
.asString()
.string());
// const TM name,\n"
args += "const ";
args += ::occa::primitiveinfo<TM>::name;
args += ' ';
args += name;
args += ",\n";
}
virtual ::occa::kernelArg KernelArgs()
{
return ::occa::kernelArg(value);
}
};
//====================================
//---[ Vector Parameter ]-------
class OccaVectorParameter : public OccaParameter
{
private:
const std::string name;
Vector v;
bool useRestrict;
std::string attr;
public:
OccaVectorParameter(const std::string &name_,
Vector &v_,
const bool useRestrict_ = false);
OccaVectorParameter(const std::string &name_,
Vector &v_,
const std::string &attr_,
const bool useRestrict_ = false);
virtual OccaParameter* Clone();
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props);
virtual ::occa::kernelArg KernelArgs();
};
//====================================
//---[ GridFunction Parameter ]-------
class OccaGridFunctionParameter : public OccaParameter
{
private:
const std::string name;
OccaGridFunction &gf;
Vector gfQuad;
bool useRestrict;
public:
OccaGridFunctionParameter(const std::string &name_,
OccaGridFunction &gf_,
const bool useRestrict_ = false);
virtual OccaParameter* Clone();
virtual void Setup(OccaIntegrator &integ,
::occa::properties &props);
virtual ::occa::kernelArg KernelArgs();
};
//====================================
//---[ Coefficient ]------------------
// [MISSING]
// Needs to know about the integrator's
// - fespace
// - ir
// Step where parameters that need the ir get called for setup
// For example, GridFunction (d, e) -> (q, e)
class OccaCoefficient
{
private:
SharedPtr<const Engine> engine;
OccaIntegrator *integ;
std::string name;
::occa::json coeffValue;
::occa::properties props;
std::vector<OccaParameter*> params;
public:
OccaCoefficient(const Engine &e, const double value = 1.0);
OccaCoefficient(const Engine &e, const std::string &source);
OccaCoefficient(const Engine &e, const char *source);
~OccaCoefficient();
OccaCoefficient(const OccaCoefficient &coeff);
const Engine &OccaEngine() const { return *engine; }
::occa::device GetDevice(int idx = 0) const
{ return engine->GetDevice(idx); }
OccaCoefficient& SetName(const std::string &name_);
void Setup(OccaIntegrator &integ_,
::occa::properties &props_);
OccaCoefficient& Add(OccaParameter *param);
OccaCoefficient& IncludeHeader(const std::string &filename);
OccaCoefficient& IncludeSource(const std::string &source);
template <class TM>
OccaCoefficient& AddDefine(const std::string &name_, const TM &value)
{
return Add(new OccaDefineParameter<TM>(name_, value));
}
template <class TM>
OccaCoefficient& AddVariable(const std::string &name_, const TM &value)
{
return Add(new OccaVariableParameter<TM>(name_, value));
}
OccaCoefficient& AddVector(const std::string &name_,
Vector &v,
const bool useRestrict = false);
OccaCoefficient& AddVector(const std::string &name_,
Vector &v,
const std::string &attr,
const bool useRestrict = false);
OccaCoefficient& AddGridFunction(const std::string &name_,
OccaGridFunction &gf,
const bool useRestrict = false);
bool IsConstant();
double GetConstantValue();
Vector Eval();
void Eval(Vector &quadCoeff);
operator ::occa::kernelArg ();
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_COEFFICIENT_HPP
-40
View File
@@ -1,40 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_OCCA_DEFINES
#define MFEM_OCCA_DEFINES
#ifndef USING_TENSOR_OPS
# define USING_TENSOR_OPS 0
#endif
#ifdef OCCA_USING_GPU
# define GPU_ORDER_2(I0, I1) @dimOrder(I0, I1)
# define GPU_ORDER_3(I0, I1, I2) @dimOrder(I0, I1, I2)
# define GPU_ORDER_4(I0, I1, I2, I3) @dimOrder(I0, I1, I2, I3)
#else
# define GPU_ORDER_2(I0, I1) @dimOrder(0, 1)
# define GPU_ORDER_3(I0, I1, I2) @dimOrder(0, 1, 2)
# define GPU_ORDER_4(I0, I1, I2, I3) @dimOrder(0, 1, 2, 3)
#endif
#ifndef COEFF
# define COEFF 1.0
# define COEFF_ARGS
#endif
#if USING_TENSOR_OPS
# include "mfem-occa://defines/tensor.okl"
#else
# include "mfem-occa://defines/simplex.okl"
#endif
#endif
-40
View File
@@ -1,40 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#define USING_LOW_ORDER 1
#define USING_HI_ORDER 0
typedef double* DofToQuad_t @dim(NUM_QUAD, NUM_DOFS);
typedef double* DofToQuadD2D_t @dim(2, NUM_QUAD, NUM_DOFS);
typedef double* DofToQuadD3D_t @dim(3, NUM_QUAD, NUM_DOFS);
typedef double* QuadToDof_t @dim(NUM_DOFS, NUM_QUAD);
typedef double* QuadToDofD2D_t @dim(2, NUM_DOFS, NUM_QUAD);
typedef double* QuadToDofD3D_t @dim(3, NUM_DOFS, NUM_QUAD);
typedef double* Jacobian2D_t @dim(2, 2, NUM_QUAD, numElements);
typedef double* Jacobian3D_t @dim(3, 3, NUM_QUAD, numElements);
typedef double* SymmOperator2D_t @dim(3, NUM_QUAD, numElements);
typedef double* SymmOperator3D_t @dim(6, NUM_QUAD, numElements);
typedef double* DLocal_t @dim(NUM_DOFS, numElements);
typedef double* QLocal_t @dim(NUM_QUAD, numElements);
#if VDIM_ORDERING == ORDERING_BY_VDIM
typedef double* DVLocal_t @dim(NUM_VDIM, NUM_DOFS, numElements);
typedef double* QVLocal_t @dim(NUM_VDIM, NUM_QUAD, numElements);
#else
typedef double* DVLocal_t @dim(NUM_VDIM, NUM_DOFS, numElements) @dimOrder(2,0,1);
typedef double* QVLocal_t @dim(NUM_VDIM, NUM_QUAD, numElements) @dimOrder(2,0,1);
#endif
typedef int* DLocalMap_t @dim(NUM_DOFS, numElements);
-85
View File
@@ -1,85 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#if NUM_QUAD_1D < NUM_DOFS_1D
# define NUM_MAX_1D NUM_DOFS_1D
#else
# define NUM_MAX_1D NUM_QUAD_1D
#endif
#define NUM_MAX_2D (NUM_MAX_1D * NUM_MAX_1D)
#define NUM_QUAD_DOFS_1D (NUM_QUAD_1D * NUM_DOFS_1D)
#define QUAD_2D_ID(X, Y) (X + ((Y) * NUM_QUAD_1D))
#define DOFS_2D_ID(X, Y) (X + ((Y) * NUM_DOFS_1D))
#define QUAD_3D_ID(X, Y, Z) (X + ((Y) * NUM_QUAD_1D) + ((Z) * NUM_QUAD_2D))
#define DOFS_3D_ID(X, Y, Z) (X + ((Y) * NUM_DOFS_1D) + ((Z) * NUM_DOFS_2D))
#if NUM_MAX_1D < 8
# define USING_LOW_ORDER 1
# define USING_HI_ORDER 0
#else
# define USING_LOW_ORDER 0
# define USING_HI_ORDER 1
#endif
#define M1_ELEMENT_BATCHES (M1_OUTER_ELEMENT_BATCH * M1_INNER_ELEMENT_BATCH)
typedef double* DofToQuad_t @dim(NUM_QUAD_1D, NUM_DOFS_1D);
typedef double* QuadToDof_t @dim(NUM_DOFS_1D, NUM_QUAD_1D);
typedef double* Jacobian_t @dim(NUM_DIM, NUM_DIM, numElements);
typedef double* Jacobian1D_t @dim(NUM_QUAD_1D, numElements);
typedef double* Jacobian2D_t @dim(2, 2, NUM_QUAD_2D, numElements);
typedef double* Jacobian3D_t @dim(3, 3, NUM_QUAD_3D, numElements);
typedef double* SymmOperator1D_t @dim(NUM_QUAD_1D, numElements);
typedef double* SymmOperator2D_t @dim(3, NUM_QUAD_2D, numElements);
typedef double* SymmOperator3D_t @dim(6, NUM_QUAD_3D, numElements);
typedef double* DLocal_t @dim(NUM_DOFS, numElements);
typedef double* DLocal1D_t @dim(NUM_DOFS_1D, numElements);
typedef double* DLocal2D_t @dim(NUM_DOFS_1D, NUM_DOFS_1D, numElements);
typedef double* DLocal3D_t @dim(NUM_DOFS_1D, NUM_DOFS_1D, NUM_DOFS_1D, numElements);
typedef double* QLocal_t @dim(NUM_QUAD, numElements);
typedef double* QLocal1D_t @dim(NUM_QUAD_1D, numElements);
typedef double* QLocal2D_t @dim(NUM_QUAD_1D, NUM_QUAD_1D, numElements);
typedef double* QLocal3D_t @dim(NUM_QUAD_1D, NUM_QUAD_1D, NUM_QUAD_1D, numElements);
#if VDIM_ORDERING == ORDERING_BY_VDIM
typedef double* DVLocal_t @dim(NUM_VDIM, NUM_DOFS, numElements);
typedef double* DVLocal1D_t @dim(NUM_VDIM, NUM_DOFS_1D, numElements);
typedef double* DVLocal2D_t @dim(NUM_VDIM, NUM_DOFS_1D, NUM_DOFS_1D, numElements);
typedef double* DVLocal3D_t @dim(NUM_VDIM, NUM_DOFS_1D, NUM_DOFS_1D, NUM_DOFS_1D, numElements);
typedef double* QVLocal_t @dim(NUM_VDIM, NUM_QUAD, numElements);
typedef double* QVLocal1D_t @dim(NUM_VDIM, NUM_QUAD_1D, numElements);
typedef double* QVLocal2D_t @dim(NUM_VDIM, NUM_QUAD_1D, NUM_QUAD_1D, numElements);
typedef double* QVLocal3D_t @dim(NUM_VDIM, NUM_QUAD_1D, NUM_QUAD_1D, NUM_QUAD_1D, numElements);
#else
typedef double* DVLocal_t @dim(NUM_VDIM, NUM_DOFS, numElements) @dimOrder(2,0,1);
typedef double* DVLocal1D_t @dim(NUM_VDIM, NUM_DOFS_1D, numElements) @dimOrder(2,0,1);
typedef double* DVLocal2D_t @dim(NUM_VDIM, NUM_DOFS_1D, NUM_DOFS_1D, numElements) @dimOrder(3,0,1,2);
typedef double* DVLocal3D_t @dim(NUM_VDIM, NUM_DOFS_1D, NUM_DOFS_1D, NUM_DOFS_1D, numElements) @dimOrder(4,0,1,2,3);
typedef double* QVLocal_t @dim(NUM_VDIM, NUM_QUAD, numElements) @dimOrder(2,0,1);
typedef double* QVLocal1D_t @dim(NUM_VDIM, NUM_QUAD_1D, numElements) @dimOrder(2,0,1);
typedef double* QVLocal2D_t @dim(NUM_VDIM, NUM_QUAD_1D, NUM_QUAD_1D, numElements) @dimOrder(3,0,1,2);
typedef double* QVLocal3D_t @dim(NUM_VDIM, NUM_QUAD_1D, NUM_QUAD_1D, NUM_QUAD_1D, numElements) @dimOrder(4,0,1,2,3);
#endif
typedef int* DLocalMap_t @dim(NUM_DOFS, numElements);
typedef int* DLocalMap1D_t @dim(NUM_DOFS_1D, numElements);
typedef int* DLocalMap2D_t @dim(NUM_DOFS_1D, NUM_DOFS_1D, numElements);
typedef int* DLocalMap3D_t @dim(NUM_DOFS_1D, NUM_DOFS_1D, NUM_DOFS_1D, numElements);
-168
View File
@@ -1,168 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 2D ]-----------------------------
@kernel void Assemble2D(const int numElements,
const double * restrict quadWeights,
const Jacobian2D_t restrict J,
COEFF_ARGS
SymmOperator2D_t restrict oper) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e);
const double c_detJ = quadWeights[q] * COEFF / ((J11 * J22) - (J21 * J12));
oper(0, q, e) = c_detJ * (J12*J12 + J22*J22); // (1,1)
oper(1, q, e) = -c_detJ * (J12*J11 + J22*J21); // (1,2) + (2,1)
oper(2, q, e) = c_detJ * (J11*J11 + J21*J21); // (2,2)
}
}
}
@kernel void MultAdd2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuadD2D_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDofD2D_t restrict quadToDofD,
const SymmOperator2D_t restrict oper,
const DLocal_t restrict solIn,
DLocal_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double r_sol[NUM_DOFS];
for (int d = 0; d < NUM_DOFS; ++d) {
r_sol[d] = 0;
}
for (int q = 0; q < NUM_QUAD; ++q) {
double gradX = 0, gradY = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double s = solIn(d, e);
gradX += s * quadToDofD(0, d, q);
gradY += s * quadToDofD(1, d, q);
}
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O22 = oper(2, q, e);
const double gradX2 = (O11 * gradX) + (O12 * gradY);
const double gradY2 = (O12 * gradX) + (O22 * gradY);
for (int d = 0; d < NUM_DOFS; ++d) {
r_sol[d] += ((gradX2 * quadToDofD(0, d, q)) +
(gradY2 * quadToDofD(1, d, q)));
}
}
for (int d = 0; d < NUM_DOFS; ++d) {
solOut(d, e) += r_sol[d];
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void Assemble3D(const int numElements,
const double * restrict quadWeights,
const Jacobian3D_t restrict J,
COEFF_ARGS
SymmOperator3D_t restrict oper) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e), J13 = J(2, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e), J23 = J(2, 1, q, e);
const double J31 = J(0, 2, q, e), J32 = J(1, 2, q, e), J33 = J(2, 2, q, e);
const double detJ = ((J11 * J22 * J33) + (J12 * J23 * J31) + (J13 * J21 * J32) -
(J13 * J22 * J31) - (J12 * J21 * J33) - (J11 * J23 * J32));
const double c_detJ = quadWeights[q] * COEFF / detJ;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J23 * J31) - (J21 * J33);
const double A13 = (J21 * J32) - (J22 * J31);
const double A21 = (J13 * J32) - (J12 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J12 * J31) - (J11 * J32);
const double A31 = (J12 * J23) - (J13 * J22);
const double A32 = (J13 * J21) - (J11 * J23);
const double A33 = (J11 * J22) - (J12 * J21);
// adj(J)^Tadj(J)
oper(0, q, e) = c_detJ * (A11*A11 + A21*A21 + A31*A31); // (1,1)
oper(1, q, e) = c_detJ * (A11*A12 + A21*A22 + A31*A32); // (1,2) + (2,1)
oper(2, q, e) = c_detJ * (A11*A13 + A21*A23 + A31*A33); // (1,3) + (3,1)
oper(3, q, e) = c_detJ * (A12*A12 + A22*A22 + A32*A32); // (2,2)
oper(4, q, e) = c_detJ * (A12*A13 + A22*A23 + A32*A33); // (2,3) + (3,2)
oper(5, q, e) = c_detJ * (A13*A13 + A23*A23 + A33*A33); // (3,3)
}
}
}
@kernel void MultAdd3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuadD3D_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDofD3D_t restrict quadToDofD,
const SymmOperator3D_t restrict oper,
const DLocal_t restrict solIn,
DLocal_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double r_sol[NUM_DOFS];
for (int d = 0; d < NUM_DOFS; ++d) {
r_sol[d] = 0;
}
for (int q = 0; q < NUM_QUAD; ++q) {
double gradX = 0, gradY = 0, gradZ = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double s = solIn(d, e);
gradX += s * quadToDofD(0, d, q);
gradY += s * quadToDofD(1, d, q);
gradZ += s * quadToDofD(2, d, q);
}
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O13 = oper(2, q, e);
const double O22 = oper(3, q, e);
const double O23 = oper(4, q, e);
const double O33 = oper(5, q, e);
const double gradX2 = (O11 * gradX) + (O12 * gradY) + (O13 * gradZ);
const double gradY2 = (O12 * gradX) + (O22 * gradY) + (O23 * gradZ);
const double gradZ2 = (O13 * gradX) + (O23 * gradY) + (O33 * gradZ);
for (int d = 0; d < NUM_DOFS; ++d) {
r_sol[d] += ((gradX2 * quadToDofD(0, d, q)) +
(gradY2 * quadToDofD(1, d, q)) +
(gradZ2 * quadToDofD(2, d, q)));
}
}
for (int d = 0; d < NUM_DOFS; ++d) {
solOut(d, e) += r_sol[d];
}
}
}
}
//======================================
@@ -1,182 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 2D ]-----------------------------
@kernel void Assemble2D(const int numElements,
const double *quadWeights,
const Jacobian2D_t J,
COEFF_ARGS
SymmOperator2D_t oper) {
for (int eOff = 0; eOff < numElements; eOff += A2_ELEMENT_BATCH; @outer) {
for (int e = eOff; e < (eOff + A2_ELEMENT_BATCH); ++e; @inner) {
if (e < numElements) {
for (int qOff = 0; qOff < A2_QUAD_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += A2_QUAD_BATCH) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e);
const double c_detJ = quadWeights[q] * COEFF / ((J11 * J22) - (J21 * J12));
oper(0, q, e) = c_detJ * (J12*J12 + J22*J22); // (1,1)
oper(1, q, e) = -c_detJ * (J12*J11 + J22*J21); // (1,2) + (2,1)
oper(2, q, e) = c_detJ * (J11*J11 + J21*J21); // (2,2)
}
}
}
}
}
}
@kernel void MultAdd2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuadD2D_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDofD2D_t restrict quadToDofD,
const SymmOperator2D_t restrict oper,
const DLocal_t restrict solIn,
DLocal_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_gradX[NUM_QUAD];
@shared double s_gradY[NUM_QUAD];
for (int qOff = 0; qOff < M2_INNER_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += M2_INNER_BATCH) {
double gradX = 0, gradY = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double s = solIn(d, e);
gradX += s * quadToDofD(0, d, q);
gradY += s * quadToDofD(1, d, q);
}
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O22 = oper(2, q, e);
s_gradX[q] = (O11 * gradX) + (O12 * gradY);
s_gradY[q] = (O12 * gradX) + (O22 * gradY);
}
}
for (int dOff = 0; dOff < M2_INNER_BATCH; ++dOff) {
for (int d = dOff; d < NUM_DOFS; d += M2_INNER_BATCH) {
double r_sol = 0;
for (int q = 0; q < NUM_QUAD; ++q) {
// FIXME: s_gradX and s_gradY are @shared used outside of @inner
r_sol += ((s_gradX[q] * quadToDofD(0, d, q)) +
(s_gradY[q] * quadToDofD(1, d, q)));
}
solOut(d, e) += r_sol;
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void Assemble3D(const int numElements,
const double *quadWeights,
const Jacobian3D_t J,
COEFF_ARGS
SymmOperator3D_t oper) {
for (int eOff = 0; eOff < numElements; eOff += A3_ELEMENT_BATCH; @outer) {
for (int e = eOff; e < (eOff + A3_ELEMENT_BATCH); ++e; @inner) {
if (e < numElements) {
for (int qOff = 0; qOff < A3_QUAD_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += A3_QUAD_BATCH) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e), J13 = J(2, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e), J23 = J(2, 1, q, e);
const double J31 = J(0, 2, q, e), J32 = J(1, 2, q, e), J33 = J(2, 2, q, e);
const double detJ = ((J11 * J22 * J33) + (J12 * J23 * J31) + (J13 * J21 * J32) -
(J13 * J22 * J31) - (J12 * J21 * J33) - (J11 * J23 * J32));
const double c_detJ = quadWeights[q] * COEFF / detJ;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J23 * J31) - (J21 * J33);
const double A13 = (J21 * J32) - (J22 * J31);
const double A21 = (J13 * J32) - (J12 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J12 * J31) - (J11 * J32);
const double A31 = (J12 * J23) - (J13 * J22);
const double A32 = (J13 * J21) - (J11 * J23);
const double A33 = (J11 * J22) - (J12 * J21);
// adj(J)^Tadj(J)
oper(0, q, e) = c_detJ * (A11*A11 + A21*A21 + A31*A31); // (1,1)
oper(1, q, e) = c_detJ * (A11*A12 + A21*A22 + A31*A32); // (1,2) + (2,1)
oper(2, q, e) = c_detJ * (A11*A13 + A21*A23 + A31*A33); // (1,3) + (3,1)
oper(3, q, e) = c_detJ * (A12*A12 + A22*A22 + A32*A32); // (2,2)
oper(4, q, e) = c_detJ * (A12*A13 + A22*A23 + A32*A33); // (2,3) + (3,2)
oper(5, q, e) = c_detJ * (A13*A13 + A23*A23 + A33*A33); // (3,3)
}
}
}
}
}
}
@kernel void MultAdd3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuadD3D_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDofD3D_t restrict quadToDofD,
const SymmOperator3D_t restrict oper,
const DLocal_t restrict solIn,
DLocal_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_gradX[NUM_QUAD];
@shared double s_gradY[NUM_QUAD];
@shared double s_gradZ[NUM_QUAD];
for (int qOff = 0; qOff < M3_INNER_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += M3_INNER_BATCH) {
double gradX = 0, gradY = 0, gradZ = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double s = solIn(d, e);
gradX += s * quadToDofD(0, d, q);
gradY += s * quadToDofD(1, d, q);
gradZ += s * quadToDofD(2, d, q);
}
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O13 = oper(2, q, e);
const double O22 = oper(3, q, e);
const double O23 = oper(4, q, e);
const double O33 = oper(5, q, e);
s_gradX[q] = (O11 * gradX) + (O12 * gradY) + (O13 * gradZ);
s_gradY[q] = (O12 * gradX) + (O22 * gradY) + (O23 * gradZ);
s_gradZ[q] = (O13 * gradX) + (O23 * gradY) + (O33 * gradZ);
}
}
for (int dOff = 0; dOff < M3_INNER_BATCH; ++dOff) {
for (int d = dOff; d < NUM_DOFS; d += M3_INNER_BATCH) {
double r_sol = 0;
for (int q = 0; q < NUM_QUAD; ++q) {
r_sol += ((s_gradX[q] * quadToDofD(0, d, q)) +
(s_gradY[q] * quadToDofD(1, d, q)) +
(s_gradZ[q] * quadToDofD(2, d, q)));
}
solOut(d, e) += r_sol;
}
}
}
}
//======================================
-370
View File
@@ -1,370 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 1D ]-----------------------------
@kernel void Assemble1D(const int numElements,
const double * restrict quadWeights,
const Jacobian1D_t restrict J,
COEFF_ARGS
SymmOperator1D_t restrict oper) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int q = 0; q < NUM_QUAD_1D; ++q; @inner) {
oper(q, e) = quadWeights[q] * COEFF / J(q, e);
}
}
}
@kernel void MultAdd1D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator1D_t restrict oper,
const DLocal1D_t restrict solIn,
DLocal1D_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double grad[NUM_QUAD_1D];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] = 0;
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double s = solIn(dx, e);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] += s * dofToQuadD(qx, dx);
}
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] *= oper(qx, e);
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const double gradX = grad[qx];
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
solOut(dx, e) += gradX * quadToDofD(dx, qx);
}
}
}
}
}
//======================================
//---[ 2D ]-----------------------------
@kernel void Assemble2D(const int numElements,
const double * restrict quadWeights,
const Jacobian2D_t restrict J,
COEFF_ARGS
SymmOperator2D_t restrict oper) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int q = 0; q < NUM_QUAD_2D; ++q; @inner) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e);
const double c_detJ = quadWeights[q] * COEFF / ((J11 * J22) - (J21 * J12));
oper(0, q, e) = c_detJ * (J21*J21 + J22*J22); // (1,1)
oper(1, q, e) = -c_detJ * (J21*J11 + J22*J12); // (1,2), (2,1)
oper(2, q, e) = c_detJ * (J11*J11 + J12*J12); // (2,2)
}
}
}
@kernel void MultAdd2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator2D_t restrict oper,
const DLocal2D_t restrict solIn,
DLocal2D_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double grad[NUM_QUAD_1D][NUM_QUAD_1D][2];
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qy][qx][0] = 0;
grad[qy][qx][1] = 0;
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double gradX[NUM_QUAD_1D][2];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
gradX[qx][0] = 0;
gradX[qx][1] = 0;
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double s = solIn(dx, dy, e);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
gradX[qx][0] += s * dofToQuad(qx, dx);
gradX[qx][1] += s * dofToQuadD(qx, dx);
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
const double wy = dofToQuad(qy, dy);
const double wDy = dofToQuadD(qy, dy);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qy][qx][0] += gradX[qx][1] * wy;
grad[qy][qx][1] += gradX[qx][0] * wDy;
}
}
}
// Calculate Dxy, xDy in plane
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const int q = QUAD_2D_ID(qx, qy);
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O22 = oper(2, q, e);
const double gradX = grad[qy][qx][0];
const double gradY = grad[qy][qx][1];
grad[qy][qx][0] = (O11 * gradX) + (O12 * gradY);
grad[qy][qx][1] = (O12 * gradX) + (O22 * gradY);
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
double gradX[NUM_DOFS_1D][2];
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
gradX[dx][0] = 0;
gradX[dx][1] = 0;
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const double gX = grad[qy][qx][0];
const double gY = grad[qy][qx][1];
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double wx = quadToDof(dx, qx);
const double wDx = quadToDofD(dx, qx);
gradX[dx][0] += gX * wDx;
gradX[dx][1] += gY * wx;
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
const double wy = quadToDof(dy, qy);
const double wDy = quadToDofD(dy, qy);
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
solOut(dx, dy, e) += ((gradX[dx][0] * wy) +
(gradX[dx][1] * wDy));
}
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void Assemble3D(const int numElements,
const double * restrict quadWeights,
const Jacobian3D_t restrict J,
COEFF_ARGS
SymmOperator3D_t restrict oper) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int q = 0; q < NUM_QUAD_3D; ++q; @inner) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e), J13 = J(2, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e), J23 = J(2, 1, q, e);
const double J31 = J(0, 2, q, e), J32 = J(1, 2, q, e), J33 = J(2, 2, q, e);
const double detJ = ((J11 * J22 * J33) + (J12 * J23 * J31) + (J13 * J21 * J32) -
(J13 * J22 * J31) - (J12 * J21 * J33) - (J11 * J23 * J32));
const double c_detJ = quadWeights[q] * COEFF / detJ;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J23 * J31) - (J21 * J33);
const double A13 = (J21 * J32) - (J22 * J31);
const double A21 = (J13 * J32) - (J12 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J12 * J31) - (J11 * J32);
const double A31 = (J12 * J23) - (J13 * J22);
const double A32 = (J13 * J21) - (J11 * J23);
const double A33 = (J11 * J22) - (J12 * J21);
// adj(J)^Tadj(J)
oper(0, q, e) = c_detJ * (A11*A11 + A21*A21 + A31*A31); // (1,1)
oper(1, q, e) = c_detJ * (A11*A12 + A21*A22 + A31*A32); // (1,2), (2,1)
oper(2, q, e) = c_detJ * (A11*A13 + A21*A23 + A31*A33); // (1,3), (3,1)
oper(3, q, e) = c_detJ * (A12*A12 + A22*A22 + A32*A32); // (2,2)
oper(4, q, e) = c_detJ * (A12*A13 + A22*A23 + A32*A33); // (2,3), (3,2)
oper(5, q, e) = c_detJ * (A13*A13 + A23*A23 + A33*A33); // (3,3)
}
}
}
@kernel void MultAdd3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator3D_t restrict oper,
const DLocal3D_t restrict solIn,
DLocal3D_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double grad[NUM_QUAD_1D][NUM_QUAD_1D][NUM_QUAD_1D][4];
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qz][qy][qx][0] = 0;
grad[qz][qy][qx][1] = 0;
grad[qz][qy][qx][2] = 0;
}
}
}
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
double gradXY[NUM_QUAD_1D][NUM_QUAD_1D][4];
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
gradXY[qy][qx][0] = 0;
gradXY[qy][qx][1] = 0;
gradXY[qy][qx][2] = 0;
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double gradX[NUM_QUAD_1D][2];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
gradX[qx][0] = 0;
gradX[qx][1] = 0;
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double s = solIn(dx, dy, dz, e);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
gradX[qx][0] += s * dofToQuad(qx, dx);
gradX[qx][1] += s * dofToQuadD(qx, dx);
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
const double wy = dofToQuad(qy, dy);
const double wDy = dofToQuadD(qy, dy);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const double wx = gradX[qx][0];
const double wDx = gradX[qx][1];
gradXY[qy][qx][0] += wDx * wy;
gradXY[qy][qx][1] += wx * wDy;
gradXY[qy][qx][2] += wx * wy;
}
}
}
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
const double wz = dofToQuad(qz, dz);
const double wDz = dofToQuadD(qz, dz);
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qz][qy][qx][0] += gradXY[qy][qx][0] * wz;
grad[qz][qy][qx][1] += gradXY[qy][qx][1] * wz;
grad[qz][qy][qx][2] += gradXY[qy][qx][2] * wDz;
}
}
}
}
// Calculate Dxyz, xDyz, xyDz in plane
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const int q = QUAD_3D_ID(qx, qy, qz);
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O13 = oper(2, q, e);
const double O22 = oper(3, q, e);
const double O23 = oper(4, q, e);
const double O33 = oper(5, q, e);
const double gradX = grad[qz][qy][qx][0];
const double gradY = grad[qz][qy][qx][1];
const double gradZ = grad[qz][qy][qx][2];
grad[qz][qy][qx][0] = (O11 * gradX) + (O12 * gradY) + (O13 * gradZ);
grad[qz][qy][qx][1] = (O12 * gradX) + (O22 * gradY) + (O23 * gradZ);
grad[qz][qy][qx][2] = (O13 * gradX) + (O23 * gradY) + (O33 * gradZ);
}
}
}
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
double gradXY[NUM_DOFS_1D][NUM_DOFS_1D][4];
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
gradXY[dy][dx][0] = 0;
gradXY[dy][dx][1] = 0;
gradXY[dy][dx][2] = 0;
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
double gradX[NUM_DOFS_1D][4];
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
gradX[dx][0] = 0;
gradX[dx][1] = 0;
gradX[dx][2] = 0;
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const double gX = grad[qz][qy][qx][0];
const double gY = grad[qz][qy][qx][1];
const double gZ = grad[qz][qy][qx][2];
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double wx = quadToDof(dx, qx);
const double wDx = quadToDofD(dx, qx);
gradX[dx][0] += gX * wDx;
gradX[dx][1] += gY * wx;
gradX[dx][2] += gZ * wx;
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
const double wy = quadToDof(dy, qy);
const double wDy = quadToDofD(dy, qy);
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
gradXY[dy][dx][0] += gradX[dx][0] * wy;
gradXY[dy][dx][1] += gradX[dx][1] * wDy;
gradXY[dy][dx][2] += gradX[dx][2] * wy;
}
}
}
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
const double wz = quadToDof(dz, qz);
const double wDz = quadToDofD(dz, qz);
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
solOut(dx, dy, dz, e) += ((gradXY[dy][dx][0] * wz) +
(gradXY[dy][dx][1] * wz) +
(gradXY[dy][dx][2] * wDz));
}
}
}
}
}
}
}
//======================================
@@ -1,433 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 1D ]-----------------------------
@kernel void Assemble1D(const int numElements,
const double *quadWeights,
const Jacobian1D_t J,
COEFF_ARGS
SymmOperator1D_t oper) {
for (int eOff = 0; eOff < numElements; eOff += A1_ELEMENT_BATCH; @outer) {
for (int e = eOff; e < (eOff + A1_ELEMENT_BATCH); ++e; @inner) {
if (e < numElements) {
for (int q = 0; q < NUM_QUAD_1D; ++q; @inner) {
oper(q, e) = quadWeights[q] * COEFF / J(q, e);
}
}
}
}
}
@kernel void MultAdd1D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator1D_t restrict oper,
const DLocal1D_t restrict solIn,
DLocal1D_t restrict solOut) {
// Iterate over elements
for (int eOff = 0; eOff < numElements; eOff += M1_ELEMENT_BATCHES; @outer) {
@shared double s_dofToQuadD[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@shared double s_quadToDofD[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
@exclusive double grad[NUM_QUAD_1D];
for (int el = 0; el < M1_INNER_ELEMENT_BATCH; ++el; @inner) {
for (int i = el; i < NUM_QUAD_DOFS_1D; i += M1_INNER_ELEMENT_BATCH) {
s_dofToQuadD[i] = dofToQuadD[i];
s_quadToDofD[i] = quadToDofD[i];
}
}
for (int b = 0; b < M1_OUTER_ELEMENT_BATCH; ++b) {
for (int el = 0; el < M1_INNER_ELEMENT_BATCH; ++el; @inner) {
const int e = eOff + b*M1_INNER_ELEMENT_BATCH + el;
if (e < numElements) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] = 0;
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double s = solIn(dx, e);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] += s * s_dofToQuadD(qx, dx);
}
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
grad[qx] *= oper(qx, e);
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
double s = 0;
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
s += grad[qx] * s_quadToDofD(dx, qx);
}
solOut(dx, e) += s;
}
}
}
}
}
}
//======================================
//---[ 2D ]-----------------------------
@kernel void Assemble2D(const int numElements,
const double *quadWeights,
const Jacobian2D_t J,
COEFF_ARGS
SymmOperator2D_t oper) {
for (int eOff = 0; eOff < numElements; eOff += A2_ELEMENT_BATCH; @outer) {
for (int e = eOff; e < (eOff + A2_ELEMENT_BATCH); ++e; @inner) {
if (e < numElements) {
for (int qOff = 0; qOff < A2_QUAD_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD_2D; q += A2_QUAD_BATCH) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e);
const double c_detJ = quadWeights[q] * COEFF / ((J11 * J22) - (J21 * J12));
oper(0, q, e) = c_detJ * (J21*J21 + J22*J22); // (1,1)
oper(1, q, e) = -c_detJ * (J21*J11 + J22*J12); // (1,2), (2,1)
oper(2, q, e) = c_detJ * (J11*J11 + J12*J12); // (2,2)
}
}
}
}
}
}
@kernel void MultAdd2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator2D_t restrict oper,
const DLocal2D_t restrict solIn,
DLocal2D_t restrict solOut) {
// Iterate over elements
for (int eOff = 0; eOff < numElements; eOff += M2_ELEMENT_BATCH; @outer) {
// Store dof <--> quad mappings
@shared double s_dofToQuad[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@shared double s_dofToQuadD[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@shared double s_quadToDof[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
@shared double s_quadToDofD[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
// Store xy planes in shared memory
@shared double s_xy[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
@shared double s_xDy[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
@shared double s_grad[2 * NUM_QUAD_2D] @dim(2, NUM_QUAD_1D, NUM_QUAD_1D);
@exclusive double r_x[NUM_MAX_1D];
@exclusive double r_y[NUM_QUAD_1D];
for (int x = 0; x < NUM_MAX_1D; ++x; @inner) {
for (int id = x; id < NUM_QUAD_DOFS_1D; id += NUM_MAX_1D) {
s_dofToQuad[id] = dofToQuad[id];
s_dofToQuadD[id] = dofToQuadD[id];
s_quadToDof[id] = quadToDof[id];
s_quadToDofD[id] = quadToDofD[id];
}
}
for (int e = eOff; e < (eOff + M2_ELEMENT_BATCH); ++e) {
if (e < numElements) {
for (int dx = 0; dx < NUM_DOFS_1D; ++dx; @inner) {
if (dx < NUM_DOFS_1D) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
s_xy(dx, qy) = 0;
s_xDy(dx, qy) = 0;
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
r_x[dy] = solIn(dx, dy, e);
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
double xy = 0;
double xDy = 0;
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
xy += r_x[dy] * s_dofToQuad(qy, dy);
xDy += r_x[dy] * s_dofToQuadD(qy, dy);
}
s_xy(dx, qy) = xy;
s_xDy(dx, qy) = xDy;
}
}
}
for (int qy = 0; qy < NUM_MAX_1D; ++qy; @inner) {
if (qy < NUM_QUAD_1D) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
double gradX = 0, gradY = 0;
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
gradX += s_xy(dx, qy) * s_dofToQuadD(qx, dx);
gradY += s_xDy(dx, qy) * s_dofToQuad(qx, dx);
}
const int q = QUAD_2D_ID(qx, qy);
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O22 = oper(2, q, e);
s_grad(0, qx, qy) = (O11 * gradX) + (O12 * gradY);
s_grad(1, qx, qy) = (O12 * gradX) + (O22 * gradY);
}
}
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx; @inner) {
if (qx < NUM_QUAD_1D) {
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
s_xy(dy, qx) = 0;
s_xDy(dy, qx) = 0;
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
r_x[qy] = s_grad(0, qx, qy);
r_y[qy] = s_grad(1, qx, qy);
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double xy = 0;
double xDy = 0;
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
xy += r_x[qy] * s_quadToDof(dy, qy);
xDy += r_y[qy] * s_quadToDofD(dy, qy);
}
s_xy(dy, qx) = xy;
s_xDy(dy, qx) = xDy;
}
}
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx; @inner) {
if (dx < NUM_DOFS_1D) {
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double s = 0;
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
s += ((s_xy(dy, qx) * s_quadToDofD(dx, qx)) +
(s_xDy(dy, qx) * s_quadToDof(dx, qx)));
}
solOut(dx, dy, e) += s;
}
}
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void Assemble3D(const int numElements,
const double *quadWeights,
const Jacobian3D_t J,
COEFF_ARGS
SymmOperator3D_t oper) {
for (int eOff = 0; eOff < numElements; eOff += A3_ELEMENT_BATCH; @outer) {
for (int e = eOff; e < (eOff + A3_ELEMENT_BATCH); ++e; @inner) {
if (e < numElements) {
for (int qOff = 0; qOff < A3_QUAD_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD_3D; q += A3_QUAD_BATCH) {
const double J11 = J(0, 0, q, e), J12 = J(1, 0, q, e), J13 = J(2, 0, q, e);
const double J21 = J(0, 1, q, e), J22 = J(1, 1, q, e), J23 = J(2, 1, q, e);
const double J31 = J(0, 2, q, e), J32 = J(1, 2, q, e), J33 = J(2, 2, q, e);
const double detJ = ((J11 * J22 * J33) + (J12 * J23 * J31) + (J13 * J21 * J32) -
(J13 * J22 * J31) - (J12 * J21 * J33) - (J11 * J23 * J32));
const double c_detJ = quadWeights[q] * COEFF / detJ;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J23 * J31) - (J21 * J33);
const double A13 = (J21 * J32) - (J22 * J31);
const double A21 = (J13 * J32) - (J12 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J12 * J31) - (J11 * J32);
const double A31 = (J12 * J23) - (J13 * J22);
const double A32 = (J13 * J21) - (J11 * J23);
const double A33 = (J11 * J22) - (J12 * J21);
// adj(J)^Tadj(J)
oper(0, q, e) = c_detJ * (A11*A11 + A21*A21 + A31*A31); // (1,1)
oper(1, q, e) = c_detJ * (A11*A12 + A21*A22 + A31*A32); // (1,2), (2,1)
oper(2, q, e) = c_detJ * (A11*A13 + A21*A23 + A31*A33); // (1,3), (3,1)
oper(3, q, e) = c_detJ * (A12*A12 + A22*A22 + A32*A32); // (2,2)
oper(4, q, e) = c_detJ * (A12*A13 + A22*A23 + A32*A33); // (2,3), (3,2)
oper(5, q, e) = c_detJ * (A13*A13 + A23*A23 + A33*A33); // (3,3)
}
}
}
}
}
}
@kernel void MultAdd3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DofToQuad_t restrict dofToQuadD,
const QuadToDof_t restrict quadToDof,
const QuadToDof_t restrict quadToDofD,
const SymmOperator3D_t restrict oper,
const DLocal3D_t restrict solIn,
DLocal3D_t restrict solOut) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
// Store dof <--> quad mappings
@shared double s_dofToQuad[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@shared double s_dofToQuadD[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@shared double s_quadToDof[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
@shared double s_quadToDofD[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
// Store xy planes in shared memory
@shared double s_z[NUM_MAX_2D] @dim(NUM_MAX_1D, NUM_MAX_1D);
@shared double s_Dz[NUM_MAX_2D] @dim(NUM_MAX_1D, NUM_MAX_1D);
@shared double s_xyDz[NUM_QUAD_2D] @dim(NUM_QUAD_1D, NUM_QUAD_1D);
// Store z axis as registers
@exclusive double r_qz[NUM_QUAD_1D];
@exclusive double r_qDz[NUM_QUAD_1D];
@exclusive double r_dDxyz[NUM_DOFS_1D];
@exclusive double r_dxDyz[NUM_DOFS_1D];
@exclusive double r_dxyDz[NUM_DOFS_1D];
for (int y = 0; y < NUM_MAX_1D; ++y; @inner) {
for (int x = 0; x < NUM_MAX_1D; ++x; @inner) {
const int id = (y * NUM_MAX_1D) + x;
// Fetch Q <--> D maps
if (id < NUM_QUAD_DOFS_1D) {
s_dofToQuad[id] = dofToQuad[id];
s_dofToQuadD[id] = dofToQuadD[id];
s_quadToDof[id] = quadToDof[id];
s_quadToDofD[id] = quadToDofD[id];
}
// Initialize our Z axis
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
r_qz[qz] = 0;
r_qDz[qz] = 0;
}
// Initialize our solution updates in the Z axis
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
r_dDxyz[dz] = 0;
r_dxDyz[dz] = 0;
r_dxyDz[dz] = 0;
}
}
}
for (int dy = 0; dy < NUM_MAX_1D; ++dy; @inner) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if ((dx < NUM_DOFS_1D) && (dy < NUM_DOFS_1D)) {
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
const double s = solIn(dx, dy, dz, e);
// Calculate D -> Q in the Z axis
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
r_qz[qz] += s * s_dofToQuad(qz, dz);
r_qDz[qz] += s * s_dofToQuadD(qz, dz);
}
}
}
}
}
// For each xy plane
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
// Fill xy plane at given z position
for (int dy = 0; dy < NUM_MAX_1D; ++dy; @inner) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if ((dx < NUM_DOFS_1D) && (dy < NUM_DOFS_1D)) {
s_z(dx, dy) = r_qz[qz];
s_Dz(dx, dy) = r_qDz[qz];
}
}
}
// Calculate Dxyz, xDyz, xyDz in plane
for (int qy = 0; qy < NUM_MAX_1D; ++qy; @inner) {
for (int qx = 0; qx < NUM_MAX_1D; ++qx; @inner) {
if ((qx < NUM_QUAD_1D) && (qy < NUM_QUAD_1D)) {
double Dxyz = 0;
double xDyz = 0;
double xyDz = 0;
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
const double wy = s_dofToQuad(qy, dy);
const double wDy = s_dofToQuadD(qy, dy);
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double wx = s_dofToQuad(qx, dx);
const double wDx = s_dofToQuadD(qx, dx);
const double z = s_z(dx, dy);
const double Dz = s_Dz(dx, dy);
Dxyz += wDx * wy * z;
xDyz += wx * wDy * z;
xyDz += wx * wy * Dz;
}
}
const int q = QUAD_3D_ID(qx, qy, qz);
const double O11 = oper(0, q, e);
const double O12 = oper(1, q, e);
const double O13 = oper(2, q, e);
const double O22 = oper(3, q, e);
const double O23 = oper(4, q, e);
const double O33 = oper(5, q, e);
const double qDxyz = (O11 * Dxyz) + (O12 * xDyz) + (O13 * xyDz);
const double qxDyz = (O12 * Dxyz) + (O22 * xDyz) + (O23 * xyDz);
const double qxyDz = (O13 * Dxyz) + (O23 * xDyz) + (O33 * xyDz);
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
const double wz = s_quadToDof(dz, qz);
const double wDz = s_quadToDofD(dz, qz);
r_dDxyz[dz] += wz * qDxyz;
r_dxDyz[dz] += wz * qxDyz;
r_dxyDz[dz] += wDz * qxyDz;
}
}
}
}
}
// Iterate over xy planes to compute solution
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
// Place xy plane in shared memory
for (int qy = 0; qy < NUM_MAX_1D; ++qy; @inner) {
for (int qx = 0; qx < NUM_MAX_1D; ++qx; @inner) {
if ((qx < NUM_QUAD_1D) && (qy < NUM_QUAD_1D)) {
s_z(qx, qy) = r_dDxyz[dz];
s_Dz(qx, qy) = r_dxDyz[dz];
s_xyDz(qx, qy) = r_dxyDz[dz];
}
}
}
// Finalize solution in xy plane
for (int dy = 0; dy < NUM_MAX_1D; ++dy; @inner) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if ((dx < NUM_DOFS_1D) && (dy < NUM_DOFS_1D)) {
double solZ = 0;
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
const double wy = s_quadToDof(dy, qy);
const double wDy = s_quadToDofD(dy, qy);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
const double wx = s_quadToDof(dx, qx);
const double wDx = s_quadToDofD(dx, qx);
const double Dxyz = s_z(qx, qy);
const double xDyz = s_Dz(qx, qy);
const double xyDz = s_xyDz(qx, qy);
solZ += ((wDx * wy * Dxyz) +
(wx * wDy * xDyz) +
(wx * wy * xyDz));
}
}
solOut(dx, dy, dz, e) += solZ;
}
}
}
}
}
}
//======================================
-140
View File
@@ -1,140 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "backend.hpp"
#include "url_handler.hpp"
#include "bilinearform.hpp"
#include "../../general/array.hpp"
namespace mfem
{
namespace occa
{
bool Engine::fileOpenerRegistered = false;
void Engine::Init(const std::string &engine_spec)
{
//
// Initialize inherited fields
//
memory_resources[0] = NULL;
workers_weights[0]= 1.0;
workers_mem_res[0] = 0;
//
// Initialize the OCCA engine
//
::occa::properties props(engine_spec);
device = new ::occa::device[1];
device[0].setup(props);
okl_path = "mfem-occa://";
// okl_defines = "...";
if (!fileOpenerRegistered)
{
// The directories from "MFEM_OCCA_OKL_PATH", if any, have the highest
// priority.
FileOpener *fo = new FileOpener("mfem-occa://", "MFEM_OCCA_OKL_PATH");
// Next in priority is the source path, if it exists.
std::string mfem_src_prefix = mfem::GetSourcePath();
fo->AddDir(mfem_src_prefix + "/backends/occa");
// And last in priority is the install path, if it exists.
std::string mfem_install_prefix = mfem::GetInstallPath();
fo->AddDir(mfem_install_prefix + "/lib/mfem/occa");
::occa::io::fileOpener::add(fo);
fileOpenerRegistered = true;
}
}
Engine::Engine(const std::string &engine_spec)
: mfem::Engine(NULL, 1, 1)
{
Init(engine_spec);
}
#ifdef MFEM_USE_MPI
Engine::Engine(MPI_Comm _comm, const std::string &engine_spec)
: mfem::Engine(NULL, 1, 1)
{
comm = _comm;
Init(engine_spec);
}
#endif
DLayout Engine::MakeLayout(std::size_t size) const
{
return DLayout(new Layout(*this, size));
}
DLayout Engine::MakeLayout(const mfem::Array<std::size_t> &offsets) const
{
MFEM_ASSERT(offsets.Size() == 2,
"multiple workers are not supported yet");
return DLayout(new Layout(*this, offsets.Last()));
}
DArray Engine::MakeArray(PLayout &layout, std::size_t item_size) const
{
MFEM_ASSERT(dynamic_cast<Layout *>(&layout) != NULL,
"invalid input layout");
Layout *lt = static_cast<Layout *>(&layout);
return DArray(new Array(*lt, item_size));
}
DVector Engine::MakeVector(PLayout &layout, int type_id) const
{
MFEM_ASSERT(type_id == ScalarId<double>::value, "invalid type_id");
MFEM_ASSERT(dynamic_cast<Layout *>(&layout) != NULL,
"invalid input layout");
Layout *lt = static_cast<Layout *>(&layout);
return DVector(new Vector(*lt));
}
DFiniteElementSpace Engine::MakeFESpace(mfem::FiniteElementSpace &fespace) const
{
return DFiniteElementSpace(new FiniteElementSpace(*this, fespace));
}
DBilinearForm Engine::MakeBilinearForm(mfem::BilinearForm &bf) const
{
return DBilinearForm(new BilinearForm(*this, bf));
}
void Engine::AssembleLinearForm(LinearForm &l_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
}
mfem::Operator *Engine::MakeOperator(const MixedBilinearForm &mbl_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
return NULL;
}
mfem::Operator *Engine::MakeOperator(const NonlinearForm &nl_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
return NULL;
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-111
View File
@@ -1,111 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_ENGINE_HPP
#define MFEM_BACKENDS_OCCA_ENGINE_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "../base/backend.hpp"
#include <occa.hpp>
namespace mfem
{
namespace occa
{
class Engine : public mfem::Engine
{
protected:
//
// Inherited fields
//
// mfem::Backend *backend;
#ifdef MFEM_USE_MPI
// MPI_Comm comm;
#endif
// int num_mem_res;
// int num_workers;
// MemoryResource **memory_resources;
// double *workers_weights;
// int *workers_mem_res;
static bool fileOpenerRegistered;
::occa::device *device; // An array of OCCA devices
std::string okl_path, okl_defines;
void Init(const std::string &engine_spec);
public:
Engine(const std::string &engine_spec);
#ifdef MFEM_USE_MPI
Engine(MPI_Comm comm, const std::string &engine_spec);
#endif
virtual ~Engine() { delete [] device; }
/**
@name OCCA specific interface, used by other objects in the OCCA backend
*/
///@{
::occa::device GetDevice(int idx = 0) const { return device[idx]; }
/// TODO: doxygen
const std::string &GetOklPath() const { return okl_path; }
/// TODO: doxygen
const std::string &GetOklDefines() const { return okl_defines; }
///@}
// End: OCCA specific interface
/**
@name Virtual interface: finite element data structures and algorithms
*/
///@{
virtual DLayout MakeLayout(std::size_t size) const;
virtual DLayout MakeLayout(const mfem::Array<std::size_t> &offsets) const;
virtual DArray MakeArray(PLayout &layout, std::size_t item_size) const;
virtual DVector MakeVector(PLayout &layout,
int type_id = ScalarId<double>::value) const;
virtual DFiniteElementSpace MakeFESpace(mfem::FiniteElementSpace &
fespace) const;
virtual DBilinearForm MakeBilinearForm(mfem::BilinearForm &bf) const;
/// FIXME - What will the actual parameters be?
virtual void AssembleLinearForm(LinearForm &l_form) const;
/// FIXME - What will the actual parameters be?
virtual mfem::Operator *MakeOperator(const MixedBilinearForm &mbl_form) const;
/// FIXME - What will the actual parameters be?
virtual mfem::Operator *MakeOperator(const NonlinearForm &nl_form) const;
///@}
// End: Virtual interface
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_ENGINE_HPP
-174
View File
@@ -1,174 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "backend.hpp"
#include "fespace.hpp"
#include "interpolation.hpp"
namespace mfem
{
namespace occa
{
FiniteElementSpace::FiniteElementSpace(const Engine &e,
mfem::FiniteElementSpace &fespace)
: PFiniteElementSpace(e, fespace),
e_layout(e, 0) // resized in SetupLocalGlobalMaps()
{
vdim = fespace.GetVDim();
ordering = fespace.GetOrdering();
SetupLocalGlobalMaps();
SetupOperators();
SetupKernels();
}
FiniteElementSpace::~FiniteElementSpace()
{
delete [] elementDofMap;
delete [] elementDofMapInverse;
delete restrictionOp;
delete prolongationOp;
}
void FiniteElementSpace::SetupLocalGlobalMaps()
{
const mfem::FiniteElement &fe = *(fes->GetFE(0));
const mfem::TensorBasisElement *el =
dynamic_cast<const mfem::TensorBasisElement*>(&fe);
const mfem::Table &e2dTable = fes->GetElementToDofTable();
const int *elementMap = e2dTable.GetJ();
const int elements = fes->GetNE();
globalDofs = fes->GetNDofs();
localDofs = fe.GetDof();
e_layout.Resize(localDofs * elements * fes->GetVDim());
elementDofMap = new int[localDofs];
elementDofMapInverse = new int[localDofs];
if (el)
{
::memcpy(elementDofMap,
el->GetDofMap().GetData(),
localDofs * sizeof(int));
}
else
{
for (int i = 0; i < localDofs; ++i)
{
elementDofMap[i] = i;
}
}
for (int i = 0; i < localDofs; ++i)
{
elementDofMapInverse[elementDofMap[i]] = i;
}
// Allocate device offsets and indices
globalToLocalOffsets.allocate(GetDevice(),
globalDofs + 1);
globalToLocalIndices.allocate(GetDevice(),
localDofs, elements);
localToGlobalMap.allocate(GetDevice(),
localDofs, elements);
int *offsets = globalToLocalOffsets.ptr();
int *indices = globalToLocalIndices.ptr();
int *l2gMap = localToGlobalMap.ptr();
// We'll be keeping a count of how many local nodes point
// to its global dof
for (int i = 0; i <= globalDofs; ++i)
{
offsets[i] = 0;
}
for (int e = 0; e < elements; ++e)
{
for (int d = 0; d < localDofs; ++d)
{
const int gid = elementMap[localDofs*e + d];
++offsets[gid + 1];
}
}
// Aggregate to find offsets for each global dof
for (int i = 1; i <= globalDofs; ++i)
{
offsets[i] += offsets[i - 1];
}
// For each global dof, fill in all local nodes that point
// to it
for (int e = 0; e < elements; ++e)
{
for (int d = 0; d < localDofs; ++d)
{
const int gid = elementMap[localDofs*e + elementDofMap[d]];
const int lid = localDofs*e + d;
indices[offsets[gid]++] = lid;
l2gMap[lid] = gid;
}
}
// We shifted the offsets vector by 1 by using it
// as a counter. Now we shift it back.
for (int i = globalDofs; i > 0; --i)
{
offsets[i] = offsets[i - 1];
}
offsets[0] = 0;
globalToLocalOffsets.keepInDevice();
globalToLocalIndices.keepInDevice();
localToGlobalMap.keepInDevice();
}
void FiniteElementSpace::SetupOperators()
{
const mfem::SparseMatrix *R = fes->GetRestrictionMatrix();
const mfem::Operator *P = fes->GetProlongationMatrix();
CreateRPOperators(OccaVLayout(), OccaTrueVLayout(),
R, P,
restrictionOp,
prolongationOp);
}
void FiniteElementSpace::SetupKernels()
{
::occa::properties props("defines: {"
" TILESIZE: 256,"
"}");
props["defines/NUM_VDIM"] = vdim;
props["defines/ORDERING_BY_NODES"] = 0;
props["defines/ORDERING_BY_VDIM"] = 1;
props["defines/VDIM_ORDERING"] = (int) (ordering == Ordering::byVDIM);
::occa::device device = GetDevice();
const std::string &okl_path = OccaEngine().GetOklPath();
const std::string &okl_defines = OccaEngine().GetOklDefines();
globalToLocalKernel = device.buildKernel(okl_path + "fespace.okl",
"GlobalToLocal",
props + okl_defines);
localToGlobalKernel = device.buildKernel(okl_path + "fespace.okl",
"LocalToGlobal",
props + okl_defines);
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-146
View File
@@ -1,146 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_FE_SPACE_HPP
#define MFEM_BACKENDS_OCCA_FE_SPACE_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "engine.hpp"
#include "operator.hpp"
#include "../../fem/fem.hpp"
namespace mfem
{
namespace occa
{
/// TODO: doxygen
class FiniteElementSpace : public mfem::PFiniteElementSpace
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// mfem::FiniteElementSpace *fes;
Layout e_layout;
int *elementDofMap;
int *elementDofMapInverse;
::occa::array<int> globalToLocalOffsets;
::occa::array<int> globalToLocalIndices;
::occa::array<int> localToGlobalMap;
::occa::kernel globalToLocalKernel, localToGlobalKernel;
mfem::Ordering::Type ordering;
int globalDofs, localDofs;
int vdim;
mfem::Operator *restrictionOp, *prolongationOp;
void SetupLocalGlobalMaps();
void SetupOperators();
void SetupKernels();
public:
/// TODO: doxygen
FiniteElementSpace(const Engine &e, mfem::FiniteElementSpace &fespace);
/// Virtual destructor
virtual ~FiniteElementSpace();
/// TODO: doxygen
const Engine &OccaEngine() const
{ return *static_cast<const Engine *>(engine.Get()); }
/// TODO: doxygen
::occa::device GetDevice(int idx = 0) const
{ return OccaEngine().GetDevice(idx); }
mfem::Mesh* GetMesh() const { return fes->GetMesh(); }
Layout &OccaVLayout() const
{ return *fes->GetVLayout().As<Layout>(); }
Layout &OccaTrueVLayout() const
{ return *fes->GetTrueVLayout().As<Layout>(); }
Layout &OccaEVLayout() { return e_layout; }
#ifdef MFEM_USE_MPI
bool isDistributed() const { return (OccaEngine().GetComm() != MPI_COMM_NULL); }
#else
bool isDistributed() const { return false; }
#endif
bool hasTensorBasis() const
{ return dynamic_cast<const mfem::TensorBasisElement*>(fes->GetFE(0)); }
mfem::Ordering::Type GetOrdering() const { return ordering; }
int GetGlobalDofs() const { return globalDofs; }
int GetLocalDofs() const { return localDofs; }
int GetDim() const { return fes->GetMesh()->Dimension(); }
int GetVDim() const { return vdim; }
int GetVSize() const { return globalDofs * vdim; }
int GetTrueVSize() const { return fes->GetTrueVSize(); }
int GetGlobalVSize() const { return globalDofs*vdim; /* FIXME: MPI */ }
int GetGlobalTrueVSize() const { return fes->GetTrueVSize(); }
int GetNE() const { return fes->GetNE(); }
const mfem::FiniteElementCollection* FEColl() const
{ return fes->FEColl(); }
const mfem::FiniteElement* GetFE(const int idx) const
{ return fes->GetFE(idx); }
const int* GetElementDofMap() const { return elementDofMap; }
const int* GetElementDofMapInverse() const { return elementDofMapInverse; }
const mfem::Operator* GetRestrictionOperator() { return restrictionOp; }
const mfem::Operator* GetProlongationOperator() { return prolongationOp; }
const ::occa::array<int> GetLocalToGlobalMap() const
{ return localToGlobalMap; }
void GlobalToLocal(const Vector &globalVec, Vector &localVec) const
{
globalToLocalKernel(globalDofs,
localDofs * fes->GetNE(),
globalToLocalOffsets,
globalToLocalIndices,
globalVec.OccaMem(), localVec.OccaMem());
}
void LocalToGlobal(const Vector &localVec, Vector &globalVec) const
{
localToGlobalKernel(globalDofs,
localDofs * fes->GetNE(),
globalToLocalOffsets,
globalToLocalIndices,
localVec.OccaMem(), globalVec.OccaMem());
}
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_FE_SPACE_HPP
-67
View File
@@ -1,67 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
/*
---[ Defines Known At Compile-Time ]------------
TILESIZE : Tilesize for iterating over entries
================================================
*/
#if VDIM_ORDERING == ORDERING_BY_VDIM
typedef double *Global_t @dim(NUM_VDIM, globalEntries);
typedef double *Local_t @dim(NUM_VDIM, localEntries);
#else
typedef double *Global_t @dim(NUM_VDIM, globalEntries) @dimOrder(1, 0);
typedef double *Local_t @dim(NUM_VDIM, localEntries) @dimOrder(1, 0);
#endif
@kernel void GlobalToLocal(const int globalEntries,
const int localEntries,
const int * restrict offsets,
const int * restrict indices,
const Global_t restrict globalX,
Local_t restrict localX) {
for (int i = 0; i < globalEntries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < globalEntries) {
const int offset = offsets[i];
const int nextOffset = offsets[i + 1];
for (int v = 0; v < NUM_VDIM; ++v) {
const double dofValue = globalX(v, i);
for (int j = offset; j < nextOffset; ++j) {
localX(v, indices[j]) = dofValue;
}
}
}
}
}
@kernel void LocalToGlobal(const int globalEntries,
const int localEntries,
const int * restrict offsets,
const int * restrict indices,
const Local_t restrict localX,
Global_t restrict globalX) {
for (int i = 0; i < globalEntries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < globalEntries) {
const int offset = offsets[i];
const int nextOffset = offsets[i + 1];
for (int v = 0; v < NUM_VDIM; ++v) {
double dofValue = 0;
for (int j = offset; j < nextOffset; ++j) {
dofValue += localX(v, indices[j]);
}
globalX(v, i) = dofValue;
}
}
}
}
-181
View File
@@ -1,181 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef STORE_JACOBIAN
# define STORE_JACOBIAN 1
#endif
#ifndef STORE_JACOBIAN_INV
# define STORE_JACOBIAN_INV 1
#endif
#ifndef STORE_JACOBIAN_DET
# define STORE_JACOBIAN_DET 1
#endif
typedef double* Local1D_t @dim(1, NUM_DOFS, numElements);
typedef double* Local2D_t @dim(2, NUM_DOFS, numElements);
typedef double* Local3D_t @dim(3, NUM_DOFS, numElements);
typedef double* QLocal_t @dim(NUM_QUAD, numElements);
typedef double* DofToQuadD1D_t @dim(NUM_QUAD, NUM_DOFS);
typedef double* DofToQuadD2D_t @dim(2, NUM_QUAD, NUM_DOFS);
typedef double* DofToQuadD3D_t @dim(3, NUM_QUAD, NUM_DOFS);
typedef double* Jacobian1D_t @dim(NUM_QUAD, numElements);
typedef double* Jacobian2D_t @dim(2, 2, NUM_QUAD, numElements);
typedef double* Jacobian3D_t @dim(3, 3, NUM_QUAD, numElements);
@kernel void InitGeometryInfo1D(const int numElements,
const DofToQuadD1D_t restrict dofToQuadD,
const Local1D_t restrict nodes,
Jacobian1D_t restrict J,
Jacobian1D_t restrict invJ,
QLocal_t restrict detJ) {
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_nodes[NUM_DOFS];
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
for (int d = q; d < NUM_DOFS; d += NUM_QUAD) {
s_nodes[d] = nodes(0, d, e);
}
}
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
double J11 = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double wx = dofToQuadD(q, d);
J11 += wx * s_nodes[d];
}
#if STORE_JACOBIAN
J(q, e) = J11;
#endif
#if STORE_JACOBIAN_INV
invJ(q, e) = 1.0 / J11;
#endif
#if STORE_JACOBIAN_DET
detJ(q, e) = J11;
#endif
}
}
}
@kernel void InitGeometryInfo2D(const int numElements,
const DofToQuadD2D_t restrict dofToQuadD,
const Local2D_t restrict nodes,
Jacobian2D_t restrict J,
Jacobian2D_t restrict invJ,
QLocal_t restrict detJ) {
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_nodes[2 * NUM_DOFS] @dim(2, NUM_DOFS);
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
for (int d = q; d < NUM_DOFS; d += NUM_QUAD) {
s_nodes(0, d) = nodes(0, d, e);
s_nodes(1, d) = nodes(1, d, e);
}
}
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
double J11 = 0, J12 = 0;
double J21 = 0, J22 = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double wx = dofToQuadD(0, q, d);
const double wy = dofToQuadD(1, q, d);
const double x = s_nodes(0, d);
const double y = s_nodes(1, d);
J11 += (wx * x); J12 += (wx * y);
J21 += (wy * x); J22 += (wy * y);
}
#if STORE_JACOBIAN_INV || STORE_JACOBIAN_DET
const double r_detJ = (J11 * J22) - (J12 * J21);
#endif
#if STORE_JACOBIAN
J(0, 0, q, e) = J11; J(1, 0, q, e) = J12;
J(0, 1, q, e) = J21; J(1, 1, q, e) = J22;
#endif
#if STORE_JACOBIAN_INV
const double r_idetJ = 1.0 / r_detJ;
invJ(0, 0, q, e) = J22 * r_idetJ;
invJ(1, 0, q, e) = -J12 * r_idetJ;
invJ(0, 1, q, e) = -J21 * r_idetJ;
invJ(1, 1, q, e) = J11 * r_idetJ;
#endif
#if STORE_JACOBIAN_DET
detJ(q, e) = r_detJ;
#endif
}
}
}
@kernel void InitGeometryInfo3D(const int numElements,
const DofToQuadD3D_t restrict dofToQuadD,
const Local3D_t restrict nodes,
Jacobian3D_t restrict J,
Jacobian3D_t restrict invJ,
QLocal_t restrict detJ) {
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_nodes[3 * NUM_DOFS] @dim(3, NUM_DOFS);
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
for (int d = q; d < NUM_DOFS; d += NUM_QUAD) {
s_nodes(0, d) = nodes(0, d, e);
s_nodes(1, d) = nodes(1, d, e);
s_nodes(2, d) = nodes(2, d, e);
}
}
for (int q = 0; q < NUM_QUAD; ++q; @inner) {
double J11 = 0, J12 = 0, J13 = 0;
double J21 = 0, J22 = 0, J23 = 0;
double J31 = 0, J32 = 0, J33 = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
const double wx = dofToQuadD(0, q, d);
const double wy = dofToQuadD(1, q, d);
const double wz = dofToQuadD(2, q, d);
const double x = s_nodes(0, d);
const double y = s_nodes(1, d);
const double z = s_nodes(2, d);
J11 += (wx * x); J12 += (wx * y); J13 += (wx * z);
J21 += (wy * x); J22 += (wy * y); J23 += (wy * z);
J31 += (wz * x); J32 += (wz * y); J33 += (wz * z);
}
#if STORE_JACOBIAN_INV || STORE_JACOBIAN_DET
const double r_detJ = ((J11 * J22 * J33) + (J12 * J23 * J31) + (J13 * J21 * J32) -
(J13 * J22 * J31) - (J12 * J21 * J33) - (J11 * J23 * J32));
#endif
#if STORE_JACOBIAN
J(0, 0, q, e) = J11; J(1, 0, q, e) = J12; J(2, 0, q, e) = J13;
J(0, 1, q, e) = J21; J(1, 1, q, e) = J22; J(2, 1, q, e) = J23;
J(0, 2, q, e) = J31; J(1, 2, q, e) = J32; J(2, 2, q, e) = J33;
#endif
#if STORE_JACOBIAN_INV
const double r_idetJ = 1.0 / r_detJ;
invJ(0, 0, q, e) = r_idetJ * ((J22 * J33) - (J23 * J32));
invJ(1, 0, q, e) = r_idetJ * ((J32 * J13) - (J33 * J12));
invJ(2, 0, q, e) = r_idetJ * ((J12 * J23) - (J13 * J22));
invJ(0, 1, q, e) = r_idetJ * ((J23 * J31) - (J21 * J33));
invJ(1, 1, q, e) = r_idetJ * ((J33 * J11) - (J31 * J13));
invJ(2, 1, q, e) = r_idetJ * ((J13 * J21) - (J11 * J23));
invJ(0, 2, q, e) = r_idetJ * ((J21 * J32) - (J22 * J31));
invJ(1, 2, q, e) = r_idetJ * ((J31 * J12) - (J32 * J11));
invJ(2, 2, q, e) = r_idetJ * ((J11 * J22) - (J12 * J21));
#endif
#if STORE_JACOBIAN_DET
detJ(q, e) = r_detJ;
#endif
}
}
}
-195
View File
@@ -1,195 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "gridfunc.hpp"
#include "bilininteg.hpp"
#include "../../fem/gridfunc.hpp"
namespace mfem
{
namespace occa
{
std::map<std::string, ::occa::kernel> gridFunctionKernels;
::occa::kernel GetGridFunctionKernel(::occa::device device,
FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir)
{
const int numQuad = ir.GetNPoints();
const FiniteElement &fe = *(fespace.GetFE(0));
const int dim = fe.GetDim();
const int vdim = fespace.GetVDim();
std::stringstream ss;
ss << ::occa::hash(device)
<< "FEColl : " << fespace.FEColl()->Name()
<< "Quad: " << numQuad
<< "Dim: " << dim
<< "VDim: " << vdim;
std::string hash = ss.str();
// Kernel defines
::occa::properties props;
props["defines/NUM_VDIM"] = vdim;
SetProperties(fespace, ir, props);
::occa::kernel kernel = gridFunctionKernels[hash];
if (!kernel.isInitialized())
{
const std::string &okl_path = fespace.OccaEngine().GetOklPath();
kernel = device.buildKernel(okl_path + "gridfunc.okl",
stringWithDim("GridFuncToQuad", dim),
props);
}
return kernel;
}
// OccaGridFunction::OccaGridFunction() :
// Vector(),
// ofespace(NULL),
// sequence(0) {}
OccaGridFunction::OccaGridFunction(FiniteElementSpace *ofespace_)
: PArray(ofespace_->OccaVLayout()),
Array(ofespace_->OccaVLayout(), sizeof(double)),
Vector(ofespace_->OccaVLayout()),
ofespace(ofespace_),
sequence(0) {}
// OccaGridFunction::OccaGridFunction(OccaFiniteElementSpace *ofespace_,
// OccaVectorRef ref) :
// OccaVector(ref),
// ofespace(ofespace_),
// sequence(0) {}
OccaGridFunction::OccaGridFunction(const OccaGridFunction &v)
: PArray(v),
Array(v),
Vector(v),
ofespace(v.ofespace),
sequence(v.sequence) {}
OccaGridFunction& OccaGridFunction::operator = (double value)
{
Fill(value);
return *this;
}
OccaGridFunction& OccaGridFunction::operator = (const Vector &v)
{
Assign<double>(v);
return *this;
}
// OccaGridFunction& OccaGridFunction::operator = (const OccaVectorRef &v)
// {
// OccaVector::operator = (v);
// return *this;
// }
OccaGridFunction& OccaGridFunction::operator = (const OccaGridFunction &v)
{
Assign<double>(v);
return *this;
}
// void OccaGridFunction::SetGridFunction(mfem::GridFunction &gf)
// {
// Vector v = *this;
// gf.MakeRef(ofespace->GetFESpace(), v, 0);
// // Make gf the owner of the data
// v.Swap(gf);
// }
void OccaGridFunction::GetTrueDofs(Vector &v)
{
const mfem::Operator *R = ofespace->GetRestrictionOperator();
if (!R)
{
v.MakeRef(*this);
}
else
{
v.Resize<double>(R->OutLayout(), NULL);
mfem::Vector mfem_v(v);
R->Mult(this->Wrap(), mfem_v);
}
}
void OccaGridFunction::SetFromTrueDofs(Vector &v)
{
const mfem::Operator *P = ofespace->GetProlongationOperator();
if (!P)
{
MakeRef(v);
}
else
{
Resize<double>(P->OutLayout(), NULL);
mfem::Vector mfem_this(*this);
P->Mult(v.Wrap(), mfem_this);
}
}
mfem::FiniteElementSpace* OccaGridFunction::GetFESpace()
{
return ofespace->GetFESpace();
}
const mfem::FiniteElementSpace* OccaGridFunction::GetFESpace() const
{
return ofespace->GetFESpace();
}
void OccaGridFunction::ToQuad(const IntegrationRule &ir, Vector &quadValues)
{
const Engine &engine = OccaLayout().OccaEngine();
::occa::device device = engine.GetDevice();
OccaDofQuadMaps &maps = OccaDofQuadMaps::Get(device, *ofespace, ir);
const int elements = ofespace->GetNE();
const int numQuad = ir.GetNPoints();
quadValues.Resize<double>(*(new Layout(engine, numQuad * elements)), NULL);
::occa::kernel g2qKernel = GetGridFunctionKernel(device, *ofespace, ir);
g2qKernel(elements,
maps.dofToQuad,
ofespace->GetLocalToGlobalMap(),
this->OccaMem(),
quadValues.OccaMem());
}
void OccaGridFunction::Distribute(const Vector &v)
{
if (ofespace->isDistributed())
{
mfem::Vector mfem_this(*this);
ofespace->GetProlongationOperator()->Mult(v.Wrap(), mfem_this);
}
else
{
*this = v;
}
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-83
View File
@@ -1,83 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_GRID_FUNC_HPP
#define MFEM_BACKENDS_OCCA_GRID_FUNC_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "vector.hpp"
#include "fespace.hpp"
namespace mfem
{
class IntegrationRule;
class GridFunction;
namespace occa
{
class OccaIntegrator;
class OccaDofQuadMaps;
// TODO: make this object part of the backend or the engine.
extern std::map<std::string, ::occa::kernel> gridFunctionKernels;
// TODO: make this a method of the backend or the engine.
::occa::kernel GetGridFunctionKernel(::occa::device device,
FiniteElementSpace &fespace,
const mfem::IntegrationRule &ir);
class OccaGridFunction : public Vector
{
protected:
FiniteElementSpace *ofespace;
long sequence;
::occa::kernel gridFuncToQuad[3];
public:
// OccaGridFunction();
OccaGridFunction(FiniteElementSpace *ofespace_);
// OccaGridFunction(FiniteElementSpace *ofespace_,
// OccaVectorRef ref);
OccaGridFunction(const OccaGridFunction &gf);
OccaGridFunction& operator = (double value);
OccaGridFunction& operator = (const Vector &v);
// OccaGridFunction& operator = (const OccaVectorRef &v);
OccaGridFunction& operator = (const OccaGridFunction &gf);
// void SetGridFunction(mfem::GridFunction &gf);
void GetTrueDofs(Vector &v);
void SetFromTrueDofs(Vector &v);
mfem::FiniteElementSpace* GetFESpace();
const mfem::FiniteElementSpace* GetFESpace() const;
void ToQuad(const mfem::IntegrationRule &ir, Vector &quadValues);
void Distribute(const Vector &v);
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_GRID_FUNC_HPP
-26
View File
@@ -1,26 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
#if USING_TENSOR_OPS
# if OCCA_USING_CPU
# include "mfem-occa://gridfunc/tensor/cpu.okl"
# else
# include "mfem-occa://gridfunc/tensor/gpuHighOrder.okl"
# endif
#else
# if OCCA_USING_CPU
# include "mfem-occa://gridfunc/simplex/cpu.okl"
# else
# include "mfem-occa://gridfunc/simplex/gpuHighOrder.okl"
# endif
#endif
-63
View File
@@ -1,63 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 2D ]-----------------------------
@kernel void GridFuncToQuad2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap_t restrict l2gMap,
const double * restrict gf,
QVLocal_t restrict out) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
for (int d = 0; d < NUM_DOFS; ++d) {
const int gid = l2gMap(d, e);
for (int v = 0; v < NUM_VDIM; ++v) {
const double r_gf = gf[v + gid*NUM_VDIM];
double r_out = 0;
for (int q = 0; q < NUM_QUAD; ++q) {
r_out += r_gf * dofToQuad(d, q);
}
out(v, d, e) = r_out;
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void GridFuncToQuad3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap_t restrict l2gMap,
const double * restrict gf,
QVLocal_t restrict out) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
for (int d = 0; d < NUM_DOFS; ++d) {
const int gid = l2gMap(d, e);
for (int v = 0; v < NUM_VDIM; ++v) {
const double r_gf = gf[v + gid*NUM_VDIM];
double r_out = 0;
for (int q = 0; q < NUM_QUAD; ++q) {
r_out += r_gf * dofToQuad(d, q);
}
out(v, d, e) = r_out;
}
}
}
}
}
//======================================
@@ -1,79 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 2D ]-----------------------------
@kernel void GridFuncToQuad2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap_t restrict l2gMap,
const double * restrict gf,
QVLocal_t restrict out) {
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_gf[NUM_VDIM][NUM_DOFS];
for (int dOff = 0; dOff < M2_INNER_BATCH; ++dOff; @inner) {
for (int d = dOff; d < NUM_DOFS; d += M2_INNER_BATCH) {
const int gid = l2gMap(d, e);
for (int v = 0; v < NUM_VDIM; ++v) {
s_gf[v][d] = gf[v + gid*NUM_VDIM]];
}
}
}
for (int qOff = 0; qOff < M2_INNER_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += M2_INNER_BATCH) {
for (int v = 0; v < NUM_VDIM; ++v) {
double r_out = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
r_out += s_gf[v][d] * dofToQuad(d, q);
}
out(v, q, e) = r_out;
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void GridFuncToQuad3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap_t restrict l2gMap,
const double * restrict gf,
QVLocal_t restrict out) {
for (int e = 0; e < numElements; ++e; @outer) {
@shared double s_gf[NUM_VDIM][NUM_DOFS];
for (int dOff = 0; dOff < M3_INNER_BATCH; ++dOff; @inner) {
for (int d = dOff; d < NUM_DOFS; d += M3_INNER_BATCH) {
const int gid = l2gMap(d, e);
for (int v = 0; v < NUM_VDIM; ++v) {
s_gf[v][d] = gf[v + gid*NUM_VDIM]];
}
}
}
for (int qOff = 0; qOff < M3_INNER_BATCH; ++qOff; @inner) {
for (int q = qOff; q < NUM_QUAD; q += M3_INNER_BATCH) {
for (int v = 0; v < NUM_VDIM; ++v) {
double r_out = 0;
for (int d = 0; d < NUM_DOFS; ++d) {
r_out += s_gf[v][d] * dofToQuad(d, q);
}
out(v, q, e) = r_out;
}
}
}
}
}
//======================================
-188
View File
@@ -1,188 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 1D ]-----------------------------
@kernel void GridFuncToQuad1D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap1D_t restrict l2gMap,
const double * restrict gf,
QVLocal1D_t restrict out) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double r_out[NUM_VDIM][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
r_out[v][qx] = 0;
}
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const int gid = l2gMap(dx, e);
for (int v = 0; v < NUM_VDIM; ++v) {
const double r_gf = gf[v + gid*NUM_VDIM];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
r_out[v][qx] += r_gf * dofToQuad(qx, dx);
}
}
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
for (int v = 0; v < NUM_VDIM; ++v) {
out(v, qx, e) = r_out[v][qx];
}
}
}
}
}
//======================================
//---[ 2D ]-----------------------------
@kernel void GridFuncToQuad2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap2D_t restrict l2gMap,
const double * restrict gf,
QVLocal2D_t restrict out) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double out_xy[NUM_VDIM][NUM_QUAD_1D][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xy[v][qy][qx] = 0;
}
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double out_x[NUM_VDIM][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
out_x[v][qy] = 0;
}
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const int gid = l2gMap(dx, dy, e);
for (int v = 0; v < NUM_VDIM; ++v) {
const double r_gf = gf[v + gid*NUM_VDIM];
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
out_x[v][qy] += r_gf * dofToQuad(qy, dx);
}
}
}
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
const double d2q = dofToQuad(qy, dy);
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xy[v][qy][qx] += d2q * out_x[v][qx];
}
}
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
for (int v = 0; v < NUM_VDIM; ++v) {
out(v, qx, qy, e) = out_xy[v][qy][qx];
}
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void GridFuncToQuad3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap3D_t restrict l2gMap,
const double * restrict gf,
QVLocal3D_t restrict out) {
for (int e = 0; e < numElements; ++e; @outer) {
for (int dummy = 0; dummy < 1; ++dummy; @inner) {
double out_xyz[NUM_VDIM][NUM_QUAD_1D][NUM_QUAD_1D][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xyz[v][qz][qy][qx] = 0;
}
}
}
}
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
double out_xy[NUM_VDIM][NUM_QUAD_1D][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xy[v][qy][qx] = 0;
}
}
}
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
double out_x[NUM_VDIM][NUM_QUAD_1D];
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_x[v][qx] = 0;
}
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const int gid = l2gMap(dx, dy, dz, e);
for (int v = 0; v < NUM_VDIM; ++v) {
const double r_gf = gf[v + gid*NUM_VDIM];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_x[v][qx] += r_gf * dofToQuad(qx, dx);
}
}
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
const double wy = dofToQuad(qy, dy);
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xy[v][qy][qx] += wy * out_x[v][qx];
}
}
}
}
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
const double wz = dofToQuad(qz, dz);
for (int v = 0; v < NUM_VDIM; ++v) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out_xyz[v][qz][qy][qx] += wz * out_xy[v][qy][qx];
}
}
}
}
}
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
for (int v = 0; v < NUM_VDIM; ++v) {
out(v, qx, qy, qz, e) = out_xyz[v][qz][qy][qx];
}
}
}
}
}
}
}
//======================================
@@ -1,183 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mfem-occa://defines.okl"
//---[ 1D ]-----------------------------
@kernel void GridFuncToQuad1D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap1D_t restrict l2gMap,
const double * restrict gf,
QLocal1D_t restrict out) {
// Iterate over elements
for (int eOff = 0; eOff < numElements; eOff += M1_ELEMENT_BATCHES; @outer) {
@shared double s_dofToQuad[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
@exclusive double r_out[NUM_QUAD_1D];
for (int el = 0; el < M1_INNER_ELEMENT_BATCH; ++el; @inner) {
for (int i = el; i < NUM_QUAD_DOFS_1D; i += M1_INNER_ELEMENT_BATCH) {
s_dofToQuad[i] = dofToQuad[i];
}
}
for (int b = 0; b < M1_OUTER_ELEMENT_BATCH; ++b) {
for (int el = 0; el < M1_INNER_ELEMENT_BATCH; ++el; @inner) {
const int e = eOff + b*M1_INNER_ELEMENT_BATCH + el;
if (e < numElements) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
r_out[qx] = 0;
}
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double r_gf = gf[l2gMap(dx, e)];
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
r_out[qx] += r_gf * s_dofToQuad(qx, dx);
}
}
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
out(qx, e) = r_out[qx];
}
}
}
}
}
}
//======================================
//---[ 2D ]-----------------------------
@kernel void GridFuncToQuad2D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap2D_t restrict l2gMap,
const double * restrict gf,
QLocal2D_t restrict out) {
// Iterate over elements
for (int eOff = 0; eOff < numElements; eOff += M2_ELEMENT_BATCH; @outer) {
// Store dof <--> quad mappings
@shared double s_dofToQuad[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
// Store xy planes in shared memory
@shared double s_xy[NUM_QUAD_DOFS_1D] @dim(NUM_DOFS_1D, NUM_QUAD_1D);
for (int x = 0; x < NUM_MAX_1D; ++x; @inner) {
for (int id = x; id < NUM_QUAD_DOFS_1D; id += NUM_MAX_1D) {
s_dofToQuad[id] = dofToQuad[id];
}
}
for (int e = eOff; e < (eOff + M2_ELEMENT_BATCH); ++e) {
if (e < numElements) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if (dx < NUM_DOFS_1D) {
double r_x[NUM_DOFS_1D];
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
r_x[dy] = gf[l2gMap(dx, dy, e)];
}
for (int qy = 0; qy < NUM_QUAD_1D; ++qy) {
double xy = 0;
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
xy += r_x[dy] * s_dofToQuad(qy, dy);
}
s_xy(dx, qy) = xy;
}
}
}
for (int qy = 0; qy < NUM_MAX_1D; ++qy; @inner) {
if (qy < NUM_QUAD_1D) {
for (int qx = 0; qx < NUM_QUAD_1D; ++qx) {
double val = 0;
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
val += s_xy(dx, qy) * s_dofToQuad(qx, dx);
}
out(qx, qy, e) = val;
}
}
}
}
}
}
}
//======================================
//---[ 3D ]-----------------------------
@kernel void GridFuncToQuad3D(const int numElements,
const DofToQuad_t restrict dofToQuad,
const DLocalMap3D_t restrict l2gMap,
const double * restrict gf,
QLocal3D_t restrict out) {
// Iterate over elements
for (int e = 0; e < numElements; ++e; @outer) {
// Store dof <--> quad mappings
@shared double s_dofToQuad[NUM_QUAD_DOFS_1D] @dim(NUM_QUAD_1D, NUM_DOFS_1D);
// Store xy planes in shared memory
@shared double s_z[NUM_MAX_2D] @dim(NUM_MAX_1D, NUM_MAX_1D);
// Store z axis as registers
@exclusive double r_qz[NUM_QUAD_1D];
for (int y = 0; y < NUM_MAX_1D; ++y; @inner) {
for (int x = 0; x < NUM_MAX_1D; ++x; @inner) {
const int id = (y * NUM_MAX_1D) + x;
// Fetch Q <--> D maps
if (id < NUM_QUAD_DOFS_1D) {
s_dofToQuad[id] = dofToQuad[id];
}
// Initialize our Z axis
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
r_qz[qz] = 0;
}
}
}
for (int dy = 0; dy < NUM_MAX_1D; ++dy; @inner) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if ((dx < NUM_DOFS_1D) && (dy < NUM_DOFS_1D)) {
for (int dz = 0; dz < NUM_DOFS_1D; ++dz) {
const double val = gf[l2gMap(dx, dy, dz, e)];
// Calculate D -> Q in the Z axis
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
r_qz[qz] += val * s_dofToQuad(qz, dz);
}
}
}
}
}
// For each xy plane
for (int qz = 0; qz < NUM_QUAD_1D; ++qz) {
// Fill xy plane at given z position
for (int dy = 0; dy < NUM_MAX_1D; ++dy; @inner) {
for (int dx = 0; dx < NUM_MAX_1D; ++dx; @inner) {
if ((dx < NUM_DOFS_1D) && (dy < NUM_DOFS_1D)) {
s_z(dx, dy) = r_qz[qz];
}
}
}
// Calculate Dxyz, xDyz, xyDz in plane
for (int qy = 0; qy < NUM_MAX_1D; ++qy; @inner) {
for (int qx = 0; qx < NUM_MAX_1D; ++qx; @inner) {
if ((qx < NUM_QUAD_1D) && (qy < NUM_QUAD_1D)) {
double val = 0;
for (int dy = 0; dy < NUM_DOFS_1D; ++dy) {
const double wy = s_dofToQuad(qy, dy);
for (int dx = 0; dx < NUM_DOFS_1D; ++dx) {
const double wx = s_dofToQuad(qx, dx);
val += wx * wy * s_z(dx, dy);
}
}
out(qx, qy, qz, e) = val;
}
}
}
}
}
}
//======================================
-162
View File
@@ -1,162 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "interpolation.hpp"
namespace mfem
{
namespace occa
{
void CreateRPOperators(Layout &v_layout, Layout &t_layout,
const mfem::SparseMatrix *R, const mfem::Operator *P,
mfem::Operator *&OccaR, mfem::Operator *&OccaP)
{
if (!P)
{
OccaR = new IdentityOperator(t_layout);
OccaP = new IdentityOperator(t_layout);
return;
}
const mfem::SparseMatrix *pmat = dynamic_cast<const mfem::SparseMatrix*>(P);
::occa::device device = v_layout.OccaEngine().GetDevice();
if (R)
{
OccaSparseMatrix *occaR =
CreateMappedSparseMatrix(v_layout, t_layout, *R);
::occa::array<int> reorderIndices = occaR->reorderIndices;
delete occaR;
OccaR = new RestrictionOperator(v_layout, t_layout, reorderIndices);
}
if (pmat)
{
const mfem::SparseMatrix *pmatT = Transpose(*pmat);
OccaSparseMatrix *occaP =
CreateMappedSparseMatrix(t_layout, v_layout, *pmat);
OccaSparseMatrix *occaPT =
CreateMappedSparseMatrix(v_layout, t_layout, *pmatT);
OccaP = new ProlongationOperator(*occaP, *occaPT);
}
else
{
OccaP = new ProlongationOperator(t_layout, v_layout, P);
}
}
RestrictionOperator::RestrictionOperator(Layout &in_layout, Layout &out_layout,
::occa::array<int> indices) :
Operator(in_layout, out_layout)
{
entries = indices.size() / 2;
trueIndices = indices;
// FIXME: paths ...
::occa::device device = in_layout.OccaEngine().GetDevice();
const std::string &okl_path = in_layout.OccaEngine().GetOklPath();
const std::string &okl_defines = in_layout.OccaEngine().GetOklDefines();
multOp = device.buildKernel(okl_path + "mappings.okl",
"ExtractSubVector",
"defines: { TILESIZE: 256 }" + okl_defines);
multTransposeOp = device.buildKernel(okl_path + "mappings.okl",
"SetSubVector",
"defines: { TILESIZE: 256 }" +
okl_defines);
}
void RestrictionOperator::Mult_(const Vector &x, Vector &y) const
{
multOp(entries, trueIndices, x.OccaMem(), y.OccaMem());
}
void RestrictionOperator::MultTranspose_(const Vector &x, Vector &y) const
{
y.Fill<double>(0.0);
multTransposeOp(entries, trueIndices, x.OccaMem(), y.OccaMem());
}
ProlongationOperator::ProlongationOperator(OccaSparseMatrix &multOp_,
OccaSparseMatrix &multTransposeOp_) :
Operator(multOp_),
pmat(NULL),
multOp(multOp_),
multTransposeOp(multTransposeOp_) {}
ProlongationOperator::ProlongationOperator(Layout &in_layout,
Layout &out_layout,
const mfem::Operator *pmat_) :
Operator(in_layout, out_layout),
pmat(pmat_),
multOp(*this),
multTransposeOp(*this)
{ }
void ProlongationOperator::Mult_(const Vector &x, Vector &y) const
{
MFEM_VERIFY(pmat == NULL, "");
multOp.Mult_(x, y);
}
void ProlongationOperator::MultTranspose_(const Vector &x, Vector &y) const
{
MFEM_VERIFY(pmat == NULL, "");
multTransposeOp.Mult_(x, y);
}
void ProlongationOperator::Mult(const mfem::Vector &x, mfem::Vector &y) const
{
if (pmat)
{
// FIXME: create an OCCA version of 'pmat'
x.Pull();
y.Pull(false);
pmat->Mult(x, y);
y.Push();
}
else
{
multOp.Mult(x, y);
}
}
void ProlongationOperator::MultTranspose(const mfem::Vector &x,
mfem::Vector &y) const
{
if (pmat)
{
// FIXME: create an OCCA version of 'pmat'
x.Pull();
y.Pull(false);
pmat->MultTranspose(x, y);
y.Push();
}
else
{
multTransposeOp.Mult(x, y);
}
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-79
View File
@@ -1,79 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_INTERPOLATION_HPP
#define MFEM_BACKENDS_OCCA_INTERPOLATION_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include <occa.hpp>
#include "vector.hpp"
#include "engine.hpp"
#include "sparsemat.hpp"
#include "../../fem/fem.hpp"
namespace mfem
{
namespace occa
{
// [MISSING] Proper destructors
void CreateRPOperators(Layout &v_layout, Layout &t_layout,
const mfem::SparseMatrix *R, const mfem::Operator *P,
mfem::Operator *&OccaR, mfem::Operator *&OccaP);
class RestrictionOperator : public Operator
{
protected:
int entries;
::occa::array<int> trueIndices;
::occa::kernel multOp, multTransposeOp;
public:
RestrictionOperator(Layout &in_layout, Layout &out_layout,
::occa::array<int> indices);
// overrides
virtual void Mult_(const Vector &x, Vector &y) const;
virtual void MultTranspose_(const Vector &x, Vector &y) const;
};
class ProlongationOperator : public Operator
{
protected:
const mfem::Operator *pmat;
OccaSparseMatrix multOp, multTransposeOp;
public:
ProlongationOperator(OccaSparseMatrix &multOp_,
OccaSparseMatrix &multTransposeOp_);
ProlongationOperator(Layout &in_layout, Layout &out_layout,
const mfem::Operator *pmat_);
// overrides
virtual void Mult_(const Vector &x, Vector &y) const;
virtual void MultTranspose_(const Vector &x, Vector &y) const;
// overrides
virtual void Mult(const mfem::Vector &x, mfem::Vector &y) const;
virtual void MultTranspose(const mfem::Vector &x, mfem::Vector &y) const;
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_INTERPOLATION_HPP
-40
View File
@@ -1,40 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "layout.hpp"
#include "../../general/array.hpp"
namespace mfem
{
namespace occa
{
void Layout::Resize(std::size_t new_size)
{
size = new_size;
}
void Layout::Resize(const Array<std::size_t> &offsets)
{
MFEM_ASSERT(offsets.Size() == 2,
"multiple workers are not supported yet");
size = offsets.Last();
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-68
View File
@@ -1,68 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_LAYOUT_HPP
#define MFEM_BACKENDS_OCCA_LAYOUT_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "../base/layout.hpp"
#include "engine.hpp"
namespace mfem
{
namespace occa
{
class Layout : public PLayout
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// std::size_t size;
public:
Layout(const Engine &e, std::size_t s = 0) : PLayout(e, s) { }
const Engine &OccaEngine() const
{ return *static_cast<const Engine *>(engine.Get()); }
::occa::memory Alloc(std::size_t bytes) const
{ return OccaEngine().GetDevice().malloc(bytes); }
virtual ~Layout() { }
/**
@name Virtual interface
*/
///@{
/// Resize the layout
virtual void Resize(std::size_t new_size);
/// Resize the layout based on the given worker offsets
virtual void Resize(const Array<std::size_t> &offsets);
///@}
// End: Virtual interface
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_LAYOUT_HPP
-54
View File
@@ -1,54 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
/*
---[ Defines Known At Compile-Time ]------------
TILESIZE : Tilesize for iterating over entries
================================================
*/
@kernel void ExtractSubVector(const int entries,
const int * restrict indices,
const double * restrict in,
double * restrict out) {
for (int i = 0; i < entries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < entries) {
out[i] = in[indices[i]];
}
}
}
@kernel void SetSubVector(const int entries,
const int * restrict indices,
const double * restrict in,
double * restrict out) {
for (int i = 0; i < entries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < entries) {
out[indices[i]] = in[i];
}
}
}
@kernel void MapSubVector(const int entries,
const int * restrict indices,
const double * restrict in,
double * restrict out) {
for (int i = 0; i < entries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < entries) {
const int fromIdx = indices[2*i + 0];
const int toIdx = indices[2*i + 1];
out[toIdx] = in[fromIdx];
}
}
}
-135
View File
@@ -1,135 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "operator.hpp"
namespace mfem
{
namespace occa
{
// FIXME: move this object to the Backend?
::occa::kernelBuilder OccaConstrainedOperator::mapDofBuilder =
::occa::linalg::customLinearMethod(
"vector_map_dofs",
"const int idx = v2[i];"
"v0[idx] = v1[idx];",
"defines: {"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" VTYPE2: 'int',"
" TILESIZE: 128,"
"}");
// FIXME: move this object to the Backend?
::occa::kernelBuilder OccaConstrainedOperator::clearDofBuilder =
::occa::linalg::customLinearMethod(
"vector_clear_dofs",
"v0[v1[i]] = 0.0;",
"defines: {"
" VTYPE0: 'double',"
" VTYPE1: 'int',"
" TILESIZE: 128,"
"}");
OccaConstrainedOperator::OccaConstrainedOperator(
mfem::Operator *A_,
const mfem::Array<int> &constraintList_,
bool own_A_)
: Operator(A_->InLayout()->As<Layout>()),
z(OutLayout_()),
w(OutLayout_()),
mfem_z((z.DontDelete(), z)),
mfem_w((w.DontDelete(), w))
{
Setup(OutLayout_().OccaEngine().GetDevice(), A_, constraintList_, own_A_);
}
void OccaConstrainedOperator::Setup(::occa::device device_,
mfem::Operator *A_,
const mfem::Array<int> &constraintList_,
bool own_A_)
{
device = device_;
A = A_;
own_A = own_A_;
constraintIndices = constraintList_.Size();
constraintList = constraintList_.Get_PArray()->As<Array>().OccaMem();
}
void OccaConstrainedOperator::EliminateRHS(const Vector &x, Vector &b) const
{
const std::string &okl_defines = InLayout_().OccaEngine().GetOklDefines();
::occa::kernel mapDofs = mapDofBuilder.build(device, okl_defines);
w.Fill<double>(0.0);
if (constraintIndices)
{
mapDofs(constraintIndices, w.OccaMem(), x.OccaMem(), constraintList);
}
A->Mult(mfem_w, mfem_z);
b.Axpby<double>(1.0, b, -1.0, z);
if (constraintIndices)
{
mapDofs(constraintIndices, b.OccaMem(), x.OccaMem(), constraintList);
}
}
void OccaConstrainedOperator::Mult_(const Vector &x, Vector &y) const
{
mfem::Vector mfem_y(y);
if (constraintIndices == 0)
{
A->Mult(x.Wrap(), mfem_y);
return;
}
const std::string &okl_defines = InLayout_().OccaEngine().GetOklDefines();
::occa::kernel mapDofs = mapDofBuilder.build(device, okl_defines);
::occa::kernel clearDofs = clearDofBuilder.build(device, okl_defines);
z.Assign<double>(x); // z = x
clearDofs(constraintIndices, z.OccaMem(), constraintList);
A->Mult(mfem_z, mfem_y);
mapDofs(constraintIndices, y.OccaMem(), x.OccaMem(), constraintList);
}
OccaConstrainedOperator::~OccaConstrainedOperator()
{
if (own_A)
{
delete A;
}
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-129
View File
@@ -1,129 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_OPERATOR_HPP
#define MFEM_BACKENDS_OCCA_OPERATOR_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "vector.hpp"
#include "../../linalg/operator.hpp"
namespace mfem
{
namespace occa
{
class Operator : public mfem::Operator
{
public:
/// Creare an operator with the same dimensions as @a orig.
Operator(const Operator &orig)
: mfem::Operator(orig) { }
Operator(Layout &layout)
: mfem::Operator(layout) { }
Operator(Layout &in_layout, Layout &out_layout)
: mfem::Operator(in_layout, out_layout) { }
Layout &InLayout_() const
{ return *static_cast<Layout*>(in_layout.Get()); }
Layout &OutLayout_() const
{ return *static_cast<Layout*>(out_layout.Get()); }
virtual void Mult_(const Vector &x, Vector &y) const = 0;
virtual void MultTranspose_(const Vector &x, Vector &y) const
{ MFEM_ABORT("method is not supported"); }
// override
virtual void Mult(const mfem::Vector &x, mfem::Vector &y) const
{
Mult_(x.Get_PVector()->As<Vector>(),
y.Get_PVector()->As<Vector>());
}
// override
virtual void MultTranspose(const mfem::Vector &x, mfem::Vector &y) const
{
MultTranspose_(x.Get_PVector()->As<Vector>(),
y.Get_PVector()->As<Vector>());
}
};
class OccaConstrainedOperator : public Operator
{
protected:
::occa::device device;
mfem::Operator *A; //< The unconstrained Operator.
bool own_A; //< Ownership flag for A.
::occa::memory constraintList; //< List of constrained indices/dofs.
int constraintIndices;
mutable Vector z, w; //< Auxiliary vectors.
mutable mfem::Vector mfem_z, mfem_w; // Wrap z, w
static ::occa::kernelBuilder mapDofBuilder, clearDofBuilder;
public:
/** @brief Constructor from a general Operator and a list of essential
indices/dofs.
Specify the unconstrained operator @a *A and a @a list of indices to
constrain, i.e. each entry @a list[i] represents an essential-dof. If the
ownership flag @a own_A is true, the operator @a *A will be destroyed
when this object is destroyed. */
OccaConstrainedOperator(mfem::Operator *A_,
const mfem::Array<int> &constraintList_,
bool own_A_ = false);
void Setup(::occa::device device_,
mfem::Operator *A_,
const mfem::Array<int> &constraintList_,
bool own_A_ = false);
/** @brief Eliminate "essential boundary condition" values specified in @a x
from the given right-hand side @a b.
Performs the following steps:
z = A((0,x_b)); b_i -= z_i; b_b = x_b;
where the "_b" subscripts denote the essential (boundary) indices/dofs of
the vectors, and "_i" -- the rest of the entries. */
void EliminateRHS(const Vector &x, Vector &b) const;
/** @brief Constrained operator action.
Performs the following steps:
z = A((x_i,0)); y_i = z_i; y_b = x_b;
where the "_b" subscripts denote the essential (boundary) indices/dofs of
the vectors, and "_i" -- the rest of the entries. */
virtual void Mult_(const Vector &x, Vector &y) const;
// Destructor: destroys the unconstrained Operator @a A if @a own_A is true.
virtual ~OccaConstrainedOperator();
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_OPERATOR_HPP
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
/*
---[ Defines Known At Compile-Time ]------------
TILESIZE : Tilesize for iterating over dofs
================================================
*/
@kernel void Mult(const int entries,
const int * restrict offsets,
const int * restrict indices,
const double * restrict weights,
const double * restrict in,
double * restrict out) {
for (int i = 0; i < entries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < entries) {
const int offset = offsets[i];
const int nextOffset = offsets[i + 1];
double value = 0;
for (int j = offset; j < nextOffset; ++j) {
value += weights[j] * in[indices[j]];
}
out[i] = value;
}
}
}
@kernel void MappedMult(const int entries,
const int * restrict offsets,
const int * restrict indices,
const double * restrict weights,
const int * restrict outIndices,
const double * restrict in,
double * restrict out) {
for (int i = 0; i < entries; ++i; @tile(TILESIZE, @outer, @inner)) {
if (i < entries) {
const int offset = offsets[i];
const int nextOffset = offsets[i + 1];
double value = 0;
for (int j = offset; j < nextOffset; ++j) {
value += weights[j] * in[indices[j]];
}
out[outIndices[i]] = value;
}
}
}
-248
View File
@@ -1,248 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "sparsemat.hpp"
namespace mfem
{
namespace occa
{
OccaSparseMatrix::OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
const mfem::SparseMatrix &m,
const ::occa::properties &props) :
Operator(in_layout, out_layout)
{
Setup(in_layout.OccaEngine().GetDevice(), m, props);
}
OccaSparseMatrix::OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
const mfem::SparseMatrix &m,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props) :
Operator(in_layout, out_layout)
{
Setup(in_layout.OccaEngine().GetDevice(), m,
reorderIndices, mappedIndices_, props);
}
OccaSparseMatrix::OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
::occa::array<int> offsets_,
::occa::array<int> indices_,
::occa::array<double> weights_,
const ::occa::properties &props) :
Operator(in_layout, out_layout),
offsets(offsets_),
indices(indices_),
weights(weights_)
{
SetupKernel(in_layout.OccaEngine().GetDevice(), props);
}
OccaSparseMatrix::OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
::occa::array<int> offsets_,
::occa::array<int> indices_,
::occa::array<double> weights_,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props) :
Operator(in_layout, out_layout),
offsets(offsets_),
indices(indices_),
weights(weights_),
reorderIndices(reorderIndices_),
mappedIndices(mappedIndices_)
{
SetupKernel(in_layout.OccaEngine().GetDevice(), props);
}
void OccaSparseMatrix::Setup(::occa::device device, const mfem::SparseMatrix &m,
const ::occa::properties &props)
{
Setup(device, m, ::occa::array<int>(), ::occa::array<int>(), props);
}
void OccaSparseMatrix::Setup(::occa::device device, const SparseMatrix &m,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props)
{
const int nnz = m.GetI()[height];
offsets.allocate(device,
height + 1, m.GetI());
indices.allocate(device,
nnz, m.GetJ());
weights.allocate(device,
nnz, m.GetData());
offsets.keepInDevice();
indices.keepInDevice();
weights.keepInDevice();
reorderIndices = reorderIndices_;
mappedIndices = mappedIndices_;
SetupKernel(device, props);
}
void OccaSparseMatrix::SetupKernel(::occa::device device,
const ::occa::properties &props)
{
const bool hasOutIndices = mappedIndices.isInitialized();
const ::occa::properties defaultProps("defines: {"
" TILESIZE: 256,"
"}");
const std::string &okl_path = InLayout_().OccaEngine().GetOklPath();
const std::string &okl_defines = InLayout_().OccaEngine().GetOklDefines();
mapKernel = device.buildKernel(okl_path + "mappings.okl",
"MapSubVector",
defaultProps + props + okl_defines);
multKernel = device.buildKernel(okl_path + "sparse.okl",
hasOutIndices ? "MappedMult" : "Mult",
defaultProps + props + okl_defines);
}
void OccaSparseMatrix::Mult_(const Vector &x, Vector &y) const
{
if (reorderIndices.isInitialized() ||
mappedIndices.isInitialized())
{
if (reorderIndices.isInitialized())
{
mapKernel((int) (reorderIndices.size() / 2),
reorderIndices,
x.OccaMem(), y.OccaMem());
}
if (mappedIndices.isInitialized())
{
multKernel((int) (mappedIndices.size()),
offsets, indices, weights,
mappedIndices,
x.OccaMem(), y.OccaMem());
}
}
else
{
multKernel((int) height,
offsets, indices, weights,
x.OccaMem(), y.OccaMem());
}
}
OccaSparseMatrix* CreateMappedSparseMatrix(Layout &in_layout,
Layout &out_layout,
const mfem::SparseMatrix &m,
const ::occa::properties &props)
{
const int mHeight = m.Height();
// const int mWidth = m.Width();
// Count indices that are only reordered (true dofs)
const int *I = m.GetI();
const int *J = m.GetJ();
const double *D = m.GetData();
int trueCount = 0;
for (int i = 0; i < mHeight; ++i)
{
trueCount += ((I[i + 1] - I[i]) == 1);
}
const int dupCount = (mHeight - trueCount);
// Create the reordering map for entries that aren't modified (true dofs)
::occa::device device(in_layout.OccaEngine().GetDevice());
::occa::array<int> reorderIndices(device,
2 * trueCount);
::occa::array<int> mappedIndices, offsets, indices;
::occa::array<double> weights;
if (dupCount)
{
mappedIndices.allocate(device,
dupCount);
}
int trueIdx = 0, dupIdx = 0;
for (int i = 0; i < mHeight; ++i)
{
const int i1 = I[i];
if ((I[i + 1] - i1) == 1)
{
reorderIndices[trueIdx++] = J[i1];
reorderIndices[trueIdx++] = i;
}
else
{
mappedIndices[dupIdx++] = i;
}
}
reorderIndices.keepInDevice();
if (dupCount)
{
mappedIndices.keepInDevice();
// Extract sparse matrix without reordered identity
const int dupNnz = I[mHeight] - trueCount;
offsets.allocate(device,
dupCount + 1);
indices.allocate(device,
dupNnz);
weights.allocate(device,
dupNnz);
int nnz = 0;
offsets[0] = 0;
for (int i = 0; i < dupCount; ++i)
{
const int idx = mappedIndices[i];
const int offStart = I[idx];
const int offEnd = I[idx + 1];
offsets[i + 1] = offsets[i] + (offEnd - offStart);
for (int j = offStart; j < offEnd; ++j)
{
indices[nnz] = J[j];
weights[nnz] = D[j];
++nnz;
}
}
offsets.keepInDevice();
indices.keepInDevice();
weights.keepInDevice();
}
return new OccaSparseMatrix(in_layout, out_layout,
offsets, indices, weights,
reorderIndices, mappedIndices,
props);
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-95
View File
@@ -1,95 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_SPARSE_MAT_HPP
#define MFEM_BACKENDS_OCCA_SPARSE_MAT_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include <occa.hpp>
#include "vector.hpp"
#include "engine.hpp"
#include "operator.hpp"
#include "../../linalg/sparsemat.hpp"
namespace mfem
{
namespace occa
{
/// TODO: doxygen
class OccaSparseMatrix : public Operator
{
public:
::occa::array<int> offsets, indices;
::occa::array<double> weights;
::occa::array<int> reorderIndices, mappedIndices;
::occa::kernel mapKernel, multKernel;
/// Construct an empty OccaSparseMatrix.
OccaSparseMatrix(const Operator &orig)
: Operator(orig) { }
OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
const mfem::SparseMatrix &m,
const ::occa::properties &props = ::occa::properties());
OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
const mfem::SparseMatrix &m,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props = ::occa::properties());
OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
::occa::array<int> offsets_,
::occa::array<int> indices_,
::occa::array<double> weights_,
const ::occa::properties &props = ::occa::properties());
OccaSparseMatrix(Layout &in_layout, Layout &out_layout,
::occa::array<int> offsets_,
::occa::array<int> indices_,
::occa::array<double> weights_,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props = ::occa::properties());
void Setup(::occa::device device, const mfem::SparseMatrix &m,
const ::occa::properties &props);
void Setup(::occa::device device, const mfem::SparseMatrix &m,
::occa::array<int> reorderIndices_,
::occa::array<int> mappedIndices_,
const ::occa::properties &props);
void SetupKernel(::occa::device device,
const ::occa::properties &props);
// override
virtual void Mult_(const Vector &x, Vector &y) const;
};
/// TODO: doxygen
OccaSparseMatrix* CreateMappedSparseMatrix(
Layout &in_layout, Layout &out_layout,
const mfem::SparseMatrix &m,
const ::occa::properties &props = ::occa::properties());
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_SPARSE_MAT_HPP
-81
View File
@@ -1,81 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "url_handler.hpp"
#include "../../general/error.hpp"
#include <cstdlib>
#include <sys/stat.h>
namespace mfem
{
namespace occa
{
FileOpener::FileOpener(const std::string &prefix,
const std::string &env_variable)
: pfx(prefix)
{
const char *env_path = getenv(env_variable.c_str());
if (!env_path) { return; }
std::string path(env_path);
for (std::size_t start = 0, end; start < path.size(); start = end + 1)
{
end = path.find(':', start);
if (end == std::string::npos)
{
AddDir(path.substr(start, end));
break;
}
AddDir(path.substr(start, end - start));
}
}
bool FileOpener::AddDir(const std::string &dir)
{
if (dir.size() == 0 || dir[0] != '/') { return false; }
struct stat dir_stat;
if (stat(dir.c_str(), &dir_stat)) { return false; }
if (!S_ISDIR(dir_stat.st_mode)) { return false; }
paths.push_back(dir + (*dir.rbegin() == '/' ? "" : "/"));
return true;
}
bool FileOpener::handles(const std::string &filename)
{
return filename.size() >= pfx.size() &&
filename.compare(0, pfx.size(), pfx) == 0;
}
std::string FileOpener::expand(const std::string &filename)
{
std::string sfx(filename.substr(pfx.size()));
for (std::size_t i = 0; i < paths.size(); i++)
{
std::string file = paths[i] + sfx;
struct stat file_stat;
if (stat(file.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode))
{
return file;
}
}
MFEM_ABORT("invalid url: " << filename);
return sfx;
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-47
View File
@@ -1,47 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_URL_HANDLER_HPP
#define MFEM_BACKENDS_OCCA_URL_HANDLER_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include <occa.hpp>
namespace mfem
{
namespace occa
{
class FileOpener : public ::occa::io::fileOpener
{
protected:
std::string pfx; // prefix, e.g. "mfem://"
std::vector<std::string> paths; // paths to search for prefix replacement
public:
FileOpener(const std::string &prefix, const std::string &env_variable);
bool AddDir(const std::string &dir);
virtual bool handles(const std::string &filename);
virtual std::string expand(const std::string &filename);
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_URL_HANDLER_HPP
-204
View File
@@ -1,204 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include "vector.hpp"
#include "../../linalg/vector.hpp"
namespace mfem
{
namespace occa
{
PVector *Vector::DoVectorClone(bool copy_data, void **buffer,
int buffer_type_id) const
{
MFEM_ASSERT(buffer_type_id == ScalarId<double>::value, "");
Vector *new_vector = new Vector(OccaLayout());
if (copy_data)
{
new_vector->slice.copyFrom(slice);
}
if (buffer)
{
*buffer = new_vector->GetBuffer();
}
return new_vector;
}
void Vector::DoDotProduct(const PVector &x, void *result,
int result_type_id) const
{
// Can be called when Size() == 0, e.g. when an MPI-parallel vector has a
// local size of 0.
MFEM_ASSERT(result_type_id == ScalarId<double>::value, "");
double *res = (double *)result;
MFEM_ASSERT(dynamic_cast<const Vector *>(&x) != NULL, "invalid Vector type");
const Vector *xp = static_cast<const Vector *>(&x);
MFEM_ASSERT(this->Size() == xp->Size(), "");
*res = ::occa::linalg::dot<double, double, double>(this->slice, xp->slice);
#ifdef MFEM_USE_MPI
double local_dot = *res;
if (IsParallel())
{
MPI_Allreduce(&local_dot, res, 1, MPI_DOUBLE, MPI_SUM,
OccaLayout().OccaEngine().GetComm());
}
#endif
}
void Vector::DoAxpby(const void *a, const PVector &x,
const void *b, const PVector &y,
int ab_type_id)
{
const std::string &okl_defines = OccaLayout().OccaEngine().GetOklDefines();
//
// TODO: move all kernel builders to class mfem::occa::Backend
//
static ::occa::kernelBuilder axpby1_builder =
::occa::linalg::customLinearMethod(
"mfem_occa_axpby1",
"v0[i] = c0 * v1[i];",
"defines: {"
" CTYPE0: 'double',"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" TILESIZE: '128',"
"}");
static ::occa::kernelBuilder axpby2_builder =
::occa::linalg::customLinearMethod(
"mfem_occa_axpby2",
"v0[i] = c0 * v0[i] + c1 * v1[i];",
"defines: {"
" CTYPE0: 'double',"
" CTYPE1: 'double',"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" TILESIZE: '128',"
"}");
static ::occa::kernelBuilder axpby3_builder =
::occa::linalg::customLinearMethod(
"mfem_occa_axpby3",
"v0[i] = c0 * v1[i] + c1 * v2[i];",
"defines: {"
" CTYPE0: 'double',"
" CTYPE1: 'double',"
" VTYPE0: 'double',"
" VTYPE1: 'double',"
" VTYPE2: 'double',"
" TILESIZE: '128',"
"}");
// called only when Size() != 0
MFEM_ASSERT(ab_type_id == ScalarId<double>::value, "");
const double da = *static_cast<const double *>(a);
const double db = *static_cast<const double *>(b);
MFEM_ASSERT(da == 0.0 || dynamic_cast<const Vector *>(&x) != NULL,
"invalid Vector x");
MFEM_ASSERT(db == 0.0 || dynamic_cast<const Vector *>(&y) != NULL,
"invalid Vector y");
const Vector *xp = static_cast<const Vector *>(&x);
const Vector *yp = static_cast<const Vector *>(&y);
MFEM_ASSERT(da == 0.0 || this->Size() == xp->Size(), "");
MFEM_ASSERT(db == 0.0 || this->Size() == yp->Size(), "");
if (da == 0.0)
{
if (db == 0.0)
{
OccaFill(&da);
}
else
{
if (this->slice == yp->slice)
{
// *this *= db
::occa::linalg::operator_mult_eq(slice, db);
}
else
{
// *this = db * y
::occa::kernel kernel = axpby1_builder.build(slice.getDevice(),
okl_defines);
kernel((int)Size(), db, slice, yp->slice);
}
}
}
else
{
if (db == 0.0)
{
if (this->slice == xp->slice)
{
// *this *= da
::occa::linalg::operator_mult_eq(slice, da);
}
else
{
// *this = da * x
::occa::kernel kernel = axpby1_builder.build(slice.getDevice(),
okl_defines);
kernel((int)Size(), da, slice, xp->slice);
}
}
else
{
MFEM_ASSERT(xp->slice != yp->slice, "invalid input");
if (this->slice == xp->slice)
{
// *this = da * (*this) + db * y
::occa::kernel kernel = axpby2_builder.build(slice.getDevice(),
okl_defines);
kernel((int)Size(), da, db, slice, yp->slice);
}
else if (this->slice == yp->slice)
{
// *this = da * x + db * (*this)
::occa::kernel kernel = axpby2_builder.build(slice.getDevice(),
okl_defines);
kernel((int)Size(), db, da, slice, xp->slice);
}
else
{
// *this = da * x + db * y
::occa::kernel kernel = axpby3_builder.build(slice.getDevice(),
okl_defines);
kernel((int)Size(), da, db, slice, xp->slice, yp->slice);
}
}
}
}
mfem::Vector Vector::Wrap()
{
return mfem::Vector(*this);
}
const mfem::Vector Vector::Wrap() const
{
return mfem::Vector(*const_cast<Vector*>(this));
}
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
-74
View File
@@ -1,74 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OCCA_VECTOR_HPP
#define MFEM_BACKENDS_OCCA_VECTOR_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#include <occa.hpp>
#include "../base/vector.hpp"
#include "array.hpp"
namespace mfem
{
namespace occa
{
class Vector : virtual public Array, public PVector
{
protected:
//
// Inherited fields
//
// DLayout layout;
/**
@name Virtual interface
*/
///@{
virtual PVector *DoVectorClone(bool copy_data, void **buffer,
int buffer_type_id) const;
virtual void DoDotProduct(const PVector &x, void *result,
int result_type_id) const;
virtual void DoAxpby(const void *a, const PVector &x,
const void *b, const PVector &y,
int ab_type_id);
///@}
// End: Virtual interface
public:
Vector(Layout &lt)
: PArray(lt), Array(lt, sizeof(double)), PVector(lt)
{ }
mfem::Vector Wrap();
const mfem::Vector Wrap() const;
#if defined(MFEM_USE_MPI)
bool IsParallel() const { return (OccaLayout().OccaEngine().GetComm() != MPI_COMM_NULL); }
#endif
};
} // namespace mfem::occa
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OCCA)
#endif // MFEM_BACKENDS_OCCA_VECTOR_HPP
-675
View File
@@ -1,675 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && \
defined(MFEM_USE_OMP) && \
defined(MFEM_USE_ACROTENSOR)
#include "adiffusioninteg.hpp"
namespace mfem
{
namespace omp
{
PAIntegrator::PAIntegrator(Coefficient &q, FiniteElementSpace &f)
{
Q = &q;
ofes = &f;
fes = ofes->GetFESpace();
onGPU = (ofes->OmpEngine().ExecTarget() == Device);
fe = fes->GetFE(0);
tfe = dynamic_cast<const TensorBasisElement*>(fe);
if (tfe)
{
tDofMap = tfe->GetDofMap();
}
else
{
tDofMap.SetSize(nDof);
for (int i = 0; i < nDof; ++i)
{
tDofMap[i] = i;
}
}
nElem = fes->GetNE();
GeomType = fe->GetGeomType();
FEOrder = fe->GetOrder();
nDim = fe->GetDim();
nDof = fe->GetDof();
ElementTransformation *Trans = fes->GetElementTransformation(0);
int irorder = 2*fe->GetOrder() + Trans->OrderW();
ir = &IntRules.Get(GeomType, irorder);
nQuad = ir->GetNPoints();
hasTensorBasis = tfe ? true : false;
if (nDim > 3)
{
mfem_error("AcroIntegrator tensor computations don't support dim > 3.");
}
}
PAIntegrator::~PAIntegrator()
{
}
AcroDiffusionIntegrator::AcroDiffusionIntegrator(Coefficient &q, FiniteElementSpace &f) :
PAIntegrator(q,f)
{
if (onGPU)
{
//TE.SetExecutorType("OneOutPerThread");
TE.SetExecutorType("Cuda");
//TODO: Set to an existing cuda context if one exists
}
else
{
TE.SetExecutorType("CPUInterpreted");
}
const IntegrationRule *ir1D = &IntRules.Get(Geometry::SEGMENT, ir->GetOrder());
nDof1D = FEOrder + 1;
nQuad1D = ir1D->GetNPoints();
if (hasTensorBasis)
{
H1_FECollection fec(FEOrder,1);
const FiniteElement *fe1D = fec.FiniteElementForGeometry(Geometry::SEGMENT);
mfem::Vector eval(nDof1D);
DenseMatrix deval(nDof1D,1);
B.Init(nQuad1D, nDof1D);
G.Init(nQuad1D, nDof1D);
std::vector<int> wdims(nDim, nQuad1D);
W.Init(wdims);
mfem::Vector w(nQuad1D);
for (int k = 0; k < nQuad1D; ++k)
{
const IntegrationPoint &ip = ir1D->IntPoint(k);
fe1D->CalcShape(ip, eval);
fe1D->CalcDShape(ip, deval);
B(k,0) = eval(0);
B(k,nDof1D-1) = eval(1);
G(k,0) = deval(0,0);
G(k,nDof1D-1) = deval(1,0);
for (int i = 1; i < nDof1D-1; ++i)
{
B(k,i) = eval(i+1);
G(k,i) = deval(i+1,0);
}
w(k) = ip.weight;
}
if (nDim == 1)
{
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
W(k1) = w(k1);
}
}
else if (nDim == 2)
{
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
for (int k2 = 0; k2 < nQuad1D; ++k2)
{
W(k1,k2) = w(k1)*w(k2);
}
}
}
else if (nDim == 3)
{
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
for (int k2 = 0; k2 < nQuad1D; ++k2)
{
for (int k3 = 0; k3 < nQuad1D; ++k3)
{
W(k1,k2,k3) = w(k1)*w(k2)*w(k3);
}
}
}
}
}
else
{
mfem::Vector eval(nDof);
DenseMatrix deval(nDof,nDim);
G.Init(nQuad, nDof,nDim);
W.Init(nQuad);
for (int k = 0; k < nQuad; ++k)
{
const IntegrationPoint &ip = ir->IntPoint(k);
fe->CalcDShape(ip, deval);
for (int i = 0; i < nDof; ++i)
{
for (int d = 0; d < nDim; ++d)
{
G(k,i,d) = deval(i,d);
}
}
W(k) = ip.weight;
}
}
if (onGPU)
{
B.MapToGPU();
G.MapToGPU();
W.MapToGPU();
}
// Assemble in the constructor!
BatchedPartialAssemble();
}
AcroDiffusionIntegrator::~AcroDiffusionIntegrator()
{
for (int i = 0; i < Btil.Size(); i++) delete Btil[i];
}
void AcroDiffusionIntegrator::ComputeBTilde()
{
Btil.SetSize(nDim);
for (int d = 0; d < nDim; ++d)
{
Btil[d] = new acro::Tensor(nDim, nDim, nQuad1D, nDof1D, nDof1D);
for (int m = 0; m < nDim; ++m)
{
for (int n = 0; n < nDim; ++n)
{
acro::Tensor &BGM = (m == d) ? G : B;
acro::Tensor &BGN = (n == d) ? G : B;
for (int k = 0; k < nQuad1D; ++k)
{
for (int i = 0; i < nDof1D; ++i)
{
for (int j = 0; j < nDof1D; ++j)
{
(*Btil[d])(m, n, k, i, j) = BGM(k,i)*BGN(k,j);
}
}
}
}
}
}
}
void AcroDiffusionIntegrator::BatchedPartialAssemble()
{
//Initilze the tensors
acro::Tensor J,Jinv,Jdet,C;
if (hasTensorBasis)
{
const IntegrationRule *ir1D = &IntRules.Get(Geometry::SEGMENT, ir->GetOrder());
IntegrationPoint ip;
if (nDim == 1)
{
D.Init(nElem, nDim, nDim, nQuad1D);
J.Init(nElem, nQuad1D, nDim, nDim);
Jinv.Init(nElem, nQuad1D, nDim, nDim);
Jdet.Init(nElem, nQuad1D);
C.Init(nElem, nQuad1D);
for (int e = 0; e < nElem; ++e)
{
ElementTransformation *Trans = fes->GetElementTransformation(e);
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
ip.x = ir1D->IntPoint(k1).x;
ip.y = 0.0;
ip.z = 0.0;
Trans->SetIntPoint(&ip);
C(e,k1) = Q->Eval(*Trans, ip);
const DenseMatrix &JMat = Trans->Jacobian();
for (int m = 0; m < nDim; ++m)
{
for (int n = 0; n < nDim; ++n)
{
J(e,k1,m,n) = JMat.Elem(m,n);
}
}
}
}
}
else if (nDim == 2)
{
D.Init(nElem, nDim, nDim, nQuad1D, nQuad1D);
J.Init(nElem, nQuad1D, nQuad1D, nDim, nDim);
Jinv.Init(nElem, nQuad1D, nQuad1D, nDim, nDim);
Jdet.Init(nElem, nQuad1D, nQuad1D);
C.Init(nElem, nQuad1D, nQuad1D);
for (int e = 0; e < nElem; ++e)
{
ElementTransformation *Trans = fes->GetElementTransformation(e);
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
for (int k2 = 0; k2 < nQuad1D; ++k2)
{
ip.x = ir1D->IntPoint(k1).x;
ip.y = ir1D->IntPoint(k2).y;
ip.z = 0.0;
Trans->SetIntPoint(&ip);
C(e,k1,k2) = Q->Eval(*Trans, ip);
const DenseMatrix &JMat = Trans->Jacobian();
for (int m = 0; m < nDim; ++m)
{
for (int n = 0; n < nDim; ++n)
{
J(e,k1,k2,m,n) = JMat.Elem(m,n);
}
}
}
}
}
}
else if (nDim == 3)
{
D.Init(nElem, nDim, nDim, nQuad1D, nQuad1D, nQuad1D);
J.Init(nElem, nQuad1D, nQuad1D, nQuad1D, nDim, nDim);
Jinv.Init(nElem, nQuad1D, nQuad1D, nQuad1D, nDim, nDim);
Jdet.Init(nElem, nQuad1D, nQuad1D, nQuad1D);
C.Init(nElem, nQuad1D, nQuad1D, nQuad1D);
for (int e = 0; e < nElem; ++e)
{
ElementTransformation *Trans = fes->GetElementTransformation(e);
for (int k1 = 0; k1 < nQuad1D; ++k1)
{
for (int k2 = 0; k2 < nQuad1D; ++k2)
{
for (int k3 = 0; k3 < nQuad1D; ++k3)
{
ip.x = ir1D->IntPoint(k1).x;
ip.y = ir1D->IntPoint(k2).y;
ip.z = ir1D->IntPoint(k3).z;
Trans->SetIntPoint(&ip);
C(e,k1,k2,k3) = Q->Eval(*Trans, ip);
const DenseMatrix &JMat = Trans->Jacobian();
for (int m = 0; m < nDim; ++m)
{
for (int n = 0; n < nDim; ++n)
{
J(e,k1,k2,k3,m,n) = JMat.Elem(m,n);
}
}
}
}
}
}
}
}
else
{
D.Init(nElem, nDim, nDim, nQuad);
J.Init(nElem, nQuad, nDim, nDim);
Jinv.Init(nElem, nQuad, nDim, nDim);
Jdet.Init(nElem, nQuad);
C.Init(nElem, nQuad);
for (int e = 0; e < nElem; ++e)
{
ElementTransformation *Trans = fes->GetElementTransformation(e);
for (int k = 0; k < nQuad; ++k)
{
const IntegrationPoint &ip = ir->IntPoint(k);
Trans->SetIntPoint(&ip);
C(e,k) = Q->Eval(*Trans, ip);
const DenseMatrix &JMat = Trans->Jacobian();
for (int m = 0; m < nDim; ++m)
{
for (int n = 0; n < nDim; ++n)
{
J(e,k,m,n) = JMat.Elem(m,n);
}
}
}
}
}
TE.BatchMatrixInvDet(Jinv, Jdet, J);
if (hasTensorBasis)
{
if (nDim == 1)
{
TE("D_e_m_n_k = W_k C_e_k Jdet_e_k Jinv_e_k_m_j Jinv_e_k_n_j",
D, W, C, Jdet, Jinv, Jinv);
}
else if (nDim == 2)
{
TE("D_e_m_n_k1_k2 = W_k1_k2 C_e_k1_k2 Jdet_e_k1_k2 Jinv_e_k1_k2_m_j Jinv_e_k1_k2_n_j",
D, W, C, Jdet, Jinv, Jinv);
}
else if (nDim == 3)
{
TE("D_e_m_n_k1_k2_k3 = W_k1_k2_k3 C_e_k1_k2_k3 Jdet_e_k1_k2_k3 Jinv_e_k1_k2_k3_n_j Jinv_e_k1_k2_k3_m_j",
D, W, C, Jdet, Jinv, Jinv);
}
}
else
{
TE("D_e_m_n_k = W_k C_e_k Jdet_e_k Jinv_e_k_m_j Jinv_e_k_n_j",
D, W, C, Jdet, Jinv, Jinv);
}
}
void AcroDiffusionIntegrator::BatchedAssembleElementMatrices(DenseTensor &elmats)
{
if (hasTensorBasis && Btil.Size() == 0)
{
ComputeBTilde();
}
if (!D.IsInitialized())
{
BatchedPartialAssemble();
}
if (!S.IsInitialized())
{
if (hasTensorBasis)
{
if (nDim == 1)
{
S.Init(nElem, nDof1D, nDof1D);
}
else if (nDim == 2)
{
S.Init(nElem, nDof1D, nDof1D, nDof1D, nDof1D);
}
else if (nDim == 3)
{
S.Init(nElem, nDof1D, nDof1D, nDof1D, nDof1D, nDof1D, nDof1D);
}
}
else
{
S.Init(nElem, nDof, nDof);
}
if (onGPU) {S.SwitchToGPU();}
}
if (hasTensorBasis) {
if (nDim == 1) {
TE("S_e_i1_j1 = Btil_m_n_k1_i1_j1 D_e_m_n_k1",
S, *Btil[0], D);
}
else if (nDim == 2)
{
TE("S_e_i1_i2_j1_j2 = Btil1_m_n_k1_i1_j1 Btil2_m_n_k2_i2_j2 D_e_m_n_k1_k2",
S, *Btil[0], *Btil[1], D);
}
else if (nDim == 3)
{
TE("S_e_i1_i2_i3_j1_j2_j3 = Btil1_m_n_k1_i1_j1 Btil2_m_n_k2_i2_j2 Btil3_m_n_k3_i3_j3 D_e_m_n_k1_k2_k3",
S, *Btil[0], *Btil[1], *Btil[2], D);
}
}
else
{
TE("S_e_i_j = G_k_i_m G_k_i_n D_e_m_n_k",
S, G, G, D);
}
S.MoveFromGPU();
for (int e = 0; e < nElem; ++e)
{
for (int ei = 0; ei < nDof; ++ei)
{
for (int ej = 0; ej < nDof; ++ej)
{
elmats(tDofMap[ei], tDofMap[ej], e) = S[e*nDof*nDof + ei*nDof + ej];
}
}
}
}
void AcroDiffusionIntegrator::ComputeElementMatrices(Vector &elmats)
{
if (hasTensorBasis && Btil.Size() == 0)
{
ComputeBTilde();
}
if (!D.IsInitialized())
{
BatchedPartialAssemble();
}
if (!S.IsInitialized())
{
if (hasTensorBasis)
{
if (nDim == 1)
{
S.Init(nElem, nDof1D, nDof1D);
}
else if (nDim == 2)
{
S.Init(nElem, nDof1D, nDof1D, nDof1D, nDof1D);
}
else if (nDim == 3)
{
S.Init(nElem, nDof1D, nDof1D, nDof1D, nDof1D, nDof1D, nDof1D);
}
}
else
{
S.Init(nElem, nDof, nDof);
}
if (onGPU) {S.SwitchToGPU();}
}
if (hasTensorBasis) {
if (nDim == 1) {
TE("S_e_i1_j1 += Btil_m_n_k1_i1_j1 D_e_m_n_k1",
S, *Btil[0], D);
}
else if (nDim == 2)
{
TE("S_e_i1_i2_j1_j2 += Btil1_m_n_k1_i1_j1 Btil2_m_n_k2_i2_j2 D_e_m_n_k1_k2",
S, *Btil[0], *Btil[1], D);
}
else if (nDim == 3)
{
TE("S_e_i1_i2_i3_j1_j2_j3 += Btil1_m_n_k1_i1_j1 Btil2_m_n_k2_i2_j2 Btil3_m_n_k3_i3_j3 D_e_m_n_k1_k2_k3",
S, *Btil[0], *Btil[1], *Btil[2], D);
}
}
else
{
TE("S_e_i_j += G_k_i_m G_k_i_n D_e_m_n_k",
S, G, G, D);
}
S.MoveFromGPU();
double *edata = elmats.GetData<double>();
for (int e = 0; e < nElem; ++e)
{
const int e_offset = e * nDof * nDof;
for (int ei = 0; ei < nDof; ++ei)
{
const int offset = e_offset + ei * tDofMap[ei] * nDof;
for (int ej = 0; ej < nDof; ++ej)
{
const int index = offset + tDofMap[ej];
edata[index] = S[e*nDof*nDof + ei*nDof + ej];
}
}
}
}
void AcroDiffusionIntegrator::ReassembleOperator()
{
BatchedPartialAssemble();
}
void AcroDiffusionIntegrator::PAMult(const Vector &x, Vector &y)
{
MFEM_ASSERT(hasTensorBasis,"AcroDiffusionIntegrator PAMult on simplices not supported");
if (!U.IsInitialized())
{
// NOTE: x and y are already sized for the fespace in the constructor
double *Xptr = const_cast<double*>(x.GetData<double>());
double *Yptr = y.GetData<double>();
if (nDim == 1) {
X.Init(nElem,nDof1D,Xptr,Xptr,onGPU);
Y.Init(nElem,nDof1D,Yptr,Yptr,onGPU);
U.Init(nDim, nElem, nQuad1D);
Z.Init(nDim, nElem, nQuad1D);
if (onGPU)
{
U.SwitchToGPU();
Z.SwitchToGPU();
}
}
else if (nDim == 2)
{
X.Init(nElem,nDof1D,nDof1D,Xptr,Xptr,onGPU);
Y.Init(nElem,nDof1D,nDof1D,Yptr,Yptr,onGPU);
U.Init(nDim, nElem, nQuad1D, nQuad1D);
Z.Init(nDim, nElem, nQuad1D, nQuad1D);
T1.Init(nElem,nDof1D,nQuad1D);
if (onGPU)
{
U.SwitchToGPU();
Z.SwitchToGPU();
T1.SwitchToGPU();
}
}
else if (nDim == 3)
{
X.Init(nElem,nDof1D,nDof1D,nDof1D,Xptr,Xptr,onGPU);
Y.Init(nElem,nDof1D,nDof1D,nDof1D,Yptr,Yptr,onGPU);
U.Init(nDim, nElem, nQuad1D, nQuad1D, nQuad1D);
Z.Init(nDim, nElem, nQuad1D, nQuad1D, nQuad1D);
T1.Init(nElem, nDof1D, nQuad1D, nQuad1D);
T2.Init(nElem, nDof1D, nDof1D, nQuad1D);
if (onGPU)
{
U.SwitchToGPU();
Z.SwitchToGPU();
T1.SwitchToGPU();
T2.SwitchToGPU();
}
}
}
else
{
// NOTE: x and y are already sized for the fespace in the constructor
double *Xptr = const_cast<double*>(x.GetData<double>());
double *Yptr = y.GetData<double>();
X.Retarget(Xptr,Xptr);
Y.Retarget(Yptr,Yptr);
}
acro::SliceTensor U1,U2,U3,Z1,Z2,Z3;
if (nDim == 1)
{
TE("U_n_e_k1 = G_k1_i1 X_e_i1", U, G, X);
TE("Z_m_e_k1 = D_e_m_n_k1 U_n_e_k1", Z, D, U);
TE("Y_e_i1 = G_k1_i1 Z_m_e_k1", Y, G, Z);
}
else if (nDim == 2)
{
U1.SliceInit(U, 0); U2.SliceInit(U, 1);
Z1.SliceInit(Z, 0); Z2.SliceInit(Z, 1);
//U1_e_k1_k2 = G_k1_i1 B_k2_i2 X_e_i1_i2
TE("BX_e_i1_k2 = B_k2_i2 X_e_i2_i1", T1, B, X);
TE("U1_e_k1_k2 = G_k1_i1 BX_e_i1_k2", U1, G, T1);
//U2_e_k1_k2 = B_k1_i1 G_k2_i2 X_e_i1_i2
TE("GX_e_i1_k2 = G_k2_i2 X_e_i2_i1", T1, G, X);
TE("U2_e_k1_k2 = B_k1_i1 GX_e_i1_k2", U2, B, T1);
TE("Z_m_e_k1_k2 = D_e_m_n_k1_k2 U_n_e_k1_k2", Z, D, U);
//Y_e_i1_i2 = G_k1_i1 B_k2_i2 Z1_e_k1_k2
TE("BZ1_e_i2_k1 = B_k2_i2 Z1_e_k1_k2", T1, B, Z1);
TE("Y_e_i2_i1 = G_k1_i1 BZ1_e_i2_k1", Y, G, T1);
//Y_e_i1_i2 += B_k1_i1 G_k2_i2 Z2_e_k1_k2
TE("GZ2_e_i2_k1 = G_k2_i2 Z2_e_k1_k2", T1, G, Z2);
TE("Y_e_i2_i1 += B_k1_i1 GZ2_e_i2_k1", Y, B, T1);
}
else if (nDim == 3)
{
U1.SliceInit(U, 0); U2.SliceInit(U, 1); U3.SliceInit(U, 2);
Z1.SliceInit(Z, 0); Z2.SliceInit(Z, 1); Z3.SliceInit(Z, 2);
TE.BeginMultiKernelLaunch();
//U1_e_k1_k2_k3 = G_k1_i1 B_k2_i2 B_k3_i3 X_e_i1_i2_i3
TE("T2_e_i1_i2_k3 = B_k3_i3 X_e_i1_i2_i3", T2, B, X);
TE("T1_e_i1_k2_k3 = B_k2_i2 T2_e_i1_i2_k3", T1, B, T2);
TE("U1_e_k1_k2_k3 = G_k1_i1 T1_e_i1_k2_k3", U1, G, T1);
//U2_e_k1_k2_k3 = B_k1_i1 G_k2_i2 B_k3_i3 X_e_i1_i2_i3
TE("T1_e_i1_k2_k3 = G_k2_i2 T2_e_i1_i2_k3", T1, G, T2);
TE("U2_e_k1_k2_k3 = B_k1_i1 T1_e_i1_k2_k3", U2, B, T1);
//U3_e_k1_k2_k3 = B_k1_i1 B_k2_i2 G_k3_i3 X_e_i1_i2_i3
TE("T2_e_i1_i2_k3 = G_k3_i3 X_e_i1_i2_i3", T2, G, X);
TE("T1_e_i1_k2_k3 = B_k2_i2 T2_e_i1_i2_k3", T1, B, T2);
TE("U3_e_k1_k2_k3 = B_k1_i1 T1_e_i1_k2_k3", U3, B, T1);
TE("Z_m_e_k1_k2_k3 = D_e_m_n_k1_k2_k3 U_n_e_k1_k2_k3", Z, D, U);
//Y_e_i1_i2_i3 = G_k1_i1 B_k2_i2 B_k3_i3 Z1_e_k1_k2_k3
TE("T1_e_i3_k1_k2 = B_k3_i3 Z1_e_k1_k2_k3", T1, B, Z1);
TE("T2_e_i2_i3_k1 = B_k2_i2 T1_e_i3_k1_k2", T2, B, T1);
TE("Y_e_i1_i2_i3 = G_k1_i1 T2_e_i2_i3_k1", Y, G, T2);
//Y_e_i1_i2_i3 += B_k1_i1 G_k2_i2 B_k3_i3 Z2_e_k1_k2_k3
TE("T1_e_i3_k1_k2 = B_k3_i3 Z2_e_k1_k2_k3", T1, B, Z2);
TE("T2_e_i2_i3_k1 = G_k2_i2 T1_e_i3_k1_k2", T2, G, T1);
TE("Y_e_i1_i2_i3 += B_k1_i1 T2_e_i2_i3_k1", Y, B, T2);
//Y_e_i1_i2_i3 += B_k1_i1 B_k2_i2 G_k3_i3 Z3_e_k1_k2_k3
TE("T1_e_i3_k1_k2 = G_k3_i3 Z3_e_k1_k2_k3", T1, G, Z3);
TE("T2_e_i2_i3_k1 = B_k2_i2 T1_e_i3_k1_k2", T2, B, T1);
TE("Y_e_i1_i2_i3 += B_k1_i1 T2_e_i2_i3_k1", Y, B, T2);
TE.EndMultiKernelLaunch();
}
}
void AcroDiffusionIntegrator::MultAdd(const Vector &x, Vector &y) const
{
const_cast<AcroDiffusionIntegrator*>(this)->PAMult(x, y);
}
void AcroDiffusionIntegrator::MultTransposeAdd(const Vector &x, Vector &y) const
{
mfem_error("Not supported");
}
} // namespace mfem::omp
} // namespace mfem
#endif
-95
View File
@@ -1,95 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_ADIFFUSIONINTEG_HPP
#define MFEM_BACKENDS_OMP_ADIFFUSIONINTEG_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && \
defined(MFEM_USE_OMP) && \
defined(MFEM_USE_ACROTENSOR)
#include "../../fem/bilininteg.hpp"
#include "../../fem/fem.hpp"
#include "vector.hpp"
#include "fespace.hpp"
#include "bilinearform.hpp"
#include "AcroTensor.hpp"
namespace mfem
{
namespace omp
{
class PAIntegrator : public TensorBilinearFormIntegrator
{
protected:
Coefficient *Q;
FiniteElementSpace *ofes;
mfem::FiniteElementSpace *fes;
const FiniteElement *fe;
const TensorBasisElement *tfe;
const IntegrationRule *ir;
mfem::Array<int> tDofMap;
int GeomType;
int FEOrder;
bool onGPU;
bool hasTensorBasis;
int nDim;
int nElem;
int nDof;
int nQuad;
public:
PAIntegrator(Coefficient &q, FiniteElementSpace &f);
virtual ~PAIntegrator();
};
class AcroDiffusionIntegrator : public PAIntegrator
{
private:
acro::TensorEngine TE;
int nDof1D;
int nQuad1D;
acro::Tensor B, G; //Basis and dbasis evaluated on the quad points
acro::Tensor W; //Integration weights
mfem::Array<acro::Tensor*> Btil; //Btilde used to compute stiffness matrix
acro::Tensor D; //Product of integration weight, physical consts, and element shape info
acro::Tensor S; //The assembled local stiffness matrices
acro::Tensor U, Z, T1, T2; //Intermediate computations for tensor product partial assembly
acro::Tensor X, Y;
void ComputeBTilde();
public:
AcroDiffusionIntegrator(BilinearFormIntegrator *integ);
AcroDiffusionIntegrator(Coefficient &q, FiniteElementSpace &f);
virtual ~AcroDiffusionIntegrator();
void BatchedPartialAssemble();
void BatchedAssembleElementMatrices(DenseTensor &elmats);
void ComputeElementMatrices(Vector &elmats);
void PAMult(const Vector &x, Vector &y);
virtual void MultTransposeAdd(const Vector &x, Vector &y) const;
virtual void MultAdd(const Vector &x, Vector &y) const;
virtual void ReassembleOperator();
};
} // namespace mfem::omp
} // namespace mfem
#endif
#endif
-128
View File
@@ -1,128 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include <cstring>
#include "array.hpp"
namespace mfem
{
namespace omp
{
PArray *Array::DoClone(bool copy_data, void **buffer,
std::size_t item_size) const
{
Array *new_array = new Array(OmpLayout(), item_size);
if (copy_data)
{
if (!ComputeOnDevice())
std::memcpy(new_array->GetData<void>(), data, bytes);
else
{
char *new_data = new_array->GetData<char>();
const bool use_target = ComputeOnDevice();
const bool use_parallel = Size() > 1000;
#pragma omp target teams distribute parallel for \
if (target: use_target) if (parallel: use_parallel) \
is_device_ptr(new_data)
for (std::size_t i = 0; i < bytes; i++) new_data[i] = data[i];
}
}
if (buffer)
{
*buffer = new_array->GetData<void>();
}
return new_array;
}
int Array::DoResize(PLayout &new_layout, void **buffer,
std::size_t item_size)
{
MFEM_ASSERT(dynamic_cast<Layout *>(&new_layout) != NULL,
"new_layout is not an OMP Layout");
Layout *lt = static_cast<Layout *>(&new_layout);
layout.Reset(lt); // Reset() checks if the pointer is the same
int err = ResizeData(lt, item_size);
if (!err && buffer)
{
*buffer = GetData<void>();
}
return err;
}
void *Array::DoPullData(void *buffer, std::size_t item_size)
{
// called only when Size() != 0
if (!IsUnifiedMemory() && ComputeOnDevice() && (buffer != NULL))
{
#pragma omp target update from(data)
std::memcpy(buffer, data, bytes);
}
else
{
buffer = data;
}
return buffer;
}
void Array::DoFill(const void *value_ptr, std::size_t item_size)
{
// called only when Size() != 0
switch (item_size)
{
case sizeof(int):
OmpFill((const int *)value_ptr);
break;
case sizeof(double):
OmpFill((const double *)value_ptr);
break;
default:
MFEM_ABORT("item_size = " << item_size << " is not supported");
}
}
void Array::DoPushData(const void *src_buffer, std::size_t item_size)
{
// called only when Size() != 0
std::memcpy(data, (char *) src_buffer, bytes);
if ((!IsUnifiedMemory() && ComputeOnDevice()) && (data != src_buffer))
{
#pragma omp target update to(data)
}
}
void Array::DoAssign(const PArray &src, std::size_t item_size)
{
// called only when Size() != 0
// Note: static_cast can not be used here since PArray is a virtual base
// class.
const Array *source = dynamic_cast<const Array *>(&src);
MFEM_ASSERT(source != NULL, "invalid source Array type");
MFEM_ASSERT(Size() == source->Size(), "");
// All arrays from this engine are of the same type, so we can simply check *this and assume the same is used in src.
DoPushData(source->GetData<void>(), item_size);
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-143
View File
@@ -1,143 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_ARRAY_HPP
#define MFEM_BACKENDS_OMP_ARRAY_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "layout.hpp"
#include "../base/array.hpp"
namespace mfem
{
namespace omp
{
class Array : public virtual mfem::PArray
{
protected:
//
// Inherited fields
//
// DLayout layout;
bool own_data;
std::size_t bytes;
char *data;
//
// Virtual interface
//
virtual void *DoGetData() const { return (void *) data; }
virtual PArray *DoClone(bool copy_data, void **buffer,
std::size_t item_size) const;
virtual int DoResize(PLayout &new_layout, void **buffer,
std::size_t item_size);
virtual void *DoPullData(void *buffer, std::size_t item_size);
virtual void DoFill(const void *value_ptr, std::size_t item_size);
virtual void DoPushData(const void *src_buffer, std::size_t item_size);
virtual void DoAssign(const PArray &src, std::size_t item_size);
//
// Auxiliary methods
//
inline int ResizeData(const Layout *lt, std::size_t item_size);
inline bool IsUnifiedMemory() const { return OmpLayout().OmpEngine().UnifiedMemory(); }
template <typename T>
void OmpFill(const T *pval)
{
T *ptr = (T*) data;
T val = *pval;
const bool use_target = ComputeOnDevice();
const bool use_parallel = (use_target || layout->Size() > 1000);
const std::size_t size = layout->Size();
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: ptr, val)
for (int i = 0; i < size; i++) ptr[i] = val;
}
public:
Array(Layout &lt, std::size_t item_size)
: PArray(lt),
own_data(true),
bytes(lt.Size() * item_size),
data(static_cast<char *>(lt.Alloc(bytes)))
{
#pragma omp target enter data map(alloc:data[:bytes]) if (!IsUnifiedMemory() && ComputeOnDevice())
}
Array(const Array &array)
: PArray(array.GetLayout()),
own_data(false),
bytes(array.bytes),
data(array.data) { }
inline bool ComputeOnDevice() const { return (OmpLayout().OmpEngine().ExecTarget() == Device); }
virtual ~Array()
{
#pragma omp target exit data map(delete:data[:bytes]) if (!IsUnifiedMemory() && ComputeOnDevice())
if (own_data) layout->As<Layout>().Dealloc(data);
}
inline void MakeRef(Array &master);
Layout &OmpLayout() const
{ return *static_cast<Layout *>(layout.Get()); }
};
//
// Inline methods
//
inline int Array::ResizeData(const Layout *lt, std::size_t item_size)
{
const std::size_t new_bytes = lt->Size() * item_size;
if (bytes < new_bytes)
{
#pragma omp target exit data map(delete:data)
OmpLayout().Dealloc(data);
data = static_cast<char *>(OmpLayout().Alloc(new_bytes));
MFEM_VERIFY(data != NULL, "");
// If memory allocation fails - an exception is thrown.
#pragma omp target enter data map(alloc:data[:new_bytes])
}
return 0;
}
inline void Array::MakeRef(Array &master)
{
layout = master.layout;
data = master.data;
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_ARRAY_HPP
-46
View File
@@ -1,46 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "backend.hpp"
#include "engine.hpp"
namespace mfem
{
namespace omp
{
bool Backend::Supports(const std::string &engine_spec) const
{
return true;
}
mfem::Engine *Create(const std::string &engine_spec)
{
return new Engine(engine_spec);
}
#ifdef MFEM_USE_MPI
mfem::Engine *Create(MPI_Comm comm, const std::string &engine_spec)
{
return new Engine(comm, engine_spec);
}
#endif
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-48
View File
@@ -1,48 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_BACKEND_HPP
#define MFEM_BACKENDS_OMP_BACKEND_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
// Only the Backend and Engine classes should be exposed through "backend.hpp"
#include "../base/backend.hpp"
#include "engine.hpp"
namespace mfem
{
namespace omp
{
class Backend : public mfem::Backend
{
public:
virtual ~Backend();
virtual bool Supports(const std::string &engine_spec) const;
virtual mfem::Engine *Create(const std::string &engine_spec);
#ifdef MFEM_USE_MPI
virtual mfem::Engine *Create(MPI_Comm comm, const std::string &engine_spec);
#endif
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_BACKEND_HPP
-399
View File
@@ -1,399 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "backend.hpp"
#include "bilinearform.hpp"
#include "adiffusioninteg.hpp"
namespace mfem
{
namespace omp
{
BilinearForm::~BilinearForm()
{
// Make sure all integrators free their data
for (int i = 0; i < tbfi.Size(); i++) delete tbfi[i];
delete element_matrices;
}
void BilinearForm::TransferIntegrators()
{
mfem::Array<mfem::BilinearFormIntegrator*> &dbfi = *bform->GetDBFI();
for (int i = 0; i < dbfi.Size(); i++)
{
std::string integ_name(dbfi[i]->Name());
Coefficient *scal_coeff = dbfi[i]->GetScalarCoefficient();
// ConstantCoefficient *const_coeff =
// dynamic_cast<ConstantCoefficient*>(scal_coeff);
// // TODO: other types of coefficients ...
// double val = const_coeff ? const_coeff->constant : 1.0;
if (integ_name == "(undefined)")
{
MFEM_ABORT("BilinearFormIntegrator does not define Name()");
}
else if (integ_name == "diffusion")
{
switch (OmpEngine().IntegType())
{
case Acrotensor:
tbfi.Append(new AcroDiffusionIntegrator(*scal_coeff, bform->FESpace()->Get_PFESpace()->As<FiniteElementSpace>()));
break;
default:
mfem_error("integrator is not supported for any MultType");
break;
}
}
else
{
MFEM_ABORT("BilinearFormIntegrator [Name() = " << integ_name
<< "] is not supported");
}
}
}
void BilinearForm::InitRHS(const mfem::Array<int> &ess_tdof_list,
mfem::Vector &mfem_x, mfem::Vector &mfem_b,
mfem::OperatorHandle &A,
mfem::Vector &mfem_X, mfem::Vector &mfem_B,
int copy_interior) const
{
const mfem::Operator *P = GetProlongation();
const mfem::Operator *R = GetRestriction();
if (P)
{
// Variational restriction with P
mfem_B.Resize(P->InLayout());
P->MultTranspose(mfem_b, mfem_B);
mfem_X.Resize(R->OutLayout());
R->Mult(mfem_x, mfem_X);
}
else
{
// rap, X and B point to the same data as this, x and b
mfem_X.MakeRef(mfem_x);
mfem_B.MakeRef(mfem_b);
}
if (A.Type() != mfem::Operator::ANY_TYPE)
{
A.EliminateBC(mat_e, ess_tdof_list, mfem_X, mfem_B);
}
if (!copy_interior && ess_tdof_list.Size() > 0)
{
Vector &X = mfem_X.Get_PVector()->As<Vector>();
const Array &constraint_list = ess_tdof_list.Get_PArray()->As<Array>();
double *X_data = X.GetData<double>();
const int* constraint_data = constraint_list.GetData<int>();
Vector subvec(constraint_list.OmpLayout());
double *subvec_data = subvec.GetData<double>();
const std::size_t num_constraint = constraint_list.Size();
const bool use_target = constraint_list.ComputeOnDevice();
const bool use_parallel = (use_target || num_constraint > 1000);
// This operation is a general version of mfem::Vector::SetSubVectorComplement()
// {
#pragma omp target teams distribute parallel for \
map(to: subvec_data, constraint_data, X_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++) subvec_data[i] = X_data[constraint_data[i]];
X.Fill(0.0);
#pragma omp target teams distribute parallel for \
map(to: X_data, constraint_data, subvec_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++) X_data[constraint_data[i]] = subvec_data[i];
// }
}
if (A.Type() == mfem::Operator::ANY_TYPE)
{
ConstrainedOperator *A_constrained = static_cast<ConstrainedOperator*>(A.Ptr());
A_constrained->EliminateRHS(mfem_X, mfem_B);
}
}
bool BilinearForm::Assemble()
{
if (!has_assembled)
{
TransferIntegrators();
has_assembled = true;
}
return true;
}
void BilinearForm::ComputeElementMatrices()
{
// Only called if performing full assembly
const int nelements = trial_fes->GetFESpace()->GetNE();
const int trial_ndofs = trial_fes->GetFESpace()->GetFE(0)->GetDof() * trial_fes->GetFESpace()->GetVDim();
const int test_ndofs = test_fes->GetFESpace()->GetFE(0)->GetDof() * test_fes->GetFESpace()->GetVDim();
const std::size_t length = nelements * trial_ndofs * test_ndofs;
if (!element_matrices) element_matrices = new mfem::Vector(*(new Layout(OmpEngine(), length)));
else element_matrices->Push();
element_matrices->Fill(0.0);
Vector &elmats = element_matrices->Get_PVector()->As<Vector>();
tbfi[0]->ComputeElementMatrices(elmats);
if (tbfi.Size() > 1)
{
for (int k = 1; k < tbfi.Size(); k++)
{
tbfi[k]->ComputeElementMatrices(elmats);
}
}
}
void BilinearForm::FormSystemMatrix(const mfem::Array<int> &ess_tdof_list,
mfem::OperatorHandle &A)
{
if (A.Type() == mfem::Operator::ANY_TYPE)
{
// FIXME: Support different test and trial spaces (MixedBilinearForm)
const mfem::Operator *P = GetProlongation();
mfem::Operator *rap = this;
if (P != NULL) rap = new mfem::RAPOperator(*P, *this, *P);
A.Reset(new ConstrainedOperator(rap, ess_tdof_list, (rap != this)));
return;
}
else
{
// ASSUMPTION: some sort of sparse matrix
// Compute the local matrices (stored in bform->element_matrices
ComputeElementMatrices();
bform->AllocateMatrix();
mfem::SparseMatrix &mat = bform->SpMat();
element_matrices->Pull();
double *data = element_matrices->GetData();
const bool skip_zeros = true;
mfem::Array<int> tr_vdofs, te_vdofs;
for (int i = 0; i < trial_fes->GetFESpace()->GetNE(); i++)
{
trial_fes->GetFESpace()->GetElementVDofs(i, tr_vdofs);
test_fes->GetFESpace()->GetElementVDofs(i, te_vdofs);
const mfem::DenseMatrix elmat(data, te_vdofs.Size(), tr_vdofs.Size());
mat.AddSubMatrix(te_vdofs, tr_vdofs, elmat, skip_zeros);
data += tr_vdofs.Size() * te_vdofs.Size();
}
}
if (A.Type() == mfem::Operator::MFEM_SPARSEMAT)
{
// This works because the FormSystemMatrix call with an explicit
// SparseMatrix doesnt call the backend version... This might
// change in the future.
bform->FormSystemMatrix(ess_tdof_list, static_cast<mfem::SparseMatrix&>(*A.Ptr()));
}
#ifdef MFEM_USE_MPI
else if (A.Type() == mfem::Operator::Hypre_ParCSR)
{
mfem::SparseMatrix &mat = bform->SpMat();
mfem::ParBilinearForm *pbform = dynamic_cast<mfem::ParBilinearForm*>(bform);
const bool skip_zeros = false;
mat.Finalize(skip_zeros);
// -------- FOR SOME VERY AGGREVATING REASON THIS DOESN'T WORK ---------
// mfem::ParFiniteElementSpace *pfes = pbform->ParFESpace();
// OperatorHandle dA(Operator::Hypre_ParCSR);
// // construct a parallel block-diagonal matrix 'A' based on 'a'
// dA.MakeSquareBlockDiag(pfes->GetComm(), *engine->MakeLayout(pfes->GlobalTrueVSize()),
// pfes->GetDofOffsets(), &mat);
// OperatorHandle Ph(pfes->Dof_TrueDof_Matrix());
// A.MakePtAP(dA, Ph);
// A.SetOperatorOwner(false);
// -------- BUT THIS DOES ---------
pbform->ParallelAssemble(A, &mat);
A.SetOperatorOwner(false);
// ---------------------
mat.Clear();
mat_e.Clear();
std::cout << "operator size (FormSystemMatrix): " << A.Ptr()->InLayout()->Size() << " " << A.Ptr()->OutLayout()->Size() << std::endl;
mat_e.EliminateRowsCols(A, ess_tdof_list);
}
#endif
else
{
MFEM_ABORT("Operator::Type is not supported, type = " << A.Type());
}
}
void BilinearForm::FormLinearSystem(const mfem::Array<int> &ess_tdof_list,
mfem::Vector &x, mfem::Vector &b,
mfem::OperatorHandle &A, mfem::Vector &X, mfem::Vector &B,
int copy_interior)
{
FormSystemMatrix(ess_tdof_list, A);
std::cout << "operator size (FormLinearSystem 1): " << A.Ptr()->InLayout()->Size() << " " << A.Ptr()->OutLayout()->Size() << std::endl;
InitRHS(ess_tdof_list, x, b, A, X, B, copy_interior);
}
void BilinearForm::RecoverFEMSolution(const mfem::Vector &X, const mfem::Vector &b,
mfem::Vector &x)
{
const mfem::Operator *P = GetProlongation();
if (P)
{
// Apply conforming prolongation
x.Resize(P->OutLayout());
P->Mult(X, x);
}
// Otherwise X and x point to the same data
}
void BilinearForm::Mult(const mfem::Vector &x, mfem::Vector &y) const
{
trial_fes->ToEVector(x.Get_PVector()->As<Vector>(), x_local);
y_local.Fill<double>(0.0);
for (int i = 0; i < tbfi.Size(); i++) tbfi[i]->MultAdd(x_local, y_local);
test_fes->ToLVector(y_local, y.Get_PVector()->As<Vector>());
}
void BilinearForm::MultTranspose(const mfem::Vector &x, mfem::Vector &y) const
{ mfem_error("mfem::omp::BilinearForm::MultTranspose() is not supported!"); }
ConstrainedOperator::ConstrainedOperator(mfem::Operator *A_,
const mfem::Array<int> &constraint_list_,
bool own_A_)
: Operator(A_->InLayout()->As<Layout>()),
A(A_),
own_A(own_A_),
// FIXME: @dudouit1 has a general fix for this
constraint_list(constraint_list_.Get_PArray()->As<Array>()),
z(OutLayout()->As<Layout>()),
w(OutLayout()->As<Layout>()),
mfem_z((z.DontDelete(), z)),
mfem_w((w.DontDelete(), w)) { }
void ConstrainedOperator::EliminateRHS(const mfem::Vector &mfem_x, mfem::Vector &mfem_b) const
{
w.Fill<double>(0.0);
const Vector &x = mfem_x.Get_PVector()->As<Vector>();
Vector &b = mfem_b.Get_PVector()->As<Vector>();
const double *x_data = x.GetData<double>();
double *b_data = b.GetData<double>();
double *w_data = w.GetData<double>();
const int* constraint_data = constraint_list.GetData<int>();
const std::size_t num_constraint = constraint_list.Size();
const bool use_target = constraint_list.ComputeOnDevice();
const bool use_parallel = (use_target || num_constraint > 1000);
if (num_constraint > 0)
{
#pragma omp target teams distribute parallel for \
map(to: w_data, constraint_data, x_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++)
w_data[constraint_data[i]] = x_data[constraint_data[i]];
}
A->Mult(mfem_w, mfem_z);
b.Axpby<double>(1.0, b, -1.0, z);
if (num_constraint > 0)
{
#pragma omp target teams distribute parallel for \
map(to: b_data, constraint_data, x_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++)
b_data[constraint_data[i]] = x_data[constraint_data[i]];
}
}
void ConstrainedOperator::Mult(const mfem::Vector &mfem_x, mfem::Vector &mfem_y) const
{
if (constraint_list.Size() == 0)
{
A->Mult(mfem_x, mfem_y);
return;
}
const Vector &x = mfem_x.Get_PVector()->As<Vector>();
Vector &y = mfem_y.Get_PVector()->As<Vector>();
const double *x_data = x.GetData<double>();
double *y_data = y.GetData<double>();
double *z_data = z.GetData<double>();
const int* constraint_data = constraint_list.GetData<int>();
const std::size_t num_constraint = constraint_list.Size();
const bool use_target = constraint_list.ComputeOnDevice();
const bool use_parallel = (use_target || num_constraint > 1000);
z.Assign<double>(x); // z = x
// z[constraint_list] = 0.0
#pragma omp target teams distribute parallel for \
map(to: z_data, constraint_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++)
z_data[constraint_data[i]] = 0.0;
// y = A * z
A->Mult(mfem_z, mfem_y);
// y[constraint_list] = x[constraint_list]
#pragma omp target teams distribute parallel for \
map(to: y_data, constraint_data, x_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (std::size_t i = 0; i < num_constraint; i++)
y_data[constraint_data[i]] = x_data[constraint_data[i]];
}
// Destructor: destroys the unconstrained Operator @a A if @a own_A is true.
ConstrainedOperator::~ConstrainedOperator()
{
if (own_A) delete A;
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-176
View File
@@ -1,176 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_BILINEARFORM_HPP
#define MFEM_BACKENDS_OMP_BILINEARFORM_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "fespace.hpp"
#include "array.hpp"
#include "vector.hpp"
#include "../../fem/bilininteg.hpp"
namespace mfem
{
namespace omp
{
class TensorBilinearFormIntegrator
{
public:
virtual ~TensorBilinearFormIntegrator() { }
virtual void ReassembleOperator() = 0;
virtual void ComputeElementMatrices(Vector &element_matrices)
{ mfem_error("TensorBilinaerFormIntegrator::ComputeElementMatrices is not overloaded"); }
virtual void MultAdd(const Vector &x, Vector &y) const = 0;
virtual void Mult(const Vector &x, Vector &y) const
{ y.Fill<double>(0.0); MultAdd(x, y); }
};
/// TODO: doxygen
class BilinearForm : public mfem::PBilinearForm, public mfem::Operator
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// mfem::BilinearForm *bform;
mfem::Array<TensorBilinearFormIntegrator*> tbfi;
bool has_assembled;
mutable FiniteElementSpace *trial_fes, *test_fes;
mutable Vector x_local, y_local;
mfem::Vector *element_matrices;
OperatorHandle mat_e;
void TransferIntegrators();
void ComputeElementMatrices();
void InitRHS(const mfem::Array<int> &constraint_list,
mfem::Vector &mfem_x, mfem::Vector &mfem_b,
mfem::OperatorHandle &A,
mfem::Vector &mfem_X, mfem::Vector &mfem_B,
int copy_interior = 0) const;
public:
/// TODO: doxygen
BilinearForm(const Engine &e, mfem::BilinearForm &bf)
: mfem::PBilinearForm(e, bf),
// FIXME: for mixed bilinear forms
mfem::Operator(*bf.FESpace()->GetVLayout().As<Layout>()),
tbfi(),
has_assembled(false),
trial_fes(&bf.FESpace()->Get_PFESpace()->As<FiniteElementSpace>()),
test_fes(&bf.FESpace()->Get_PFESpace()->As<FiniteElementSpace>()),
x_local(trial_fes->GetELayout()),
y_local(test_fes->GetELayout()),
element_matrices(NULL),
mat_e() { }
/// Virtual destructor
virtual ~BilinearForm();
/// Return the engine as an OpenMP engine
const Engine &OmpEngine() { return static_cast<const Engine&>(*engine); }
/** @brief Prolongation operator from linear algebra (linear system) vectors,
to input vectors for the operator. `NULL` means identity. */
virtual const Operator *GetProlongation() const { return trial_fes->GetProlongation(); }
/** @brief Restriction operator from input vectors for the operator to linear
algebra (linear system) vectors. `NULL` means identity. */
virtual const Operator *GetRestriction() const { return test_fes->GetRestriction(); }
/// Assemble the PBilinearForm.
/** This method is called from the method BilinearForm::Assemble() of the
associated BilinearForm #bform.
@returns True, if the host assembly should be skipped. */
virtual bool Assemble();
/// TODO: doxygen
virtual void FormSystemMatrix(const mfem::Array<int> &ess_tdof_list,
mfem::OperatorHandle &A);
/// TODO: doxygen
virtual void FormLinearSystem(const mfem::Array<int> &ess_tdof_list,
mfem::Vector &x, mfem::Vector &b,
mfem::OperatorHandle &A, mfem::Vector &mfem_X, mfem::Vector &mfem_B,
int copy_interior);
/// TODO: doxygen
virtual void RecoverFEMSolution(const mfem::Vector &mfem_X, const mfem::Vector &mfem_b,
mfem::Vector &mfem_x);
/// Operator application: `y=A(x)`.
virtual void Mult(const mfem::Vector &mfem_x, mfem::Vector &mfem_y) const;
/** @brief Action of the transpose operator: `y=A^t(x)`. The default behavior
in class Operator is to generate an error. */
virtual void MultTranspose(const mfem::Vector &mfem_x, mfem::Vector &mfem_y) const;
};
class ConstrainedOperator : public mfem::Operator
{
const mfem::Operator *A;
const bool own_A;
const Array constraint_list;
mutable Vector z, w;
mutable mfem::Vector mfem_z, mfem_w;
public:
ConstrainedOperator(mfem::Operator *A_,
const mfem::Array<int> &constraint_list_,
bool own_A_ = false);
// Destructor: destroys the unconstrained Operator @a A if @a own_A is true.
virtual ~ConstrainedOperator();
/** @brief Eliminate "essential boundary condition" values specified in @a x
from the given right-hand side @a b.
Performs the following steps:
z = A((0,x_b)); b_i -= z_i; b_b = x_b;
where the "_b" subscripts denote the essential (boundary) indices/dofs of
the vectors, and "_i" -- the rest of the entries. */
void EliminateRHS(const mfem::Vector &mfem_x, mfem::Vector &mfem_b) const;
/** @brief Constrained operator action.
Performs the following steps:
z = A((x_i,0)); y_i = z_i; y_b = x_b;
where the "_b" subscripts denote the essential (boundary) indices/dofs of
the vectors, and "_i" -- the rest of the entries. */
virtual void Mult(const mfem::Vector &mfem_x, mfem::Vector &mfem_y) const;
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_BILINEAR_FORM_HPP
-253
View File
@@ -1,253 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "engine.hpp"
#include "array.hpp"
#include "layout.hpp"
#include "vector.hpp"
#include "fespace.hpp"
#include "bilinearform.hpp"
#include "memory_resource.hpp"
#include <map>
namespace mfem
{
namespace omp
{
typedef std::map<std::string, std::string> keyval_pair_t;
template<typename T, typename P>
static T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
void parse_token(const std::string &token, std::string &key, std::string &val)
{
std::size_t sep = token.find_first_of(':');
if (sep > token.size()) mfem_error("Parse error");
key = token.substr(0, sep);
key.erase(mfem::omp::remove_if(key.begin(), key.end(), isspace), key.end());
key.erase(std::remove(key.begin(), key.end(), '\''), key.end());
val = token.substr(sep+1);
val.erase(mfem::omp::remove_if(val.begin(), val.end(), isspace), val.end());
val.erase(std::remove(val.begin(), val.end(), '\''), val.end());
}
keyval_pair_t parse_engine_spec(const std::string &engine_spec)
{
keyval_pair_t map;
std::size_t token_extent = 0;
std::string key, val;
while (token_extent < engine_spec.size())
{
const std::string remaining(engine_spec, token_extent);
std::size_t next_comma = remaining.find_first_of(',');
if (next_comma == std::string::npos) next_comma = engine_spec.size() - 1;
const std::string token(remaining, 0, next_comma);
parse_token(token, key, val);
map[key] = val;
token_extent += next_comma+1;
}
return map;
}
void Engine::Init(const std::string &engine_spec)
{
keyval_pair_t tokens(parse_engine_spec(engine_spec));
keyval_pair_t::iterator it;
it = tokens.find("exec_target");
if (it != tokens.end())
{
if (!std::strncmp(it->second.data(), "device", 6))
{
exec_target = Device;
device_number = 0;
}
else if (!std::strncmp(it->second.data(), "host", 4))
{
exec_target = Host;
device_number = -1;
}
else
{
mfem_error("Parse error. Possible values for exec_target are: ['host', 'device']");
}
}
else
{
// Default to host if not specified
mfem::out << "Did not specify exec_target. Defaulting to host..." << std::endl;
exec_target = Host;
device_number = -1;
}
it = tokens.find("mem_type");
if (it != tokens.end())
{
if (!std::strncmp(it->second.data(), "unified", 7))
{
#if defined(MFEM_USE_CUDAUM)
memory_resources[0] = new UnifiedMemoryResource();
unified_memory = true;
#else
mfem_error("Have not compiled support for CUDA unified memory.");
#endif
}
else if (!std::strncmp(it->second.data(), "separate", 4))
{
memory_resources[0] = new NewDeleteMemoryResource();
unified_memory = false;
}
else
{
mfem_error("Parse error. Possible values for mem_type are: ['separate', 'unified']");
}
}
else {
if (exec_target == Device)
{
#if defined(MFEM_USE_CUDAUM)
mfem::out << "Did not specify mem_type in engine spec. Defaulting to unified memory..." << std::endl;
// Default to unified memory
memory_resources[0] = new UnifiedMemoryResource();
unified_memory = true;
#else
mfem::out << "Did not specify mem_type in engine spec. Defaulting to standard host memory..." << std::endl;
memory_resources[0] = new NewDeleteMemoryResource();
unified_memory = false;
#endif
}
else
{
mfem::out << "Did not specify mem_type in engine spec. Defaulting to standard host memory..." << std::endl;
memory_resources[0] = new NewDeleteMemoryResource();
unified_memory = false;
}
}
it = tokens.find("mult_engine");
if (it != tokens.end())
{
if (!std::strncmp(it->second.data(), "acrotensor", 10))
{
mult_type = Acrotensor;
}
else
{
mfem_error("Parse error. Possible values for mem_type are: ['acrotensor'].");
}
}
else
{
mfem::out << "Did not specify mult_engine in engine spec. Defaulting to Acrotensor..." << std::endl;
#ifndef MFEM_USE_ACROTENSOR
mfem_error("Must compile with Acrotensor support");
#endif
mult_type = Acrotensor;
}
}
Engine::Engine(const std::string &engine_spec)
: mfem::Engine(NULL, 1, 1)
{
Init(engine_spec);
}
#ifdef MFEM_USE_MPI
Engine::Engine(MPI_Comm _comm, const std::string &engine_spec)
: mfem::Engine(NULL, 1, 1)
{
comm = _comm;
Init(engine_spec);
}
#endif
DLayout Engine::MakeLayout(std::size_t size) const
{
return DLayout(new Layout(*this, size));
}
DLayout Engine::MakeLayout(const mfem::Array<std::size_t> &offsets) const
{
MFEM_ASSERT(offsets.Size() == 2,
"multiple workers are not supported yet");
return DLayout(new Layout(*this, offsets.Last()));
}
DArray Engine::MakeArray(PLayout &layout, std::size_t item_size) const
{
MFEM_ASSERT(dynamic_cast<Layout *>(&layout) != NULL,
"invalid input layout");
Layout *lt = static_cast<Layout *>(&layout);
return DArray(new Array(*lt, item_size));
}
DVector Engine::MakeVector(PLayout &layout, int type_id) const
{
MFEM_ASSERT(type_id == ScalarId<double>::value, "invalid type_id");
MFEM_ASSERT(dynamic_cast<Layout *>(&layout) != NULL,
"invalid input layout");
Layout *lt = static_cast<Layout *>(&layout);
return DVector(new Vector(*lt));
}
DFiniteElementSpace Engine::MakeFESpace(mfem::FiniteElementSpace &fespace) const
{
return DFiniteElementSpace(new FiniteElementSpace(*this, fespace));
}
DBilinearForm Engine::MakeBilinearForm(mfem::BilinearForm &bf) const
{
return DBilinearForm(new BilinearForm(*this, bf));
}
void Engine::AssembleLinearForm(LinearForm &l_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
}
mfem::Operator *Engine::MakeOperator(const MixedBilinearForm &mbl_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
return NULL;
}
mfem::Operator *Engine::MakeOperator(const NonlinearForm &nl_form) const
{
/// FIXME - What will the actual parameters be?
MFEM_ABORT("FIXME");
return NULL;
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-123
View File
@@ -1,123 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_ENGINE_HPP
#define MFEM_BACKENDS_OMP_ENGINE_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "../base/engine.hpp"
namespace mfem
{
namespace omp
{
enum ExecutionTarget { Host, Device };
enum IntegratorType { Acrotensor };
class Engine : public mfem::Engine
{
protected:
//
// Inherited fields
//
// mfem::Backend *backend;
#ifdef MFEM_USE_MPI
// MPI_Comm comm;
#endif
// int num_mem_res;
// int num_workers;
// MemoryResource **memory_resources;
// double *workers_weights;
// int *workers_mem_res;
enum ExecutionTarget exec_target;
bool unified_memory;
int device_number;
IntegratorType mult_type;
void Init(const std::string &engine_spec);
public:
Engine(const std::string &engine_spec);
#ifdef MFEM_USE_MPI
Engine(MPI_Comm comm, const std::string &engine_spec);
#endif
virtual ~Engine() { }
/**
@name OMP specific interface, used by other objects in the OMP backend
*/
///@{
IntegratorType IntegType() const { return mult_type; }
ExecutionTarget ExecTarget() const { return exec_target; }
inline bool UnifiedMemory() const { return unified_memory; }
void* Malloc(std::size_t bytes) const
{
return memory_resources[0]->Allocate(bytes, 16);
}
void Dealloc(void *ptr, std::size_t bytes = 0) const
{
memory_resources[0]->Deallocate(ptr, bytes);
}
///@}
// End: OMP specific interface
/**
@name Virtual interface: finite element data structures and algorithms
*/
///@{
virtual DLayout MakeLayout(std::size_t size) const;
virtual DLayout MakeLayout(const mfem::Array<std::size_t> &offsets) const;
virtual DArray MakeArray(PLayout &layout, std::size_t item_size) const;
virtual DVector MakeVector(PLayout &layout,
int type_id = ScalarId<double>::value) const;
virtual DFiniteElementSpace MakeFESpace(mfem::FiniteElementSpace &
fespace) const;
virtual DBilinearForm MakeBilinearForm(mfem::BilinearForm &bf) const;
/// FIXME - What will the actual parameters be?
virtual void AssembleLinearForm(LinearForm &l_form) const;
/// FIXME - What will the actual parameters be?
virtual mfem::Operator *MakeOperator(const MixedBilinearForm &mbl_form) const;
/// FIXME - What will the actual parameters be?
virtual mfem::Operator *MakeOperator(const NonlinearForm &nl_form) const;
///@}
// End: Virtual interface
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_ENGINE_HPP
-237
View File
@@ -1,237 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "fespace.hpp"
namespace mfem
{
namespace omp
{
FiniteElementSpace::FiniteElementSpace(const Engine &e,
mfem::FiniteElementSpace &fespace)
: PFiniteElementSpace(e, fespace),
e_layout(e, 0),
tensor_offsets(NULL),
tensor_indices(NULL),
prolongation(NULL),
restriction(NULL)
{
std::size_t lsize = 0;
for (int e = 0; e < fespace.GetNE(); e++) { lsize += fespace.GetFE(e)->GetDof(); }
e_layout.Resize(lsize);
// The e_layout will be stored inside multiple shared DLayout objects
e_layout.DontDelete();
}
void FiniteElementSpace::BuildDofMaps()
{
mfem::FiniteElementSpace *mfem_fes = GetFESpace();
const int local_size = GetELayout().Size();
const int global_size = mfem_fes->GetVLayout()->Size();
const int vdim = mfem_fes->GetVDim();
// Now we can allocate and fill the global map
tensor_offsets = new mfem::Array<int>(*(new Layout(OmpEngine(), global_size + 1)));
tensor_indices = new mfem::Array<int>(*(new Layout(OmpEngine(), local_size)));
mfem::Array<int> &offsets = *tensor_offsets;
mfem::Array<int> &indices = *tensor_indices;
mfem::Array<int> global_map(local_size);
mfem::Array<int> elem_vdof;
int offset = 0;
for (int e = 0; e < mfem_fes->GetNE(); e++)
{
const FiniteElement *fe = mfem_fes->GetFE(e);
const int dofs = fe->GetDof();
const TensorBasisElement *tfe = dynamic_cast<const TensorBasisElement *>(fe);
const mfem::Array<int> &dof_map = tfe->GetDofMap();
mfem_fes->GetElementVDofs(e, elem_vdof);
for (int vd = 0; vd < vdim; vd++)
for (int i = 0; i < dofs; i++)
{
global_map[offset + dofs*vd + i] = elem_vdof[dofs*vd + dof_map[i]];
}
offset += dofs * vdim;
}
// global_map[i] = index in global vector for local dof i
// NOTE: multiple i values will yield same global_map[i] for shared DOF.
// We want to now invert this map so we have indices[j] = (local dof for global dof j).
// Zero the offset vector
offsets = 0;
// Keep track of how many local dof point to its global dof
// Count how many times each dof gets hit
for (int i = 0; i < local_size; i++)
{
const int g = global_map[i];
++offsets[g + 1];
}
// Aggregate the offsets
for (int i = 1; i <= global_size; i++)
{
offsets[i] += offsets[i - 1];
}
for (int i = 0; i < local_size; i++)
{
const int g = global_map[i];
indices[offsets[g]++] = i;
}
// Shift the offset vector back by one, since it was used as a
// counter above.
for (int i = global_size; i > 0; i--)
{
offsets[i] = offsets[i - 1];
}
offsets[0] = 0;
offsets.Push();
indices.Push();
}
/// Convert an E vector to L vector
void FiniteElementSpace::ToLVector(const Vector &e_vector, Vector &l_vector)
{
if (tensor_indices == NULL) BuildDofMaps();
if (l_vector.Size() != (std::size_t) GetFESpace()->GetVSize())
{
l_vector.Resize<double>(GetFESpace()->GetVLayout(), NULL);
}
const int lsize = l_vector.Size();
const int *offsets = tensor_offsets->Get_PArray()->As<Array>().GetData<int>();
const int *indices = tensor_indices->Get_PArray()->As<Array>().GetData<int>();
const double *e_data = e_vector.GetData<double>();
double *l_data = l_vector.GetData<double>();
const bool use_target = l_vector.ComputeOnDevice();
const bool use_parallel = (use_target || lsize > 1000);
#pragma omp target teams distribute parallel for \
map (to: offsets, indices, l_data, e_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (int i = 0; i < lsize; i++)
{
const int offset = offsets[i];
const int next_offset = offsets[i + 1];
double dof_value = 0;
for (int j = offset; j < next_offset; j++)
{
dof_value += e_data[indices[j]];
}
l_data[i] = dof_value;
}
}
/// Covert an L vector to E vector
void FiniteElementSpace::ToEVector(const Vector &l_vector, Vector &e_vector)
{
if (tensor_indices == NULL) BuildDofMaps();
if (e_vector.Size() != (std::size_t) e_layout.Size())
{
e_vector.Resize<double>(GetELayout(), NULL);
}
const int lsize = l_vector.Size();
const int *offsets = tensor_offsets->Get_PArray()->As<Array>().GetData<int>();
const int *indices = tensor_indices->Get_PArray()->As<Array>().GetData<int>();
const double *l_data = l_vector.GetData<double>();
double *e_data = e_vector.GetData<double>();
const bool use_target = l_vector.ComputeOnDevice();
const bool use_parallel = (use_target || lsize > 1000);
#pragma omp target teams distribute parallel for \
map (to: offsets, indices, l_data, e_data) \
if (target: use_target) \
if (parallel: use_parallel)
for (int i = 0; i < lsize; i++)
{
const int offset = offsets[i];
const int next_offset = offsets[i + 1];
const double dof_value = l_data[i];
for (int j = offset; j < next_offset; j++)
{
e_data[indices[j]] = dof_value;
}
}
}
/// Get the finite element space prolongation matrix
const Operator *FiniteElementSpace::GetProlongation() const
{
// FIXME: This relies on unified memory if using a device other than the CPU
if (!prolongation)
{
Layout &v_layout = GetVLayout();
Layout &t_layout = GetTrueVLayout();
const mfem::Operator *op = GetFESpace()->GetProlongationMatrix();
if (!op)
{
prolongation = new mfem::IdentityOperator(t_layout);
}
else
{
prolongation = new BackendOperator(t_layout, v_layout, op);
}
}
return prolongation;
}
/// Get the finite element space restriction matrix
const Operator *FiniteElementSpace::GetRestriction() const
{
// FIXME: This relies on unified memory if using a device other than the CPU
if (!restriction)
{
Layout &v_layout = GetVLayout();
Layout &t_layout = GetTrueVLayout();
const mfem::Operator *op = GetFESpace()->GetRestrictionMatrix();
if (!op)
{
restriction = new mfem::IdentityOperator(t_layout);
}
else
{
restriction = new BackendOperator(v_layout, t_layout, op);
}
}
return restriction;
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-106
View File
@@ -1,106 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_FESPACE_HPP
#define MFEM_BACKENDS_OMP_FESPACE_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "engine.hpp"
#include "array.hpp"
#include "vector.hpp"
#include "../../fem/fem.hpp"
namespace mfem
{
namespace omp
{
/*
Wraps an mfem::Operator that does not contain layout information.
*/
class BackendOperator : public mfem::Operator
{
const mfem::Operator *op;
public:
BackendOperator(Layout &in_layout, Layout &out_layout,
const mfem::Operator *op_) : Operator(in_layout, out_layout), op(op_) { }
virtual void Mult(const mfem::Vector &x, mfem::Vector &y) const { op->Mult(x, y); }
virtual void MultTranspose(const mfem::Vector &x, mfem::Vector &y) const { op->MultTranspose(x, y); }
};
/// TODO: doxygen
class FiniteElementSpace : public mfem::PFiniteElementSpace
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// mfem::FiniteElementSpace *fes;
Layout e_layout;
mfem::Array<int> *tensor_offsets, *tensor_indices;
mutable mfem::Operator *prolongation, *restriction;
void BuildDofMaps();
public:
/// Nearly-empty class that stores a pointer to a mfem::FiniteElementSpace instance and the engine
FiniteElementSpace(const Engine &e, mfem::FiniteElementSpace &fespace);
/// Virtual destructor
virtual ~FiniteElementSpace()
{
delete tensor_offsets;
delete tensor_indices;
delete prolongation;
delete restriction;
}
Layout &GetELayout() { return e_layout; }
Layout &GetVLayout() const
{ return *fes->GetVLayout().As<Layout>(); }
Layout &GetTrueVLayout() const
{ return *fes->GetTrueVLayout().As<Layout>(); }
/// Return the engine as an OpenMP engine
const Engine &OmpEngine() { return static_cast<const Engine&>(*engine); }
/// Convert an E vector to L vector
void ToLVector(const Vector &e_vector, Vector &l_vector);
/// Covert an L vector to E vector
void ToEVector(const Vector &l_vector, Vector &e_vector);
/// Get the finite element space prolongation matrix
const Operator *GetProlongation() const;
/// Get the finite element space restriction matrix
const Operator *GetRestriction() const;
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_FESPACE_HPP
-40
View File
@@ -1,40 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "layout.hpp"
#include "../../general/array.hpp"
namespace mfem
{
namespace omp
{
void Layout::Resize(std::size_t new_size)
{
size = new_size;
}
void Layout::Resize(const Array<std::size_t> &offsets)
{
MFEM_ASSERT(offsets.Size() == 2,
"multiple workers are not supported yet");
size = offsets.Last();
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-71
View File
@@ -1,71 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_LAYOUT_HPP
#define MFEM_BACKENDS_OMP_LAYOUT_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "../base/layout.hpp"
#include "engine.hpp"
namespace mfem
{
namespace omp
{
class Layout : public mfem::PLayout
{
protected:
//
// Inherited fields
//
// SharedPtr<const mfem::Engine> engine;
// std::size_t size;
public:
Layout(const Engine &e, std::size_t s = 0) : PLayout(e, s) { }
const Engine &OmpEngine() const
{ return *static_cast<const Engine *>(engine.Get()); }
void *Alloc(std::size_t bytes) const
{ return OmpEngine().Malloc(bytes); }
void Dealloc(void *ptr) const
{ return OmpEngine().Dealloc(ptr); }
virtual ~Layout() { }
/**
@name Virtual interface
*/
///@{
/// Resize the layout
virtual void Resize(std::size_t new_size);
/// Resize the layout based on the given worker offsets
virtual void Resize(const Array<std::size_t> &offsets);
///@}
// End: Virtual interface
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_LAYOUT_HPP
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "memory_resource.hpp"
#include "../../general/error.hpp"
#ifdef MFEM_USE_CUDAUM
#include "cuda_runtime.h"
#include "cuda.h"
#endif
namespace mfem
{
namespace omp
{
#ifdef MFEM_USE_CUDAUM
void *UnifiedMemoryResource::DoAllocate(std::size_t bytes,
std::size_t alignment)
{
void *p = NULL;
if (bytes > 0)
{
cudaError_t ret = cudaMallocManaged(&p, bytes);
MFEM_VERIFY(ret == cudaSuccess, "");
}
return p;
}
void UnifiedMemoryResource::DoDeallocate(void *p, std::size_t bytes,
std::size_t alignment)
{
if (p != NULL)
{
cudaFree(p);
}
}
#endif
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-44
View File
@@ -1,44 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_MEMORY_RESOURCE_HPP
#define MFEM_BACKENDS_OMP_MEMORY_RESOURCE_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "../../backends/base/memory_resource.hpp"
namespace mfem
{
namespace omp
{
/// Polymorphic memory resource. Similar to C++17's std::pmr::memory_resource.
#ifdef MFEM_USE_CUDAUM
/** @brief Memory resource using unified memory. */
class UnifiedMemoryResource : public MemoryResource
{
protected:
virtual void *DoAllocate(std::size_t bytes, std::size_t alignment);
virtual void DoDeallocate(void *p, std::size_t bytes, std::size_t alignment);
};
#endif
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_MEMORY_RESOURCE_HPP
-205
View File
@@ -1,205 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "vector.hpp"
#include "../../linalg/vector.hpp"
namespace mfem
{
namespace omp
{
PVector *Vector::DoVectorClone(bool copy_data, void **buffer,
int buffer_type_id) const
{
MFEM_ASSERT(buffer_type_id == ScalarId<double>::value, "");
Vector *new_vector = new Vector(OmpLayout());
if (copy_data)
{
const std::size_t total_size = sizeof(double) * OmpLayout().Size();
if (!ComputeOnDevice())
std::memcpy(new_vector->GetData<void>(), data, total_size);
else
{
char *new_data = new_vector->GetData<char>();
#pragma omp target teams distribute parallel for is_device_ptr(new_data)
for (std::size_t i = 0; i < total_size; i++) new_data[i] = data[i];
}
}
if (buffer)
{
*buffer = new_vector->GetData<void>();
}
return new_vector;
}
void Vector::DoDotProduct(const PVector &x, void *result,
int result_type_id) const
{
// Can be called when Size() == 0, e.g. when an MPI-parallel vector has a
// local size of 0.
MFEM_ASSERT(result_type_id == ScalarId<double>::value, "");
double *res = (double *)result;
double local_dot = 0.;
MFEM_ASSERT(dynamic_cast<const Vector *>(&x) != NULL, "invalid Vector type");
const Vector *xp = static_cast<const Vector *>(&x);
MFEM_ASSERT(this->Size() == xp->Size(), "");
const double *ptr = GetData<double>();
const double *xptr = xp->GetData<double>();
const std::size_t size = Size();
if (!ComputeOnDevice())
{
for (std::size_t i = 0; i < size; i++) local_dot += ptr[i] * xptr[i];
}
else
{
#pragma omp target teams distribute parallel for map(to: ptr, xptr) reduction(+:local_dot)
for (std::size_t i = 0; i < size; i++) local_dot += ptr[i] * xptr[i];
}
*res = local_dot;
#ifdef MFEM_USE_MPI
MPI_Comm comm = OmpLayout().OmpEngine().GetComm();
if (comm != MPI_COMM_NULL)
{
MPI_Allreduce(&local_dot, res, 1, MPI_DOUBLE, MPI_SUM, comm);
}
#endif
}
void Vector::DoAxpby(const void *a, const PVector &x,
const void *b, const PVector &y,
int ab_type_id)
{
// called only when Size() != 0
MFEM_ASSERT(ab_type_id == ScalarId<double>::value, "");
const double da = *static_cast<const double *>(a);
const double db = *static_cast<const double *>(b);
MFEM_ASSERT(da == 0.0 || dynamic_cast<const Vector *>(&x) != NULL,
"invalid Vector x");
MFEM_ASSERT(db == 0.0 || dynamic_cast<const Vector *>(&y) != NULL,
"invalid Vector y");
const Vector *xp = static_cast<const Vector *>(&x);
const Vector *yp = static_cast<const Vector *>(&y);
MFEM_ASSERT(da == 0.0 || this->Size() == xp->Size(), "");
MFEM_ASSERT(db == 0.0 || this->Size() == yp->Size(), "");
const std::size_t size = Size();
const std::size_t critical_size = 1000;
const double *xd = xp->GetData<double>();
const double *yd = yp->GetData<double>();
double *td = GetData<double>();
const bool use_target = ComputeOnDevice();
const bool use_parallel = (use_target || size > critical_size);
if (da == 0.0)
{
if (db == 0.0)
{
OmpFill(&da);
}
else
{
if (td == yd)
{
// *this *= db
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: db)
for (std::size_t i = 0; i < size; i++) td[i] *= db;
}
else
{
// *this = db * y
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: yd, db)
for (std::size_t i = 0; i < size; i++) td[i] = yd[i] * db;
}
}
}
else
{
if (db == 0.0)
{
if (td == xd)
{
// *this *= da
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: da)
for (std::size_t i = 0; i < size; i++) td[i] *= da;
}
else
{
// *this = da * x
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: xd, da)
for (std::size_t i = 0; i < size; i++) td[i] = xd[i] * da;
}
}
else
{
MFEM_ASSERT(xd != yd, "invalid input");
if (td == xd)
{
// *this = da * (*this) + db * y
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: da, td, db, yd)
for (std::size_t i = 0; i < size; i++) td[i] = da * td[i] + db * yd[i];
}
else if (td == yd)
{
// *this = da * x + db * (*this)
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: da, xd, db, td)
for (std::size_t i = 0; i < size; i++) td[i] = da * xd[i] + db * td[i];
}
else
{
// *this = da * x + db * y
#pragma omp target teams distribute parallel for \
if (target: use_target) \
if (parallel: use_parallel) map (to: da, xd, db, yd)
for (std::size_t i = 0; i < size; i++) td[i] = da * xd[i] + db * yd[i];
}
}
}
}
mfem::Vector Vector::Wrap()
{
return mfem::Vector(*this);
}
const mfem::Vector Vector::Wrap() const
{
return mfem::Vector(*const_cast<Vector*>(this));
}
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
-71
View File
@@ -1,71 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_BACKENDS_OMP_VECTOR_HPP
#define MFEM_BACKENDS_OMP_VECTOR_HPP
#include "../../config/config.hpp"
#if defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#include "../base/vector.hpp"
#include "array.hpp"
namespace mfem
{
namespace omp
{
class Vector : virtual public Array, public mfem::PVector
{
protected:
//
// Inherited fields
//
// DLayout layout;
// char *data;
// std::size_t size;
/**
@name Virtual interface
*/
///@{
virtual PVector *DoVectorClone(bool copy_data, void **buffer,
int buffer_type_id) const;
virtual void DoDotProduct(const PVector &x, void *result,
int result_type_id) const;
virtual void DoAxpby(const void *a, const PVector &x,
const void *b, const PVector &y,
int ab_type_id);
///@}
// End: Virtual interface
public:
Vector(Layout &lt)
: PArray(lt), Array(lt, sizeof(double)), PVector(lt)
{ }
mfem::Vector Wrap();
const mfem::Vector Wrap() const;
};
} // namespace mfem::omp
} // namespace mfem
#endif // defined(MFEM_USE_BACKENDS) && defined(MFEM_USE_OMP)
#endif // MFEM_BACKENDS_OMP_VECTOR_HPP
+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()
+1
View File
@@ -39,6 +39,7 @@ set(MFEM_USE_PETSC @MFEM_USE_PETSC@)
set(MFEM_USE_MPFR @MFEM_USE_MPFR@)
set(MFEM_USE_SIDRE @MFEM_USE_SIDRE@)
set(MFEM_USE_CONDUIT @MFEM_USE_CONDUIT@)
set(MFEM_USE_PUMI @MFEM_USE_PUMI@)
set(MFEM_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
set(MFEM_CXX_FLAGS "@CMAKE_CXX_FLAGS@")
+7 -4
View File
@@ -98,6 +98,9 @@
// Enable MFEM functionality based on Conduit
#cmakedefine MFEM_USE_CONDUIT
// Enable MFEM functionality based on the PUMI library
#cmakedefine MFEM_USE_PUMI
// Which library functions to use in class StopWatch for measuring time.
// For a list of the available options, see INSTALL.
// If not defined, an option is selected automatically.
@@ -106,11 +109,11 @@
// 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@
// Macro defined when PUMI is built with support for the Simmetrix SimModSuite
// library.
#cmakedefine MFEM_USE_SIMMETRIX
#endif // MFEM_CONFIG_HEADER
@@ -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()
+15 -8
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
@@ -36,12 +48,7 @@
#ifdef MFEM_USE_PETSC
#error Building with PETSc (MFEM_USE_PETSC=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#endif // MFEM_USE_MPI not defined
// Macro that returns its first arg when MFEM_USE_BACKENDS is defined, and its
// second arg if it is not defined.
#ifdef MFEM_USE_BACKENDS
#define MFEM_IF_BACKENDS(x,y) (x)
#else
#define MFEM_IF_BACKENDS(x,y) (y)
#ifdef MFEM_USE_PUMI
#error Building with PUMI (MFEM_USE_PUMI=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#endif // MFEM_USE_MPI not defined
+6 -26
View File
@@ -33,12 +33,6 @@
// Description of the git commit used to build MFEM.
// #define MFEM_GIT_STRING "@MFEM_GIT_STRING@"
// The absolute path of the MFEM source prefix
// #define MFEM_SOURCE_DIR "@MFEM_SOURCE_DIR@"
// The absolute path of the MFEM installation prefix
// #define MFEM_INSTALL_DIR "@MFEM_INSTALL_DIR@"
// Build the parallel MFEM library.
// Requires an MPI compiler, and the libraries HYPRE and METIS.
// #define MFEM_USE_MPI
@@ -115,28 +109,14 @@
// Enable functionality based on the MPFR library.
// #define MFEM_USE_MPFR
// Enable the use of MFEM backends.
// #define MFEM_USE_BACKENDS
// Enable the OCCA backend.
// #define MFEM_USE_OCCA
// Enable the OMP backend.
// #define MFEM_USE_OMP
// Enable use of acrotensor in backends.
// #define MFEM_USE_ACROTENSOR
// Enable use of unified memory.
// #define MFEM_USE_CUDAUM
// Windows specific options
#ifdef _WIN32
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
#define _USE_MATH_DEFINES
#endif
// Enable MFEM functionality based on the PUMI library
// #define MFEM_USE_PUMI
// Version of HYPRE used for building MFEM.
// #define MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
// Macro defined when PUMI is built with support for the Simmetrix SimModSuite
// library.
// #define MFEM_USE_SIMMETRIX
#endif // MFEM_CONFIG_HEADER
+1 -7
View File
@@ -13,8 +13,6 @@
MFEM_VERSION = @MFEM_VERSION@
MFEM_VERSION_STRING = @MFEM_VERSION_STRING@
MFEM_GIT_STRING = @MFEM_GIT_STRING@
MFEM_SOURCE_DIR = @MFEM_SOURCE_DIR@
MFEM_INSTALL_DIR = @MFEM_INSTALL_DIR@
MFEM_USE_MPI = @MFEM_USE_MPI@
MFEM_USE_METIS = @MFEM_USE_METIS@
MFEM_USE_METIS_5 = @MFEM_USE_METIS_5@
@@ -39,11 +37,7 @@ MFEM_USE_PETSC = @MFEM_USE_PETSC@
MFEM_USE_MPFR = @MFEM_USE_MPFR@
MFEM_USE_SIDRE = @MFEM_USE_SIDRE@
MFEM_USE_CONDUIT = @MFEM_USE_CONDUIT@
MFEM_USE_BACKENDS = @MFEM_USE_BACKENDS@
MFEM_USE_OCCA = @MFEM_USE_OCCA@
MFEM_USE_OMP = @MFEM_USE_OMP@
MFEM_USE_ACROTENSOR = @MFEM_USE_ACROTENSOR@
MFEM_USE_CUDAUM = @MFEM_USE_CUDAUM@
MFEM_USE_PUMI = @MFEM_USE_PUMI@
# Compiler, compile options, and link options
MFEM_CXX = @MFEM_CXX@
+6
View File
@@ -40,6 +40,9 @@ option(MFEM_USE_PETSC "Enable PETSc support." OFF)
option(MFEM_USE_MPFR "Enable MPFR usage." OFF)
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
@@ -145,6 +148,9 @@ set(AXOM_DIR "${MFEM_DIR}/../axom" CACHE PATH "Path to the Axom library.")
set(Axom_REQUIRED_PACKAGES "Conduit/relay" CACHE STRING
"Additional packages required by Axom.")
set(PUMI_DIR "${MFEM_DIR}/../pumi-2.1.0" CACHE STRING
"Directory where PUMI is installed")
set(BLAS_INCLUDE_DIRS "" CACHE STRING "Path to BLAS headers.")
set(BLAS_LIBRARIES "" CACHE STRING "The BLAS library.")
set(LAPACK_INCLUDE_DIRS "" CACHE STRING "Path to LAPACK headers.")
+7 -31
View File
@@ -83,9 +83,6 @@ MFEM_MPI_NP = 4
# in config.mk and config.hpp.
MFEM_USE_MPI = NO
# FIXME: add MFEM_USE_BACKENDS, MFEM_USE_OCCA to the CMake build system
MFEM_USE_BACKENDS = YES
MFEM_USE_OCCA = YES
MFEM_USE_METIS = $(MFEM_USE_MPI)
MFEM_USE_METIS_5 = NO
MFEM_DEBUG = NO
@@ -109,10 +106,7 @@ MFEM_USE_PETSC = NO
MFEM_USE_MPFR = NO
MFEM_USE_SIDRE = NO
MFEM_USE_CONDUIT = NO
# FIXME: add MFEM_USE_OMP and MFEM_USE_ACROTENSOR to the CMake build system
MFEM_USE_OMP = NO
MFEM_USE_ACROTENSOR = NO
MFEM_USE_CUDAUM = NO
MFEM_USE_PUMI = NO
# Compile and link options for zlib.
ZLIB_DIR =
@@ -278,30 +272,12 @@ SIDRE_LIB = \
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
-lsidre -lslic -laxom_utils -lconduit -lconduit_relay -lhdf5 $(ZLIB_LIB) -ldl
OCCA_DIR = @MFEM_DIR@/../occa
OCCA_OPT = -I$(OCCA_DIR)/include
OCCA_LIB = -Wl,-rpath,$(OCCA_DIR)/lib -L$(OCCA_DIR)/lib -locca
CUDA_DIR = /usr/local/cuda
CUDAUM_LIB = -L$(CUDA_DIR)/lib64 -lcudart
CUDAUM_OPT = -I$(CUDA_DIR)/include
OMP_OPT = -qsmp=omp -qoffload
ACROTENSOR_DIR = @MFEM_DIR@/../acrotensor
ACROTENSOR_OPT = -std=c++11 -I$(ACROTENSOR_DIR)/inc
ACROTENSOR_LIB = -Wl,-rpath,$(ACROTENSOR_DIR)/lib/shared -L$(ACROTENSOR_DIR)/lib/shared -lacrotensor
# If Acrotensor was compile with CUDA support, but MFEM_USE_CUDAUM==NO, then uncomment the lines below
# ACROTENSOR_OPT += -I$(CUDA_DIR)/include
# ACROTENSOR_LIB += -L$(CUDA_DIR)/lib64 -lcuda -lcudart -lnvrtc
ifeq ($(MFEM_USE_CUDAUM),YES)
ifeq ($(MFEM_USE_MPI),YES)
# HYPRE needs some extra libraries in parallel on the GPU
# FIXME: We need another solution for compilers other than XL for the
# dlink CUDA step, but fixes need to happen elsewhere as well.
HYPRE_LIB += -qcuda -lcublas -lcusparse -lnvToolsExt
endif
endif
# PUMI
# Note that PUMI_DIR is needed -- it is used to check for gmi_sim.h
PUMI_DIR = @MFEM_DIR@/../pumi-2.1.0
PUMI_OPT = -I$(PUMI_DIR)/include
PUMI_LIB = -L$(PUMI_DIR)/lib -lpumi -lcrv -lma -lmds -lapf -lpcu -lgmi -lparma\
-llion -lmth -lapf_zoltan -lspr
# If YES, enable some informational messages
VERBOSE = NO
+11 -2
View File
@@ -38,6 +38,9 @@ all: header config-mk
MPI = $(MFEM_USE_MPI:NO=)
GHV = get_hypre_version
GHV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(HYPRE_OPT))
SMX = $(if $(MFEM_USE_PUMI:NO=),MFEM_USE_SIMMETRIX)
SMX_PATH = $(PUMI_DIR)/include/gmi_sim.h
SMX_FILE = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(SMX_PATH))
$(GHV): $(SRC)$(GHV).cpp
$(call mfem-info, Determining HYPRE version ...)
@@ -52,10 +55,16 @@ get-hypre-version: $(GHV).out
$(info HYPRE version: $(MFEM_HYPRE_VERSION)),\
$(error Unable to determine HYPRE version))
header: $(if $(MPI),get-hypre-version,)
check-smx:
$(call mfem-info, Checking for Simmetrix header [$(SMX_FILE)] ...)
$(eval MFEM_USE_SIMMETRIX:=$(if $(wildcard $(SMX_FILE)),YES,NO))
$(call mfem-info, MFEM_USE_SIMMETRIX = $(MFEM_USE_SIMMETRIX))
$(eval export MFEM_USE_SIMMETRIX)
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx)
$(call mfem-info, Writing $(CONFIG_HPP) ...)
@set -- && \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION,); do \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX); do \
eval var=\$$$$def && \
if [ "NO" != "$${var}" ]; then \
set -- "$$@" -e "s|// \(#define $${def} \)|\1|" && \
+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"
+5 -2
View File
@@ -14,11 +14,13 @@
# Colors used below:
# green '\033[0;32m'
# red '\033[0;31m'
# yellow '\033[0;33m'
# no color '\033[0m'
COLOR_PRINT = if [ -t 1 ]; then \
printf $(1)$(2)'\033[0m'$(3); else printf $(2)$(3); fi
PRINT_OK = $(call COLOR_PRINT,'\033[0;32m',OK," ($$1 $$2)\n")
PRINT_FAILED = $(call COLOR_PRINT,'\033[0;31m',FAILED," ($$1 $$2)\n")
PRINT_SKIP = $(call COLOR_PRINT,'\033[0;33m',SKIP,"\n")
# Timing support
define TIMECMD_detect
@@ -36,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
@@ -58,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

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