From 59175df4bf5eb196fedb00ed0a1073539db63c85 Mon Sep 17 00:00:00 2001 From: WilkAndy Date: Thu, 30 Jul 2020 14:50:37 +1000 Subject: [PATCH 1/2] ConservativeAdvection uses VectorVariableValue instead of RealVectorValue. Fixes #15683 --- framework/include/kernels/ConservativeAdvection.h | 3 +-- framework/src/kernels/ConservativeAdvection.C | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/framework/include/kernels/ConservativeAdvection.h b/framework/include/kernels/ConservativeAdvection.h index cbdde79d90ec..c1237f7ed186 100644 --- a/framework/include/kernels/ConservativeAdvection.h +++ b/framework/include/kernels/ConservativeAdvection.h @@ -35,7 +35,7 @@ class ConservativeAdvection : public Kernel virtual void computeJacobian() override; /// advection velocity - RealVectorValue _velocity; + const VectorVariableValue & _velocity; /// enum to make the code clearer enum class JacRes @@ -62,4 +62,3 @@ class ConservativeAdvection : public Kernel /// Calculates the fully-upwind Residual and Jacobian (depending on res_or_jac) void fullUpwind(JacRes res_or_jac); }; - diff --git a/framework/src/kernels/ConservativeAdvection.C b/framework/src/kernels/ConservativeAdvection.C index 172bad138553..3dcd2c888f4f 100644 --- a/framework/src/kernels/ConservativeAdvection.C +++ b/framework/src/kernels/ConservativeAdvection.C @@ -20,7 +20,7 @@ ConservativeAdvection::validParams() InputParameters params = Kernel::validParams(); params.addClassDescription("Conservative form of $\\nabla \\cdot \\vec{v} u$ which in its weak " "form is given by: $(-\\nabla \\psi_i, \\vec{v} u)$."); - params.addRequiredParam("velocity", "Velocity vector"); + params.addRequiredCoupledVar("velocity", "Velocity vector"); MooseEnum upwinding_type("none full", "none"); params.addParam("upwinding_type", upwinding_type, @@ -32,7 +32,7 @@ ConservativeAdvection::validParams() ConservativeAdvection::ConservativeAdvection(const InputParameters & parameters) : Kernel(parameters), - _velocity(getParam("velocity")), + _velocity(coupledVectorValue("velocity")), _upwinding(getParam("upwinding_type").getEnum()), _u_nodal(_var.dofValues()), _upwind_node(0), @@ -43,7 +43,7 @@ ConservativeAdvection::ConservativeAdvection(const InputParameters & parameters) Real ConservativeAdvection::negSpeedQp() const { - return -_grad_test[_i][_qp] * _velocity; + return -_grad_test[_i][_qp] * _velocity[_qp]; } Real From 822bc3250baf6221d342f7a5f11e21de2647b123 Mon Sep 17 00:00:00 2001 From: WilkAndy Date: Thu, 30 Jul 2020 14:53:23 +1000 Subject: [PATCH 2/2] Transport Kernels added to Geochemistry. Refs #15668 --- .../source/kernels/GeochemistryDispersion.md | 19 ++++ .../kernels/GeochemistryTimeDerivative.md | 23 +++++ .../include/kernels/GeochemistryDispersion.h | 32 ++++++ .../kernels/GeochemistryTimeDerivative.h | 34 +++++++ .../src/kernels/GeochemistryDispersion.C | 41 ++++++++ .../src/kernels/GeochemistryTimeDerivative.C | 47 +++++++++ .../test/tests/kernels/advection_1.i | 87 +++++++++++++++++ .../test/tests/kernels/dispersion_1.i | 89 +++++++++++++++++ .../test/tests/kernels/dispersion_jac.i | 50 ++++++++++ .../tests/kernels/gold/advection_1_out.csv | 12 +++ .../tests/kernels/gold/dispersion_1_out.e | Bin 0 -> 41028 bytes .../tests/kernels/gold/time_deriv_1_out.csv | 3 + .../tests/kernels/gold/time_deriv_2_out.csv | 3 + modules/geochemistry/test/tests/kernels/tests | 52 ++++++++++ .../test/tests/kernels/time_deriv_1.i | 83 ++++++++++++++++ .../test/tests/kernels/time_deriv_2.i | 91 ++++++++++++++++++ .../test/tests/kernels/time_deriv_jac.i | 49 ++++++++++ 17 files changed, 715 insertions(+) create mode 100644 modules/geochemistry/doc/content/source/kernels/GeochemistryDispersion.md create mode 100644 modules/geochemistry/doc/content/source/kernels/GeochemistryTimeDerivative.md create mode 100644 modules/geochemistry/include/kernels/GeochemistryDispersion.h create mode 100644 modules/geochemistry/include/kernels/GeochemistryTimeDerivative.h create mode 100644 modules/geochemistry/src/kernels/GeochemistryDispersion.C create mode 100644 modules/geochemistry/src/kernels/GeochemistryTimeDerivative.C create mode 100644 modules/geochemistry/test/tests/kernels/advection_1.i create mode 100644 modules/geochemistry/test/tests/kernels/dispersion_1.i create mode 100644 modules/geochemistry/test/tests/kernels/dispersion_jac.i create mode 100644 modules/geochemistry/test/tests/kernels/gold/advection_1_out.csv create mode 100644 modules/geochemistry/test/tests/kernels/gold/dispersion_1_out.e create mode 100644 modules/geochemistry/test/tests/kernels/gold/time_deriv_1_out.csv create mode 100644 modules/geochemistry/test/tests/kernels/gold/time_deriv_2_out.csv create mode 100644 modules/geochemistry/test/tests/kernels/tests create mode 100644 modules/geochemistry/test/tests/kernels/time_deriv_1.i create mode 100644 modules/geochemistry/test/tests/kernels/time_deriv_2.i create mode 100644 modules/geochemistry/test/tests/kernels/time_deriv_jac.i diff --git a/modules/geochemistry/doc/content/source/kernels/GeochemistryDispersion.md b/modules/geochemistry/doc/content/source/kernels/GeochemistryDispersion.md new file mode 100644 index 000000000000..d67fa99a86e6 --- /dev/null +++ b/modules/geochemistry/doc/content/source/kernels/GeochemistryDispersion.md @@ -0,0 +1,19 @@ +# GeochemistryDispersion + +This Kernel implements the PDE fragment +\begin{equation} +\nabla(\phi D\nabla c) \ , +\end{equation} +which is part of the [transport](transport.md) equations. Here + +- $\phi$ is the porosity, which may be a fixed real number or may be an `AuxVariable` that is spatially-dependent +- $D$ is the hydrodynamic dispersion tensor (called `tensor_coeff` in the input file) +- $c$ is the concentration (mol/m$^{3}$(aqueous solution)) of an aqueous species +- $\nabla$ denotes the vector of spatial derivatives + +!syntax parameters /Kernels/GeochemistryDispersion + +!syntax inputs /Kernels/GeochemistryDispersion + +!syntax children /Kernels/GeochemistryDispersion + diff --git a/modules/geochemistry/doc/content/source/kernels/GeochemistryTimeDerivative.md b/modules/geochemistry/doc/content/source/kernels/GeochemistryTimeDerivative.md new file mode 100644 index 000000000000..c1fde4364cf9 --- /dev/null +++ b/modules/geochemistry/doc/content/source/kernels/GeochemistryTimeDerivative.md @@ -0,0 +1,23 @@ +# GeochemistryTimeDerivative + +This Kernel implements the PDE fragment +\begin{equation} +\phi \frac{\partial c}{\partial t} \ , +\end{equation} +which is part of the [transport](transport.md) equations. Here + +- $\phi$ is the porosity, which may be a fixed real number or may be an `AuxVariable` that is spatially-dependent +- $c$ is the concentration (mol/m$^{3}$(aqueous solution)) of an aqueous species +- $t$ is time + +Two notable features of this Kernel are: + +- it should not be used for cases were porosity is time-dependent (in this case $\phi$ should be inside the time derivative); +- mass lumping to the nodes is used in order to reduce the possibility that concentration becomes negative. + +!syntax parameters /Kernels/GeochemistryTimeDerivative + +!syntax inputs /Kernels/GeochemistryTimeDerivative + +!syntax children /Kernels/GeochemistryTimeDerivative + diff --git a/modules/geochemistry/include/kernels/GeochemistryDispersion.h b/modules/geochemistry/include/kernels/GeochemistryDispersion.h new file mode 100644 index 000000000000..e7b0f0091971 --- /dev/null +++ b/modules/geochemistry/include/kernels/GeochemistryDispersion.h @@ -0,0 +1,32 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "AnisotropicDiffusion.h" + +/** + * Kernel describing grad(porosity * dispersion * grad(concentration)), where porosity is an + * AuxVariable, dispersion is the hydrodynamic dispersion tensor (input by user as tensor_coeff), + * and concentration is the variable for this Kernel + */ +class GeochemistryDispersion : public AnisotropicDiffusion +{ +public: + static InputParameters validParams(); + + GeochemistryDispersion(const InputParameters & parameters); + +protected: + virtual Real computeQpResidual() override; + virtual Real computeQpJacobian() override; + +private: + const VariableValue & _porosity; +}; diff --git a/modules/geochemistry/include/kernels/GeochemistryTimeDerivative.h b/modules/geochemistry/include/kernels/GeochemistryTimeDerivative.h new file mode 100644 index 000000000000..6e766f21ba7a --- /dev/null +++ b/modules/geochemistry/include/kernels/GeochemistryTimeDerivative.h @@ -0,0 +1,34 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "TimeKernel.h" + +/** + * Kernel describing porosity * d(concentration)/dt, where porosity is an AuxVariable. + * This Kernel should not be used if porosity is time-dependent. + * Mass lumping is employed for numerical stability + */ +class GeochemistryTimeDerivative : public TimeKernel +{ +public: + static InputParameters validParams(); + + GeochemistryTimeDerivative(const InputParameters & parameters); + +protected: + virtual Real computeQpResidual() override; + virtual Real computeQpJacobian() override; + +private: + const VariableValue & _nodal_u_dot; + const VariableValue & _nodal_du_dot_du; + const VariableValue & _porosity; +}; diff --git a/modules/geochemistry/src/kernels/GeochemistryDispersion.C b/modules/geochemistry/src/kernels/GeochemistryDispersion.C new file mode 100644 index 000000000000..74078ae11202 --- /dev/null +++ b/modules/geochemistry/src/kernels/GeochemistryDispersion.C @@ -0,0 +1,41 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "GeochemistryDispersion.h" + +registerMooseObject("GeochemistryApp", GeochemistryDispersion); + +InputParameters +GeochemistryDispersion::validParams() +{ + InputParameters params = AnisotropicDiffusion::validParams(); + params.addCoupledVar("porosity", 1.0, "Porosity"); + params.addClassDescription("Kernel describing grad(porosity * tensor_coeff * " + "grad(concentration)), where porosity is an AuxVariable (or just " + "a real number), tensor_coeff is the hydrodynamic dispersion tensor " + "and concentration is the 'variable' for this Kernel"); + return params; +} + +GeochemistryDispersion::GeochemistryDispersion(const InputParameters & parameters) + : AnisotropicDiffusion(parameters), _porosity(coupledValue("porosity")) +{ +} + +Real +GeochemistryDispersion::computeQpResidual() +{ + return _porosity[_qp] * AnisotropicDiffusion::computeQpResidual(); +} + +Real +GeochemistryDispersion::computeQpJacobian() +{ + return _porosity[_qp] * AnisotropicDiffusion::computeQpJacobian(); +} diff --git a/modules/geochemistry/src/kernels/GeochemistryTimeDerivative.C b/modules/geochemistry/src/kernels/GeochemistryTimeDerivative.C new file mode 100644 index 000000000000..bd315e682b7c --- /dev/null +++ b/modules/geochemistry/src/kernels/GeochemistryTimeDerivative.C @@ -0,0 +1,47 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "GeochemistryTimeDerivative.h" + +registerMooseObject("GeochemistryApp", GeochemistryTimeDerivative); + +InputParameters +GeochemistryTimeDerivative::validParams() +{ + InputParameters params = TimeKernel::validParams(); + params.addCoupledVar("porosity", 1.0, "Porosity"); + params.addClassDescription( + "Kernel describing porosity * d(concentration)/dt, where porosity is an AuxVariable (or just " + "a real number) and concentration is the 'variable' for this Kernel. This Kernel should not " + "be used if porosity is time-dependent. Mass lumping is employed for numerical stability"); + return params; +} + +GeochemistryTimeDerivative::GeochemistryTimeDerivative(const InputParameters & parameters) + : TimeKernel(parameters), + _nodal_u_dot(_var.dofValuesDot()), + _nodal_du_dot_du(_var.dofValuesDuDotDu()), + _porosity(coupledValue("porosity")) +{ +} + +Real +GeochemistryTimeDerivative::computeQpResidual() +{ + return _test[_i][_qp] * _porosity[_qp] * _nodal_u_dot[_i]; +} + +Real +GeochemistryTimeDerivative::computeQpJacobian() +{ + if (_i == _j) + return _test[_i][_qp] * _porosity[_qp] * _nodal_du_dot_du[_j]; + else + return 0.0; +} diff --git a/modules/geochemistry/test/tests/kernels/advection_1.i b/modules/geochemistry/test/tests/kernels/advection_1.i new file mode 100644 index 000000000000..2793ef629885 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/advection_1.i @@ -0,0 +1,87 @@ +# A step-like initial concentration is advected to the right using a constant velocity. +# Because of the Dirichlet BC on the left, the step-like concentration profile is maintained (up to the usual numerical diffusion) +# Because upwinding_type=full in the ConservativeAdvection Kernel, there are no overshoots and undershoots +# The total amount of "conc" should increase by dt * velocity every timestep, as recorded by the front_position Postprocessor +[Mesh] + type = GeneratedMesh + dim = 1 + nx = 100 +[] + +[Variables] + [./conc] + [../] +[] + +[ICs] + [./conc] + type = FunctionIC + function = 'if(x<=0.25, 1, 0)' + variable = conc + [../] +[] + +[BCs] + [./left] + type = DirichletBC + boundary = left + value = 1.0 + variable = conc + [../] +[] + +[Kernels] + [./dot] + type = GeochemistryTimeDerivative + variable = conc + [../] + [./adv] + type = ConservativeAdvection + velocity = velocity + upwinding_type = full + variable = conc + [../] +[] + +[AuxVariables] + [./velocity] + family = MONOMIAL_VEC + order = CONSTANT + [../] +[] + +[AuxKernels] + [./velocity] + type = VectorFunctionAux + function = vel_fcn + variable = velocity + [../] +[] + +[Functions] + [./vel_fcn] + type = ParsedVectorFunction + value_x = 1 + value_y = 0 + value_z = 0 + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + dt = 0.01 + end_time = 0.1 +[] + +[Postprocessors] + [./front_position] + type = ElementIntegralVariablePostprocessor + variable = conc + [../] +[] + +[Outputs] + csv = true +[] + diff --git a/modules/geochemistry/test/tests/kernels/dispersion_1.i b/modules/geochemistry/test/tests/kernels/dispersion_1.i new file mode 100644 index 000000000000..c5c84cc1bdfc --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/dispersion_1.i @@ -0,0 +1,89 @@ +# Dispersion of a step-function front of concentration +# The initial condition is such that the theoretical result is exactly +# c = erf(x/sqrt(4*t*D)), where D = hydrodynamic_dispersion +# +# The finite mesh resolution and large time-step size means this is only achieved approximately (increasing nx and decreasing results in the error decreasing, but note the series approximation to the error function means that the error should never be exactly zero) + +por = 2.0 # this is the porosity. The result should not depend on por in this example since it appears in both terms of the PDE +[Mesh] + type = GeneratedMesh + dim = 1 + nx = 100 + xmin = -5 + xmax = 5 +[] + +[Variables] + [./conc] + [../] +[] + +[ICs] + [./spike] + type = FunctionIC + variable = conc + function = 'if(x<=0.0, -1.0, 1.0)' + [../] +[] + +[Kernels] + [./dot] + type = GeochemistryTimeDerivative + porosity = ${por} + variable = conc + [../] + [./disp] + type = GeochemistryDispersion + variable = conc + porosity = ${por} + tensor_coeff = '0.3 0 0 0 0 0 0 0 0' + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + dt = 0.5 + end_time = 1.0 +[] + +[AuxVariables] + [./expected] + [../] + [./should_be_zero] + [../] +[] + +[AuxKernels] + [./expected] + type = FunctionAux + variable = expected + function = erf + [../] + [./should_be_zero] + type = ParsedAux + args = 'expected conc' + function = 'expected - conc' + variable = should_be_zero + [../] +[] + +[Postprocessors] + [./error] + type = ElementL2Norm + variable = should_be_zero + [../] +[] + +[Functions] + [./erf] + type = ParsedFunction + # series expansion for evaluating the error function + value = 'xi := x / sqrt(4 * t * 0.3); expxi := exp(-xi * xi); if(x < 0.0, -1.0, if(x > 0.0, 1.0, 0.0)) * 2 / sqrt(pi) * sqrt(1 - expxi) * (sqrt(pi) / 2.0 + 31.0 * expxi / 200.0 - 341.0 * expxi * expxi / 8000.0)' + [../] +[] + +[Outputs] + exodus = true + execute_on = final +[] diff --git a/modules/geochemistry/test/tests/kernels/dispersion_jac.i b/modules/geochemistry/test/tests/kernels/dispersion_jac.i new file mode 100644 index 000000000000..a10aaffba66e --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/dispersion_jac.i @@ -0,0 +1,50 @@ +# Tests that the GeochemistryDispersion Jacobian is correctly computed +[Mesh] + type = GeneratedMesh + dim = 2 + nx = 3 + ny = 2 +[] + +[Variables] + [./conc] + [../] +[] + +[Kernels] + [./disp] + type = GeochemistryDispersion + variable = conc + porosity = porosity + tensor_coeff = '1 2 3 4 5 6 7 8 9' + [../] +[] + +[AuxVariables] + [./porosity] + [../] +[] + +[AuxKernels] + [./porosity] + type = FunctionAux + function = '1.0 + x + y + z' + variable = porosity + [../] +[] + +[Preconditioning] + [./check] + type = SMP + full = true + petsc_options = '-snes_test_jacobian -snes_force_iteration' + petsc_options_iname = '-snes_type -ksp_type -pc_type -snes_convergence_test' + petsc_options_value = ' ksponly preonly none skip' + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + num_steps = 1 +[] diff --git a/modules/geochemistry/test/tests/kernels/gold/advection_1_out.csv b/modules/geochemistry/test/tests/kernels/gold/advection_1_out.csv new file mode 100644 index 000000000000..91f630757e64 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/gold/advection_1_out.csv @@ -0,0 +1,12 @@ +time,front_position +0,0 +0.01,0.265 +0.02,0.275 +0.03,0.285 +0.04,0.295 +0.05,0.305 +0.06,0.315 +0.07,0.325 +0.08,0.335 +0.09,0.345 +0.1,0.355 diff --git a/modules/geochemistry/test/tests/kernels/gold/dispersion_1_out.e b/modules/geochemistry/test/tests/kernels/gold/dispersion_1_out.e new file mode 100644 index 0000000000000000000000000000000000000000..441a12f157b18001caa2cecc95e294e75de2abf7 GIT binary patch literal 41028 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 YJZtBfzqt$Npl6k|-S}Jh=6UD;3vx}IrT_o{ literal 0 HcmV?d00001 diff --git a/modules/geochemistry/test/tests/kernels/gold/time_deriv_1_out.csv b/modules/geochemistry/test/tests/kernels/gold/time_deriv_1_out.csv new file mode 100644 index 000000000000..0c6b90e27588 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/gold/time_deriv_1_out.csv @@ -0,0 +1,3 @@ +time,error +0,0 +2,0 diff --git a/modules/geochemistry/test/tests/kernels/gold/time_deriv_2_out.csv b/modules/geochemistry/test/tests/kernels/gold/time_deriv_2_out.csv new file mode 100644 index 000000000000..0c6b90e27588 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/gold/time_deriv_2_out.csv @@ -0,0 +1,3 @@ +time,error +0,0 +2,0 diff --git a/modules/geochemistry/test/tests/kernels/tests b/modules/geochemistry/test/tests/kernels/tests new file mode 100644 index 000000000000..799cfe8dd63e --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/tests @@ -0,0 +1,52 @@ +[Tests] + [./time_deriv_1] + type = CSVDiff + input = time_deriv_1.i + csvdiff = time_deriv_1_out.csv + abs_zero = 1.0E-10 + requirement = 'The geochemistry module shall simulate simple transport problems' + issues = '#15668' + design = 'transport.md GeochemistryTimeDerivative.md' + [../] + [./time_deriv_2] + type = CSVDiff + input = time_deriv_2.i + csvdiff = time_deriv_2_out.csv + abs_zero = 1.0E-10 + requirement = 'The geochemistry module shall simulate simple transport problems' + issues = '#15668' + design = 'transport.md GeochemistryTimeDerivative.md' + [../] + [./time_deriv_jac] + type = PetscJacobianTester + input = time_deriv_jac.i + threading = '!pthreads' + requirement = "The geochemistry module shall compute all Jacobian entries of all Kernels" + issues = '#15668' + design = 'transport.md GeochemistryTimeDerivative.md' + [../] + [./advection_1] + type = CSVDiff + input = advection_1.i + csvdiff = advection_1_out.csv + requirement = 'The geochemistry module shall simulate simple transport problems involving advection' + issues = '#15668' + design = 'transport.md ConservativeAdvection.md' + [../] + [./dispersion_jac] + type = 'PetscJacobianTester' + input = dispersion_jac.i + threading = '!pthreads' + requirement = "The geochemistry module shall compute all Jacobian entries of all Kernels" + issues = '#15668' + design = 'transport.md GeochemistryDispersion.md' + [../] + [./dispersion_1] + type = Exodiff + input = dispersion_1.i + exodiff = dispersion_1_out.e + requirement = 'The geochemistry module shall simulate simple transport problems involving hydrodynamic dispersion' + issues = '#15668' + design = 'transport.md GeochemistryDispersion.md' + [../] +[] diff --git a/modules/geochemistry/test/tests/kernels/time_deriv_1.i b/modules/geochemistry/test/tests/kernels/time_deriv_1.i new file mode 100644 index 000000000000..68e2305d1f84 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/time_deriv_1.i @@ -0,0 +1,83 @@ +# An initial concentration field in a material with constant porosity is subjected to a constant source +# porosity * d(concentration)/dt = source +# The result is checked vs the expected solution, which is conc = conc_old + dt * source / porosity +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 2 + ny = 4 + nz = 2 +[] + +[Variables] + [./conc] + [../] +[] + +[Kernels] + [./dot] + type = GeochemistryTimeDerivative + porosity = porosity + variable = conc + [../] + [./source] + type = BodyForce + function = 3.0 + variable = conc + [../] +[] + +[ICs] + [./conc] + type = FunctionIC + function = 'z * z + 4 * x * x * x + y' + variable = conc + [../] +[] + +[AuxVariables] + [./porosity] + [../] + [./expected] + [../] + [./should_be_zero] + [../] +[] + +[AuxKernels] + [./porosity] + type = FunctionAux + function = '6.0' + variable = porosity + [../] + [./expected] + type = FunctionAux + function = 'z * z + 4 * x * x * x + y + 2.0 * 3.0 / 6.0' + variable = expected + [../] + [./should_be_zero] + type = ParsedAux + args = 'expected conc' + function = 'expected - conc' + variable = should_be_zero + [../] +[] + +[Postprocessors] + [./error] + type = NodalL2Norm + variable = should_be_zero + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + dt = 2 + end_time = 2 +[] + +[Outputs] + csv = true +[] + diff --git a/modules/geochemistry/test/tests/kernels/time_deriv_2.i b/modules/geochemistry/test/tests/kernels/time_deriv_2.i new file mode 100644 index 000000000000..c31b532d66e8 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/time_deriv_2.i @@ -0,0 +1,91 @@ +# A point-source is added to fluid in a material with spatially-varying porosity +# porosity * d(concentration)/dt = 3.0 * delta(x - 1.0) +# where delta is the Dirac delta function (a ConstantPointSource DiracKernel) +# The solution, at x = 1.0 is +# concentration = concentration_old + 3 * dt / porosity +# while concentration is unchanged elsewhere. +# Note that since GeochemistryTimeDerivative is mass-lumped, it produces this solution. +# If mass lumping had not been used, concentration would have decreased at x != 1.0 +[Mesh] + type = GeneratedMesh + dim = 1 + nx = 2 + xmax = 2 +[] + +[Variables] + [./conc] + [../] +[] + +[Kernels] + [./dot] + type = GeochemistryTimeDerivative + porosity = porosity + variable = conc + [../] +[] + +[DiracKernels] + [./source] + type = ConstantPointSource + point = '1.0 0 0' + variable = conc + value = 12.0 + [../] +[] + +[ICs] + [./conc] + type = FunctionIC + function = 'x * x' + variable = conc + [../] +[] + +[AuxVariables] + [./porosity] + [../] + [./expected] + [../] + [./should_be_zero] + [../] +[] + +[AuxKernels] + [./porosity] + type = FunctionAux + function = '6.0 + x' + variable = porosity + [../] + [./expected] + type = FunctionAux + function = 'if(x > 0.5 & x < 1.5, x * x + 2.0 * 12.0 / (6.0 + x), x * x)' + variable = expected + [../] + [./should_be_zero] + type = ParsedAux + args = 'expected conc' + function = 'expected - conc' + variable = should_be_zero + [../] +[] + +[Postprocessors] + [./error] + type = NodalL2Norm + variable = should_be_zero + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + dt = 2 + end_time = 2 +[] + +[Outputs] + csv = true +[] + diff --git a/modules/geochemistry/test/tests/kernels/time_deriv_jac.i b/modules/geochemistry/test/tests/kernels/time_deriv_jac.i new file mode 100644 index 000000000000..ba03fce4f085 --- /dev/null +++ b/modules/geochemistry/test/tests/kernels/time_deriv_jac.i @@ -0,0 +1,49 @@ +# The Jacobian of the GeochemistryTimeDerivative Kernel is checked +[Mesh] + type = GeneratedMesh + dim = 1 + nx = 2 +[] + +[Variables] + [./conc] + [../] +[] + +[Kernels] + [./dot] + type = GeochemistryTimeDerivative + porosity = porosity + variable = conc + [../] +[] + +[AuxVariables] + [./porosity] + [../] +[] + +[AuxKernels] + [./porosity] + type = FunctionAux + function = '1.0 + x' + variable = porosity + [../] +[] + +[Preconditioning] + [./check] + type = SMP + full = true + petsc_options = '-snes_test_jacobian -snes_force_iteration' + petsc_options_iname = '-snes_type -ksp_type -pc_type -snes_convergence_test' + petsc_options_value = ' ksponly preonly none skip' + [../] +[] + +[Executioner] + type = Transient + solve_type = Newton + num_steps = 1 +[] +