diff --git a/framework/include/actions/AddVariableAction.h b/framework/include/actions/AddVariableAction.h index cdafa82968a6..d93c3a485eba 100644 --- a/framework/include/actions/AddVariableAction.h +++ b/framework/include/actions/AddVariableAction.h @@ -74,6 +74,9 @@ class AddVariableAction : public Action, public OutputInterface /// True if the variable being created is a scalar bool _scalar_var; + /// Number of components for an array variable + unsigned int _component; + /// Absolute zero tolerance static const Real _abs_zero_tol; }; diff --git a/framework/include/ics/ArrayConstantIC.h b/framework/include/ics/ArrayConstantIC.h new file mode 100644 index 000000000000..7273a5355f19 --- /dev/null +++ b/framework/include/ics/ArrayConstantIC.h @@ -0,0 +1,36 @@ +//* 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 + +#ifndef ARRAYCONSTANTIC_H +#define ARRAYCONSTANTIC_H + +#include "ArrayInitialCondition.h" + +// Forward Declarations +class ArrayConstantIC; +namespace libMesh +{ +class Point; +} + +template <> +InputParameters validParams(); + +class ArrayConstantIC : public ArrayInitialCondition +{ +public: + ArrayConstantIC(const InputParameters & parameters); + + virtual RealArrayValue value(const Point & p) override; + +protected: + const RealArrayValue _value; +}; + +#endif // VECTORCONSTANTIC_H diff --git a/framework/include/ics/ArrayInitialCondition.h b/framework/include/ics/ArrayInitialCondition.h new file mode 100644 index 000000000000..f2d387ac6288 --- /dev/null +++ b/framework/include/ics/ArrayInitialCondition.h @@ -0,0 +1,15 @@ +//* 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 + +#ifndef ARRAYINITIALCONDITION_H +#define ARRAYINITIALCONDITION_H + +#include "InitialConditionTempl.h" + +#endif // ARRAYINITIALCONDITION_H diff --git a/framework/include/ics/InitialConditionTempl.h b/framework/include/ics/InitialConditionTempl.h index 0c06e84107ea..ce5187e0d3e8 100644 --- a/framework/include/ics/InitialConditionTempl.h +++ b/framework/include/ics/InitialConditionTempl.h @@ -26,6 +26,8 @@ template <> InputParameters validParams>(); template <> InputParameters validParams>(); +template <> +InputParameters validParams>(); /** * This is a template class that implements the workhorse `compute` and `computeNodal` methods. The @@ -37,9 +39,11 @@ template class InitialConditionTempl : public InitialConditionBase { public: - typedef FEGenericBase FEBaseType; typedef typename OutputTools::OutputShape ValueType; typedef typename OutputTools::OutputGradient GradientType; + typedef typename OutputTools::OutputShapeGradient GradientShapeType; + typedef typename OutputTools::OutputData DataType; + typedef FEGenericBase FEBaseType; /** * Constructor @@ -60,7 +64,7 @@ class InitialConditionTempl : public InitialConditionBase * * This must be overridden by derived classes. */ - virtual ValueType value(const Point & p) = 0; + virtual T value(const Point & p) = 0; /** * The gradient of the variable at a point. @@ -70,6 +74,8 @@ class InitialConditionTempl : public InitialConditionBase */ virtual GradientType gradient(const Point & /*p*/) { return GradientType(); }; + T gradientComponent(GradientType grad, unsigned int i); + /** * set the temporary solution vector for node projections of C0 variables */ @@ -87,13 +93,26 @@ class InitialConditionTempl : public InitialConditionBase * Helps perform multiplication of GradientTypes: a normal dot product for vectors and a * contraction for tensors */ - Real dotHelper(const GradientType & op1, const GradientType & op2); + Real dotHelper(const RealGradient & op1, const RealGradient & op2) { return op1 * op2; } + Real dotHelper(const RealTensor & op1, const RealTensor & op2) { return op1.contract(op2); } + RealArrayValue dotHelper(const RealVectorArrayValue & op1, const RealGradient & op2) + { + RealArrayValue v = op1.col(0) * op2(0); + for (unsigned int i = 1; i < LIBMESH_DIM; ++i) + v += op1.col(i) * op2(i); + return v; + } /** * Perform the cholesky solves for edge, side, and interior projections */ void choleskySolve(bool is_volume); + /** + * Assemble a small local system for cholesky solve + */ + void choleskyAssembly(bool is_volume); + protected: FEProblemBase & _fe_problem; THREAD_ID _tid; @@ -123,9 +142,9 @@ class InitialConditionTempl : public InitialConditionBase /// Matrix storage member DenseMatrix _Ke; /// Linear b vector - DenseVector _Fe; + DenseVector _Fe; /// Linear solution vector - DenseVector _Ue; + DenseVector _Ue; /// The finite element type for the IC variable const FEType & _fe_type; @@ -157,7 +176,7 @@ class InitialConditionTempl : public InitialConditionBase /// pointers to shape functions const std::vector> * _phi; /// pointers to shape function gradients - const std::vector> * _dphi; + const std::vector> * _dphi; /// pointers to the Jacobian * quadrature weights for current element const std::vector * _JxW; /// pointers to the xyz coordinates of the quadrature points for the current element @@ -171,3 +190,4 @@ class InitialConditionTempl : public InitialConditionBase typedef InitialConditionTempl InitialCondition; typedef InitialConditionTempl VectorInitialCondition; +typedef InitialConditionTempl ArrayInitialCondition; diff --git a/framework/include/postprocessors/ElementIntegralArrayVariablePostprocessor.h b/framework/include/postprocessors/ElementIntegralArrayVariablePostprocessor.h new file mode 100644 index 000000000000..a8e8c2660006 --- /dev/null +++ b/framework/include/postprocessors/ElementIntegralArrayVariablePostprocessor.h @@ -0,0 +1,45 @@ +//* 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 + +#ifndef ELEMENTINTEGRALVARIABLEARRAYPOSTPROCESSOR_H +#define ELEMENTINTEGRALVARIABLEARRAYPOSTPROCESSOR_H + +#include "ElementIntegralPostprocessor.h" +#include "MooseVariableInterface.h" + +// Forward Declarations +class ElementIntegralArrayVariablePostprocessor; + +template <> +InputParameters validParams(); + +/** + * This postprocessor computes a volume integral of the specified variable. + * + * Note that specializations of this integral are possible by deriving from this + * class and overriding computeQpIntegral(). + */ +class ElementIntegralArrayVariablePostprocessor : public ElementIntegralPostprocessor, + public MooseVariableInterface +{ +public: + ElementIntegralArrayVariablePostprocessor(const InputParameters & parameters); + +protected: + virtual Real computeQpIntegral() override; + + /// Holds the solution at current quadrature points + const ArrayVariableValue & _u; + /// Holds the solution gradient at the current quadrature points + const ArrayVariableGradient & _grad_u; + /// The component + const unsigned int _component; +}; + +#endif diff --git a/framework/src/actions/AddAuxVariableAction.C b/framework/src/actions/AddAuxVariableAction.C index f0292e7cc9a1..3a421ef4d599 100644 --- a/framework/src/actions/AddAuxVariableAction.C +++ b/framework/src/actions/AddAuxVariableAction.C @@ -29,7 +29,9 @@ validParams() "Specifies the order of the FE shape function to use " "for this variable (additional orders not listed are " "allowed)"); - params.addParam("initial_condition", "Specifies the initial condition for this variable"); + params.addParam("component", 1, "Number of component for an array variable"); + params.addParam>("initial_condition", + "Specifies the initial condition for this variable"); params.addParam>("block", "The block id where this variable lives"); return params; diff --git a/framework/src/actions/AddVariableAction.C b/framework/src/actions/AddVariableAction.C index 903d1ed6a188..2c59c8916f40 100644 --- a/framework/src/actions/AddVariableAction.C +++ b/framework/src/actions/AddVariableAction.C @@ -50,12 +50,15 @@ validParams() "Specifies the order of the FE shape function to use " "for this variable (additional orders not listed are " "allowed)"); - params.addParam("initial_condition", "Specifies the initial condition for this variable"); + params.addParam("component", 1, "Number of component for an array variable"); + params.addParam>("initial_condition", + "Specifies the initial condition for this variable"); params.addParam>("block", "The block id where this variable lives"); params.addParam("eigen", false, "True to make this variable an eigen variable"); // Advanced input options - params.addParam("scaling", 1.0, "Specifies a scaling factor to apply to this variable"); + params.addParam>("scaling", + "Specifies a scaling factor to apply to this variable"); params.addParamNamesToGroup("scaling eigen", "Advanced"); return params; @@ -66,7 +69,8 @@ AddVariableAction::AddVariableAction(InputParameters params) OutputInterface(params, false), _fe_type(Utility::string_to_enum(getParam("order")), Utility::string_to_enum(getParam("family"))), - _scalar_var(_fe_type.family == SCALAR) + _scalar_var(_fe_type.family == SCALAR), + _component(getParam("component")) { } @@ -113,8 +117,10 @@ AddVariableAction::createInitialConditionAction() if (_scalar_var) action_params.set("type") = "ScalarConstantIC"; - else + else if (_component == 1) action_params.set("type") = "ConstantIC"; + else + action_params.set("type") = "ArrayConstantIC"; // Create the action std::shared_ptr action = std::static_pointer_cast( @@ -122,7 +128,18 @@ AddVariableAction::createInitialConditionAction() // Set the required parameters for the object to be created action->getObjectParams().set("variable") = var_name; - action->getObjectParams().set("value") = getParam("initial_condition"); + auto value = getParam>("initial_condition"); + if (value.size() != _component) + mooseError("Size of 'initial_condition' is not consistent"); + if (_component > 1) + { + RealArrayValue v(_component); + for (unsigned int i = 0; i < _component; ++i) + v(i) = value[i]; + action->getObjectParams().set("value") = v; + } + else + action->getObjectParams().set("value") = value[0]; // Store the action in the ActionWarehouse _awh.addActionBlock(action); @@ -132,19 +149,34 @@ void AddVariableAction::addVariable(const std::string & var_name) { std::set blocks = getSubdomainIDs(); - Real scale_factor = isParamValid("scaling") ? getParam("scaling") : 1; + std::vector scale_factor = isParamValid("scaling") ? getParam>("scaling") + : std::vector(_component, 1); + if (scale_factor.size() != _component) + mooseError("Size of 'scaling' is not consistent"); // Scalar variable if (_scalar_var) - _problem->addScalarVariable(var_name, _fe_type.order, scale_factor); + _problem->addScalarVariable(var_name, _fe_type.order, scale_factor[0]); // Block restricted variable - else if (blocks.empty()) - _problem->addVariable(var_name, _fe_type, scale_factor); + else if (_component == 1) + { + if (blocks.empty()) + _problem->addVariable(var_name, _fe_type, scale_factor[0]); - // Non-block restricted variable + // Non-block restricted variable + else + _problem->addVariable(var_name, _fe_type, scale_factor[0], &blocks); + } else - _problem->addVariable(var_name, _fe_type, scale_factor, &blocks); + { + if (blocks.empty()) + _problem->addArrayVariable(var_name, _fe_type, _component, scale_factor); + + // Non-block restricted variable + else + _problem->addArrayVariable(var_name, _fe_type, _component, scale_factor, &blocks); + } if (getParam("eigen")) { diff --git a/framework/src/ics/ArrayConstantIC.C b/framework/src/ics/ArrayConstantIC.C new file mode 100644 index 000000000000..e934fc886b62 --- /dev/null +++ b/framework/src/ics/ArrayConstantIC.C @@ -0,0 +1,37 @@ +//* 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 "ArrayConstantIC.h" + +#include "libmesh/point.h" + +registerMooseObject("MooseApp", ArrayConstantIC); + +template <> +InputParameters +validParams() +{ + InputParameters params = validParams(); + params.addRequiredParam("value", "The values to be set in IC"); + params.addClassDescription("Sets constant component values for an array field variable."); + return params; +} + +ArrayConstantIC::ArrayConstantIC(const InputParameters & parameters) + : ArrayInitialCondition(parameters), _value(getParam("value")) +{ + if (_var.count() != _value.size()) + mooseError("'value' size is inconsistent to the number of components of the array variable"); +} + +RealArrayValue +ArrayConstantIC::value(const Point & /*p*/) +{ + return _value; +} diff --git a/framework/src/ics/InitialConditionTempl.C b/framework/src/ics/InitialConditionTempl.C index 26a96015438e..49b116d127e2 100644 --- a/framework/src/ics/InitialConditionTempl.C +++ b/framework/src/ics/InitialConditionTempl.C @@ -28,6 +28,13 @@ validParams>() return validParams(); } +template <> +InputParameters +validParams>() +{ + return validParams(); +} + template InitialConditionTempl::InitialConditionTempl(const InputParameters & parameters) : InitialConditionBase(parameters), @@ -90,7 +97,7 @@ InitialConditionTempl::compute() if (_cont == C_ONE) { - const std::vector> & ref_dphi = fe->get_dphi(); + const std::vector> & ref_dphi = fe->get_dphi(); _dphi = &ref_dphi; } @@ -228,31 +235,12 @@ InitialConditionTempl::compute() NumericVector & solution = _var.sys().solution(); - // 'first' and 'last' are no longer used, see note about subdomain-restricted variables below - // const dof_id_type - // first = solution.first_local_index(), - // last = solution.last_local_index(); - // Lock the new_vector since it is shared among threads. { Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx); - for (unsigned int i = 0; i < n_dofs; i++) - // We may be projecting a new zero value onto - // an old nonzero approximation - RHS - // if (_Ue(i) != 0.) - - // This is commented out because of subdomain restricted variables. - // It can be the case that if a subdomain restricted variable's boundary - // aligns perfectly with a processor boundary that the variable will get - // no value. To counteract this we're going to let every processor set a - // value at every node and then let PETSc figure it out. - // Later we can choose to do something different / better. - // if ((_dof_indices[i] >= first) && (_dof_indices[i] < last)) - { - solution.set(_dof_indices[i], _Ue(i)); - } _var.setDofValues(_Ue); + _var.insert(solution); } } @@ -285,6 +273,27 @@ InitialConditionTempl::setCZeroVertices() } } +template +T +InitialConditionTempl::gradientComponent(GradientType grad, unsigned int i) +{ + return grad(i); +} + +template <> +RealVectorValue +InitialConditionTempl::gradientComponent(GradientType grad, unsigned int i) +{ + return grad.row(i); +} + +template <> +RealArrayValue +InitialConditionTempl::gradientComponent(GradientType grad, unsigned int i) +{ + return grad.col(i); +} + template void InitialConditionTempl::setHermiteVertices() @@ -295,9 +304,9 @@ InitialConditionTempl::setHermiteVertices() _Ue(_current_dof) = value(*_current_node); _dof_is_fixed[_current_dof] = true; _current_dof++; - Gradient grad = gradient(*_current_node); + GradientType grad = gradient(*_current_node); // x derivative - _Ue(_current_dof) = grad(0); + _Ue(_current_dof) = gradientComponent(grad, 0); _dof_is_fixed[_current_dof] = true; _current_dof++; if (_dim > 1) @@ -306,35 +315,38 @@ InitialConditionTempl::setHermiteVertices() Point nxminus = _current_elem->point(_n), nxplus = _current_elem->point(_n); nxminus(0) -= TOLERANCE; nxplus(0) += TOLERANCE; - Gradient gxminus = gradient(nxminus); - Gradient gxplus = gradient(nxplus); + GradientType gxminus = gradient(nxminus); + GradientType gxplus = gradient(nxplus); // y derivative - _Ue(_current_dof) = grad(1); + _Ue(_current_dof) = gradientComponent(grad, 1); _dof_is_fixed[_current_dof] = true; _current_dof++; // xy derivative - _Ue(_current_dof) = (gxplus(1) - gxminus(1)) / 2. / TOLERANCE; + _Ue(_current_dof) = + (gradientComponent(gxplus, 1) - gradientComponent(gxminus, 1)) / 2. / TOLERANCE; _dof_is_fixed[_current_dof] = true; _current_dof++; if (_dim > 2) { // z derivative - _Ue(_current_dof) = grad(2); + _Ue(_current_dof) = gradientComponent(grad, 2); _dof_is_fixed[_current_dof] = true; _current_dof++; // xz derivative - _Ue(_current_dof) = (gxplus(2) - gxminus(2)) / 2. / TOLERANCE; + _Ue(_current_dof) = + (gradientComponent(gxplus, 2) - gradientComponent(gxminus, 2)) / 2. / TOLERANCE; _dof_is_fixed[_current_dof] = true; _current_dof++; // We need new points for yz Point nyminus = _current_elem->point(_n), nyplus = _current_elem->point(_n); nyminus(1) -= TOLERANCE; nyplus(1) += TOLERANCE; - Gradient gyminus = gradient(nyminus); - Gradient gyplus = gradient(nyplus); + GradientType gyminus = gradient(nyminus); + GradientType gyplus = gradient(nyplus); // xz derivative - _Ue(_current_dof) = (gyplus(2) - gyminus(2)) / 2. / TOLERANCE; + _Ue(_current_dof) = + (gradientComponent(gyplus, 2) - gradientComponent(gyminus, 2)) / 2. / TOLERANCE; _dof_is_fixed[_current_dof] = true; _current_dof++; // Getting a 2nd order xyz is more tedious @@ -348,12 +360,14 @@ InitialConditionTempl::setHermiteVertices() nxpym(1) -= TOLERANCE; nxpyp(0) += TOLERANCE; nxpyp(1) += TOLERANCE; - Gradient gxmym = gradient(nxmym); - Gradient gxmyp = gradient(nxmyp); - Gradient gxpym = gradient(nxpym); - Gradient gxpyp = gradient(nxpyp); - Number gxzplus = (gxpyp(2) - gxmyp(2)) / 2. / TOLERANCE; - Number gxzminus = (gxpym(2) - gxmym(2)) / 2. / TOLERANCE; + GradientType gxmym = gradient(nxmym); + GradientType gxmyp = gradient(nxmyp); + GradientType gxpym = gradient(nxpym); + GradientType gxpyp = gradient(nxpyp); + DataType gxzplus = + (gradientComponent(gxpyp, 2) - gradientComponent(gxmyp, 2)) / 2. / TOLERANCE; + DataType gxzminus = + (gradientComponent(gxpym, 2) - gradientComponent(gxmym, 2)) / 2. / TOLERANCE; // xyz derivative _Ue(_current_dof) = (gxzplus - gxzminus) / 2. / TOLERANCE; _dof_is_fixed[_current_dof] = true; @@ -380,10 +394,10 @@ InitialConditionTempl::setOtherCOneVertices() _Ue(_current_dof) = value(*_current_node); _dof_is_fixed[_current_dof] = true; _current_dof++; - Gradient grad = gradient(*_current_node); + GradientType grad = gradient(*_current_node); for (unsigned int i = 0; i != _dim; ++i) { - _Ue(_current_dof) = grad(i); + _Ue(_current_dof) = gradientComponent(grad, i); _dof_is_fixed[_current_dof] = true; _current_dof++; } @@ -395,32 +409,10 @@ InitialConditionTempl::setOtherCOneVertices() { } -template -Real -InitialConditionTempl::dotHelper(const GradientType & op1, const GradientType & op2) -{ - return op1 * op2; -} - -template <> -Real -InitialConditionTempl::dotHelper(const GradientType & op1, - const GradientType & op2) -{ - return op1.contract(op2); -} - template void -InitialConditionTempl::choleskySolve(bool is_volume) +InitialConditionTempl::choleskyAssembly(bool is_volume) { - _Ke.resize(_free_dofs, _free_dofs); - _Ke.zero(); - _Fe.resize(_free_dofs); - _Fe.zero(); - // The new edge coefficients - DenseVector U(_free_dofs); - // Loop over the quadrature points for (_qp = 0; _qp < _n_qp; _qp++) { @@ -464,6 +456,21 @@ InitialConditionTempl::choleskySolve(bool is_volume) freei++; } } +} + +template +void +InitialConditionTempl::choleskySolve(bool is_volume) +{ + _Ke.resize(_free_dofs, _free_dofs); + _Ke.zero(); + _Fe.resize(_free_dofs); + _Fe.zero(); + + choleskyAssembly(is_volume); + + // The new edge coefficients + DenseVector U(_free_dofs); _Ke.cholesky_solve(_Fe, U); @@ -471,13 +478,51 @@ InitialConditionTempl::choleskySolve(bool is_volume) for (unsigned int i = 0; i != _free_dofs; ++i) { auto the_dof = is_volume ? _free_dof[i] : _side_dofs[_free_dof[i]]; - Number & ui = _Ue(the_dof); + DataType & ui = _Ue(the_dof); libmesh_assert(std::abs(ui) < TOLERANCE || std::abs(ui - U(i)) < TOLERANCE); ui = U(i); _dof_is_fixed[the_dof] = true; } } +template <> +void +InitialConditionTempl::choleskySolve(bool is_volume) +{ + _Ke.resize(_free_dofs, _free_dofs); + _Ke.zero(); + _Fe.resize(_free_dofs); + for (unsigned int i = 0; i < _free_dofs; ++i) + _Fe(i).setZero(_var.count()); + + choleskyAssembly(is_volume); + + // The new edge coefficients + DenseVector U = _Fe; + + for (unsigned int i = 0; i < _var.count(); ++i) + { + DenseVector v(_free_dofs), x(_free_dofs); + for (unsigned int j = 0; j < _free_dofs; ++j) + v(j) = _Fe(j)(i); + + _Ke.cholesky_solve(v, x); + + for (unsigned int j = 0; j < _free_dofs; ++j) + U(j)(i) = x(j); + } + + // Transfer new edge solutions to element + for (unsigned int i = 0; i != _free_dofs; ++i) + { + auto the_dof = is_volume ? _free_dof[i] : _side_dofs[_free_dof[i]]; + DataType & ui = _Ue(the_dof); + libmesh_assert(ui.matrix().norm() < TOLERANCE || (ui - U(i)).matrix().norm() < TOLERANCE); + ui = U(i); + _dof_is_fixed[the_dof] = true; + } +} + template void InitialConditionTempl::computeNodal(const Point & p) @@ -498,3 +543,4 @@ InitialConditionTempl::computeNodal(const Point & p) template class InitialConditionTempl; template class InitialConditionTempl; +template class InitialConditionTempl; diff --git a/framework/src/postprocessors/ElementIntegralArrayVariablePostprocessor.C b/framework/src/postprocessors/ElementIntegralArrayVariablePostprocessor.C new file mode 100644 index 000000000000..3f094e33f7c4 --- /dev/null +++ b/framework/src/postprocessors/ElementIntegralArrayVariablePostprocessor.C @@ -0,0 +1,40 @@ +//* 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 "ElementIntegralArrayVariablePostprocessor.h" + +registerMooseObject("MooseApp", ElementIntegralArrayVariablePostprocessor); + +template <> +InputParameters +validParams() +{ + InputParameters params = validParams(); + params.addRequiredCoupledVar("variable", "The name of the variable that this object operates on"); + params.addParam("component", 0, ""); + return params; +} + +ElementIntegralArrayVariablePostprocessor::ElementIntegralArrayVariablePostprocessor( + const InputParameters & parameters) + : ElementIntegralPostprocessor(parameters), + MooseVariableInterface( + this, false, "variable", Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_ARRAY), + _u(coupledArrayValue("variable")), + _grad_u(coupledArrayGradient("variable")), + _component(getParam("component")) +{ + addMooseVariableDependency(mooseVariable()); +} + +Real +ElementIntegralArrayVariablePostprocessor::computeQpIntegral() +{ + return _u[_qp](_component); +} diff --git a/framework/src/problems/FEProblemBase.C b/framework/src/problems/FEProblemBase.C index 068e66e22138..8a7808d76c26 100644 --- a/framework/src/problems/FEProblemBase.C +++ b/framework/src/problems/FEProblemBase.C @@ -2256,6 +2256,8 @@ FEProblemBase::addInitialCondition(const std::string & ic_name, ic = _factory.create(ic_name, name, parameters, tid); else if (dynamic_cast(&var)) ic = _factory.create(ic_name, name, parameters, tid); + else if (dynamic_cast(&var)) + ic = _factory.create(ic_name, name, parameters, tid); else mooseError("Your FE variable in initial condition ", name, diff --git a/test/tests/variables/array_variable/array_variable_test.i b/test/tests/variables/array_variable/array_variable_test.i new file mode 100644 index 000000000000..c0c77693fe95 --- /dev/null +++ b/test/tests/variables/array_variable/array_variable_test.i @@ -0,0 +1,141 @@ +[Mesh] + type = GeneratedMesh + dim = 2 + nx = 10 + ny = 8 +[] + +[Problem] + kernel_coverage_check = false + solve = false +[] + +[Variables] + [./u] + order = FIRST + family = LAGRANGE + component = 4 + initial_condition = '1 2 3 4' + [../] + [./uu] + order = FIRST + family = LAGRANGE + component = 2 + initial_condition = '1 2' + [../] + [./v] + order = FIRST + family = LAGRANGE + component = 2 + initial_condition = '5 6' + [../] + [./w] + order = CONSTANT + family = MONOMIAL + component = 3 + initial_condition = '7 8 9' + [../] + [./x] + order = THIRD + family = MONOMIAL + component = 2 + initial_condition = '10 11' + [../] + [./y] + order = FIRST + family = L2_LAGRANGE + component = 3 + initial_condition = '12 13 14' + [../] +[] + +[Postprocessors] + [u0int] + type = ElementIntegralArrayVariablePostprocessor + variable = u + component = 0 + [] + [u1int] + type = ElementIntegralArrayVariablePostprocessor + variable = u + component = 1 + [] + [u2int] + type = ElementIntegralArrayVariablePostprocessor + variable = u + component = 2 + [] + [u3int] + type = ElementIntegralArrayVariablePostprocessor + variable = u + component = 3 + [] + [uu0int] + type = ElementIntegralArrayVariablePostprocessor + variable = uu + component = 0 + [] + [uu1int] + type = ElementIntegralArrayVariablePostprocessor + variable = uu + component = 1 + [] + [v0int] + type = ElementIntegralArrayVariablePostprocessor + variable = v + component = 0 + [] + [v1int] + type = ElementIntegralArrayVariablePostprocessor + variable = v + component = 1 + [] + [w0int] + type = ElementIntegralArrayVariablePostprocessor + variable = w + component = 0 + [] + [w1int] + type = ElementIntegralArrayVariablePostprocessor + variable = w + component = 1 + [] + [w2int] + type = ElementIntegralArrayVariablePostprocessor + variable = w + component = 2 + [] + [x0int] + type = ElementIntegralArrayVariablePostprocessor + variable = x + component = 0 + [] + [x1int] + type = ElementIntegralArrayVariablePostprocessor + variable = x + component = 1 + [] + [y0int] + type = ElementIntegralArrayVariablePostprocessor + variable = y + component = 0 + [] + [y1int] + type = ElementIntegralArrayVariablePostprocessor + variable = y + component = 1 + [] + [y2int] + type = ElementIntegralArrayVariablePostprocessor + variable = y + component = 2 + [] +[] + +[Executioner] + type = Steady +[] + +[Outputs] + exodus = true +[] diff --git a/test/tests/variables/array_variable/gold/array_variable_test_out.e b/test/tests/variables/array_variable/gold/array_variable_test_out.e new file mode 100644 index 000000000000..9f579ef1ded4 Binary files /dev/null and b/test/tests/variables/array_variable/gold/array_variable_test_out.e differ diff --git a/test/tests/variables/array_variable/tests b/test/tests/variables/array_variable/tests new file mode 100644 index 000000000000..a66bb1fc5b78 --- /dev/null +++ b/test/tests/variables/array_variable/tests @@ -0,0 +1,11 @@ +[Tests] + [./block_aux_kernel_test] + type = 'Exodiff' + input = 'array_variable_test.i' + exodiff = 'array_variable_test_out.e' + group = 'requirements' + requirement = 'MOOSE shall provide an ability to add array variables with constant initial conditions.' + issues = '#6881' + design = 'moose_variables.md' + [../] +[]