Compare commits

...
88 Commits
Author SHA1 Message Date
Robert 1b31e07cbd Merge remote-tracking branch 'upstream/feature/partial_ess_bcs' into exaconstit-csr 2022-06-07 11:03:02 -07:00
Robert 63db5c481c fix build issue noted on github ci 2022-06-07 10:45:36 -07:00
Robert da100e4205 make style 2022-06-07 10:34:25 -07:00
Robert 1ae09de13d Merge remote-tracking branch 'origin/master' into feature/partial_ess_bcs 2022-06-07 10:14:43 -07:00
Robert cfcdffd0b1 Removed duplicated code to address reviewers comments
Removed the more or less duplicated FESpace::GetEssentialVDofs and moved the necessary book-keeping portions of things to GetEssentialTrueDofs
Additionally, I added an overwrite optional variable (defaulted to true) to GetEssentialVDofs in-order to allow one to overwrite the values of ess_vdofs if they'd like.
I still need to add some unit tests for the functionality though.
2022-06-07 10:10:31 -07:00
Robert 8216f862ce fix doxygen comments 2022-02-22 14:47:14 -08:00
Robert 6dabc0341e make style 2022-02-22 12:50:21 -08:00
Robert c328515f93 Changes from ExaConstit mfem branch that are useful for having varying partial Essential DOFs per boundary attribute 2022-02-22 12:42:03 -08:00
Robert d8a811cd0f Merge branch 'exaconstit-dev' into exaconstit-csr 2022-02-18 12:22:03 -08:00
Robert 0fb3ee7e98 Merge branch 'master' into exaconstit-dev 2022-02-18 12:21:37 -08:00
Robert Carson 444fa76832 Various fixes needed for BCs usage in exaconstit 2022-02-11 16:29:10 -08:00
Robert 5ebca1fc46 Merge fixes 2021-07-29 11:00:07 -07:00
Robert 6e2a238bfd Merge remote-tracking branch 'upstream/mfem-4.3-dev' into exaconstit-mfem-4.3-test 2021-07-29 10:31:45 -07:00
Robert 87d45dd5a6 Features needed for changing BCs in ExaConstit 2021-01-20 15:29:43 -08:00
Robert 77742567de Merge branch 'master' into exaconstit-dev 2020-12-17 12:45:58 -08:00
Robert 61840db326 Add Assemble Element Assembly hooks into NLFIntegrator class 2020-06-19 16:34:04 -07:00
Robert a365b639b9 Add AssembleDiagonalPA to NonlinearFormIntegrator class 2020-06-18 11:25:14 -07:00
Robert 8b4125f5d6 Merge branch 'master' into exaconstit-dev 2020-06-05 14:57:40 -07:00
Robert 1d3f056641 Merge branch 'master' into exaconstit-dev 2020-03-30 15:13:19 -07:00
Robert a32294af71 Merge branch 'master' into exaconstit-dev 2020-03-13 17:17:13 -07:00
Robert 589c1eeeea Merge branch 'master' into exaconstit-dev 2020-03-08 10:31:02 -07:00
rcarson3 cdd38a6419 Changes related CUDA runs for ExaConstit 2020-02-14 16:38:35 -08:00
rcarson3 d7a56a008a Merge branch 'master' into exaconstit-dev 2020-02-14 16:23:08 -08:00
rcarson3 5e2dccbbc9 NonlinearFormIntegrator addition to allow for Partial Assembly for GetGradient methods 2020-02-03 18:55:29 -08:00
rcarson3 3a296deaff Fix merge issues related IntegrationPoints.index
During the merge there were some leftover parts that used the old integration point ipID rather than the index.
2020-02-03 18:53:10 -08:00
rcarson3 640e35f419 Merge remote-tracking branch 'origin/master' into exaconstit-dev 2020-02-03 17:59:31 -08:00
rcarson3 df2e2fc516 Merge branch 'exaconstit-dev' of https://github.com/rcarson3/mfem into exaconstit-dev 2019-10-16 14:16:04 -07:00
rcarson3 beec7406cb Remove proof of concept xtal plasticity miniapp
The miniapp is no longer needed now that ExaConstit is a full fledge app available on LLNL's github page
2019-10-16 14:12:54 -07:00
rcarson3 a660b511df Merge branch 'master' into exaconstit-dev 2019-10-02 10:45:03 -07:00
Robert Carson ca8363c3e7 Bug fix in VectorFunctionRestrictedCoefficient class
Left in a small bug when updating the VectorFunctionRestrictedCoefficient class
2019-08-14 16:15:39 -07:00
rcarson3 20369095e7 Reduce number of variables passed into VectorFunctionRestrictedCoefficient's TDFunction
This was a class added by ExaConstit to MFEM's main library. It turns out that the function pointer used in that class requires fewer variables than were being used.
2019-08-02 15:30:26 -07:00
rcarson3 acb8766d23 Conduit fixes
Found a few buges. Conduit should now work no matter what. I ended up swapping back to using the MFEM Find_Conduit package to locate Conduit, since SPACK doesn't include all of the nice CMAKE config files.
2019-07-31 15:47:37 -07:00
rcarson3 abe80d02c2 Add support for Conduit post-processing files
Conduit provides a single binary data file that contains all of the outputted variables for each processor which greatly reduces the number of files created when using a large number of processors.
2019-07-31 14:07:26 -07:00
rcarson3 bf0e7c5d22 Merge local branch 'exaconstit-dev-4.0rc1' into exaconstit-dev 2019-07-31 13:47:47 -07:00
rcarson3 b5e5364b63 Better Initial Step Guess
The first initial step for the Exacmech model now constructs the tangent stiffness matrix by making the assumption that there is no velocity applied anywhere. This should result in the purely elastic stiffness matrix being returned. The stress during this step is still solved for with the applied velocity boundary condition. Overall, I have found this to lead to quicker solutions for the larger problem sizes.
2019-07-31 13:39:16 -07:00
rcarson3 f05f805cf9 Rectangular meshes autogenerated now supported
Rectangular meshes can now be specified in the option file and they'll be auto generated.
Also, the grain ID reordering is no longer required since the CA results now return things in the xyz ordering
2019-07-31 13:22:11 -07:00
Robert Carson 03213ce2f7 Minor bug fix to Vector.cpp
Forgot to include this bug fix in my updates.
2019-07-02 20:47:32 -07:00
Robert Carson 0d124d1aa9 Merge pull request #2 from rcarson3/exaconstit-dev-4.0rc1
MFEMv4.0 and initial c++ material model support
2019-07-02 15:49:46 -07:00
rcarson3 7ea8265a83 Bug fixes related to projection/data output
A bug was found in the QuadratureVectorFunction Eval method and was fixed. The projected quaternions are now returned normalized. The default precision for the Visit output has been increased to 12 decimal points. The projected stress is also now returned.
2019-07-02 15:46:16 -07:00
rcarson3 374f9a650c Added more data outputs for newer material models
If the newer C++ models are being used then additional data is outputted using the MFEM visit data format. Some of these formats can't be viewed in Visit itself.
2019-06-22 13:18:50 -07:00
rcarson3 e530f0f13b Bug fix for MTS like model
For the properties a total of 24 were needed instead of 23. I'd missed one while I was counting them all up.
2019-06-20 14:26:45 -07:00
rcarson3 be4dcbeb3d Bug fixes related to ExaCMech integration
Several bug fixes were needed to get at least the Voce ExaCMech model properly running in ExaConstit. The Kocks-Mecking model still hasn't been fully tested at this point.
2019-06-20 11:40:58 -07:00
rcarson3 51f6dbac7c Added plumbing for ExaCMech type models and makefile replaced with CMake plus reorganizing files/dirs
The initial plumbing for ExaCMech has been added. Also, the old makefile was getting tough to  keep up with. Therefore, I've made the move over to using CMake. The current implementation of this is rather ugly and really could use some help to not require the user to pass in where all the different libraries are located. Next, I haven't checked to see if moving over to this build system has broken any of the old code. Further testing is required.
2019-06-16 12:26:06 -07:00
rcarson3 a71548f0ba Merge branch 'master' into exaconstit-dev-4.0rc1 2019-06-12 15:41:53 -07:00
Robert Carson f8f48e1327 Merge pull request #1 from rcarson3/exaconstit-dev-4.0rc1
Exaconstit dev 4.0rc1
2019-04-25 12:38:13 -07:00
rcarson3 1fa911f522 Typo fix 2019-04-25 12:35:31 -07:00
rcarson3 2d06a2dda5 Bug fix related to updated inline mesh generation options
The newer inline mesh generation introduced in the pre-okina tag of MFEM changed how elements were ordered according to a space-filling order. This option was made default in-order to satisfy some issues related to non-conforming meshes. It turns out this caused some diverging material responses in some of our standard monotonic tension tests out to 1% strain when using symmetric BCs. We therefore need to tell the inline mesh generator that we want to use the old lexicographic ordering.
2019-04-25 12:16:28 -07:00
rcarson3 0bab3cb3dd Merge tag 'v4.0-rc1' into exaconstit-dev-4.0rc1
Release candidate #1 for version 4.0
2019-04-24 09:15:52 -07:00
rcarson3 d07f450843 Fix Potential Higher Order Bug
When using higher order elements the mesh wasn't initially promoted to the higher order element. Although, it was later on in the code when the original nodes are swapped out for beggining time step gridfunction. Next, it was noted that the mesh being printed out does not include the higher order mesh... I'm not exactly sure why this is the case.
2019-04-09 16:09:36 -07:00
rcarson3 976809a942 Get rid of compiler warnings and add hydrostatic stress as a visit output
Fixed the various compiler warnings that we were getting. The hydrostatic stress was also added as an output to the Visit files.
2019-04-01 13:09:04 -07:00
rcarson3 09fc9c6744 Modified Newton Raphson method added and some basic timers
A modified newton raphson method has been added in place of the old pure newton raphson. It's nothing fancy it just sets the relaxation factor for the next time step to 0.5 if it notes that the ratio in the norm of the current residual and the previous residual hasn't decreased by a factor of 10 or greater. The relaxation factor is set to 1.0 if it is converging fast enough. The main motivation behind this is to push the solution in the right direction when it starts to oscillate the actual answer. Next, a few basic timers have been set around the entire solution set to provide some very basic profiling for how long each time step takes to solve.
2019-02-26 09:04:06 -08:00
rcarson3 31cc114950 Refactor code related to UMAT in anticipation of writing GPGPU kernels for some of the UMAT code
Several changes were made to the code, but one of the biggest is the computation of all of the incremental and end time step deformation gradients all at once. Next, the local shape function gradiants associated with the initial mesh are saved, so we don't have to constantly swap between the beginning and end time step coordinates. From these changes, a few other functions have been touched. Overall, it looks like this new method does provide more stability when running certain types of xtal plasticity problems that caused the old method to fail. I have a feeling this was related to the end time step deformation gradient being calculated as F_end = F_incr F_beg which over time could lead to problems from floating point errors.
2019-02-14 16:11:20 -08:00
rcarson3 c33e377f75 Fix bug related to ProjectCoefficients for quadrature functions
The integration point ids were not initially set which was causing issues related to quadrature functions to grid functions.
2019-02-08 15:49:24 -08:00
rcarson3 3a6a3bdd35 Moved the NonlinearMechOperator class to its own file
The NonlinearMechOperator had previously been residing in the mechanics_driver file even though it was a fairly lengthy and extensive class. It has since been moved over to the mechanics_operator file, so it should now be easier to navigate and modify both the operator class and the functions/procedures related to the driver.
2019-02-06 12:27:02 -08:00
rcarson3 8559c826a6 Remove hyperelastic model and some minor bug fixes
The hyper elastic model was no longer supported when the code base was swapped over to a velocity based solution field. Therefore, it has been removed from the code base. Hyperelastic type models can still be used in this code through the UMAT interface. Next, a logical bug was introduced when portions of the checkMaterialArgs function were commented out in the last commit. This bug has since been fixed.
2019-02-06 11:47:54 -08:00
rcarson3 17b39bf850 New option file driver replacing old command line option driver
The old command line option driver has been completely replaced by a TOML file option driver. The new option file allowed us to move all of the various options over to a single class. It also allowed for the removal of several checks that were put into place related to the mesh and orientation types being used. Now only one type may be supplied at a time. This commit does rely on several C++11 features in order to work, and these are mainly found in the TOML parser.
2019-02-04 13:18:40 -08:00
rcarson3 e9d9ab94d8 Reduce runtime print output
Several functions were accidentally having all processors print out info. A small change has been made so now only 1 processor should be outputting data.
2019-01-25 14:52:20 -08:00
rcarson3 81baed1c1c Add a first step ramp solver for when solution doesn't converge
It was found with large meshes that the initial applied boundary conditions would not converge. However, the solution would converge if some reduced value of the initial applied boundary conditions is applied. Therefore, an initial step solver is added that ramps up the solution to the desired applied boundary conditions if it doesn't converge initially. After the first step, the old solver is used.
2019-01-24 16:04:27 -08:00
rcarson3 9d75ab3303 Preconditioner update for PCG
After a few discussions on mfem github issue #725, it was discussed that a few preconditioner options were leading to the bug noted in the PCG solver. The new changes seen here seemed to resolve these issues.
2019-01-22 13:36:55 -08:00
rcarson3 75039da7e4 Make GMRES default solver and bug fix to hexmesh BCs
The automatic hexmesh generated from the -hexmesh option was incorrectly relabeling the boundary element attributes over to the ExaConstit convention. This commit fixes this issue. Next, a bug appears to exist in the PCG iterative solver, and therefore the GMRES solver is being set to the default solver until the bug is found and fixed in the PCG solver.
2019-01-18 12:11:07 -08:00
Tzanio fd87a574a0 make style 2019-01-16 10:32:40 -08:00
rcarson3 4e8e1a1276 Merge branch 'master' into exaconstit-dev 2019-01-15 14:09:49 -08:00
rcarson3 69ce10a116 Bug fixes, preconditioner updates, and residual reformulations
A few bug fixes related to the strain calculations were found and fixed. A specific preconditioner is being used based on being used in other xtal plasticity codes that group members have used. The residual has been updated to explicitly solve for the divergence of the cauchy stress. The material stiffness matrix for the UMATs has also been updated so it now has something akin to the d sigma/d def_rate so we get out the divergence of cauchy stress for our [B]^t [C_stiff] [B] {Velocity} calculation.
2019-01-15 13:53:10 -08:00
rcarson3 07e296698c Rebase ExaConstit so it is now a velocity-based FEM code
Rewrote ExaConstit so that it solves for the velocity field instead of the displacement field. The advantages of this are that many crystal plasticity methods use quantities derived from the velocity gradient. Therefore, it's a lot easier to deal with these quantities when your solution field is the velocity field. One can also think of this as changing the code base from an Updated Total Lagrangian formulation to an Updated Lagrangian formulation.
2019-01-08 13:30:05 -08:00
rcarson3 6e814c7e1b Merge branch 'master' into exaconstit-dev 2018-11-16 09:40:00 -08:00
rcarson3 5b64fcc6ac Small bug fix related to how some UMAT variables were being initialized 2018-11-16 09:33:41 -08:00
rcarson3 e3c8fbc5c9 Bug fixes related to BC and reduced number of prints in driver file when running in parallel 2018-11-15 13:58:44 -08:00
rcarson3 bf1d5e8f23 Additional bug fixes, small refactoring, and added functionality 2018-11-12 14:22:09 -08:00
rcarson3 b566f22027 Bug fixes, added a few unit tests, and additional features added 2018-11-06 12:17:57 -08:00
rcarson3 655feea5e6 Merge latest changes from mfem/exaconstit-dev/branch 2018-10-05 13:24:38 -07:00
Steven Robert Wopschall 29239e34bf including bash script to run isochoric compression problem 2018-10-04 21:06:41 -07:00
Steven Robert Wopschall b0e94cfa70 functioning hyperelastic implementation for Robert to use to debug quadrature functions on the ExaModel 2018-10-04 20:59:00 -07:00
rcarson3 3ae3550282 Fixed the GetEssentialVDofs and GetEssentialTrueDofs issue related to examples not compiling 2018-09-21 09:22:34 -07:00
Carson a8dc62a6cf Merged changes from master branch into exaconstit-dev 2018-09-17 11:45:11 -07:00
Steven Robert Wopschall 7ebd03cb7f compiling version of the code with the ExaModel interface implementation 2018-09-05 15:43:05 -07:00
Steven Robert Wopschall b5332c0512 code is not debugged and tested, last commit works, this commit introduces incremental form, new model class, extensive work to umat interface, etc. 2018-08-09 16:10:21 -07:00
Steven Robert Wopschall 0c1103c6b5 added version printout and removed debug prints 2018-04-20 08:22:04 -07:00
Steven Robert Wopschall 2fba048e2b added quadrature functions for cp grain orientations, state variables, stress; added a boundary condition manager to more easily handle essential BCs; added plumbing for user defined material models including a UMAT interface; added a quadrature function coefficient wrapper; tested and debugged serial and parallel refinement and boundary conditions on isochoric cube compression problem using native NeoHookean hyperelastic model 2018-04-19 15:31:08 -07:00
Steven Robert Wopschall 3eed69f9db added a vector set function, a VectorFunctionCoefficient constructor, a GetElement QuadratureFunction routine and the mechanics coefficient and integrator files 2018-03-13 20:49:58 -07:00
Steven Robert Wopschall ed74c45d81 merging branch master into exavconstit-dev
Merge branch 'master' of https://github.com/mfem/mfem into exaconstit-dev
2018-01-25 09:33:02 -08:00
Steven R. Wopschall f36d0903cf fixed merge conflict in driver 2017-09-28 08:54:16 -07:00
Steven R. Wopschall 60ca5e54c1 slight modification to comments in driver and boundary ordering in cube-hex.mesh 2017-09-28 08:52:09 -07:00
Jamie A. Bramwell fa0eac49c6 Fixed run command in driver file 2017-09-27 15:28:56 -07:00
Steven R. Wopschall 97eee74bd6 added cube-hex mesh to be run with ExaConstit miniapp 2017-09-27 14:56:01 -07:00
Steven R. Wopschall d95afacf4b "made changes to gridfunc files"
Merge branch 'exaconstit-dev' of https://github.com/mfem/mfem into exaconstit-dev
2017-09-27 14:43:22 -07:00
Steven R. Wopschall b9e4a76487 modified gridfunc files to get branch up to date 2017-09-27 14:31:59 -07:00
Jamie A. Bramwell cad582afd2 Build fixes and cleanup 2017-09-27 13:15:53 -07:00
Jamie A. Bramwell 229073893d Moving over Steve Wopschall's initial implementation 2017-09-27 12:54:10 -07:00
20 changed files with 865 additions and 23 deletions
+86
View File
@@ -0,0 +1,86 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
#
dimension
3
elements
8
1 5 0 1 10 9 3 4 13 12
1 5 1 2 11 10 4 5 14 13
1 5 3 4 13 12 6 7 16 15
1 5 4 5 14 13 7 8 17 16
1 5 9 10 19 18 12 13 22 21
1 5 10 11 20 19 13 14 23 22
1 5 12 13 22 21 15 16 25 24
1 5 13 14 23 22 16 17 26 25
#
boundary
24
1 3 1 0 9 10
1 3 2 1 10 11
1 3 10 9 18 19
1 3 11 10 19 20
2 3 0 3 12 9
2 3 9 12 21 18
2 3 3 6 15 12
2 3 12 15 24 21
3 3 0 1 4 3
3 3 1 2 5 4
3 3 3 4 7 6
3 3 4 5 8 7
4 3 6 7 16 15
4 3 7 8 17 16
4 3 15 16 25 24
4 3 16 17 26 25
5 3 18 21 22 19
5 3 19 22 23 20
5 3 21 24 25 22
5 3 22 25 26 23
6 3 2 11 14 5
6 3 11 20 23 14
6 3 5 14 17 8
6 3 14 23 26 17
vertices
27
3
0.0 0.0 0.0
0.5 0.0 0.0
1.0 0.0 0.0
0.0 0.0 0.5
0.5 0.0 0.5
1.0 0.0 0.5
0.0 0.0 1.0
0.5 0.0 1.0
1.0 0.0 1.0
0.0 0.5 0.0
0.5 0.5 0.0
1.0 0.5 0.0
0.0 0.5 0.5
0.5 0.5 0.5
1.0 0.5 0.5
0.0 0.5 1.0
0.5 0.5 1.0
1.0 0.5 1.0
0.0 1.0 0.0
0.5 1.0 0.0
1.0 1.0 0.0
0.0 1.0 0.5
0.5 1.0 0.5
1.0 1.0 0.5
0.0 1.0 1.0
0.5 1.0 1.0
1.0 1.0 1.0
+84
View File
@@ -0,0 +1,84 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
#
dimension
3
elements
8
1 5 0 1 4 3 9 10 13 12
1 5 1 2 5 4 10 11 14 13
1 5 9 10 13 12 18 19 22 21
1 5 10 11 14 13 19 20 23 22
1 5 3 4 7 6 12 13 16 15
1 5 4 5 8 7 13 14 17 16
1 5 12 13 16 15 21 22 25 24
1 5 13 14 17 16 22 23 26 25
boundary
24
1 3 0 1 10 9
1 3 1 2 11 10
1 3 9 10 19 18
1 3 10 11 20 19
3 3 0 3 4 1
3 3 1 4 5 2
3 3 3 6 7 4
3 3 4 7 8 5
3 3 18 19 22 21
3 3 19 20 23 22
3 3 21 22 25 24
3 3 22 23 26 25
3 3 2 5 14 11
3 3 11 14 23 20
3 3 5 8 17 14
3 3 14 17 26 23
3 3 0 9 12 3
3 3 9 18 21 12
3 3 3 12 15 6
3 3 12 21 24 15
2 3 6 15 16 7
2 3 7 16 17 8
2 3 15 24 25 16
2 3 16 25 26 17
vertices
27
3
0.0 0.0 0.0
0.5 0.0 0.0
1.0 0.0 0.0
0.0 0.0 0.5
0.5 0.0 0.5
1.0 0.0 0.5
0.0 0.0 1.0
0.5 0.0 1.0
1.0 0.0 1.0
0.0 0.5 0.0
0.5 0.5 0.0
1.0 0.5 0.0
0.0 0.5 0.5
0.5 0.5 0.5
1.0 0.5 0.5
0.0 0.5 1.0
0.5 0.5 1.0
1.0 0.5 1.0
0.0 1.0 0.0
0.5 1.0 0.0
1.0 1.0 0.0
0.0 1.0 0.5
0.5 1.0 0.5
1.0 1.0 0.5
0.0 1.0 1.0
0.5 1.0 1.0
1.0 1.0 1.0
+24
View File
@@ -517,6 +517,30 @@ void VectorRestrictedCoefficient::Eval(
}
}
void VectorFunctionRestrictedCoefficient::Eval(Vector &V,
ElementTransformation &T,
const IntegrationPoint &ip)
{
double x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
V.SetSize(vdim);
if (active_attr[T.Attribute-1])
{
(*TDFunction)(T.Attribute, V);
}
else
{
V = 0.0;
}
if (Q)
{
V *= Q->Eval(T, ip, GetTime());
}
}
void PWMatrixCoefficient::InitMap(const Array<int> & attr,
const Array<MatrixCoefficient*> & coefs)
{
+38
View File
@@ -439,12 +439,19 @@ public:
/// Initialize the VectorCoefficient with vector dimension @a vd.
VectorCoefficient(int vd) { vdim = vd; time = 0.; }
// add constructor with no argument list (this is for the
// QuadratureVectorFunctionCoefficient extended class), srw
VectorCoefficient() { vdim = 0; time = 0.; }
/// Set the time for time dependent coefficients
virtual void SetTime(double t) { time = t; }
/// Get the time for time dependent coefficients
double GetTime() { return time; }
/// Set the dimension of the vector.
void SetVDim(int dim) { vdim = dim; }
/// Returns dimension of the vector.
int GetVDim() { return vdim; }
@@ -870,6 +877,37 @@ public:
const IntegrationRule &ir);
};
/// VectorFunctionCoefficient defined on a subset of domain or boundary attributes, srw
class VectorFunctionRestrictedCoefficient : public VectorCoefficient
{
private:
void (*TDFunction)(int, Vector &);
const Array<int> &active_attr;
const Array2D<double> &active_scale;
Coefficient *Q;
public:
/// Construct a time-dependent vector coefficient from a C-function
VectorFunctionRestrictedCoefficient(int dim,
void (*TDF)(int, Vector &),
Array<int> &attr,
Array2D<double> &scale,
Coefficient *q = NULL)
: VectorCoefficient(dim), Q(q), active_attr(attr), active_scale(scale)
{
TDFunction = TDF;
}
using VectorCoefficient::Eval;
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
virtual ~VectorFunctionRestrictedCoefficient() { }
const Array<int> &GetActiveAttr() { return active_attr; }
const Array2D<double> &GetActiveScale() { return active_scale; }
};
typedef VectorCoefficient DiagonalMatrixCoefficient;
/// Base class for Matrix Coefficients that optionally depend on time and space.
+53 -3
View File
@@ -494,12 +494,21 @@ static void mark_dofs(const Array<int> &dofs, Array<int> &mark_array)
void FiniteElementSpace::GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_vdofs,
int component) const
int component,
bool overwrite) const
{
Array<int> vdofs, dofs;
ess_vdofs.SetSize(GetVSize());
ess_vdofs = 0;
if (overwrite)
{
ess_vdofs.SetSize(GetVSize());
ess_vdofs = 0;
}
else
{
MFEM_ASSERT(ess_vdofs.Size() == GetVSize(),
"ess_vdofs size is not equal to FESpaces GetVSize().");
}
for (int i = 0; i < GetNBE(); i++)
{
@@ -579,6 +588,47 @@ void FiniteElementSpace::GetEssentialTrueDofs(const Array<int> &bdr_attr_is_ess,
MarkerToList(ess_tdofs, ess_tdof_list);
}
void FiniteElementSpace::GetEssentialTrueDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_tdof_list,
const Array2D<bool> &component)
{
MFEM_ASSERT(component.NumCols() == vdim,
"Number of columns of component was not equal to FESpace vdim");
MFEM_ASSERT(component.NumRows() == bdr_attr_is_ess.Size(),
"Number of rows of component was not equal to bdr_attr_is_ess.Size()");
Array<int> ess_vdofs, ess_tdofs, bdr_attr_is_ess_single_comp;
bdr_attr_is_ess_single_comp.SetSize(bdr_attr_is_ess.Size());
for (int i = 0; i < vdim; i++)
{
// Only overwrite ess_vdofs on first iteration
// all other iterations we want to preserve values of
// ess_vdofs.
const bool overwrite = (i == 0) ? true : false;
bdr_attr_is_ess_single_comp = 0;
for (int j = 0; j < bdr_attr_is_ess.Size(); j++)
{
if (bdr_attr_is_ess[j] && component(j, i))
{
bdr_attr_is_ess_single_comp[j] = bdr_attr_is_ess[j];
}
}
GetEssentialVDofs(bdr_attr_is_ess_single_comp, ess_vdofs, i, overwrite);
}
const SparseMatrix *R = GetConformingRestriction();
if (!R)
{
ess_tdofs.MakeRef(ess_vdofs);
}
else
{
R->BooleanMult(ess_vdofs, ess_tdofs);
}
MarkerToList(ess_tdofs, ess_tdof_list);
}
void FiniteElementSpace::GetBoundaryTrueDofs(Array<int> &boundary_dofs,
int component)
{
+21 -2
View File
@@ -775,11 +775,16 @@ public:
/** @brief Mark degrees of freedom associated with boundary elements with
the specified boundary attributes (marked in 'bdr_attr_is_ess').
For spaces with 'vdim' > 1, the 'component' parameter can be used
to restricts the marked vDOFs to the specified component. */
to restricts the marked vDOFs to the specified component.
If overwrite is set to false then values in ess_vdofs are preserved
and not reset. However, the assumption here is that ess_vdofs is set to
the correct size already.*/
virtual void GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_vdofs,
int component = -1) const;
int component = -1,
bool overwrite = true) const;
/** @brief Get a list of essential true dofs, ess_tdof_list, corresponding to the
boundary attributes marked in the array bdr_attr_is_ess.
@@ -789,6 +794,20 @@ public:
Array<int> &ess_tdof_list,
int component = -1);
/** @brief Get a list of essential true dofs, ess_tdof_list, corresponding to the
boundary attributes marked in the array bdr_attr_is_ess.
For spaces with 'vdim' > 1, the 'component' array can be used
to restricts the marked tDOFs per boundary to the specified components.
If vdim > 1 then one can specify per boundary attribute which components
on a boundary are essential by assigning a value of true to its location
in the component array.
The component has dimensions number of boundary attributes x vdim. */
virtual void GetEssentialTrueDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_tdof_list,
const Array2D<bool> &component);
/** @brief Get a list of all boundary true dofs, @a boundary_dofs. For spaces
with 'vdim' > 1, the 'component' parameter can be used to restricts the
marked tDOFs to the specified component. Equivalent to
+96
View File
@@ -2025,6 +2025,7 @@ void GridFunction::AccumulateAndCountZones(Coefficient &coeff,
// Local interpolation
Array<int> vdofs;
Vector vals;
this->HostReadWrite();
*this = 0.0;
HostReadWrite();
@@ -2066,6 +2067,7 @@ void GridFunction::AccumulateAndCountZones(VectorCoefficient &vcoeff,
// Local interpolation
Array<int> vdofs;
Vector vals;
this->HostReadWrite();
*this = 0.0;
HostReadWrite();
@@ -2672,6 +2674,100 @@ void GridFunction::ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr)
#endif
}
void GridFunction::ProjectBdrCoefficient(VectorFunctionCoefficient &vfcoeff,
Array<int> &attr)
{
int i, j, fdof, d, ind, vdim;
Vector val;
const FiniteElement *fe;
ElementTransformation *transf;
Array<int> vdofs;
this->HostReadWrite();
vdim = fes->GetVDim();
// loop over boundary elements
for (i = 0; i < fes->GetNBE(); i++)
{
// if boundary attribute is 1 (Dirichlet)
if (attr[fes->GetBdrAttribute(i) - 1])
{
fe = fes->GetBE(i);
fdof = fe->GetDof();
transf = fes->GetBdrElementTransformation(i);
const IntegrationRule &ir = fe->GetNodes();
fes->GetBdrElementVDofs(i, vdofs);
// loop over dofs
for (j = 0; j < fdof; j++)
{
const IntegrationPoint &ip = ir.IntPoint(j);
transf->SetIntPoint(&ip);
vfcoeff.Eval(val, *transf, ip);
// loop over vector dimensions
for (d = 0; d < vdim; d++)
{
ind = vdofs[fdof*d+j];
if ( (ind = vdofs[fdof*d+j]) < 0 )
{
val(d) = -val(d), ind = -1-ind;
}
(*this)(ind) = val(d);
}
}
}
}
}
void GridFunction::ProjectBdrCoefficient(VectorFunctionRestrictedCoefficient &vfcoeff)
{
int i, j, fdof, d, ind, vdim;
Vector val;
const FiniteElement *fe;
ElementTransformation *transf;
Array<int> vdofs;
const Array<int> &active_attr = vfcoeff.GetActiveAttr();
const Array2D<double> &scale = vfcoeff.GetActiveScale();
this->HostReadWrite();
vdim = fes->GetVDim();
// loop over boundary elements
for (i = 0; i < fes->GetNBE(); i++) {
// if boundary attribute is 1 (Dirichlet)
if (active_attr[fes->GetBdrAttribute(i) - 1]) {
// instantiate a BC object
fe = fes->GetBE(i);
fdof = fe->GetDof();
transf = fes->GetBdrElementTransformation(i);
const IntegrationRule &ir = fe->GetNodes();
fes->GetBdrElementVDofs(i, vdofs);
// loop over dofs
for (j = 0; j < fdof; j++) {
const IntegrationPoint &ip = ir.IntPoint(j);
transf->SetIntPoint(&ip);
vfcoeff.Eval(val, *transf, ip);
// loop over vector dimensions
for (d = 0; d < vdim; d++) {
// check if the vector component (i.e. dof) is not constrained by a
// partial essential BC
if (scale(transf->Attribute - 1, d) > 0.0) {
ind = vdofs[fdof * d + j];
if ( (ind = vdofs[fdof * d + j]) < 0) {
val(d) = -val(d), ind = -1 - ind;
}
(*this)(ind) = val(d); // placing computed value in grid function
}
}
}
}
}
}
void GridFunction::ProjectBdrCoefficientNormal(
VectorCoefficient &vcoeff, Array<int> &bdr_attr)
{
+15 -2
View File
@@ -463,6 +463,20 @@ public:
will not be touched. */
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
/** add ProjectBdrCoefficient() taking a VectorFunctionCoefficient and projecting
onto the grid function, srw. */
void ProjectBdrCoefficient(VectorFunctionCoefficient &vfcoeff,
Array<int> &attr);
/** add ProjectBdrCoefficient() taking a VectorFunctionRestrictedCoefficient, srw
This is the same as the function above taking a VectorFunctionCoefficient, it
is just that the function coefficient is now restricted. This function
specifically projects values associated with ExaConstits essential BC
management and input. This routine does not, at this time, project a
VectorFunctionRestrictedCoefficient onto all grid function dofs.
This function should be renamed to reflect this. */
void ProjectBdrCoefficient(VectorFunctionRestrictedCoefficient &vfcoeff);
/** Project the normal component of the given VectorCoefficient on
the boundary. Only boundary attributes that are marked in
'bdr_attr' are projected. Assumes RT-type VectorFE GridFunction. */
@@ -724,7 +738,6 @@ public:
virtual ~GridFunction() { Destroy(); }
};
/** Overload operator<< for std::ostream and GridFunction; valid also for the
derived class ParGridFunction */
std::ostream &operator<<(std::ostream &out, const GridFunction &sol);
@@ -928,7 +941,6 @@ public:
/// Overload operator<< for std::ostream and QuadratureFunction.
std::ostream &operator<<(std::ostream &out, const QuadratureFunction &qf);
double ZZErrorEstimator(BilinearFormIntegrator &blfi,
GridFunction &u,
GridFunction &flux,
@@ -1042,6 +1054,7 @@ inline void QuadratureFunction::SetSpace(QuadratureSpace *qspace_,
inline void QuadratureFunction::GetElementValues(int idx, Vector &values)
{
// element offset is the number of quadrature points for that element
const int s_offset = qspace->element_offsets[idx];
const int sl_size = qspace->element_offsets[idx+1] - s_offset;
values.NewDataAndSize(data + vdim*s_offset, vdim*sl_size);
+16
View File
@@ -53,6 +53,22 @@ void NonlinearForm::SetEssentialBC(const Array<int> &bdr_attr_is_ess,
}
}
void NonlinearForm::SetEssentialBC(const Array<int> &bdr_attr_is_ess,
const Array2D<bool> &bdr_component,
Vector *rhs)
{
// virtual call, works in parallel too
fes->GetEssentialTrueDofs(bdr_attr_is_ess, ess_tdof_list, bdr_component);
if (rhs)
{
for (int i = 0; i < ess_tdof_list.Size(); i++)
{
(*rhs)(ess_tdof_list[i]) = 0.0;
}
}
}
void NonlinearForm::SetEssentialVDofs(const Array<int> &ess_vdofs_list)
{
if (!P)
+20 -1
View File
@@ -146,8 +146,26 @@ public:
have zero entries at the essential true dofs. */
void SetEssentialBC(const Array<int> &bdr_attr_is_ess, Vector *rhs = NULL);
/** @brief Specify essential boundary conditions.
For spaces with 'vdim' > 1, the 'bdr_component' array can be used
to restricts the marked tDOFs per boundary to the specified components.
If vdim > 1 then one can specify per boundary attribute which components
on a boundary are essential by assigning a value of true to its location
in the bdr_component array.
The bdr_component has dimensions number of boundary attributes x vdim
This method calls FiniteElementSpace::GetEssentialTrueDofs() and stores
the result internally for use by other methods. If the @a rhs pointer is
not NULL, its essential true dofs will be set to zero. This makes it
"compatible" with the output vectors from the Mult() method which also
have zero entries at the essential true dofs. */
void SetEssentialBC(const Array<int> &bdr_attr_is_ess,
const Array2D<bool> &bdr_component,
Vector *rhs);
/// Specify essential boundary conditions.
/** Use either SetEssentialBC() or SetEssentialTrueDofs() if possible. */
/** @deprecated Use either SetEssentialBC() or SetEssentialTrueDofs(). */
void SetEssentialVDofs(const Array<int> &ess_vdofs_list);
/// Specify essential boundary conditions.
@@ -179,6 +197,7 @@ public:
vectors, i.e. their size must be fes->GetTrueVSize(). */
virtual void Mult(const Vector &x, Vector &y) const;
/** @brief Compute the gradient Operator of the NonlinearForm corresponding
to the state @a x. */
/** Any previously specified essential boundary conditions will be
+23 -1
View File
@@ -80,6 +80,15 @@ void NonlinearFormIntegrator::AssembleElementVector(
" is not overloaded!");
}
void NonlinearFormIntegrator::AssembleElementVector(
const FiniteElement &el, ElementTransformation &Ttr_beg,
ElementTransformation &Ttr_end,
const Vector &elfun, Vector &elvect, const Vector &elvel)
{
mfem_error("NonlinearFormIntegrator::AssembleElementVector"
" is not overloaded!");
}
void NonlinearFormIntegrator::AssembleFaceVector(
const FiniteElement &el1, const FiniteElement &el2,
FaceElementTransformations &Tr, const Vector &elfun, Vector &elvect)
@@ -105,6 +114,20 @@ void NonlinearFormIntegrator::AssembleFaceGrad(
" is not overloaded!");
}
void NonlinearFormIntegrator::AssembleGradPA(
const FiniteElementSpace &fes)
{
mfem_error("NonlinearFormIntegrator::AssembleGradPA"
" is not overloaded!");
}
void NonlinearFormIntegrator::AssembleEA(
const FiniteElementSpace &fes, Vector &emat)
{
mfem_error("NonlinearFormIntegrator::AssembleEA"
" is not overloaded!");
}
double NonlinearFormIntegrator::GetElementEnergy(
const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun)
{
@@ -166,7 +189,6 @@ double BlockNonlinearFormIntegrator::GetElementEnergy(
return 0.0;
}
double InverseHarmonicModel::EvalW(const DenseMatrix &J) const
{
Z.SetSize(J.Width());
+34 -10
View File
@@ -57,6 +57,16 @@ public:
ElementTransformation &Tr,
const Vector &elfun, Vector &elvect);
//This function really only be used whenever UMATs are being used,
//since UMATs require a velocity based solution vector,
//However, they depend on a lot of variables based on displacements
//to evolve their models. So, we need to be able to take
//derivatives using the beginning and the end time step mesh nodes.
//The other models should be using the one above this
virtual void AssembleElementVector(const FiniteElement &el,
ElementTransformation &Ttr_beg,
ElementTransformation &Ttr_end,
const Vector &elfun, Vector &elvect, const Vector &elvel);
/// @brief Perform the local action of the NonlinearFormIntegrator resulting
/// from a face integral term.
virtual void AssembleFaceVector(const FiniteElement &el1,
@@ -112,6 +122,14 @@ public:
This method can be called only after the method AssemblePA() has been
called. */
virtual void AddMultPA(const Vector &x, Vector &y) const;
/** @brief Prepare the integrator for partial assembly (PA) gradient
evaluations on the given FE space @a fes */
/** The result of the partial assembly is stored internally so that it can be
used later in the methods AddMultGradPA() and AssembleGradDiagonalPA().
The state Vector @a x is an E-vector. */
virtual void AssembleGradPA(const FiniteElementSpace &fes);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
/// Method for partially assembled gradient action.
/** All arguments are E-vectors. This method can be called only after the
@@ -188,17 +206,16 @@ public:
virtual ~BlockNonlinearFormIntegrator() { }
};
/// Abstract class for hyperelastic models
class HyperelasticModel
/// Abstract class for nonlinear models
class NonlinearModel
{
protected:
ElementTransformation *Ttr; /**< Reference-element to target-element
transformation. */
public:
HyperelasticModel() : Ttr(NULL) { }
virtual ~HyperelasticModel() { }
NonlinearModel() : Ttr(NULL) { }
virtual ~NonlinearModel() { }
/// A reference-element to target-element transformation that can be used to
/// evaluate Coefficient%s.
@@ -206,11 +223,6 @@ public:
point of interest. */
void SetTransformation(ElementTransformation &Ttr_) { Ttr = &Ttr_; }
/** @brief Evaluate the strain energy density function, W = W(Jpt).
@param[in] Jpt Represents the target->physical transformation
Jacobian matrix. */
virtual double EvalW(const DenseMatrix &Jpt) const = 0;
/** @brief Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
@param[in] Jpt Represents the target->physical transformation
Jacobian matrix.
@@ -235,6 +247,18 @@ public:
};
/// Abstract class for hyperelastic models
class HyperelasticModel : public NonlinearModel
{
public:
/** @brief Evaluate the strain energy density function, W = W(Jpt).
@param[in] Jpt Represents the target->physical transformation
Jacobian matrix. */
virtual double EvalW(const DenseMatrix &Jpt) const = 0;
};
/** Inverse-harmonic hyperelastic model with a strain energy density function
given by the formula: W(J) = (1/2) det(J) Tr((J J^t)^{-1}) where J is the
deformation gradient. */
+56 -2
View File
@@ -1020,9 +1020,11 @@ void ParFiniteElementSpace::Synchronize(Array<int> &ldof_marker) const
void ParFiniteElementSpace::GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_dofs,
int component) const
int component,
bool overwrite) const
{
FiniteElementSpace::GetEssentialVDofs(bdr_attr_is_ess, ess_dofs, component);
FiniteElementSpace::GetEssentialVDofs(bdr_attr_is_ess, ess_dofs, component,
overwrite);
// Make sure that processors without boundary elements mark
// their boundary dofs (if they have any).
@@ -1059,6 +1061,58 @@ void ParFiniteElementSpace::GetEssentialTrueDofs(const Array<int>
MarkerToList(true_ess_dofs, ess_tdof_list);
}
void ParFiniteElementSpace::GetEssentialTrueDofs(const Array<int>
&bdr_attr_is_ess,
Array<int> &ess_tdof_list,
const Array2D<bool> &component)
{
MFEM_ASSERT(component.NumCols() == vdim,
"Number of columns of component was not equal to ParFESpace vdim");
MFEM_ASSERT(component.NumRows() == bdr_attr_is_ess.Size(),
"Number of rows of component was not equal to bdr_attr_is_ess.Size()");
Array<int> ess_dofs, true_ess_dofs, bdr_attr_is_ess_single_comp;
bdr_attr_is_ess_single_comp.SetSize(bdr_attr_is_ess.Size());
for (int i = 0; i < vdim; i++)
{
// Only overwrite ess_vdofs on first iteration
// all other iterations we want to preserve values of
// ess_vdofs.
const bool overwrite = (i == 0) ? true : false;
bdr_attr_is_ess_single_comp = 0;
for (int j = 0; j < bdr_attr_is_ess.Size(); j++)
{
if (bdr_attr_is_ess[j] && component(j, i))
{
bdr_attr_is_ess_single_comp[j] = bdr_attr_is_ess[j];
}
}
GetEssentialVDofs(bdr_attr_is_ess_single_comp, ess_dofs, i, overwrite);
}
GetRestrictionMatrix()->BooleanMult(ess_dofs, true_ess_dofs);
#ifdef MFEM_DEBUG
// Verify that in boolean arithmetic: P^T ess_dofs = R ess_dofs.
Array<int> true_ess_dofs2(true_ess_dofs.Size());
HypreParMatrix *Pt = Dof_TrueDof_Matrix()->Transpose();
const int *ess_dofs_data = ess_dofs.HostRead();
Pt->BooleanMult(1, ess_dofs_data, 0, true_ess_dofs2);
delete Pt;
int counter = 0;
const int *ted = true_ess_dofs.HostRead();
for (int i = 0; i < true_ess_dofs.Size(); i++)
{
if (bool(ted[i]) != bool(true_ess_dofs2[i])) { counter++; }
}
MFEM_VERIFY(counter == 0, "internal MFEM error: counter = " << counter
<< ", rank = " << MyRank);
#endif
MarkerToList(true_ess_dofs, ess_tdof_list);
}
int ParFiniteElementSpace::GetLocalTDofNumber(int ldof) const
{
if (Nonconforming())
+23 -2
View File
@@ -350,10 +350,18 @@ public:
"partially conforming") space. */
void Synchronize(Array<int> &ldof_marker) const;
/// Determine the boundary degrees of freedom
/** @brief Mark degrees of freedom associated with boundary elements with
the specified boundary attributes (marked in 'bdr_attr_is_ess').
For spaces with 'vdim' > 1, the 'component' parameter can be used
to restricts the marked vDOFs to the specified component.
If overwrite is set to false then values in ess_vdofs are preserved
and not reset. However, the assumption here is that ess_vdofs is set to
the correct size already.*/
virtual void GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_dofs,
int component = -1) const;
int component = -1,
bool overwrite = true) const;
/** Get a list of essential true dofs, ess_tdof_list, corresponding to the
boundary attributes marked in the array bdr_attr_is_ess. */
@@ -361,6 +369,19 @@ public:
Array<int> &ess_tdof_list,
int component = -1);
/** @brief Get a list of essential true dofs, ess_tdof_list, corresponding to the
boundary attributes marked in the array bdr_attr_is_ess.
For spaces with 'vdim' > 1, the 'component' array can be used
to restricts the marked tDOFs per boundary to the specified components.
If vdim > 1 then one can specify per boundary attribute which components
on a boundary are essential by assigning a value of true to its location
in the component array.
The component has dimensions number of boundary attributes x vdim. */
virtual void GetEssentialTrueDofs(const Array<int> &bdr_attr_is_ess,
Array<int> &ess_tdof_list,
const Array2D<bool> &component);
/** If the given ldof is owned by the current processor, return its local
tdof number, otherwise return -1 */
int GetLocalTDofNumber(int ldof) const;
+6
View File
@@ -543,6 +543,12 @@ void ParGridFunction::ProjectCoefficient(Coefficient &coeff)
}
}
//void ParGridFunction::ProjectBdrCoefficient(VectorFunctionCoefficient &vfcoeff,
// Array<int> &attr)
//{
// GridFunction::ProjectBdrCoefficient(vfcoeff, attr);
//}
void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff)
{
// local maximal element attribute for each dof
+4
View File
@@ -238,6 +238,10 @@ public:
using GridFunction::ProjectCoefficient;
virtual void ProjectCoefficient(Coefficient &coeff);
// using GridFunction::ProjectBdrCoefficient;
// void ProjectBdrCoefficient(VectorFunctionCoefficient &vfcoeff,
// Array<int> &attr);
using GridFunction::ProjectDiscCoefficient;
/** @brief Project a discontinuous vector coefficient as a grid function on
a continuous finite element space. The values in shared dofs are
+216
View File
@@ -94,6 +94,195 @@ void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
MFEM_FORALL(i, N, Y_RW[idx[i]] = 0.0; );
}
void ParNonlinearForm::Mult(const Vector &x, Vector &y, ParMesh* pmesh,
ParGridFunction* end_crds, ParGridFunction* beg_crds,
const Vector &v) const
{
//We're going to pretty much take everything from in NonlinearForm::Mult(x, y) into here
//with a few changes made to it
Array<int> vdofs;
Vector el_x, el_y, el_v;
const FiniteElement *fe;
IsoparametricTransformation beg_T;
IsoparametricTransformation end_T;
Mesh *mesh = fes->GetMesh();
const Vector &ptemp = Prolongate(x);
const Vector px(ptemp);
const Vector &ptemp1 = Prolongate(v);
const Vector pv(ptemp1);
Vector &py = P ? aux2.SetSize(P->Height()), aux2 : y;
py = 0.0;
GridFunction *nodes;
if (dnfi.Size())
{
for (int i = 0; i < fes->GetNE(); i++)
{
//Here we're pretty much forced to do things a little different
//from before since we have to explicitly call the pmesh GetElementTransformation
//if we don't then we end up with the exact same ElementTransformations
//for beg_T and end_T
fe = fes->GetFE(i);
fes->GetElementVDofs(i, vdofs);
pmesh->GetElementTransformation(i, &beg_T);
//These lines are updating
int own_nodes = 0;
nodes = end_crds;
pmesh->SwapNodes(nodes, own_nodes);
fe = fes->GetFE(i);
fes->GetElementVDofs(i, vdofs);
pmesh->GetElementTransformation(i, &end_T);
px.GetSubVector(vdofs, el_x);
pv.GetSubVector(vdofs, el_v);
for (int k = 0; k < dnfi.Size(); k++)
{
//This is the part that we're changing by adding more transformation terms
//as well
dnfi[k]->AssembleElementVector(*fe, beg_T, end_T, el_x, el_y, el_v);
py.AddElementVector(vdofs, el_y);
}
nodes = beg_crds;
pmesh->SwapNodes(nodes, own_nodes);
}
}
nodes = NULL;
//fix_me: Do we need to worry about the face transformations down here as well
//and what their element transformation is based upon? I'm feeling like the answer
//might be yes for certain applications. However, I'm not seeing the need for something
//like UMATs for the below at least currently.
if (fnfi.Size())
{
FaceElementTransformations *tr;
const FiniteElement *fe1, *fe2;
Array<int> vdofs2;
for (int i = 0; i < mesh->GetNumFaces(); i++)
{
tr = mesh->GetInteriorFaceTransformations(i);
if (tr != NULL)
{
fes->GetElementVDofs(tr->Elem1No, vdofs);
fes->GetElementVDofs(tr->Elem2No, vdofs2);
vdofs.Append (vdofs2);
px.GetSubVector(vdofs, el_x);
fe1 = fes->GetFE(tr->Elem1No);
fe2 = fes->GetFE(tr->Elem2No);
for (int k = 0; k < fnfi.Size(); k++)
{
fnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
py.AddElementVector(vdofs, el_y);
}
}
}
}
//fix_me: Same as the previous fix_me in this function.
if (bfnfi.Size())
{
FaceElementTransformations *tr;
const FiniteElement *fe1, *fe2;
// Which boundary attributes need to be processed?
Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
mesh->bdr_attributes.Max() : 0);
bdr_attr_marker = 0;
for (int k = 0; k < bfnfi.Size(); k++)
{
if (bfnfi_marker[k] == NULL)
{
bdr_attr_marker = 1;
break;
}
Array<int> &bdr_marker = *bfnfi_marker[k];
MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
"invalid boundary marker for boundary face integrator #"
<< k << ", counting from zero");
for (int i = 0; i < bdr_attr_marker.Size(); i++)
{
bdr_attr_marker[i] |= bdr_marker[i];
}
}
for (int i = 0; i < fes -> GetNBE(); i++)
{
const int bdr_attr = mesh->GetBdrAttribute(i);
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
tr = mesh->GetBdrFaceTransformations (i);
if (tr != NULL)
{
fes->GetElementVDofs(tr->Elem1No, vdofs);
px.GetSubVector(vdofs, el_x);
fe1 = fes->GetFE(tr->Elem1No);
// The fe2 object is really a dummy and not used on the boundaries,
// but we can't dereference a NULL pointer, and we don't want to
// actually make a fake element.
fe2 = fe1;
for (int k = 0; k < bfnfi.Size(); k++)
{
if (bfnfi_marker[k] &&
(*bfnfi_marker[k])[bdr_attr-1] == 0) { continue; }
bfnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
py.AddElementVector(vdofs, el_y);
}
}
}
}
//The below is directly from ParNonlinearForm::Mult(x,y)
Y.SetData(aux2.GetData()); // aux2 contains A_local.P.x
//fix_me: same as the other previous fix_mes in this function
if (fnfi.Size())
{
// Terms over shared interior faces in parallel.
ParFiniteElementSpace *pfes = ParFESpace();
ParMesh *pmesh = pfes->GetParMesh();
FaceElementTransformations *tr;
const FiniteElement *fe1, *fe2;
Array<int> vdofs1, vdofs2;
Vector el_x, el_y;
X.SetData(aux1.GetData()); // aux1 contains P.x
X.ExchangeFaceNbrData();
const int n_shared_faces = pmesh->GetNSharedFaces();
for (int i = 0; i < n_shared_faces; i++)
{
tr = pmesh->GetSharedFaceTransformations(i, true);
fe1 = pfes->GetFE(tr->Elem1No);
fe2 = pfes->GetFaceNbrFE(tr->Elem2No);
pfes->GetElementVDofs(tr->Elem1No, vdofs1);
pfes->GetFaceNbrElementVDofs(tr->Elem2No, vdofs2);
el_x.SetSize(vdofs1.Size() + vdofs2.Size());
X.GetSubVector(vdofs1, el_x.GetData());
X.FaceNbrData().GetSubVector(vdofs2, el_x.GetData() + vdofs1.Size());
for (int k = 0; k < fnfi.Size(); k++)
{
fnfi[k]->AssembleFaceVector(*fe1, *fe2, *tr, el_x, el_y);
Y.AddElementVector(vdofs1, el_y.GetData());
}
}
}
P->MultTranspose(Y, y);
for (int i = 0; i < ess_tdof_list.Size(); i++)
{
y(ess_tdof_list[i]) = 0.0;
}
}
const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
{
MFEM_VERIFY(NonlinearForm::ext == nullptr,
@@ -104,6 +293,33 @@ const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
return *Grad;
}
Operator &ParNonlinearForm::GetLocalGradient2(const Vector &x) const
{
ParFiniteElementSpace *pfes = ParFESpace();
pGrad.Clear();
NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type());
if (fnfi.Size() == 0)
{
dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
pfes->GetDofOffsets(), Grad);
}
else
{
MFEM_ABORT("TODO: assemble contributions from shared face terms");
}
// TODO - construct Dof_TrueDof_Matrix directly in the pGrad format
Ph.ConvertFrom(pfes->Dof_TrueDof_Matrix());
pGrad.MakePtAP(dA, Ph);
return *pGrad.Ptr();
}
Operator &ParNonlinearForm::GetGradient(const Vector &x) const
{
if (NonlinearForm::ext) { return NonlinearForm::GetGradient(x); }
+21
View File
@@ -18,6 +18,8 @@
#include "pgridfunc.hpp"
#include "nonlinearform.hpp"
#include "../mesh/pmesh.hpp"
namespace mfem
{
@@ -51,10 +53,29 @@ public:
virtual void Mult(const Vector &x, Vector &y) const;
/** The input essential dofs in @a x will, generally, be non-zero. However,
the output essential dofs in @a y will always be set to zero.
The input @a pmesh, @a end_crds @ beg_crds will be used to supply an element transformation
at a beggining time step and then one at an end time step. The ParMesh initially has its
nodes set at the beggining time step nodes and are updated to the current configuration location
before being returned to the beggining time step.
We're making sure the mesh returns to the same state we obtained it.
Both the input and the output vectors, @a x and @a y, must be true-dof
vectors, i.e. their size must be fes->GetTrueVSize().
The ParGridFunctions @a end_crds and @a beg_crds have virtual-dofs.*/
virtual void Mult(const Vector &x, Vector &y, ParMesh* pmesh,
ParGridFunction* end_crds, ParGridFunction* beg_crds,
const Vector &v) const;
/// Return the local gradient matrix for the given true-dof vector x.
/** The returned matrix does NOT have any boundary conditions imposed. */
const SparseMatrix &GetLocalGradient(const Vector &x) const;
/// Return the local gradient matrix for the given true-dof vector x.
/** The returned matrix does NOT have any boundary conditions imposed. */
virtual Operator &GetLocalGradient2(const Vector &x) const;
virtual Operator &GetGradient(const Vector &x) const;
/// Set the operator type id for the parallel gradient matrix/operator.
+24
View File
@@ -289,6 +289,30 @@ void Vector::SetVector(const Vector &v, int offset)
}
}
void Vector::SetVector(const Vector &v, int offset, int sslen, int ssoffset)
{
int vs = v.Size();
const double *vp = v.data + ssoffset;
double *p = data + offset;
#ifdef MFEM_DEBUG
if (offset+sslen > size)
{
mfem_error("Vector::SetVector(const Vector &, int, int, int)");
}
if (ssoffset+sslen > vs)
{
mfem_error("Vector::SetVector(const Vector &, int, int, int)");
}
#endif
for (int i = 0; i < sslen; i++)
{
p[i] = vp[i];
}
}
void Vector::Neg()
{
const bool use_dev = UseDevice();
+5
View File
@@ -315,6 +315,11 @@ public:
void SetVector(const Vector &v, int offset);
/// Set the subset of element in (*this) defined by @a offset
/// and the subset length, @a sslen, equal to the subset of
/// elements in @a v defined by @a ssoffset and @a sslen.
void SetVector (const Vector &v, int offset, int sslen, int ssoffset);
/// (*this) = -(*this)
void Neg();