diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_EvaluatorStyle.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_EvaluatorStyle.hpp new file mode 100644 index 000000000000..a02e524453ef --- /dev/null +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_EvaluatorStyle.hpp @@ -0,0 +1,63 @@ +// @HEADER +// *********************************************************************** +// +// Panzer: A partial differential equation assembly +// engine for strongly coupled complex multiphysics systems +// Copyright (2011) Sandia Corporation +// +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, +// the U.S. Government retains certain rights in this software. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the Corporation nor the names of the +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and +// Eric C. Cyr (eccyr@sandia.gov) +// *********************************************************************** +// @HEADER + +#ifndef __Panzer_EvaluatorStyle_hpp__ +#define __Panzer_EvaluatorStyle_hpp__ + +namespace panzer +{ + /** + * \brief An indication of how an `Evaluator` will behave. + * + * An `Evaluator` will compute the result of its evaluation and then + * behave according to the table below. + */ + enum class EvaluatorStyle + { + CONTRIBUTES, /*!< Contribute the result to a specified residual, not saving + anything. */ + EVALUATES, /*!< Save the result under a specified name for future use. */ + }; // end of enum class EnumeratorStyle + +} // end of namespace panzer + +#endif // __Panzer_EvaluatorStyle_hpp__ diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_decl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_decl.hpp index f5c29ce0879b..5c4dbaad8d6a 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_decl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_decl.hpp @@ -40,61 +40,255 @@ // *********************************************************************** // @HEADER -#ifndef PANZER_EVALUATOR_BASISTIMESSCALAR_DECL_HPP -#define PANZER_EVALUATOR_BASISTIMESSCALAR_DECL_HPP +#ifndef __Panzer_Integrator_BasisTimesScalar_decl_hpp__ +#define __Panzer_Integrator_BasisTimesScalar_decl_hpp__ +/////////////////////////////////////////////////////////////////////////////// +// +// Include Files +// +/////////////////////////////////////////////////////////////////////////////// + +// C++ #include -#include "Panzer_Dimension.hpp" -#include "Phalanx_Evaluator_Macros.hpp" -#include "Phalanx_MDField.hpp" + +// Kokkos #include "Kokkos_DynRankView.hpp" -#include "Panzer_Evaluator_Macros.hpp" +// Panzer +#include "Panzer_Evaluator_WithBaseImpl.hpp" +#include "Panzer_EvaluatorStyle.hpp" + +// Phalanx +#include "Phalanx_Evaluator_Derived.hpp" +#include "Phalanx_MDField.hpp" + +namespace panzer +{ + /** + * \brief Computes \f$ Ma(x)b(x)\cdots\int s(x)\phi(x)\,dx \f$. + * + * Evaluates the integral + * \f[ + Ma(x)b(x)\cdots\int s(x)\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., are + * some fields that depend on position, \f$ s \f$ is some scalar function, + * and \f$ \phi \f$ is some basis. + */ + template + class Integrator_BasisTimesScalar + : + public panzer::EvaluatorWithBaseImpl, + public PHX::EvaluatorDerived + { + public: + + /** + * \brief Main Constructor. + * + * Creates an `Evaluator` to evaluate the integral + * \f[ + Ma(x)b(x)\cdots\int s(x)\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., + * are some fields that depend on position, \f$ s \f$ is some scalar + * function, and \f$ \phi \f$ is some basis. + * + * \param[in] evalStyle An `enum` declaring the behavior of this + * `Evaluator`, which is to either: + * - compute and contribute (`CONTRIBUTES`), or + * - compute and store (`EVALUATES`). + * \param[in] resName The name of either the contributed or evaluated + * field, depending on `evalStyle`. + * \param[in] valName The name of the scalar value being integrated + * (\f$ s \f$). + * \param[in] basis The basis that you'd like to use (\f$ \phi + \f$). + * \param[in] ir The integration rule that you'd like to use. + * \param[in] multiplier The scalar multiplier out in front of the + * integral you're computing (\f$ M \f$). If not + * specified, this defaults to 1. + * \param[in] fmNames A list of names of fields that are multipliers + * out in front of the integral you're computing + * (\f$ a(x) \f$, \f$ b(x) \f$, etc.). If not + * specified, this defaults to an empty `vector`. + * + * \throws std::invalid_argument If any of the inputs are invalid. + * \throws std::logic_error If the `basis` supplied is not a scalar + * basis. + */ + Integrator_BasisTimesScalar( + const panzer::EvaluatorStyle& evalStyle, + const std::string& resName, + const std::string& valName, + const panzer::BasisIRLayout& basis, + const panzer::IntegrationRule& ir, + const double& multiplier = 1, + const std::vector& fmNames = + std::vector()); + + /** + * \brief `ParameterList` Constructor. + * + * Creates an `Evaluator` to evaluate the integral + * \f[ + Ma(x)b(x)\cdots\int s(x)\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., + * are some fields that depend on position, \f$ s \f$ is some scalar + * function, and \f$ \phi \f$ is some basis. + * + * \note This constructor exists to preserve the older way of creating + * an `Evaluator` with a `ParameterList`; however, it is + * _strongly_ advised that you _not_ use this `ParameterList` + * Constructor, but rather that you favor the Main Constructor + * with its compile-time argument checking instead. + * + * \param[in] p A `ParameterList` of the form + \code{.xml} + + + + + + + + + \endcode + * where + * - "Residual Name" is the name for the term this + * `Evaluator` is evaluating, + * - "Value Name" is the name of the scalar value being + * integrated (\f$ s \f$), + * - "Basis" is the basis that you'd like to use (\f$ \phi + \f$), + * - "IR" is the integration rule that you'd like to use, + * - "Multiplier" is the scalar multiplier out in front of + * the integral you're computing (\f$ M \f$), and + * - "Field Multipliers" is an optional list of names of + * fields that are multipliers out in front of the + * integral you're computing (\f$ a(x) \f$, \f$ b(x) \f$, + * etc.). + */ + Integrator_BasisTimesScalar( + const Teuchos::ParameterList& p); + + /** + * \brief Post-Registration Setup. + * + * Sets the number of nodes and quadrature points, sets the basis index, + * sets the contributed field data in the field manager (if applicable), + * and then creates the `tmp_` `Kokkos::View`. + * + * \param[in] sd Essentially a list of `Workset`s, which are collections + * of cells (elements) that all live on a single process. + * \param[in] fm The field manager, used in setting the field data for + * the contributed field, if there is one. + */ + void + postRegistrationSetup( + typename Traits::SetupData sd, + PHX::FieldManager& fm); + + /** + * \brief Evaluate Fields. + * + * This actually performs the integration by looping over cells in the + * `Workset`, and then over bases and integration points on the cell. + * + * \param[in] workset The `Workset` on which you're going to do the + * integration. + */ + void + evaluateFields( + typename Traits::EvalData workset); + + private: + + /** + * \brief Get Valid Parameters. + * + * Get all the parameters that we support such that the `ParameterList` + * Constructor can do some validation of the input `ParameterList`. + * + * \returns A `ParameterList` with all the valid parameters (keys) in + * it. The values tied to those keys are meaningless default + * values. + */ + Teuchos::RCP + getValidParameters() const; + + /** + * \brief The scalar type. + */ + typedef typename EvalT::ScalarT ScalarT; + + /** + * \brief An `enum` determining the behavior of this `Evaluator`. + * + * This `Evaluator` will compute the result of its integration and then: + * - CONTRIBUTES: contribute it to a specified residual, + * not saving anything; or + * - EVALUATES: save it under a specified name for + * future use. + */ + const panzer::EvaluatorStyle evalStyle_; -namespace panzer { + /** + * \brief A field to which we'll contribute, or in which we'll store, + * the result of computing this integral. + */ + PHX::MDField field_; -/** Computes the integral - * \f[ - \int s(x) \phi(x) \, d x - \f] - * where \f$\phi\f$is the test function and \f$s\f$ is - * the scalar quantity. The parameter list passed into the construction - * is formatted as follows - \verbatim - - - - - - - - - \endverbatim - */ -PANZER_EVALUATOR_CLASS(Integrator_BasisTimesScalar) - - PHX::MDField residual; - - PHX::MDField scalar; + /** + * \brief A field representing the scalar function we're integrating + * (\f$ s \f$). + */ + PHX::MDField scalar_; - std::vector > field_multipliers; + /** + * \brief The scalar multiplier out in front of the integral (\f$ M + \f$). + */ + double multiplier_; - std::size_t num_nodes; + /** + * \brief The (possibly empty) list of fields that are multipliers out + * in front of the integral (\f$ a(x) \f$, \f$ b(x) \f$, etc.). + */ + std::vector> + fieldMults_; - std::size_t num_qp; + /** + * \brief The number of nodes for each cell. + */ + int numNodes_; - double multiplier; + /** + * \brief The number of quadrature points for each cell. + */ + int numQP_; - std::string basis_name; - std::size_t basis_index; + /** + * \brief The name of the basis we're using. + */ + std::string basisName_; - Kokkos::DynRankView tmp; + /** + * \brief The index in the `Workset` bases for our particular + * `BasisIRLayout` name. + */ + std::size_t basisIndex_; -private: - Teuchos::RCP getValidParameters() const; + /** + * \brief A temporary `Kokkos::View` that we'll use in computing the + * result of this integral. + */ + Kokkos::DynRankView tmp_; -PANZER_EVALUATOR_CLASS_END + }; // end of class Integrator_BasisTimesScalar -} +} // end of namespace panzer -#endif +#endif // __Panzer_Integrator_BasisTimesScalar_decl_hpp__ diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_impl.hpp index 830373552d80..3860349dc557 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_BasisTimesScalar_impl.hpp @@ -40,167 +40,224 @@ // *********************************************************************** // @HEADER -#ifndef PANZER_EVALUATOR_BASISTIMESSCALAR_IMPL_HPP -#define PANZER_EVALUATOR_BASISTIMESSCALAR_IMPL_HPP +#ifndef __Panzer_Integrator_BasisTimesScalar_impl_hpp__ +#define __Panzer_Integrator_BasisTimesScalar_impl_hpp__ -#include "Intrepid2_FunctionSpaceTools.hpp" -#include "Panzer_IntegrationRule.hpp" +/////////////////////////////////////////////////////////////////////////////// +// +// Include Files +// +/////////////////////////////////////////////////////////////////////////////// + +// Panzer #include "Panzer_BasisIRLayout.hpp" +#include "Panzer_IntegrationRule.hpp" #include "Panzer_Workset_Utilities.hpp" -#include "Kokkos_ViewFactory.hpp" -#define PANZER_USE_FAST_QUAD 1 -// #define PANZER_USE_FAST_QUAD 0 +namespace panzer +{ + ///////////////////////////////////////////////////////////////////////////// + // + // Main Constructor + // + ///////////////////////////////////////////////////////////////////////////// + template + Integrator_BasisTimesScalar:: + Integrator_BasisTimesScalar( + const panzer::EvaluatorStyle& evalStyle, + const std::string& resName, + const std::string& valName, + const panzer::BasisIRLayout& basis, + const panzer::IntegrationRule& ir, + const double& multiplier, /* = 1 */ + const std::vector& fmNames /* = + std::vector() */) + : + evalStyle_(evalStyle), + multiplier_(multiplier), + basisName_(basis.name()) + { + using panzer::BASIS; + using panzer::Cell; + using panzer::EvaluatorStyle; + using panzer::IP; + using PHX::MDField; + using PHX::typeAsString; + using std::invalid_argument; + using std::logic_error; + using std::string; + using Teuchos::RCP; -namespace panzer { + // Ensure the input makes sense. + TEUCHOS_TEST_FOR_EXCEPTION(resName == "", invalid_argument, "Error: " \ + "Integrator_BasisTimesScalar called with an empty residual name.") + TEUCHOS_TEST_FOR_EXCEPTION(valName == "", invalid_argument, "Error: " \ + "Integrator_BasisTimesScalar called with an empty value name.") + RCP tmpBasis = basis.getBasis(); + TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->isScalarBasis(), logic_error, + "Error: Integrator_BasisTimesScalar: Basis of type \"" + << tmpBasis->name() << "\" is not a scalar basis.") -//********************************************************************** -PHX_EVALUATOR_CTOR(Integrator_BasisTimesScalar,p) : - residual( p.get("Residual Name"), - p.get< Teuchos::RCP >("Basis")->functional), - scalar( p.get("Value Name"), - p.get< Teuchos::RCP >("IR")->dl_scalar), - basis_name(p.get< Teuchos::RCP >("Basis")->name()) -{ - using Teuchos::RCP; - - Teuchos::RCP valid_params = this->getValidParameters(); - p.validateParameters(*valid_params); - - Teuchos::RCP basis - = p.get< Teuchos::RCP >("Basis")->getBasis(); - - // Verify that this basis supports the gradient operation - TEUCHOS_TEST_FOR_EXCEPTION(!basis->isScalarBasis(),std::logic_error, - "Integrator_BasisTimesScalar: Basis of type \"" << basis->name() << "\" is not " - "a scalar basis"); - - this->addEvaluatedField(residual); - this->addDependentField(scalar); - - multiplier = p.get("Multiplier"); - - - // build field multpliers if vector is nonnull (defaults to null) - if(p.isType > >("Field Multipliers")) { - RCP > field_multiplier_names = - p.get > >("Field Multipliers"); - if(field_multiplier_names!=Teuchos::null) { - for (std::vector::const_iterator name = - field_multiplier_names->begin(); - name != field_multiplier_names->end(); ++name) { - PHX::MDField tmp_field(*name, p.get< Teuchos::RCP >("IR")->dl_scalar); - field_multipliers.push_back(tmp_field); - } - } - } - - // add dependent field multiplers - for (typename std::vector >::iterator field = field_multipliers.begin(); - field != field_multipliers.end(); ++field) - this->addDependentField(*field); - - std::string n = "Integrator_BasisTimesScalar: " + residual.fieldTag().name(); - this->setName(n); -} - -//********************************************************************** -PHX_POST_REGISTRATION_SETUP(Integrator_BasisTimesScalar,sd,fm) -{ - this->utils.setFieldData(residual,fm); - this->utils.setFieldData(scalar,fm); - - for (typename std::vector >::iterator field = field_multipliers.begin(); - field != field_multipliers.end(); ++field) - this->utils.setFieldData(*field,fm); - - num_nodes = residual.dimension(1); - num_qp = scalar.dimension(1); - - basis_index = panzer::getBasisIndex(basis_name, (*sd.worksets_)[0], this->wda); - - tmp = Kokkos::createDynRankView(scalar.get_static_view(),"tmp",scalar.dimension(0), num_qp); -} - -//********************************************************************** -PHX_EVALUATE_FIELDS(Integrator_BasisTimesScalar,workset) -{ - // for (int i=0; i < residual.size(); ++i) - // residual[i] = 0.0; - // Irina modified - residual.deep_copy(ScalarT(0.0)); - -#if PANZER_USE_FAST_QUAD - // do a scaled copy - // Irina modified - // for (int i=0; i < scalar.size(); ++i) - // tmp[i] = multiplier * scalar[i]; - for (int i=0; i < scalar.extent_int(0); ++i) - for (int j=0; j < scalar.extent_int(1); ++j) - tmp(i,j) = multiplier * scalar(i,j); - - for (typename std::vector >::iterator field = field_multipliers.begin(); - field != field_multipliers.end(); ++field) { - const PHX::MDField & field_data = *field; - - //Irina modified - //for (int i=0; i < field_data.size(); ++i) - // tmp[i] *= field_data[i]; - for (int i=0; i < scalar.extent_int(0); ++i) - for (int j=0; j < scalar.extent_int(1); ++j) - tmp(i,j) = tmp(i,j) * field_data(i,j); - } - - // const Kokkos::DynRankView & weighted_basis = this->wda(workset).bases[basis_index]->weighted_basis; - const BasisValues2 & bv = *this->wda(workset).bases[basis_index]; - - for (index_t cell = 0; cell < workset.num_cells; ++cell) { - for (std::size_t basis = 0; basis < num_nodes; ++basis) { - for (std::size_t qp = 0; qp < num_qp; ++qp) { - residual(cell,basis) += tmp(cell,qp)*bv.weighted_basis_scalar(cell,basis,qp); - } - } - } - -#else - for (index_t cell = 0; cell < workset.num_cells; ++cell) { - for (std::size_t qp = 0; qp < num_qp; ++qp) { - tmp(cell,qp) = multiplier * scalar(cell,qp); - for (typename std::vector >::iterator field = field_multipliers.begin(); - field != field_multipliers.end(); ++field) - tmp(cell,qp) = tmp(cell,qp) * (*field)(cell,qp); - } - } - - if(workset.num_cells>0) - Intrepid2::FunctionSpaceTools:: - integrate(residual, tmp, - (this->wda(workset).bases[basis_index])->weighted_basis, - Intrepid2::COMP_CPP); -#endif -} - -//********************************************************************** -template -Teuchos::RCP -Integrator_BasisTimesScalar::getValidParameters() const -{ - Teuchos::RCP p = Teuchos::rcp(new Teuchos::ParameterList); - p->set("Residual Name", "?"); - p->set("Value Name", "?"); - Teuchos::RCP basis; - p->set("Basis", basis); - Teuchos::RCP ir; - p->set("IR", ir); - p->set("Multiplier", 1.0); - Teuchos::RCP > fms; - p->set("Field Multipliers", fms); - return p; -} + // Create the field for the scalar quantity we're integrating. + scalar_ = MDField(valName, ir.dl_scalar); + this->addDependentField(scalar_); + + // Create the field that we're either contributing to or evaluating + // (storing). + field_ = MDField(resName, basis.functional); + if (evalStyle == EvaluatorStyle::CONTRIBUTES) + this->addContributedField(field_); + else // if (evalStyle == EvaluatorStyle::EVALUATES) + this->addEvaluatedField(field_); + + // Add the dependent field multipliers, if there are any. + for (const auto& name : fmNames) + fieldMults_.push_back(MDField(name, + ir.dl_scalar)); + for (const auto& mult : fieldMults_) + this->addDependentField(mult); + + // Set the name of this object. + string n("Integrator_BasisTimesScalar ("); + if (evalStyle_ == EvaluatorStyle::CONTRIBUTES) + n += "Cont"; + else // if (evalStyle_ == EvaluatorStyle::EVALUATES) + n += "Eval"; + n += ", " + typeAsString() + "): " + field_.fieldTag().name(); + this->setName(n); + } // end of Main Constructor + + ///////////////////////////////////////////////////////////////////////////// + // + // ParameterList Constructor + // + ///////////////////////////////////////////////////////////////////////////// + template + Integrator_BasisTimesScalar:: + Integrator_BasisTimesScalar( + const Teuchos::ParameterList& p) + : + Integrator_BasisTimesScalar( + panzer::EvaluatorStyle::EVALUATES, + p.get("Residual Name"), + p.get("Value Name"), + (*p.get>("Basis")), + (*p.get>("IR")), + p.get("Multiplier"), + p.isType>> + ("Field Multipliers") ? + (*p.get>> + ("Field Multipliers")) : std::vector()) + { + using Teuchos::ParameterList; + using Teuchos::RCP; + + // Ensure that the input ParameterList didn't contain any bogus entries. + RCP validParams = this->getValidParameters(); + p.validateParameters(*validParams); + } // end of ParameterList Constructor + + ///////////////////////////////////////////////////////////////////////////// + // + // postRegistrationSetup() + // + ///////////////////////////////////////////////////////////////////////////// + template + void + Integrator_BasisTimesScalar:: + postRegistrationSetup( + typename Traits::SetupData sd, + PHX::FieldManager& fm) + { + using Kokkos::createDynRankView; + using panzer::getBasisIndex; + + // Determine the number of nodes and quadrature points. + numNodes_ = static_cast(field_.extent(1)); + numQP_ = static_cast(scalar_.extent(1)); + + // Determine the index in the Workset bases for our particular basis name. + basisIndex_ = getBasisIndex(basisName_, (*sd.worksets_)[0], this->wda); + + // Create a temporary View that we'll use in computing the integral. + tmp_ = createDynRankView(scalar_.get_static_view(), "tmp", + scalar_.dimension(0), numQP_); + } // end of postRegistrationSetup() + + ///////////////////////////////////////////////////////////////////////////// + // + // evaluateFields() + // + ///////////////////////////////////////////////////////////////////////////// + template + void + Integrator_BasisTimesScalar:: + evaluateFields( + typename Traits::EvalData workset) + { + using panzer::BasisValues2; + using panzer::EvaluatorStyle; + using panzer::index_t; + using PHX::MDField; + + // Initialize the evaluated field. + if (evalStyle_ == EvaluatorStyle::EVALUATES) + field_.deep_copy(ScalarT(0)); + + // Scale the integrand by the multiplier, and any field multipliers, out in + // front of the integral. + for (index_t cell(0); cell < workset.num_cells; ++cell) + { + for (int qp(0); qp < numQP_; ++qp) + { + tmp_(cell, qp) = multiplier_ * scalar_(cell, qp); + for (const auto& mult : fieldMults_) + tmp_(cell, qp) *= mult(cell, qp); + } // end loop over the quadrature points + } // end loop over the cells in the workset + + // Do the actual integration, looping over the cells in the workset, the + // bases, and the quadrature points. + const BasisValues2& bv = *this->wda(workset).bases[basisIndex_]; + for (index_t cell(0); cell < workset.num_cells; ++cell) + for (int basis(0); basis < numNodes_; ++basis) + for (int qp(0); qp < numQP_; ++qp) + field_(cell, basis) += tmp_(cell, qp) * + bv.weighted_basis_scalar(cell, basis, qp); + } // end of evaluateFields() -//********************************************************************** + ///////////////////////////////////////////////////////////////////////////// + // + // getValidParameters() + // + ///////////////////////////////////////////////////////////////////////////// + template + Teuchos::RCP + Integrator_BasisTimesScalar:: + getValidParameters() const + { + using panzer::BasisIRLayout; + using panzer::IntegrationRule; + using std::string; + using std::vector; + using Teuchos::ParameterList; + using Teuchos::RCP; + using Teuchos::rcp; -} + // Create a ParameterList with all the valid keys we support. + auto p = rcp(new ParameterList); + p->set("Residual Name", "?"); + p->set("Value Name", "?"); + RCP basis; + p->set("Basis", basis); + RCP ir; + p->set("IR", ir); + p->set("Multiplier", 1.0); + RCP> fms; + p->set("Field Multipliers", fms); + return p; + } // end of getValidParameters() -#endif +} // end of namespace panzer +#endif // __Panzer_Integrator_BasisTimesScalar_impl_hpp__ diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_decl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_decl.hpp index 17fc009f25e1..7154c8b5ba40 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_decl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_decl.hpp @@ -40,42 +40,272 @@ // *********************************************************************** // @HEADER -#ifndef PANZER_EVALUATOR_GRADBASISDOTVECTOR_DECL_HPP -#define PANZER_EVALUATOR_GRADBASISDOTVECTOR_DECL_HPP +#ifndef __Panzer_Integrator_GradBasisDotVector_decl_hpp__ +#define __Panzer_Integrator_GradBasisDotVector_decl_hpp__ +/////////////////////////////////////////////////////////////////////////////// +// +// Include Files +// +/////////////////////////////////////////////////////////////////////////////// + +// C++ #include -#include "Panzer_Dimension.hpp" -#include "Phalanx_Evaluator_Macros.hpp" -#include "Phalanx_MDField.hpp" + +// Kokkos #include "Kokkos_DynRankView.hpp" -#include "Panzer_Evaluator_Macros.hpp" +// Panzer +#include "Panzer_EvaluatorStyle.hpp" +#include "Panzer_Evaluator_WithBaseImpl.hpp" + +// Phalanx +#include "Phalanx_Evaluator_Derived.hpp" +#include "Phalanx_MDField.hpp" + +namespace panzer +{ + /** + * \brief Computes \f$ Ma(x)b(x)\cdots\int\vec{s}(x)\cdot\nabla\phi(x)\,dx + \f$. + * + * Evaluates the integral + * \f[ + Ma(x)b(x)\cdots\int\vec{s}(x)\cdot\nabla\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., are + * some fields that depend on position, \f$ \vec{s} \f$ is some + * vector-valued function, and \f$ \phi \f$ is some basis. + */ + template + class Integrator_GradBasisDotVector + : + public panzer::EvaluatorWithBaseImpl, + public PHX::EvaluatorDerived + { + public: + + /** + * \brief Main Constructor. + * + * Creates an `Evaluator` to evaluate the integral + * \f[ + Ma(x)b(x)\cdots\int\vec{s}(x)\cdot\nabla\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., + * are some fields that depend on position, \f$ \vec{s} \f$ is some + * vector-valued function, and \f$ \phi \f$ is some basis. + * + * \param[in] evalStyle An `enum` declaring the behavior of this + * `Evaluator`, which is to either: + * - compute and contribute (`CONTRIBUTES`), or + * - compute and store (`EVALUATES`). + * \param[in] resName The name of either the contributed or evaluated + * field, depending on `evalStyle`. + * \param[in] fluxName The name of the vector-valued function being + * integrated (\f$ \vec{s} \f$). + * \param[in] basis The basis that you'd like to use (\f$ \phi + \f$). + * \param[in] ir The integration rule that you'd like to use. + * \param[in] multiplier The scalar multiplier out in front of the + * integral you're computing (\f$ M \f$). If not + * specified, this defaults to 1. + * \param[in] fmNames A list of names of fields that are multipliers + * out in front of the integral you're computing + * (\f$ a(x) \f$, \f$ b(x) \f$, etc.). If not + * specified, this defaults to an empty `vector`. + * \param[in] vecDL The vector data layout that you'd like to use. + * If not specified, this defaults to + * `Teuchos::null` and the vector data layout from + * the given `ir` is used. + * + * \throws std::invalid_argument If any of the inputs are invalid. + * \throws std::logic_error If the `basis` supplied does not + * support the gradient operator, or if + * the dimension of the space exceeds the + * dimension of the vector data layout. + */ + Integrator_GradBasisDotVector( + const panzer::EvaluatorStyle& evalStyle, + const std::string& resName, + const std::string& fluxName, + const panzer::BasisIRLayout& basis, + const panzer::IntegrationRule& ir, + const double& multiplier = 1, + const std::vector& fmNames = + std::vector(), + const Teuchos::RCP& vecDL = Teuchos::null); + + /** + * \brief `ParameterList` Constructor. + * + * Creates an `Evaluator` to evaluate the integral + * \f[ + Ma(x)b(x)\cdots\int\vec{s}(x)\cdot\nabla\phi(x)\,dx, + \f] + * where \f$ M \f$ is some constant, \f$ a(x) \f$, \f$ b(x) \f$, etc., + * are some fields that depend on position, \f$ \vec{s} \f$ is some + * vector-valued function, and \f$ \phi \f$ is some basis. + * + * \note This constructor exists to preserve the older way of creating + * an `Evaluator` with a `ParameterList`; however, it is + * _strongly_ advised that you _not_ use this `ParameterList` + * Constructor, but rather that you favor either of the other + * constructors with their compile-time argument checking instead. + * + * \param[in] p A `ParameterList` of the form + \code{.xml} + + + + + + + + + + \endcode + * where + * - "Residual Name" is the name for the term this + * `Evaluator` is evaluating, + * - "Flux Name" is the name of the vector-valued function + * being integrated (\f$ \vec{s} \f$), + * - "Basis" is the basis that you'd like to use (\f$ \phi + \f$), + * - "IR" is the integration rule that you'd like to use, + * - "Multiplier" is the scalar multiplier out in front of + * the integral you're computing (\f$ M \f$), and + * - "Field Multipliers" is an optional list of names of + * fields that are multipliers out in front of the + * integral you're computing (\f$ a(x) \f$, \f$ b(x) \f$, + * etc.). + * - "Vector Data Layout" is the vector data layout that + * you'd like to use. + */ + Integrator_GradBasisDotVector( + const Teuchos::ParameterList& p); + + /** + * \brief Post-Registration Setup. + * + * Sets the number of nodes and quadrature points, sets the basis index, + * sets the contributed field data in the field manager (if applicable), + * and then creates the `tmp_` `Kokkos::View`. + * + * \param[in] sd Essentially a list of `Workset`s, which are collections + * of cells (elements) that all live on a single process. + * \param[in] fm The field manager, used in setting the field data for + * the contributed field, if there is one. + */ + void + postRegistrationSetup( + typename Traits::SetupData d, + PHX::FieldManager& fm); + + /** + * \brief Evaluate Fields. + * + * This actually performs the integration by looping over cells in the + * `Workset`, then over bases and integration points on the cell, and + * finally over the dimensions of the vector field. + * + * \param[in] workset The `Workset` on which you're going to do the + * integration. + */ + void + evaluateFields( + typename Traits::EvalData d); + + private: + + /** + * \brief Get Valid Parameters. + * + * Get all the parameters that we support such that the `ParameterList` + * Constructor can do some validation of the input `ParameterList`. + * + * \returns A `ParameterList` with all the valid parameters (keys) in + * it. The values tied to those keys are meaningless default + * values. + */ + Teuchos::RCP + getValidParameters() const; + + /** + * \brief The scalar type. + */ + typedef typename EvalT::ScalarT ScalarT; + + /** + * \brief An `enum` determining the behavior of this `Evaluator`. + * + * This `Evaluator` will compute the result of its integration and then: + * - CONTRIBUTES: contribute it to a specified residual, + * not saving anything; or + * - EVALUATES: save it under a specified name for + * future use. + */ + const panzer::EvaluatorStyle evalStyle_; + + /** + * \brief A field to which we'll contribute, or in which we'll store, + * the result of computing this integral. + */ + PHX::MDField field_; + + /** + * \brief A field representing the vector-valued function we're + * integrating (\f$ \vec{s} \f$). + */ + PHX::MDField flux_; + + /** + * \brief The scalar multiplier out in front of the integral (\f$ M + \f$). + */ + double multiplier_; -namespace panzer { - -PANZER_EVALUATOR_CLASS(Integrator_GradBasisDotVector) - - PHX::MDField residual; - - PHX::MDField flux; - - std::vector > field_multipliers; + /** + * \brief The (possibly empty) list of fields that are multipliers out + * in front of the integral (\f$ a(x) \f$, \f$ b(x) \f$, etc.). + */ + std::vector> + fieldMults_; - std::size_t num_nodes; + /** + * \brief The number of nodes for each cell. + */ + int numNodes_; - std::size_t num_qp; + /** + * \brief The number of quadrature points for each cell. + */ + int numQP_; - std::size_t num_dim; + /** + * \brief The number of dimensions in the vector field \f$ \vec{s} \f$. + */ + int numDim_; - double multiplier; + /** + * \brief The name of the basis we're using. + */ + std::string basisName_; - std::string basis_name; - std::size_t basis_index; + /** + * \brief The index in the `Workset` bases for our particular + * `BasisIRLayout` name. + */ + std::size_t basisIndex_; - Kokkos::DynRankView tmp; + /** + * \brief A temporary `Kokkos::View` that we'll use in computing the + * result of this integral. + */ + Kokkos::DynRankView tmp; -PANZER_EVALUATOR_CLASS_END + }; // end of class Integrator_GradBasisDotVector -} +} // end of namespace panzer -#endif +#endif // __Panzer_Integrator_GradBasisDotVector_decl_hpp__ diff --git a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_impl.hpp b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_impl.hpp index bb66806c1cab..74c814d1cd20 100644 --- a/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_impl.hpp +++ b/packages/panzer/disc-fe/src/evaluators/Panzer_Integrator_GradBasisDotVector_impl.hpp @@ -40,171 +40,249 @@ // *********************************************************************** // @HEADER -#ifndef PANZER_EVALUATOR_GRADBASISDOTVECTOR_IMPL_HPP -#define PANZER_EVALUATOR_GRADBASISDOTVECTOR_IMPL_HPP +#ifndef __Panzer_Integrator_GradBasisDotVector_impl_hpp__ +#define __Panzer_Integrator_GradBasisDotVector_impl_hpp__ -#include "Intrepid2_FunctionSpaceTools.hpp" -#include "Panzer_IntegrationRule.hpp" -#include "Panzer_BasisIRLayout.hpp" -#include "Panzer_Workset_Utilities.hpp" -#include "Kokkos_ViewFactory.hpp" +/////////////////////////////////////////////////////////////////////////////// +// +// Include Files +// +/////////////////////////////////////////////////////////////////////////////// -#define PANZER_USE_FAST_QUAD 1 -// #define PANZER_USE_FAST_QUAD 0 +// Kokkos +#include "Kokkos_ViewFactory.hpp" -namespace panzer { +// Panzer +#include "Panzer_BasisIRLayout.hpp" +#include "Panzer_IntegrationRule.hpp" +#include "Panzer_Workset_Utilities.hpp" -//********************************************************************** -PHX_EVALUATOR_CTOR(Integrator_GradBasisDotVector,p) : - residual( p.get("Residual Name"), - p.get< Teuchos::RCP >("Basis")->functional), -// flux( p.get("Flux Name"), -// p.get< Teuchos::RCP >("IR")->dl_vector ), - basis_name(p.get< Teuchos::RCP >("Basis")->name()) +namespace panzer { - Teuchos::RCP basis - = p.get< Teuchos::RCP >("Basis")->getBasis(); - - - // Default to this so we don't break anything - Teuchos::RCP vector = p.get< Teuchos::RCP >("IR")->dl_vector; - if(p.isType >("Vector Data Layout")){ - vector = p.get >("Vector Data Layout"); - } - - flux = PHX::MDField( p.get("Flux Name"), vector); - - // Number of dimensions has to be based on the spatial dimensions NOT THE DIMENSIONS OF THE VECTOR - num_dim = p.get< Teuchos::RCP >("IR")->dl_vector->dimension(2); - - // Verify that this basis supports the gradient operation - TEUCHOS_TEST_FOR_EXCEPTION(!basis->supportsGrad(),std::logic_error, - "Integrator_GradBasisDotVector: Basis of type \"" << basis->name() << "\" does not support GRAD"); - - // Make sure the Grad dimensions includes the vector - TEUCHOS_TEST_FOR_EXCEPTION(vector->dimension(2) < num_dim,std::logic_error, - "Integrator_GradBasisDotVector: Dimension of space exceeds dimension of vector."); - - this->addEvaluatedField(residual); - this->addDependentField(flux); - - multiplier = p.get("Multiplier"); - - if (p.isType > >("Field Multipliers")) + ///////////////////////////////////////////////////////////////////////////// + // + // Main Constructor + // + ///////////////////////////////////////////////////////////////////////////// + template + Integrator_GradBasisDotVector:: + Integrator_GradBasisDotVector( + const panzer::EvaluatorStyle& evalStyle, + const std::string& resName, + const std::string& fluxName, + const panzer::BasisIRLayout& basis, + const panzer::IntegrationRule& ir, + const double& multiplier, /* = 1 */ + const std::vector& fmNames, /* = + std::vector() */ + const Teuchos::RCP& vecDL /* = Teuchos::null */) + : + evalStyle_(evalStyle), + multiplier_(multiplier), + numDim_(static_cast(ir.dl_vector->extent(2))), + basisName_(basis.name()) { - const std::vector& field_multiplier_names = - *(p.get > >("Field Multipliers")); - - for (std::vector::const_iterator name = field_multiplier_names.begin(); - name != field_multiplier_names.end(); ++name) + using panzer::BASIS; + using panzer::Cell; + using panzer::EvaluatorStyle; + using panzer::IP; + using PHX::DataLayout; + using PHX::MDField; + using PHX::typeAsString; + using std::invalid_argument; + using std::logic_error; + using std::string; + using Teuchos::RCP; + + // Ensure the input makes sense. + TEUCHOS_TEST_FOR_EXCEPTION(resName == "", invalid_argument, "Error: " \ + "Integrator_GradBasisDotVector called with an empty residual name.") + TEUCHOS_TEST_FOR_EXCEPTION(fluxName == "", invalid_argument, "Error: " \ + "Integrator_GradBasisDotVector called with an empty flux name.") + RCP tmpBasis = basis.getBasis(); + TEUCHOS_TEST_FOR_EXCEPTION(not tmpBasis->supportsGrad(), logic_error, + "Integrator_GradBasisDotVector: Basis of type \"" << tmpBasis->name() << + "\" does not support the gradient operator."); + RCP tmpVecDL = ir.dl_vector; + if (not vecDL.is_null()) { - PHX::MDField tmp_field(*name, p.get< Teuchos::RCP >("IR")->dl_scalar); - field_multipliers.push_back(tmp_field); - } - } - - for (auto & field : field_multipliers){ - this->addDependentField(field); - } - - std::string n = - "Integrator_GradBasisDotVector: " + residual.fieldTag().name(); + tmpVecDL = vecDL; + TEUCHOS_TEST_FOR_EXCEPTION( + static_cast(tmpVecDL->extent(2)) < numDim_, logic_error, + "Integrator_GradBasisDotVector: Dimension of space exceeds " \ + "dimension of Vector Data Layout."); + } // end if (not vecDL.is_null()) + + // Create the field for the vector-valued function we're integrating. + flux_ = MDField(fluxName, tmpVecDL); + this->addDependentField(flux_); + + // Create the field that we're either contributing to or evaluating + // (storing). + field_ = MDField(resName, basis.functional); + if (evalStyle_ == EvaluatorStyle::CONTRIBUTES) + this->addContributedField(field_); + else // if (evalStyle_ == EvaluatorStyle::EVALUATES) + this->addEvaluatedField(field_); + + // Add the dependent field multipliers, if there are any. + for (const auto& name : fmNames) + fieldMults_.push_back(MDField(name, + ir.dl_scalar)); + for (const auto& mult : fieldMults_) + this->addDependentField(mult); + + // Set the name of this object. + string n("Integrator_GradBasisDotVector ("); + if (evalStyle_ == EvaluatorStyle::CONTRIBUTES) + n += "Cont"; + else // if (evalStyle_ == EvaluatorStyle::EVALUATES) + n += "Eval"; + n += ", " + typeAsString() + "): " + field_.fieldTag().name(); + this->setName(n); + } // end of Main Constructor + + ///////////////////////////////////////////////////////////////////////////// + // + // ParameterList Constructor + // + ///////////////////////////////////////////////////////////////////////////// + template + Integrator_GradBasisDotVector:: + Integrator_GradBasisDotVector( + const Teuchos::ParameterList& p) + : + Integrator_GradBasisDotVector( + panzer::EvaluatorStyle::EVALUATES, + p.get("Residual Name"), + p.get("Flux Name"), + (*p.get>("Basis")), + (*p.get>("IR")), + p.get("Multiplier"), + p.isType>> + ("Field Multipliers") ? + (*p.get>> + ("Field Multipliers")) : std::vector(), + p.isType>("Vector Data Layout") ? + p.get>("Vector Data Layout") : + Teuchos::null) + { + using Teuchos::ParameterList; + using Teuchos::RCP; + + // Ensure that the input ParameterList didn't contain any bogus entries. + RCP validParams = this->getValidParameters(); + p.validateParameters(*validParams); + } // end of ParameterList Constructor + + ///////////////////////////////////////////////////////////////////////////// + // + // postRegistrationSetup() + // + ///////////////////////////////////////////////////////////////////////////// + template + void + Integrator_GradBasisDotVector:: + postRegistrationSetup( + typename Traits::SetupData sd, + PHX::FieldManager& fm) + { + using Kokkos::createDynRankView; + using panzer::getBasisIndex; + + // Determine the number of nodes and quadrature points. + numNodes_ = static_cast(field_.extent(1)); + numQP_ = static_cast(flux_.extent(1)); + + // Determine the index in the Workset bases for our particular basis name. + basisIndex_ = getBasisIndex(basisName_, (*sd.worksets_)[0], this->wda); + + // Create a temporary View that we'll use in computing the integral. + tmp = createDynRankView(field_.get_static_view(), "tmp", + flux_.dimension(0), numQP_, numDim_); + } // end of postRegistrationSetup() + + ///////////////////////////////////////////////////////////////////////////// + // + // evaluateFields() + // + ///////////////////////////////////////////////////////////////////////////// + template + void + Integrator_GradBasisDotVector:: + evaluateFields( + typename Traits::EvalData workset) + { + using panzer::index_t; + using PHX::MDField; - this->setName(n); -} + // Initialize the evaluated field. + if (evalStyle_ == EvaluatorStyle::EVALUATES) + field_.deep_copy(ScalarT(0)); -//********************************************************************** -PHX_POST_REGISTRATION_SETUP(Integrator_GradBasisDotVector,sd,fm) -{ - this->utils.setFieldData(residual,fm); - this->utils.setFieldData(flux,fm); - - for (auto & field : field_multipliers) - this->utils.setFieldData(field,fm); - - num_nodes = residual.dimension(1); - num_qp = flux.dimension(1); - - basis_index = panzer::getBasisIndex(basis_name, (*sd.worksets_)[0], this->wda); - - tmp = Kokkos::createDynRankView(residual.get_static_view(),"tmp",flux.dimension(0), num_qp, num_dim); -} - -//********************************************************************** -PHX_EVALUATE_FIELDS(Integrator_GradBasisDotVector,workset) -{ - //for (int i=0; i < residual.size(); ++i) - // residual[i] = 0.0; - - Kokkos::deep_copy(residual.get_static_view(), ScalarT(0.0)); - -#if PANZER_USE_FAST_QUAD - // do a scaled copy - for (int i(0); i < flux.extent_int(0); ++i) - for (int j(0); j < flux.extent_int(1); ++j) - for (int k(0); k < static_cast(num_dim); ++k) - tmp(i,j,k) = multiplier * flux(i,j,k); -//Irina modified -// for (int i=0; i < flux.size(); ++i) -// tmp[i] = multiplier * flux[i]; - - for (auto & field : field_multipliers) { - PHX::MDField field_data = field; - - for (index_t cell = 0; cell < workset.num_cells; ++cell) { - for (std::size_t qp = 0; qp < num_qp; ++qp) { - ScalarT tmpVar = field_data(cell,qp); - - for (std::size_t dim = 0; dim < num_dim; ++dim) - tmp(cell,qp,dim) *= tmpVar; - } - } - } - - // const Kokkos::DynRankView & weighted_grad_basis = this->wda(workset).bases[basis_index]->weighted_grad_basis; - const BasisValues2 & bv = *this->wda(workset).bases[basis_index]; - - // perform integration and vector dot product (at the same time! whoah!) - for (index_t cell = 0; cell < workset.num_cells; ++cell) { - for (std::size_t basis = 0; basis < num_nodes; ++basis) { - for (std::size_t qp = 0; qp < num_qp; ++qp) { - for (std::size_t dim = 0; dim < num_dim; ++dim) { - residual(cell,basis) += tmp(cell,qp,dim)*bv.weighted_grad_basis(cell,basis,qp,dim); - - /* - std::cout << residual(cell,basis) << " " - << tmp(cell,qp,dim) << " " - << bv.weighted_grad_basis(cell,basis,qp,dim) << std::endl; - */ - } - } - } - } -#else - for (index_t cell = 0; cell < workset.num_cells; ++cell) - { - for (std::size_t qp = 0; qp < num_qp; ++qp) + // Scale the integrand by the multiplier, and any field multipliers, out in + // front of the integral. + for (index_t cell(0); cell < workset.num_cells; ++cell) { - ScalarT tmpVar = 1.0; - for (typename std::vector >::iterator field = field_multipliers.begin(); - field != field_multipliers.end(); ++field) - tmpVar = tmpVar * (*field)(cell,qp); - - for (std::size_t dim = 0; dim < num_dim; ++dim) - tmp(cell,qp,dim) = multiplier * tmpVar * flux(cell,qp,dim); - } - } - - if(workset.num_cells>0) - Intrepid2::FunctionSpaceTools:: - integrate(residual, tmp, - (this->wda(workset).bases[basis_index])->weighted_grad_basis, - Intrepid2::COMP_CPP); -#endif -} - -//********************************************************************** - -} - -#endif + for (int qp(0); qp < numQP_; ++qp) + { + for (int dim(0); dim < numDim_; ++dim) + { + tmp(cell, qp, dim) = multiplier_ * flux_(cell, qp, dim); + for (const auto& mult : fieldMults_) + tmp(cell, qp, dim) *= mult(cell, qp); + } // end loop over the dimensions + } // end loop over the quadrature points + } // end loop over the cells in the workset + + // Perform integration and vector dot product via looping over the cells in + // the worksheet, the bases, the quadrature points, and the number of + // dimensions of the flux vector. + const BasisValues2 & bv = *this->wda(workset).bases[basisIndex_]; + ScalarT quantity(0); + for (index_t cell(0); cell < workset.num_cells; ++cell) + for (int basis(0); basis < numNodes_; ++basis) + for (int qp(0); qp < numQP_; ++qp) + for (int dim(0); dim < numDim_; ++dim) + field_(cell, basis) += tmp(cell, qp, dim) * + bv.weighted_grad_basis(cell, basis, qp, dim); + } // end of evaluateFields() + + ///////////////////////////////////////////////////////////////////////////// + // + // getValidParameters() + // + ///////////////////////////////////////////////////////////////////////////// + template + Teuchos::RCP + Integrator_GradBasisDotVector:: + getValidParameters() const + { + using panzer::BasisIRLayout; + using panzer::IntegrationRule; + using PHX::DataLayout; + using std::string; + using std::vector; + using Teuchos::ParameterList; + using Teuchos::RCP; + using Teuchos::rcp; + + // Create a ParameterList with all the valid keys we support. + auto p = rcp(new ParameterList); + p->set("Residual Name", "?"); + p->set("Flux Name", "?"); + RCP basis; + p->set("Basis", basis); + RCP ir; + p->set("IR", ir); + p->set("Multiplier", 1.0); + RCP> fms; + p->set("Field Multipliers", fms); + RCP vecDL; + p->set("Vector Data Layout", vecDL); + return p; + } // end of getValidParameters() + +} // end of namespace panzer + +#endif // __Panzer_Integrator_GradBasisDotVector_impl_hpp__